cursor-guard 4.9.12 → 4.9.15
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 +697 -697
- package/README.zh-CN.md +696 -696
- package/ROADMAP.md +1775 -1758
- package/SKILL.md +631 -629
- package/docs/RELEASE.md +197 -196
- package/docs/SNAPSHOT-BOOKMARK.md +47 -0
- package/package.json +2 -1
- package/references/dashboard/public/app.js +2079 -2050
- package/references/dashboard/public/style.css +1660 -1628
- package/references/lib/core/backups.js +509 -507
- package/references/lib/core/core.test.js +39 -1
- package/references/lib/core/snapshot.js +441 -416
- package/references/mcp/mcp.test.js +381 -362
- package/references/mcp/server.js +404 -347
- package/references/vscode-extension/{cursor-guard-ide-4.9.12.vsix → dist/cursor-guard-ide-4.9.15.vsix} +0 -0
- package/references/vscode-extension/dist/dashboard/public/app.js +2079 -2050
- package/references/vscode-extension/dist/dashboard/public/style.css +1660 -1628
- package/references/vscode-extension/dist/extension.js +780 -704
- package/references/vscode-extension/dist/guard-version.json +1 -1
- package/references/vscode-extension/dist/lib/auto-setup.js +201 -192
- package/references/vscode-extension/dist/lib/core/backups.js +509 -507
- package/references/vscode-extension/dist/lib/core/snapshot.js +441 -416
- package/references/vscode-extension/dist/mcp/server.js +78 -12
- package/references/vscode-extension/dist/package.json +7 -1
- package/references/vscode-extension/dist/skill/ROADMAP.md +1775 -1758
- package/references/vscode-extension/dist/skill/SKILL.md +631 -629
- package/references/vscode-extension/extension.js +780 -704
- package/references/vscode-extension/lib/auto-setup.js +201 -192
- package/references/vscode-extension/package.json +7 -1
- package/references/vscode-extension/dist/cursor-guard-ide-4.9.12.vsix +0 -0
|
@@ -35594,7 +35594,7 @@ var require_package = __commonJS({
|
|
|
35594
35594
|
"package.json"(exports2, module2) {
|
|
35595
35595
|
module2.exports = {
|
|
35596
35596
|
name: "cursor-guard",
|
|
35597
|
-
version: "4.9.
|
|
35597
|
+
version: "4.9.15",
|
|
35598
35598
|
description: "Protects code from accidental AI overwrite or deletion in Cursor IDE \u2014 mandatory pre-write snapshots, review-before-apply, local Git safety net, and deterministic recovery. | \u4FDD\u62A4\u4EE3\u7801\u514D\u53D7 Cursor AI \u4EE3\u7406\u610F\u5916\u8986\u5199\u6216\u5220\u9664\u2014\u2014\u5F3A\u5236\u5199\u524D\u5FEB\u7167\u3001\u9884\u89C8\u518D\u6267\u884C\u3001\u672C\u5730 Git \u5B89\u5168\u7F51\u3001\u786E\u5B9A\u6027\u6062\u590D\u3002",
|
|
35599
35599
|
keywords: [
|
|
35600
35600
|
"cursor",
|
|
@@ -35633,6 +35633,7 @@ var require_package = __commonJS({
|
|
|
35633
35633
|
"README.md",
|
|
35634
35634
|
"README.zh-CN.md",
|
|
35635
35635
|
"docs/RELEASE.md",
|
|
35636
|
+
"docs/SNAPSHOT-BOOKMARK.md",
|
|
35636
35637
|
"ROADMAP.md",
|
|
35637
35638
|
"LICENSE",
|
|
35638
35639
|
"references/auto-backup.ps1",
|
|
@@ -36078,6 +36079,10 @@ var require_snapshot = __commonJS({
|
|
|
36078
36079
|
}
|
|
36079
36080
|
return excluded;
|
|
36080
36081
|
}
|
|
36082
|
+
function trailerScalar2(val, maxLen = 500) {
|
|
36083
|
+
if (val == null) return "";
|
|
36084
|
+
return String(val).replace(/\r\n/g, " ").replace(/\r/g, " ").replace(/\n/g, " ").trim().slice(0, maxLen);
|
|
36085
|
+
}
|
|
36081
36086
|
function buildCommitMessage(ts, opts) {
|
|
36082
36087
|
if (opts.message && !opts.context) return opts.message;
|
|
36083
36088
|
const ctx = opts.context || {};
|
|
@@ -36085,11 +36090,12 @@ var require_snapshot = __commonJS({
|
|
|
36085
36090
|
const subject = opts.message || `guard: auto-backup ${ts}${countTag}`;
|
|
36086
36091
|
const trailers = [];
|
|
36087
36092
|
if (ctx.changedFileCount != null) trailers.push(`Files-Changed: ${ctx.changedFileCount}`);
|
|
36088
|
-
if (ctx.summary) trailers.push(`Summary: ${ctx.summary}`);
|
|
36089
|
-
if (ctx.trigger) trailers.push(`Trigger: ${ctx.trigger}`);
|
|
36090
|
-
if (ctx.intent) trailers.push(`Intent: ${ctx.intent}`);
|
|
36091
|
-
if (ctx.agent) trailers.push(`Agent: ${ctx.agent}`);
|
|
36092
|
-
if (ctx.session) trailers.push(`Session: ${ctx.session}`);
|
|
36093
|
+
if (ctx.summary) trailers.push(`Summary: ${trailerScalar2(ctx.summary, 2e3)}`);
|
|
36094
|
+
if (ctx.trigger) trailers.push(`Trigger: ${trailerScalar2(ctx.trigger)}`);
|
|
36095
|
+
if (ctx.intent) trailers.push(`Intent: ${trailerScalar2(ctx.intent)}`);
|
|
36096
|
+
if (ctx.agent) trailers.push(`Agent: ${trailerScalar2(ctx.agent)}`);
|
|
36097
|
+
if (ctx.session) trailers.push(`Session: ${trailerScalar2(ctx.session)}`);
|
|
36098
|
+
if (ctx.guardEvent) trailers.push(`Guard-Event: ${trailerScalar2(ctx.guardEvent)}`);
|
|
36093
36099
|
if (trailers.length === 0) return subject;
|
|
36094
36100
|
return subject + "\n\n" + trailers.join("\n");
|
|
36095
36101
|
}
|
|
@@ -36128,6 +36134,7 @@ var require_snapshot = __commonJS({
|
|
|
36128
36134
|
if (newTree === parentTree && !opts.allowEmptyTree) {
|
|
36129
36135
|
return { status: "skipped", reason: "tree unchanged" };
|
|
36130
36136
|
}
|
|
36137
|
+
const isBookmarkCommit = !!(opts.allowEmptyTree && parentTree && newTree === parentTree);
|
|
36131
36138
|
let changedCount;
|
|
36132
36139
|
let incrementalSummary;
|
|
36133
36140
|
let changedFiles;
|
|
@@ -36216,6 +36223,13 @@ var require_snapshot = __commonJS({
|
|
|
36216
36223
|
if (changedCount != null && opts.context) {
|
|
36217
36224
|
opts.context.changedFileCount = changedCount;
|
|
36218
36225
|
}
|
|
36226
|
+
if (isBookmarkCommit && opts.context) {
|
|
36227
|
+
const s = opts.context.summary;
|
|
36228
|
+
if (s == null || String(s).trim() === "") {
|
|
36229
|
+
opts.context.summary = "No file changes since last Guard baseline (bookmark).";
|
|
36230
|
+
}
|
|
36231
|
+
if (opts.context.changedFileCount == null) opts.context.changedFileCount = 0;
|
|
36232
|
+
}
|
|
36219
36233
|
const ts = formatTimestamp(/* @__PURE__ */ new Date());
|
|
36220
36234
|
let msg = buildCommitMessage(ts, opts);
|
|
36221
36235
|
const autoTip = git(["rev-parse", "--verify", REF_GUARD_AUTO_BACKUP], { cwd, allowFail: true });
|
|
@@ -36230,7 +36244,7 @@ var require_snapshot = __commonJS({
|
|
|
36230
36244
|
}
|
|
36231
36245
|
const scopeTrailer = narrowProtect ? "narrow" : "full";
|
|
36232
36246
|
const guardBlock = `Guard-Diff-Base: ${diffBaseLabel}
|
|
36233
|
-
Guard-Scope: ${scopeTrailer}`;
|
|
36247
|
+
Guard-Scope: ${scopeTrailer}${isBookmarkCommit ? "\nGuard-Bookmark: true" : ""}`;
|
|
36234
36248
|
msg = msg.includes("\n\n") ? `${msg}
|
|
36235
36249
|
${guardBlock}` : `${msg}
|
|
36236
36250
|
|
|
@@ -36251,7 +36265,8 @@ ${guardBlock}`;
|
|
|
36251
36265
|
changedCount,
|
|
36252
36266
|
changedFiles,
|
|
36253
36267
|
incrementalSummary,
|
|
36254
|
-
secretsExcluded: secretsExcluded.length > 0 ? secretsExcluded : void 0
|
|
36268
|
+
secretsExcluded: secretsExcluded.length > 0 ? secretsExcluded : void 0,
|
|
36269
|
+
...isBookmarkCommit ? { bookmark: true } : {}
|
|
36255
36270
|
};
|
|
36256
36271
|
} catch (e) {
|
|
36257
36272
|
return { status: "error", error: e.message };
|
|
@@ -36335,7 +36350,7 @@ ${guardBlock}`;
|
|
|
36335
36350
|
return { status: "error", error: e.message };
|
|
36336
36351
|
}
|
|
36337
36352
|
}
|
|
36338
|
-
module2.exports = { createGitSnapshot: createGitSnapshot2, createShadowCopy: createShadowCopy2, formatTimestamp, removeSecretsFromIndex };
|
|
36353
|
+
module2.exports = { createGitSnapshot: createGitSnapshot2, createShadowCopy: createShadowCopy2, formatTimestamp, removeSecretsFromIndex, trailerScalar: trailerScalar2 };
|
|
36339
36354
|
}
|
|
36340
36355
|
});
|
|
36341
36356
|
|
|
@@ -36387,11 +36402,13 @@ var require_backups = __commonJS({
|
|
|
36387
36402
|
"Intent": { key: "intent" },
|
|
36388
36403
|
"Agent": { key: "agent" },
|
|
36389
36404
|
"Session": { key: "session" },
|
|
36405
|
+
"Guard-Event": { key: "guardEvent" },
|
|
36390
36406
|
"From": { key: "from" },
|
|
36391
36407
|
"Restore-To": { key: "restoreTo" },
|
|
36392
36408
|
"File": { key: "restoreFile" },
|
|
36393
36409
|
"Guard-Diff-Base": { key: "guardDiffBase" },
|
|
36394
|
-
"Guard-Scope": { key: "guardScope" }
|
|
36410
|
+
"Guard-Scope": { key: "guardScope" },
|
|
36411
|
+
"Guard-Bookmark": { key: "guardBookmark", parse: (v) => String(v).trim().toLowerCase() === "true" }
|
|
36395
36412
|
};
|
|
36396
36413
|
function parseCommitTrailers(body) {
|
|
36397
36414
|
if (!body) return {};
|
|
@@ -38101,7 +38118,7 @@ var { McpServer } = require_mcp();
|
|
|
38101
38118
|
var { StdioServerTransport } = require_stdio2();
|
|
38102
38119
|
var { z } = require_zod();
|
|
38103
38120
|
var { runDiagnostics } = require_doctor();
|
|
38104
|
-
var { createGitSnapshot, createShadowCopy } = require_snapshot();
|
|
38121
|
+
var { createGitSnapshot, createShadowCopy, trailerScalar } = require_snapshot();
|
|
38105
38122
|
var { listBackups } = require_backups();
|
|
38106
38123
|
var { restoreFile, previewProjectRestore, executeProjectRestore } = require_restore();
|
|
38107
38124
|
var { runFixes } = require_doctor_fix();
|
|
@@ -38223,7 +38240,7 @@ server.tool(
|
|
|
38223
38240
|
);
|
|
38224
38241
|
server.tool(
|
|
38225
38242
|
"snapshot_now",
|
|
38226
|
-
"Create an immediate backup snapshot of the current project state. Use before risky operations to preserve a restore point.",
|
|
38243
|
+
"Create an immediate backup snapshot of the current project state. Use before risky operations to preserve a restore point. If the snapshot tree matches the previous Guard baseline (no file changes), a bookmark commit is still created on refs/guard/snapshot so intent/time stay visible \u2014 not silently skipped.",
|
|
38227
38244
|
{
|
|
38228
38245
|
path: z.string().describe("Absolute path to the project directory"),
|
|
38229
38246
|
strategy: z.enum(["git", "shadow", "both"]).optional().describe('Backup strategy (default: from config, or "git")'),
|
|
@@ -38268,6 +38285,55 @@ server.tool(
|
|
|
38268
38285
|
};
|
|
38269
38286
|
}
|
|
38270
38287
|
);
|
|
38288
|
+
server.tool(
|
|
38289
|
+
"record_guard_event",
|
|
38290
|
+
"Create a Git bookmark on refs/guard/snapshot focused on MCP/agent audit: stores Guard-Event (what happened), optional detail/summary, intent, agent, session. When the tree matches the previous baseline, still creates a commit (same as snapshot_now) so the timeline shows the event with no silent skip. Use after other MCP calls when you need a visible record without relying on file diffs alone.",
|
|
38291
|
+
{
|
|
38292
|
+
path: z.string().describe("Absolute path to the project directory"),
|
|
38293
|
+
event: z.string().describe("Short event label, e.g. restore_project:execute, doctor_fix, list_backups:query"),
|
|
38294
|
+
detail: z.string().optional().describe("Longer text stored in Summary trailer (optional)"),
|
|
38295
|
+
intent: z.string().optional().describe("Human-readable intent; defaults to event if omitted"),
|
|
38296
|
+
agent: z.string().optional().describe("AI model identifier"),
|
|
38297
|
+
session: z.string().optional().describe("Conversation or session ID")
|
|
38298
|
+
},
|
|
38299
|
+
async ({ path: projectPath, event, detail, intent, agent, session }) => {
|
|
38300
|
+
const resolved = path.resolve(projectPath);
|
|
38301
|
+
ensureWatcher(resolved);
|
|
38302
|
+
const { cfg } = loadConfig(resolved);
|
|
38303
|
+
const ev = trailerScalar(event);
|
|
38304
|
+
if (!ev) {
|
|
38305
|
+
const err = { git: { status: "error", error: "event must be a non-empty string" } };
|
|
38306
|
+
injectPreWarning(resolved, injectAlert(resolved, err));
|
|
38307
|
+
injectWatcherWarning(resolved, err);
|
|
38308
|
+
return { content: [{ type: "text", text: JSON.stringify(err, null, 2) }] };
|
|
38309
|
+
}
|
|
38310
|
+
const context = {
|
|
38311
|
+
trigger: "mcp-event",
|
|
38312
|
+
guardEvent: ev,
|
|
38313
|
+
summary: detail ? trailerScalar(detail, 2e3) : `MCP event: ${ev}`
|
|
38314
|
+
};
|
|
38315
|
+
if (intent) context.intent = trailerScalar(intent);
|
|
38316
|
+
if (agent) context.agent = trailerScalar(agent);
|
|
38317
|
+
if (session) context.session = trailerScalar(session);
|
|
38318
|
+
const results = {
|
|
38319
|
+
git: createGitSnapshot(resolved, cfg, {
|
|
38320
|
+
branchRef: "refs/guard/snapshot",
|
|
38321
|
+
message: `guard: MCP event ${(/* @__PURE__ */ new Date()).toISOString()}`,
|
|
38322
|
+
context,
|
|
38323
|
+
allowEmptyTree: true,
|
|
38324
|
+
fullWorkspaceSnapshot: true
|
|
38325
|
+
})
|
|
38326
|
+
};
|
|
38327
|
+
injectPreWarning(resolved, injectAlert(resolved, results));
|
|
38328
|
+
injectWatcherWarning(resolved, results);
|
|
38329
|
+
return {
|
|
38330
|
+
content: [{
|
|
38331
|
+
type: "text",
|
|
38332
|
+
text: JSON.stringify(results, null, 2)
|
|
38333
|
+
}]
|
|
38334
|
+
};
|
|
38335
|
+
}
|
|
38336
|
+
);
|
|
38271
38337
|
server.tool(
|
|
38272
38338
|
"restore_file",
|
|
38273
38339
|
"Restore a single file from a backup source (git commit/ref or shadow copy timestamp). By default, preserves the current version in a pre-restore snapshot before restoring.",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "cursor-guard-ide",
|
|
3
3
|
"displayName": "Cursor Guard",
|
|
4
4
|
"description": "AI code protection dashboard embedded in your IDE — real-time alerts, backup history, one-click snapshots",
|
|
5
|
-
"version": "4.9.
|
|
5
|
+
"version": "4.9.15",
|
|
6
6
|
"publisher": "zhangqiang8vipp",
|
|
7
7
|
"license": "BUSL-1.1",
|
|
8
8
|
"engines": {
|
|
@@ -67,6 +67,12 @@
|
|
|
67
67
|
"category": "Cursor Guard",
|
|
68
68
|
"icon": "$(search)"
|
|
69
69
|
},
|
|
70
|
+
{
|
|
71
|
+
"command": "cursorGuard.setupSkill",
|
|
72
|
+
"title": "Install Agent Skill",
|
|
73
|
+
"category": "Cursor Guard",
|
|
74
|
+
"icon": "$(book)"
|
|
75
|
+
},
|
|
70
76
|
{
|
|
71
77
|
"command": "cursorGuard.addToProtect",
|
|
72
78
|
"title": "Add to Protected",
|