dravix-agent 0.1.0
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/.claude/settings.example.json +30 -0
- package/ARCHITECTURE.md +410 -0
- package/LICENSE +21 -0
- package/README.md +153 -0
- package/ROADMAP.md +117 -0
- package/data/vulnkb.json +666 -0
- package/dist/bin/aegis.d.ts +3 -0
- package/dist/bin/aegis.d.ts.map +1 -0
- package/dist/bin/aegis.js +489 -0
- package/dist/bin/aegis.js.map +1 -0
- package/dist/cache.d.ts +9 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +146 -0
- package/dist/cache.js.map +1 -0
- package/dist/engines/ai-sinks.d.ts +52 -0
- package/dist/engines/ai-sinks.d.ts.map +1 -0
- package/dist/engines/ai-sinks.js +204 -0
- package/dist/engines/ai-sinks.js.map +1 -0
- package/dist/engines/eslint.d.ts +9 -0
- package/dist/engines/eslint.d.ts.map +1 -0
- package/dist/engines/eslint.js +245 -0
- package/dist/engines/eslint.js.map +1 -0
- package/dist/engines/joern.d.ts +3 -0
- package/dist/engines/joern.d.ts.map +1 -0
- package/dist/engines/joern.js +98 -0
- package/dist/engines/joern.js.map +1 -0
- package/dist/engines/js-sinks.d.ts +70 -0
- package/dist/engines/js-sinks.d.ts.map +1 -0
- package/dist/engines/js-sinks.js +370 -0
- package/dist/engines/js-sinks.js.map +1 -0
- package/dist/engines/llm-critic.d.ts +130 -0
- package/dist/engines/llm-critic.d.ts.map +1 -0
- package/dist/engines/llm-critic.js +551 -0
- package/dist/engines/llm-critic.js.map +1 -0
- package/dist/engines/pragma.d.ts +20 -0
- package/dist/engines/pragma.d.ts.map +1 -0
- package/dist/engines/pragma.js +83 -0
- package/dist/engines/pragma.js.map +1 -0
- package/dist/engines/property-test.d.ts +3 -0
- package/dist/engines/property-test.d.ts.map +1 -0
- package/dist/engines/property-test.js +134 -0
- package/dist/engines/property-test.js.map +1 -0
- package/dist/engines/pyright.d.ts +10 -0
- package/dist/engines/pyright.d.ts.map +1 -0
- package/dist/engines/pyright.js +143 -0
- package/dist/engines/pyright.js.map +1 -0
- package/dist/engines/pysa.d.ts +3 -0
- package/dist/engines/pysa.d.ts.map +1 -0
- package/dist/engines/pysa.js +83 -0
- package/dist/engines/pysa.js.map +1 -0
- package/dist/engines/python-sinks.d.ts +82 -0
- package/dist/engines/python-sinks.d.ts.map +1 -0
- package/dist/engines/python-sinks.js +459 -0
- package/dist/engines/python-sinks.js.map +1 -0
- package/dist/engines/registry.d.ts +26 -0
- package/dist/engines/registry.d.ts.map +1 -0
- package/dist/engines/registry.js +70 -0
- package/dist/engines/registry.js.map +1 -0
- package/dist/engines/secret-scan.d.ts +22 -0
- package/dist/engines/secret-scan.d.ts.map +1 -0
- package/dist/engines/secret-scan.js +179 -0
- package/dist/engines/secret-scan.js.map +1 -0
- package/dist/engines/semgrep.d.ts +10 -0
- package/dist/engines/semgrep.d.ts.map +1 -0
- package/dist/engines/semgrep.js +200 -0
- package/dist/engines/semgrep.js.map +1 -0
- package/dist/engines/treesitter.d.ts +18 -0
- package/dist/engines/treesitter.d.ts.map +1 -0
- package/dist/engines/treesitter.js +135 -0
- package/dist/engines/treesitter.js.map +1 -0
- package/dist/engines/tsc.d.ts +10 -0
- package/dist/engines/tsc.d.ts.map +1 -0
- package/dist/engines/tsc.js +142 -0
- package/dist/engines/tsc.js.map +1 -0
- package/dist/engines/types.d.ts +47 -0
- package/dist/engines/types.d.ts.map +1 -0
- package/dist/engines/types.js +27 -0
- package/dist/engines/types.js.map +1 -0
- package/dist/findings.d.ts +121 -0
- package/dist/findings.d.ts.map +1 -0
- package/dist/findings.js +98 -0
- package/dist/findings.js.map +1 -0
- package/dist/hooks/claude-code.d.ts +3 -0
- package/dist/hooks/claude-code.d.ts.map +1 -0
- package/dist/hooks/claude-code.js +187 -0
- package/dist/hooks/claude-code.js.map +1 -0
- package/dist/index/context.d.ts +127 -0
- package/dist/index/context.d.ts.map +1 -0
- package/dist/index/context.js +267 -0
- package/dist/index/context.js.map +1 -0
- package/dist/index/embeddings.d.ts +68 -0
- package/dist/index/embeddings.d.ts.map +1 -0
- package/dist/index/embeddings.js +570 -0
- package/dist/index/embeddings.js.map +1 -0
- package/dist/index/graph_routing.d.ts +36 -0
- package/dist/index/graph_routing.d.ts.map +1 -0
- package/dist/index/graph_routing.js +170 -0
- package/dist/index/graph_routing.js.map +1 -0
- package/dist/index/joern.d.ts +76 -0
- package/dist/index/joern.d.ts.map +1 -0
- package/dist/index/joern.js +782 -0
- package/dist/index/joern.js.map +1 -0
- package/dist/index/property-test.d.ts +88 -0
- package/dist/index/property-test.d.ts.map +1 -0
- package/dist/index/property-test.js +466 -0
- package/dist/index/property-test.js.map +1 -0
- package/dist/index/proto/scip.proto +897 -0
- package/dist/index/pysa.d.ts +91 -0
- package/dist/index/pysa.d.ts.map +1 -0
- package/dist/index/pysa.js +617 -0
- package/dist/index/pysa.js.map +1 -0
- package/dist/index/scip.d.ts +76 -0
- package/dist/index/scip.d.ts.map +1 -0
- package/dist/index/scip.js +541 -0
- package/dist/index/scip.js.map +1 -0
- package/dist/index/vulrag.d.ts +86 -0
- package/dist/index/vulrag.d.ts.map +1 -0
- package/dist/index/vulrag.js +242 -0
- package/dist/index/vulrag.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/install/claude-code.d.ts +31 -0
- package/dist/install/claude-code.d.ts.map +1 -0
- package/dist/install/claude-code.js +447 -0
- package/dist/install/claude-code.js.map +1 -0
- package/dist/lang.d.ts +5 -0
- package/dist/lang.d.ts.map +1 -0
- package/dist/lang.js +52 -0
- package/dist/lang.js.map +1 -0
- package/dist/learning/suppressions.d.ts +70 -0
- package/dist/learning/suppressions.d.ts.map +1 -0
- package/dist/learning/suppressions.js +179 -0
- package/dist/learning/suppressions.js.map +1 -0
- package/dist/mcp/server.d.ts +2 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +187 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/tools/explain.d.ts +58 -0
- package/dist/mcp/tools/explain.d.ts.map +1 -0
- package/dist/mcp/tools/explain.js +60 -0
- package/dist/mcp/tools/explain.js.map +1 -0
- package/dist/mcp/tools/precheck.d.ts +29 -0
- package/dist/mcp/tools/precheck.d.ts.map +1 -0
- package/dist/mcp/tools/precheck.js +42 -0
- package/dist/mcp/tools/precheck.js.map +1 -0
- package/dist/mcp/tools/validate.d.ts +73 -0
- package/dist/mcp/tools/validate.d.ts.map +1 -0
- package/dist/mcp/tools/validate.js +66 -0
- package/dist/mcp/tools/validate.js.map +1 -0
- package/dist/mcp/warm.d.ts +88 -0
- package/dist/mcp/warm.d.ts.map +1 -0
- package/dist/mcp/warm.js +331 -0
- package/dist/mcp/warm.js.map +1 -0
- package/dist/orchestrator.d.ts +46 -0
- package/dist/orchestrator.d.ts.map +1 -0
- package/dist/orchestrator.js +596 -0
- package/dist/orchestrator.js.map +1 -0
- package/dist/policy.d.ts +51 -0
- package/dist/policy.d.ts.map +1 -0
- package/dist/policy.js +201 -0
- package/dist/policy.js.map +1 -0
- package/dist/risk.d.ts +31 -0
- package/dist/risk.d.ts.map +1 -0
- package/dist/risk.js +92 -0
- package/dist/risk.js.map +1 -0
- package/dist/stats.d.ts +72 -0
- package/dist/stats.d.ts.map +1 -0
- package/dist/stats.js +217 -0
- package/dist/stats.js.map +1 -0
- package/dist/telemetry/collector.d.ts +10 -0
- package/dist/telemetry/collector.d.ts.map +1 -0
- package/dist/telemetry/collector.js +75 -0
- package/dist/telemetry/collector.js.map +1 -0
- package/dist/telemetry/consent.d.ts +9 -0
- package/dist/telemetry/consent.d.ts.map +1 -0
- package/dist/telemetry/consent.js +42 -0
- package/dist/telemetry/consent.js.map +1 -0
- package/dist/telemetry/installation.d.ts +2 -0
- package/dist/telemetry/installation.d.ts.map +1 -0
- package/dist/telemetry/installation.js +32 -0
- package/dist/telemetry/installation.js.map +1 -0
- package/dist/telemetry/sanitizer.d.ts +5 -0
- package/dist/telemetry/sanitizer.d.ts.map +1 -0
- package/dist/telemetry/sanitizer.js +60 -0
- package/dist/telemetry/sanitizer.js.map +1 -0
- package/dist/telemetry/types.d.ts +39 -0
- package/dist/telemetry/types.d.ts.map +1 -0
- package/dist/telemetry/types.js +4 -0
- package/dist/telemetry/types.js.map +1 -0
- package/dist/telemetry/uploader.d.ts +12 -0
- package/dist/telemetry/uploader.d.ts.map +1 -0
- package/dist/telemetry/uploader.js +92 -0
- package/dist/telemetry/uploader.js.map +1 -0
- package/dist/util/logger.d.ts +19 -0
- package/dist/util/logger.d.ts.map +1 -0
- package/dist/util/logger.js +58 -0
- package/dist/util/logger.js.map +1 -0
- package/dist/util/safe-paths.d.ts +8 -0
- package/dist/util/safe-paths.d.ts.map +1 -0
- package/dist/util/safe-paths.js +102 -0
- package/dist/util/safe-paths.js.map +1 -0
- package/dist/util/subprocess.d.ts +32 -0
- package/dist/util/subprocess.d.ts.map +1 -0
- package/dist/util/subprocess.js +137 -0
- package/dist/util/subprocess.js.map +1 -0
- package/package.json +93 -0
|
@@ -0,0 +1,447 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code installer — registers aegis as a PreToolUse hook + MCP server
|
|
3
|
+
* + writes a mandatory-validate block to ~/.claude/CLAUDE.md.
|
|
4
|
+
*
|
|
5
|
+
* Cross-platform (Windows / macOS / Linux). Atomic + idempotent + reversible:
|
|
6
|
+
* - Re-running install is a no-op (markers detect prior install).
|
|
7
|
+
* - Backs up every file it touches as <file>.bak-dravix-<unix_ts>.
|
|
8
|
+
* - --dry-run prints what would change without writing.
|
|
9
|
+
* - `aegis uninstall` removes everything cleanly.
|
|
10
|
+
*/
|
|
11
|
+
import { copyFileSync, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync, } from "node:fs";
|
|
12
|
+
import { homedir } from "node:os";
|
|
13
|
+
import { dirname, resolve } from "node:path";
|
|
14
|
+
import { fileURLToPath } from "node:url";
|
|
15
|
+
import { randomBytes } from "node:crypto";
|
|
16
|
+
const BEGIN_MARKER = "<!-- BEGIN DRAVIX-AGENT -->";
|
|
17
|
+
const END_MARKER = "<!-- END DRAVIX-AGENT -->";
|
|
18
|
+
/** Old FixMe block detection — pre-dravix users will have this header.
|
|
19
|
+
* Strip from `# FixMe Agent ...` up to the next top-level `#`/`## ` header
|
|
20
|
+
* (or EOF). Matches the block layout in user's original ~/.claude/CLAUDE.md. */
|
|
21
|
+
const FIXME_HEADER_RE = /^# FixMe Agent[^\n]*\n[\s\S]*?(?=^#{1,2} \S|\Z)/m;
|
|
22
|
+
/** Locate the absolute path of dist/bin/aegis.js. Reads from import.meta.url
|
|
23
|
+
* so it works no matter where the package is installed (global, local, link). */
|
|
24
|
+
function locateAegisBin() {
|
|
25
|
+
const here = fileURLToPath(import.meta.url);
|
|
26
|
+
// here = .../dist/install/claude-code.js
|
|
27
|
+
return resolve(dirname(here), "..", "bin", "aegis.js");
|
|
28
|
+
}
|
|
29
|
+
/** ~/.claude/ on all platforms (Claude Code uses the same path everywhere). */
|
|
30
|
+
function locateClaudeHome(override) {
|
|
31
|
+
if (override)
|
|
32
|
+
return override;
|
|
33
|
+
return resolve(homedir(), ".claude");
|
|
34
|
+
}
|
|
35
|
+
/** Locate ~/.claude.json — the user-scope MCP server config Claude Code reads. */
|
|
36
|
+
function locateClaudeMcpConfig() {
|
|
37
|
+
return resolve(homedir(), ".claude.json");
|
|
38
|
+
}
|
|
39
|
+
/** Atomic write: tmp file + rename. On Windows rename is mostly-atomic; good
|
|
40
|
+
* enough for config files since we always have a .bak alongside. The tmp
|
|
41
|
+
* suffix uses crypto.randomBytes (not for security; just collision-resistant
|
|
42
|
+
* unique naming on concurrent installs). */
|
|
43
|
+
function atomicWriteFile(filePath, content) {
|
|
44
|
+
mkdirSync(dirname(filePath), { recursive: true });
|
|
45
|
+
const tmp = `${filePath}.tmp-${Date.now()}-${randomBytes(3).toString("hex")}`;
|
|
46
|
+
writeFileSync(tmp, content, "utf8");
|
|
47
|
+
renameSync(tmp, filePath);
|
|
48
|
+
}
|
|
49
|
+
/** Backup an existing file as <file>.bak-dravix-<ts>. No-op if file missing. */
|
|
50
|
+
function backupFile(filePath) {
|
|
51
|
+
if (!existsSync(filePath))
|
|
52
|
+
return;
|
|
53
|
+
const bak = `${filePath}.bak-dravix-${Date.now()}`;
|
|
54
|
+
copyFileSync(filePath, bak);
|
|
55
|
+
}
|
|
56
|
+
/** Read JSON file, return parsed object or empty object on missing/bad json.
|
|
57
|
+
* We never throw — config files belong to the user and must round-trip safely. */
|
|
58
|
+
function readJsonSafe(filePath) {
|
|
59
|
+
if (!existsSync(filePath))
|
|
60
|
+
return {};
|
|
61
|
+
try {
|
|
62
|
+
const raw = readFileSync(filePath, "utf8");
|
|
63
|
+
const trimmed = raw.trim();
|
|
64
|
+
if (trimmed.length === 0)
|
|
65
|
+
return {};
|
|
66
|
+
const parsed = JSON.parse(trimmed);
|
|
67
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
68
|
+
return parsed;
|
|
69
|
+
}
|
|
70
|
+
return {};
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return {};
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/** Merge our aegis MCP server entry into ~/.claude.json without disturbing
|
|
77
|
+
* other servers. Returns the merged JSON string (pretty-printed). */
|
|
78
|
+
function mergeMcpConfig(existing, aegisBin) {
|
|
79
|
+
const out = { ...existing };
|
|
80
|
+
const servers = out.mcpServers && typeof out.mcpServers === "object" && !Array.isArray(out.mcpServers)
|
|
81
|
+
? { ...out.mcpServers }
|
|
82
|
+
: {};
|
|
83
|
+
servers.aegis = {
|
|
84
|
+
type: "stdio",
|
|
85
|
+
command: process.execPath,
|
|
86
|
+
args: [aegisBin, "mcp"],
|
|
87
|
+
};
|
|
88
|
+
out.mcpServers = servers;
|
|
89
|
+
return JSON.stringify(out, null, 2) + "\n";
|
|
90
|
+
}
|
|
91
|
+
/** Merge our PreToolUse Write|Edit hook into ~/.claude/settings.json.
|
|
92
|
+
* Preserves other hooks (other matchers, other events). If our exact hook
|
|
93
|
+
* command already exists under the right matcher, we don't double-register. */
|
|
94
|
+
function mergeSettings(existing, aegisBin) {
|
|
95
|
+
const out = { ...existing };
|
|
96
|
+
const hooks = out.hooks ? { ...out.hooks } : {};
|
|
97
|
+
const pre = Array.isArray(hooks.PreToolUse) ? [...hooks.PreToolUse] : [];
|
|
98
|
+
const ourCmd = `${JSON.stringify(process.execPath)} ${JSON.stringify(aegisBin)} hook`;
|
|
99
|
+
// Match an existing aegis-hook entry (any path variant) so re-install
|
|
100
|
+
// upgrades it in place rather than appending a duplicate.
|
|
101
|
+
const isAegisHook = (h) => typeof h.command === "string" && /aegis(?:\.js)?["'\s]+hook(?:\b|$)/.test(h.command);
|
|
102
|
+
let foundMatcher = -1;
|
|
103
|
+
for (let i = 0; i < pre.length; i++) {
|
|
104
|
+
if (pre[i].matcher === "Write|Edit") {
|
|
105
|
+
foundMatcher = i;
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
const aegisHook = { type: "command", command: ourCmd, timeout: 60 };
|
|
110
|
+
if (foundMatcher === -1) {
|
|
111
|
+
pre.push({ matcher: "Write|Edit", hooks: [aegisHook] });
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
const existingHooks = Array.isArray(pre[foundMatcher].hooks) ? pre[foundMatcher].hooks : [];
|
|
115
|
+
const others = existingHooks.filter((h) => !isAegisHook(h));
|
|
116
|
+
pre[foundMatcher] = { matcher: "Write|Edit", hooks: [...others, aegisHook] };
|
|
117
|
+
}
|
|
118
|
+
hooks.PreToolUse = pre;
|
|
119
|
+
out.hooks = hooks;
|
|
120
|
+
return JSON.stringify(out, null, 2) + "\n";
|
|
121
|
+
}
|
|
122
|
+
/** The mandatory-validate block written into ~/.claude/CLAUDE.md.
|
|
123
|
+
* Marked with BEGIN/END comments so uninstall can strip it precisely. */
|
|
124
|
+
function claudeMdBlock() {
|
|
125
|
+
return `${BEGIN_MARKER}
|
|
126
|
+
|
|
127
|
+
# Dravix Agent — Real-Time Code Quality Guard (MANDATORY)
|
|
128
|
+
|
|
129
|
+
## BLOCKING REQUIREMENT: Pre-Validate ALL Code
|
|
130
|
+
|
|
131
|
+
Before EVERY file write, edit, or creation, you MUST call the Dravix MCP tool \`validate_edit\`:
|
|
132
|
+
|
|
133
|
+
\`\`\`
|
|
134
|
+
mcp__aegis-v2__validate_edit(file_path="absolute/path", content="full file content")
|
|
135
|
+
\`\`\`
|
|
136
|
+
|
|
137
|
+
This is NOT optional. This is NOT a suggestion. This is a hard requirement.
|
|
138
|
+
If you skip this step, the code WILL contain bugs that could have been prevented.
|
|
139
|
+
|
|
140
|
+
## Step-by-Step Workflow
|
|
141
|
+
|
|
142
|
+
1. Compose the full post-edit content (for Edit: read the file, apply the swap)
|
|
143
|
+
2. BEFORE applying the Write/Edit, call \`mcp__aegis-v2__validate_edit(file_path, content)\`
|
|
144
|
+
3. If \`verdict === "block"\`:
|
|
145
|
+
a. Read the rule ID, line number, severity, remediation
|
|
146
|
+
b. Fix ALL findings
|
|
147
|
+
c. Re-call \`validate_edit\` with the fixed content
|
|
148
|
+
d. Repeat until \`verdict === "allow"\`
|
|
149
|
+
4. ONLY THEN apply the Write/Edit
|
|
150
|
+
5. End your response with a Validation Report
|
|
151
|
+
|
|
152
|
+
## Available Dravix MCP Tools
|
|
153
|
+
|
|
154
|
+
| Tool | Use | When |
|
|
155
|
+
|---|---|---|
|
|
156
|
+
| \`mcp__aegis-v2__validate_edit(file_path, content)\` | Authoritative gate (allow/warn/block + findings) | EVERY Write/Edit |
|
|
157
|
+
| \`mcp__aegis-v2__precheck_change(file_path, content)\` | Fast advisory (<200ms, never blocks) | When deciding whether to attempt an edit |
|
|
158
|
+
| \`mcp__aegis-v2__explain_risk(finding_id OR file_path,line)\` | Look up prior gate decision | When investigating a past block |
|
|
159
|
+
| \`mcp__aegis-v2__aegis_health\` | Engine availability + cache stats | When diagnosing why a tool errored |
|
|
160
|
+
|
|
161
|
+
## What Dravix Catches
|
|
162
|
+
|
|
163
|
+
- SQL injection, XSS, command injection, path traversal (CRITICAL)
|
|
164
|
+
- Hardcoded secrets, API keys, JWT signing keys (CRITICAL)
|
|
165
|
+
- \`eval()\`, \`exec()\`, \`os.system()\`, \`subprocess(shell=True)\`, pickle.loads (HIGH)
|
|
166
|
+
- Cross-file taint (caller-of-risky import + Joern CPG + Pysa)
|
|
167
|
+
- Race conditions (concurrency hint routing -> LLM critic)
|
|
168
|
+
- Logic bugs (Hypothesis property tests produce concrete counterexamples)
|
|
169
|
+
- Weak crypto (MD5 / SHA1 / Math.random for security)
|
|
170
|
+
- JWT misuse (alg:none, hardcoded secret, no algorithms set)
|
|
171
|
+
- Prompt injection in LLM apps, hardcoded LLM API keys
|
|
172
|
+
- 52+ deterministic rules across Python / JS / TS / multi-lang
|
|
173
|
+
|
|
174
|
+
## MANDATORY: Validation Report (End of EVERY Response with Code Changes)
|
|
175
|
+
|
|
176
|
+
After completing ANY coding task, you MUST end your response with this exact format:
|
|
177
|
+
|
|
178
|
+
\`\`\`
|
|
179
|
+
## Validation Report
|
|
180
|
+
|
|
181
|
+
**Issues prevented:** X issues caught and fixed before code was written
|
|
182
|
+
**Issues breakdown:**
|
|
183
|
+
- Critical: X (e.g., SQL injection in db.py:15 -> fixed with parameterized query)
|
|
184
|
+
- High: X (e.g., hardcoded API key in config.py:3 -> moved to env var)
|
|
185
|
+
- Medium: X
|
|
186
|
+
- Low: X
|
|
187
|
+
|
|
188
|
+
**What was caught:**
|
|
189
|
+
1. [RULE-ID] file:line — what was wrong -> what was fixed
|
|
190
|
+
2. [RULE-ID] file:line — description -> fix
|
|
191
|
+
|
|
192
|
+
**Verdicts:** orchestrator.ts -> allow, db.py -> block->fixed->allow
|
|
193
|
+
\`\`\`
|
|
194
|
+
|
|
195
|
+
If no issues were caught (all code passed on first try):
|
|
196
|
+
|
|
197
|
+
\`\`\`
|
|
198
|
+
## Validation Report
|
|
199
|
+
All code passed validation on first attempt. Zero issues detected.
|
|
200
|
+
\`\`\`
|
|
201
|
+
|
|
202
|
+
## NEVER Skip Validation
|
|
203
|
+
|
|
204
|
+
- Do NOT write code without calling \`validate_edit\` first
|
|
205
|
+
- Do NOT retry the same code that was rejected — fix it first
|
|
206
|
+
- Do NOT ignore warn-level findings — review and address
|
|
207
|
+
- Do NOT apologize for "extra steps" — this protects the user's codebase
|
|
208
|
+
|
|
209
|
+
${END_MARKER}`;
|
|
210
|
+
}
|
|
211
|
+
/** Strip the legacy FixMe block (if present) and any prior dravix block,
|
|
212
|
+
* then append the fresh dravix block. Preserves all other user content. */
|
|
213
|
+
function injectClaudeMdBlock(existing) {
|
|
214
|
+
let out = existing;
|
|
215
|
+
let fixmeRemoved = false;
|
|
216
|
+
// Strip prior dravix block (BEGIN_MARKER ... END_MARKER, inclusive +
|
|
217
|
+
// surrounding blank lines).
|
|
218
|
+
const dravixBlock = new RegExp(`\\n*${escapeRe(BEGIN_MARKER)}[\\s\\S]*?${escapeRe(END_MARKER)}\\n*`, "g");
|
|
219
|
+
out = out.replace(dravixBlock, "\n");
|
|
220
|
+
// Strip legacy FixMe block, if present.
|
|
221
|
+
if (FIXME_HEADER_RE.test(out)) {
|
|
222
|
+
out = out.replace(FIXME_HEADER_RE, "");
|
|
223
|
+
fixmeRemoved = true;
|
|
224
|
+
}
|
|
225
|
+
// Trim trailing whitespace, then append our block + a trailing newline.
|
|
226
|
+
out = out.replace(/\s+$/, "");
|
|
227
|
+
if (out.length > 0)
|
|
228
|
+
out += "\n\n";
|
|
229
|
+
out += claudeMdBlock() + "\n";
|
|
230
|
+
return { content: out, fixmeRemoved };
|
|
231
|
+
}
|
|
232
|
+
function escapeRe(s) {
|
|
233
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
234
|
+
}
|
|
235
|
+
/** Public entry: register aegis in Claude Code. */
|
|
236
|
+
export function installClaudeCode(opts = {}) {
|
|
237
|
+
const aegisBin = locateAegisBin();
|
|
238
|
+
const claudeHome = locateClaudeHome(opts.claudeHome);
|
|
239
|
+
const mcpFile = locateClaudeMcpConfig();
|
|
240
|
+
const settingsFile = resolve(claudeHome, "settings.json");
|
|
241
|
+
const claudeMdFile = resolve(claudeHome, "CLAUDE.md");
|
|
242
|
+
const changes = [];
|
|
243
|
+
// 1. ~/.claude.json (MCP servers)
|
|
244
|
+
{
|
|
245
|
+
const before = existsSync(mcpFile) ? readFileSync(mcpFile, "utf8") : "";
|
|
246
|
+
const merged = mergeMcpConfig(readJsonSafe(mcpFile), aegisBin);
|
|
247
|
+
if (before.trim() === merged.trim()) {
|
|
248
|
+
changes.push({ file: mcpFile, op: "skip", reason: "aegis MCP already registered" });
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
if (!opts.dryRun) {
|
|
252
|
+
backupFile(mcpFile);
|
|
253
|
+
atomicWriteFile(mcpFile, merged);
|
|
254
|
+
}
|
|
255
|
+
changes.push({
|
|
256
|
+
file: mcpFile,
|
|
257
|
+
op: existsSync(mcpFile) ? "modify" : "create",
|
|
258
|
+
reason: "added mcpServers.aegis",
|
|
259
|
+
before: before.slice(0, 800),
|
|
260
|
+
after: merged.slice(0, 800),
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
// 2. ~/.claude/settings.json (PreToolUse hook)
|
|
265
|
+
{
|
|
266
|
+
const before = existsSync(settingsFile) ? readFileSync(settingsFile, "utf8") : "";
|
|
267
|
+
const merged = mergeSettings(readJsonSafe(settingsFile), aegisBin);
|
|
268
|
+
if (before.trim() === merged.trim()) {
|
|
269
|
+
changes.push({ file: settingsFile, op: "skip", reason: "PreToolUse hook already registered" });
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
if (!opts.dryRun) {
|
|
273
|
+
backupFile(settingsFile);
|
|
274
|
+
atomicWriteFile(settingsFile, merged);
|
|
275
|
+
}
|
|
276
|
+
changes.push({
|
|
277
|
+
file: settingsFile,
|
|
278
|
+
op: existsSync(settingsFile) ? "modify" : "create",
|
|
279
|
+
reason: "added PreToolUse Write|Edit hook",
|
|
280
|
+
before: before.slice(0, 800),
|
|
281
|
+
after: merged.slice(0, 800),
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
// 3. ~/.claude/CLAUDE.md (mandatory-validate block)
|
|
286
|
+
let fixmeBlockRemoved = false;
|
|
287
|
+
if (!opts.skipClaudeMd) {
|
|
288
|
+
const before = existsSync(claudeMdFile) ? readFileSync(claudeMdFile, "utf8") : "";
|
|
289
|
+
const { content: merged, fixmeRemoved } = injectClaudeMdBlock(before);
|
|
290
|
+
fixmeBlockRemoved = fixmeRemoved;
|
|
291
|
+
if (before === merged) {
|
|
292
|
+
changes.push({ file: claudeMdFile, op: "skip", reason: "Dravix block already present and current" });
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
if (!opts.dryRun) {
|
|
296
|
+
backupFile(claudeMdFile);
|
|
297
|
+
atomicWriteFile(claudeMdFile, merged);
|
|
298
|
+
}
|
|
299
|
+
changes.push({
|
|
300
|
+
file: claudeMdFile,
|
|
301
|
+
op: existsSync(claudeMdFile) ? "modify" : "create",
|
|
302
|
+
reason: fixmeRemoved
|
|
303
|
+
? "replaced legacy FixMe block with Dravix block"
|
|
304
|
+
: "added Dravix block",
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
return {
|
|
309
|
+
dryRun: opts.dryRun === true,
|
|
310
|
+
aegisBinPath: aegisBin,
|
|
311
|
+
claudeHome,
|
|
312
|
+
changes,
|
|
313
|
+
fixmeBlockRemoved,
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
/** Public entry: remove aegis from Claude Code. Idempotent. */
|
|
317
|
+
export function uninstallClaudeCode(opts = {}) {
|
|
318
|
+
const aegisBin = locateAegisBin();
|
|
319
|
+
const claudeHome = locateClaudeHome(opts.claudeHome);
|
|
320
|
+
const mcpFile = locateClaudeMcpConfig();
|
|
321
|
+
const settingsFile = resolve(claudeHome, "settings.json");
|
|
322
|
+
const claudeMdFile = resolve(claudeHome, "CLAUDE.md");
|
|
323
|
+
const changes = [];
|
|
324
|
+
// 1. ~/.claude.json — remove mcpServers.aegis
|
|
325
|
+
if (existsSync(mcpFile)) {
|
|
326
|
+
const data = readJsonSafe(mcpFile);
|
|
327
|
+
const servers = data.mcpServers && typeof data.mcpServers === "object" && !Array.isArray(data.mcpServers)
|
|
328
|
+
? { ...data.mcpServers }
|
|
329
|
+
: null;
|
|
330
|
+
if (servers && "aegis" in servers) {
|
|
331
|
+
delete servers.aegis;
|
|
332
|
+
data.mcpServers = servers;
|
|
333
|
+
const merged = JSON.stringify(data, null, 2) + "\n";
|
|
334
|
+
if (!opts.dryRun) {
|
|
335
|
+
backupFile(mcpFile);
|
|
336
|
+
atomicWriteFile(mcpFile, merged);
|
|
337
|
+
}
|
|
338
|
+
changes.push({ file: mcpFile, op: "modify", reason: "removed mcpServers.aegis" });
|
|
339
|
+
}
|
|
340
|
+
else {
|
|
341
|
+
changes.push({ file: mcpFile, op: "skip", reason: "aegis MCP not registered" });
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
else {
|
|
345
|
+
changes.push({ file: mcpFile, op: "skip", reason: "file does not exist" });
|
|
346
|
+
}
|
|
347
|
+
// 2. ~/.claude/settings.json — remove our hook
|
|
348
|
+
if (existsSync(settingsFile)) {
|
|
349
|
+
const data = readJsonSafe(settingsFile);
|
|
350
|
+
const pre = Array.isArray(data.hooks?.PreToolUse) ? [...data.hooks.PreToolUse] : [];
|
|
351
|
+
let removed = false;
|
|
352
|
+
const cleaned = [];
|
|
353
|
+
for (const m of pre) {
|
|
354
|
+
if (!Array.isArray(m.hooks)) {
|
|
355
|
+
cleaned.push(m);
|
|
356
|
+
continue;
|
|
357
|
+
}
|
|
358
|
+
const filtered = m.hooks.filter((h) => {
|
|
359
|
+
const isOurs = typeof h.command === "string" && /aegis(?:\.js)?["'\s]+hook(?:\b|$)/.test(h.command);
|
|
360
|
+
if (isOurs)
|
|
361
|
+
removed = true;
|
|
362
|
+
return !isOurs;
|
|
363
|
+
});
|
|
364
|
+
if (filtered.length > 0)
|
|
365
|
+
cleaned.push({ ...m, hooks: filtered });
|
|
366
|
+
}
|
|
367
|
+
if (removed) {
|
|
368
|
+
if (cleaned.length > 0) {
|
|
369
|
+
data.hooks = { ...data.hooks, PreToolUse: cleaned };
|
|
370
|
+
}
|
|
371
|
+
else if (data.hooks) {
|
|
372
|
+
const h = { ...data.hooks };
|
|
373
|
+
delete h.PreToolUse;
|
|
374
|
+
data.hooks = h;
|
|
375
|
+
}
|
|
376
|
+
const merged = JSON.stringify(data, null, 2) + "\n";
|
|
377
|
+
if (!opts.dryRun) {
|
|
378
|
+
backupFile(settingsFile);
|
|
379
|
+
atomicWriteFile(settingsFile, merged);
|
|
380
|
+
}
|
|
381
|
+
changes.push({ file: settingsFile, op: "modify", reason: "removed PreToolUse aegis hook" });
|
|
382
|
+
}
|
|
383
|
+
else {
|
|
384
|
+
changes.push({ file: settingsFile, op: "skip", reason: "aegis hook not present" });
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
else {
|
|
388
|
+
changes.push({ file: settingsFile, op: "skip", reason: "file does not exist" });
|
|
389
|
+
}
|
|
390
|
+
// 3. ~/.claude/CLAUDE.md — strip Dravix block (leaves user content + legacy
|
|
391
|
+
// FixMe block, if any, untouched).
|
|
392
|
+
if (existsSync(claudeMdFile)) {
|
|
393
|
+
const before = readFileSync(claudeMdFile, "utf8");
|
|
394
|
+
const stripRe = new RegExp(`\\n*${escapeRe(BEGIN_MARKER)}[\\s\\S]*?${escapeRe(END_MARKER)}\\n*`, "g");
|
|
395
|
+
const after = before.replace(stripRe, "\n").replace(/\s+$/, "") + "\n";
|
|
396
|
+
if (after === before) {
|
|
397
|
+
changes.push({ file: claudeMdFile, op: "skip", reason: "no Dravix block to remove" });
|
|
398
|
+
}
|
|
399
|
+
else {
|
|
400
|
+
if (!opts.dryRun) {
|
|
401
|
+
backupFile(claudeMdFile);
|
|
402
|
+
atomicWriteFile(claudeMdFile, after);
|
|
403
|
+
}
|
|
404
|
+
changes.push({ file: claudeMdFile, op: "modify", reason: "removed Dravix block" });
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
else {
|
|
408
|
+
changes.push({ file: claudeMdFile, op: "skip", reason: "file does not exist" });
|
|
409
|
+
}
|
|
410
|
+
return {
|
|
411
|
+
dryRun: opts.dryRun === true,
|
|
412
|
+
aegisBinPath: aegisBin,
|
|
413
|
+
claudeHome,
|
|
414
|
+
changes,
|
|
415
|
+
fixmeBlockRemoved: false,
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
/** Human-readable summary for the CLI. */
|
|
419
|
+
export function formatReport(r) {
|
|
420
|
+
const lines = [];
|
|
421
|
+
lines.push(r.dryRun ? "(dry-run — no files written)" : "Done.");
|
|
422
|
+
lines.push("");
|
|
423
|
+
lines.push(`Aegis binary: ${r.aegisBinPath}`);
|
|
424
|
+
lines.push(`Claude home: ${r.claudeHome}`);
|
|
425
|
+
if (r.fixmeBlockRemoved) {
|
|
426
|
+
lines.push("Removed legacy FixMe block from CLAUDE.md.");
|
|
427
|
+
}
|
|
428
|
+
lines.push("");
|
|
429
|
+
lines.push("Changes:");
|
|
430
|
+
for (const c of r.changes) {
|
|
431
|
+
const op = c.op.padEnd(7);
|
|
432
|
+
lines.push(` ${op} ${c.file}`);
|
|
433
|
+
lines.push(` ${c.reason}`);
|
|
434
|
+
}
|
|
435
|
+
lines.push("");
|
|
436
|
+
if (!r.dryRun) {
|
|
437
|
+
lines.push("Next steps:");
|
|
438
|
+
lines.push(" 1. Restart Claude Code so it picks up the new MCP + hook.");
|
|
439
|
+
lines.push(" 2. Open a new conversation and try editing a file —");
|
|
440
|
+
lines.push(" the PreToolUse hook should fire, and Claude should");
|
|
441
|
+
lines.push(" proactively call mcp__aegis-v2__validate_edit.");
|
|
442
|
+
lines.push(" 3. Run `aegis doctor` to see which engines are live.");
|
|
443
|
+
lines.push(" 4. To remove later: `aegis uninstall`.");
|
|
444
|
+
}
|
|
445
|
+
return lines.join("\n");
|
|
446
|
+
}
|
|
447
|
+
//# sourceMappingURL=claude-code.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../src/install/claude-code.ts"],"names":[],"mappings":"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"}
|
package/dist/lang.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type Lang = "python" | "javascript" | "typescript" | "jsx" | "tsx" | "go" | "rust" | "java" | "ruby" | "php" | "c" | "cpp" | "csharp" | "shell" | "yaml" | "json" | "dockerfile" | "unknown";
|
|
2
|
+
export declare function detectLang(filePath: string): Lang;
|
|
3
|
+
/** Focus-language predicate — covers our primary engines */
|
|
4
|
+
export declare function isFocusLang(lang: Lang): boolean;
|
|
5
|
+
//# sourceMappingURL=lang.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lang.d.ts","sourceRoot":"","sources":["../src/lang.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,IAAI,GACZ,QAAQ,GACR,YAAY,GACZ,YAAY,GACZ,KAAK,GACL,KAAK,GACL,IAAI,GACJ,MAAM,GACN,MAAM,GACN,MAAM,GACN,KAAK,GACL,GAAG,GACH,KAAK,GACL,QAAQ,GACR,OAAO,GACP,MAAM,GACN,MAAM,GACN,YAAY,GACZ,SAAS,CAAC;AAyCd,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAMjD;AAED,4DAA4D;AAC5D,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAE/C"}
|
package/dist/lang.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/** Language detection from file extension. */
|
|
2
|
+
import { basename, extname } from "node:path";
|
|
3
|
+
const EXT_LANG = {
|
|
4
|
+
".py": "python",
|
|
5
|
+
".pyi": "python",
|
|
6
|
+
".js": "javascript",
|
|
7
|
+
".mjs": "javascript",
|
|
8
|
+
".cjs": "javascript",
|
|
9
|
+
".jsx": "jsx",
|
|
10
|
+
".ts": "typescript",
|
|
11
|
+
".tsx": "tsx",
|
|
12
|
+
".mts": "typescript",
|
|
13
|
+
".cts": "typescript",
|
|
14
|
+
".go": "go",
|
|
15
|
+
".rs": "rust",
|
|
16
|
+
".java": "java",
|
|
17
|
+
".rb": "ruby",
|
|
18
|
+
".php": "php",
|
|
19
|
+
".c": "c",
|
|
20
|
+
".h": "c",
|
|
21
|
+
".cpp": "cpp",
|
|
22
|
+
".cc": "cpp",
|
|
23
|
+
".cxx": "cpp",
|
|
24
|
+
".hpp": "cpp",
|
|
25
|
+
".cs": "csharp",
|
|
26
|
+
".sh": "shell",
|
|
27
|
+
".bash": "shell",
|
|
28
|
+
".zsh": "shell",
|
|
29
|
+
".yml": "yaml",
|
|
30
|
+
".yaml": "yaml",
|
|
31
|
+
".json": "json",
|
|
32
|
+
};
|
|
33
|
+
const FILENAME_LANG = {
|
|
34
|
+
Dockerfile: "dockerfile",
|
|
35
|
+
dockerfile: "dockerfile",
|
|
36
|
+
Makefile: "shell",
|
|
37
|
+
".eslintrc.cjs": "javascript",
|
|
38
|
+
".eslintrc.js": "javascript",
|
|
39
|
+
};
|
|
40
|
+
export function detectLang(filePath) {
|
|
41
|
+
const base = basename(filePath);
|
|
42
|
+
const byName = FILENAME_LANG[base];
|
|
43
|
+
if (byName)
|
|
44
|
+
return byName;
|
|
45
|
+
const ext = extname(filePath).toLowerCase();
|
|
46
|
+
return EXT_LANG[ext] ?? "unknown";
|
|
47
|
+
}
|
|
48
|
+
/** Focus-language predicate — covers our primary engines */
|
|
49
|
+
export function isFocusLang(lang) {
|
|
50
|
+
return ["python", "javascript", "typescript", "jsx", "tsx", "go"].includes(lang);
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=lang.js.map
|
package/dist/lang.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lang.js","sourceRoot":"","sources":["../src/lang.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAsB9C,MAAM,QAAQ,GAAmC;IAC/C,KAAK,EAAE,QAAQ;IACf,MAAM,EAAE,QAAQ;IAChB,KAAK,EAAE,YAAY;IACnB,MAAM,EAAE,YAAY;IACpB,MAAM,EAAE,YAAY;IACpB,MAAM,EAAE,KAAK;IACb,KAAK,EAAE,YAAY;IACnB,MAAM,EAAE,KAAK;IACb,MAAM,EAAE,YAAY;IACpB,MAAM,EAAE,YAAY;IACpB,KAAK,EAAE,IAAI;IACX,KAAK,EAAE,MAAM;IACb,OAAO,EAAE,MAAM;IACf,KAAK,EAAE,MAAM;IACb,MAAM,EAAE,KAAK;IACb,IAAI,EAAE,GAAG;IACT,IAAI,EAAE,GAAG;IACT,MAAM,EAAE,KAAK;IACb,KAAK,EAAE,KAAK;IACZ,MAAM,EAAE,KAAK;IACb,MAAM,EAAE,KAAK;IACb,KAAK,EAAE,QAAQ;IACf,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,OAAO;IAChB,MAAM,EAAE,OAAO;IACf,MAAM,EAAE,MAAM;IACd,OAAO,EAAE,MAAM;IACf,OAAO,EAAE,MAAM;CAChB,CAAC;AAEF,MAAM,aAAa,GAAmC;IACpD,UAAU,EAAE,YAAY;IACxB,UAAU,EAAE,YAAY;IACxB,QAAQ,EAAE,OAAO;IACjB,eAAe,EAAE,YAAY;IAC7B,cAAc,EAAE,YAAY;CAC7B,CAAC;AAEF,MAAM,UAAU,UAAU,CAAC,QAAgB;IACzC,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAChC,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;IACnC,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAC1B,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;IAC5C,OAAO,QAAQ,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC;AACpC,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,WAAW,CAAC,IAAU;IACpC,OAAO,CAAC,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACnF,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
declare const SuppressionEntry: z.ZodObject<{
|
|
3
|
+
op: z.ZodEnum<["add", "remove"]>;
|
|
4
|
+
id: z.ZodString;
|
|
5
|
+
ts: z.ZodString;
|
|
6
|
+
reason: z.ZodOptional<z.ZodString>;
|
|
7
|
+
expires_at: z.ZodOptional<z.ZodString>;
|
|
8
|
+
who: z.ZodOptional<z.ZodString>;
|
|
9
|
+
}, "strip", z.ZodTypeAny, {
|
|
10
|
+
id: string;
|
|
11
|
+
op: "add" | "remove";
|
|
12
|
+
ts: string;
|
|
13
|
+
reason?: string | undefined;
|
|
14
|
+
expires_at?: string | undefined;
|
|
15
|
+
who?: string | undefined;
|
|
16
|
+
}, {
|
|
17
|
+
id: string;
|
|
18
|
+
op: "add" | "remove";
|
|
19
|
+
ts: string;
|
|
20
|
+
reason?: string | undefined;
|
|
21
|
+
expires_at?: string | undefined;
|
|
22
|
+
who?: string | undefined;
|
|
23
|
+
}>;
|
|
24
|
+
export type SuppressionEntry = z.infer<typeof SuppressionEntry>;
|
|
25
|
+
export interface ActiveSuppression {
|
|
26
|
+
id: string;
|
|
27
|
+
added_at: string;
|
|
28
|
+
reason?: string;
|
|
29
|
+
expires_at?: string;
|
|
30
|
+
who?: string;
|
|
31
|
+
}
|
|
32
|
+
export declare function suppressionsPath(projectRoot: string): string;
|
|
33
|
+
export interface SuppressOptions {
|
|
34
|
+
reason?: string;
|
|
35
|
+
expiresAt?: string;
|
|
36
|
+
who?: string;
|
|
37
|
+
}
|
|
38
|
+
/** Add an `add` event to the log. Idempotent — adding an already-active
|
|
39
|
+
* suppression is a no-op log entry (we still append for audit). */
|
|
40
|
+
export declare function suppress(projectRoot: string, findingId: string, opts?: SuppressOptions): {
|
|
41
|
+
ok: true;
|
|
42
|
+
entry: SuppressionEntry;
|
|
43
|
+
} | {
|
|
44
|
+
ok: false;
|
|
45
|
+
reason: string;
|
|
46
|
+
};
|
|
47
|
+
/** Add a `remove` event — the finding will be ALLOWED through again on
|
|
48
|
+
* the next gate run. */
|
|
49
|
+
export declare function unsuppress(projectRoot: string, findingId: string, opts?: {
|
|
50
|
+
who?: string;
|
|
51
|
+
reason?: string;
|
|
52
|
+
}): {
|
|
53
|
+
ok: true;
|
|
54
|
+
entry: SuppressionEntry;
|
|
55
|
+
} | {
|
|
56
|
+
ok: false;
|
|
57
|
+
reason: string;
|
|
58
|
+
};
|
|
59
|
+
/** Return the currently-active suppressions (folded from the append log,
|
|
60
|
+
* with expired entries dropped). O(1) hit on the per-project cache when
|
|
61
|
+
* the log mtime hasn't changed since the last call. */
|
|
62
|
+
export declare function listActive(projectRoot: string): ActiveSuppression[];
|
|
63
|
+
/** Fast O(1) check used by the orchestrator. Returns true iff the finding
|
|
64
|
+
* id is currently suppressed (added + not removed + not expired). */
|
|
65
|
+
export declare function isSuppressed(projectRoot: string, findingId: string): boolean;
|
|
66
|
+
/** Test-only — wipe the in-memory cache so a test can re-read after
|
|
67
|
+
* writing fresh entries. */
|
|
68
|
+
export declare function _resetActiveCacheForTests(): void;
|
|
69
|
+
export {};
|
|
70
|
+
//# sourceMappingURL=suppressions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"suppressions.d.ts","sourceRoot":"","sources":["../../src/learning/suppressions.ts"],"names":[],"mappings":"AA8BA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAWxB,QAAA,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;EAOpB,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAEhE,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAYD,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAE5D;AASD,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;mEACmE;AACnE,wBAAgB,QAAQ,CACtB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,eAAe,GACrB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,gBAAgB,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAavE;AAED;wBACwB;AACxB,wBAAgB,UAAU,CACxB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GACvC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,gBAAgB,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAYvE;AAoBD;;uDAEuD;AACvD,wBAAgB,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAEnE;AAED;qEACqE;AACrE,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAE5E;AA6DD;4BAC4B;AAC5B,wBAAgB,yBAAyB,IAAI,IAAI,CAEhD"}
|