feat: add LexAI status bar and suggestion panel
Some checks failed
CI — Test & Build / Test & Build (push) Has been cancelled
Some checks failed
CI — Test & Build / Test & Build (push) Has been cancelled
- Implemented a status bar item for LexAI with dynamic status updates (ready, processing, notReady). - Created a suggestion panel for displaying and interacting with AI-generated suggestions. - Added functionality for accepting, regenerating, and discarding suggestions within the suggestion zone. - Introduced configuration options for writing style, prompt patterns, personas, and formats. - Integrated progress indicators for long-running tasks and improved user feedback. - Established TypeScript configuration for the vscode package.
This commit is contained in:
72
.cursor/hooks/guard-destructive.mjs
Normal file
72
.cursor/hooks/guard-destructive.mjs
Normal file
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* beforeShellExecution hook — turn the kit's "explicit authorization before
|
||||
* destructive or external action" rule into something that actually stops.
|
||||
*
|
||||
* A rule in a prompt is advice the model can rationalize past under momentum.
|
||||
* This is a gate. It never denies on its own — it returns "ask", so you decide,
|
||||
* with the reason named. That keeps the failure mode "one extra confirmation"
|
||||
* rather than "the agent cannot work".
|
||||
*
|
||||
* Contract: stdin is the beforeShellExecution payload; stdout is
|
||||
* {"permission": "allow"|"ask"|"deny", "user_message": "...", "agent_message": "..."}.
|
||||
* Exit 0 = success. This hook has no failClosed flag in hooks.json, so if node is
|
||||
* missing or this script throws, Cursor fails open and the session keeps working.
|
||||
*/
|
||||
|
||||
// Routine `git push` is deliberately NOT gated: a prompt that fires on every push gets
|
||||
// approved reflexively and stops meaning anything. Force pushes are. Add your own.
|
||||
const PATTERNS = [
|
||||
[/\brm\s+(-[a-zA-Z]*[rf][a-zA-Z]*\s+)+/, "recursive or forced delete"],
|
||||
[/\bgit\s+push\b.*(--force|-f)\b/, "force push"],
|
||||
[/\bgit\s+(reset\s+--hard|clean\s+-[a-zA-Z]*f)/, "discards uncommitted work"],
|
||||
[/\b(drop|truncate)\s+(table|database|schema)\b/i, "destructive database statement"],
|
||||
[/\b(migrate|db:migrate|alembic\s+upgrade|prisma\s+migrate\s+deploy)\b/i, "database migration"],
|
||||
[/\b(terraform|pulumi)\s+(apply|destroy)\b/, "infrastructure change"],
|
||||
[/\bkubectl\s+(delete|apply)\b/, "cluster change"],
|
||||
[/\b(npm|pnpm|yarn)\s+publish\b/, "package publish"],
|
||||
[/\b(vercel|netlify|fly|heroku|wrangler)\s+(deploy|publish)\b/i, "deployment"],
|
||||
[/\bdocker\s+(push|system\s+prune)\b/, "registry push or prune"],
|
||||
[/\bchmod\s+(-R\s+)?777\b/, "world-writable permissions"],
|
||||
[/\bcurl\b[^|]*\|\s*(ba)?sh\b/, "pipe-to-shell from the network"],
|
||||
[/>\s*\/dev\/sd[a-z]|\bmkfs\b|\bdd\s+if=.*of=\/dev\//, "raw device write"],
|
||||
];
|
||||
|
||||
const readAll = () =>
|
||||
new Promise((resolve) => {
|
||||
let data = "";
|
||||
process.stdin.setEncoding("utf8");
|
||||
process.stdin.on("data", (c) => (data += c));
|
||||
process.stdin.on("end", () => resolve(data));
|
||||
setTimeout(() => resolve(data), 2000).unref();
|
||||
});
|
||||
|
||||
const allow = () => {
|
||||
process.stdout.write(JSON.stringify({ permission: "allow" }));
|
||||
process.exit(0);
|
||||
};
|
||||
|
||||
const raw = await readAll();
|
||||
let command = "";
|
||||
try {
|
||||
command = JSON.parse(raw || "{}").command || "";
|
||||
} catch {
|
||||
allow();
|
||||
}
|
||||
|
||||
const hit = PATTERNS.find(([re]) => re.test(command));
|
||||
if (!hit) allow();
|
||||
|
||||
const reason = hit[1];
|
||||
process.stdout.write(
|
||||
JSON.stringify({
|
||||
permission: "ask",
|
||||
user_message: `Gated: ${reason}. Approve only if you intended this.`,
|
||||
agent_message:
|
||||
`This command was gated as a ${reason}. Per the quality gates in AGENTS.md, destructive, external, ` +
|
||||
`and irreversible actions need explicit owner authorization — loop momentum is not authorization. ` +
|
||||
`If the owner declines, record it as a decision-ready item in docs/PROGRESS.md and re-route to another ` +
|
||||
`independent unit rather than looking for a way around this command.`,
|
||||
}),
|
||||
);
|
||||
process.exit(0);
|
||||
Reference in New Issue
Block a user