@hiro-c/agent-gate 1.3.0 → 1.5.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/README.md +1 -1
- package/dist/cli/agent-gate.d.ts +1 -0
- package/dist/cli/agent-gate.d.ts.map +1 -1
- package/dist/cli/agent-gate.js +24 -5
- package/dist/deterministic/bashAnalysis.d.ts +31 -0
- package/dist/deterministic/bashAnalysis.d.ts.map +1 -0
- package/dist/deterministic/bashAnalysis.js +108 -0
- package/dist/deterministic/rules/preventBashSecretWrite.d.ts.map +1 -1
- package/dist/deterministic/rules/preventBashSecretWrite.js +19 -11
- package/dist/deterministic/rules/preventRmRfRoot.d.ts.map +1 -1
- package/dist/deterministic/rules/preventRmRfRoot.js +28 -10
- package/dist/doctor/findings.d.ts +1 -1
- package/dist/doctor/findings.d.ts.map +1 -1
- package/dist/doctor/lintRuleSourcesWithAi.d.ts +5 -0
- package/dist/doctor/lintRuleSourcesWithAi.d.ts.map +1 -0
- package/dist/doctor/lintRuleSourcesWithAi.js +111 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -74,7 +74,7 @@ Full options: see [docs/config.md](docs/config.md) (TODO) or `AgentGatePluginCon
|
|
|
74
74
|
|---|---|
|
|
75
75
|
| `agent-gate` | Run as hook (reads stdin, used internally) |
|
|
76
76
|
| `agent-gate install` / `uninstall` | Register or remove the Claude Code hook |
|
|
77
|
-
| `agent-gate lint` | Audit instruction files for ambiguity, emptiness, missing rules |
|
|
77
|
+
| `agent-gate lint [--ai]` | Audit instruction files for ambiguity, emptiness, missing rules. `--ai` adds AI-driven contradiction / ambiguity / missing-imperative checks |
|
|
78
78
|
| `agent-gate stats` | Summarize the decision log (after `AGENT_GATE_LOG=1`) |
|
|
79
79
|
| `agent-gate daemon` | Long-lived server on a Unix socket (opt-in speedup, set `AGENT_GATE_DAEMON=1`) |
|
|
80
80
|
|
package/dist/cli/agent-gate.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-gate.d.ts","sourceRoot":"","sources":["../../src/cli/agent-gate.ts"],"names":[],"mappings":";AAIA,OAAO,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAA;AAYtE,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"agent-gate.d.ts","sourceRoot":"","sources":["../../src/cli/agent-gate.ts"],"names":[],"mappings":";AAIA,OAAO,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAA;AAYtE,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AA4C7C,wBAAsB,GAAG,CACvB,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,OAAO,GAChB,OAAO,CAAC,gBAAgB,CAAC,CAE3B;AAuHD,UAAU,UAAU;IAClB,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,OAAO,CAAA;IACjB,WAAW,EAAE,OAAO,CAAA;IACpB,EAAE,EAAE,OAAO,CAAA;CACZ;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CAqCpD"}
|
package/dist/cli/agent-gate.js
CHANGED
|
@@ -11,7 +11,11 @@ const stats_1 = require("../observability/stats");
|
|
|
11
11
|
const decisionLogger_1 = require("../observability/decisionLogger");
|
|
12
12
|
const collectRuleSources_1 = require("../collector/collectRuleSources");
|
|
13
13
|
const lintRuleSources_1 = require("../doctor/lintRuleSources");
|
|
14
|
+
const lintRuleSourcesWithAi_1 = require("../doctor/lintRuleSourcesWithAi");
|
|
14
15
|
const formatFindings_1 = require("../doctor/formatFindings");
|
|
16
|
+
const Config_1 = require("../config/Config");
|
|
17
|
+
const AnthropicApi_1 = require("../validation/models/AnthropicApi");
|
|
18
|
+
const ClaudeCli_1 = require("../validation/models/ClaudeCli");
|
|
15
19
|
const server_1 = require("../daemon/server");
|
|
16
20
|
const client_1 = require("../daemon/client");
|
|
17
21
|
const protocol_1 = require("../daemon/protocol");
|
|
@@ -24,7 +28,8 @@ Usage:
|
|
|
24
28
|
agent-gate install Register the hook in ~/.claude/settings.json
|
|
25
29
|
agent-gate uninstall Remove the hook from ~/.claude/settings.json
|
|
26
30
|
agent-gate stats Summarize decisions from the log file
|
|
27
|
-
agent-gate lint
|
|
31
|
+
agent-gate lint [--ai] Audit CLAUDE.md / AGENTS.md / etc. for AI-friendliness
|
|
32
|
+
(--ai adds AI-driven contradiction / ambiguity / missing-imperative checks)
|
|
28
33
|
agent-gate daemon Start the long-lived daemon (Unix socket)
|
|
29
34
|
agent-gate --help Show this help
|
|
30
35
|
agent-gate --version Show version
|
|
@@ -146,6 +151,7 @@ function parseArgs(args) {
|
|
|
146
151
|
let agentId = adapters_1.DEFAULT_ADAPTER_ID;
|
|
147
152
|
let showHelp = false;
|
|
148
153
|
let showVersion = false;
|
|
154
|
+
let ai = false;
|
|
149
155
|
const positional = [];
|
|
150
156
|
for (let i = 0; i < args.length; i++) {
|
|
151
157
|
const a = args[i];
|
|
@@ -161,6 +167,10 @@ function parseArgs(args) {
|
|
|
161
167
|
agentId = a.slice('--agent='.length);
|
|
162
168
|
continue;
|
|
163
169
|
}
|
|
170
|
+
if (a === '--ai') {
|
|
171
|
+
ai = true;
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
164
174
|
if (a === '--help' || a === '-h' || a === 'help') {
|
|
165
175
|
showHelp = true;
|
|
166
176
|
continue;
|
|
@@ -171,7 +181,7 @@ function parseArgs(args) {
|
|
|
171
181
|
}
|
|
172
182
|
positional.push(a);
|
|
173
183
|
}
|
|
174
|
-
return { positional, agentId, showHelp, showVersion };
|
|
184
|
+
return { positional, agentId, showHelp, showVersion, ai };
|
|
175
185
|
}
|
|
176
186
|
function main() {
|
|
177
187
|
const parsedArgs = parseArgs(process.argv.slice(2));
|
|
@@ -203,7 +213,7 @@ function main() {
|
|
|
203
213
|
runStats();
|
|
204
214
|
return;
|
|
205
215
|
case 'lint':
|
|
206
|
-
runLint();
|
|
216
|
+
void runLint(parsedArgs.ai);
|
|
207
217
|
return;
|
|
208
218
|
case 'daemon':
|
|
209
219
|
void runDaemon();
|
|
@@ -218,13 +228,22 @@ function runStats() {
|
|
|
218
228
|
const stats = (0, stats_1.readStats)((0, decisionLogger_1.defaultLogPath)());
|
|
219
229
|
console.log((0, stats_1.formatStats)(stats));
|
|
220
230
|
}
|
|
221
|
-
function runLint() {
|
|
222
|
-
const
|
|
231
|
+
async function runLint(useAi) {
|
|
232
|
+
const cwd = process.cwd();
|
|
233
|
+
const sources = (0, collectRuleSources_1.collectRuleSources)(cwd);
|
|
223
234
|
if (sources.length === 0) {
|
|
224
235
|
console.log('No instruction files found (looked for CLAUDE.md, AGENTS.md, .cursorrules, .cursor/rules/*.mdc, .clinerules/*.md, .windsurf/rules/*.md, .github/copilot-instructions.md, CONVENTIONS.md).');
|
|
225
236
|
return;
|
|
226
237
|
}
|
|
227
238
|
const findings = (0, lintRuleSources_1.lintRuleSources)(sources);
|
|
239
|
+
if (useAi) {
|
|
240
|
+
const config = new Config_1.Config();
|
|
241
|
+
const client = config.useApi
|
|
242
|
+
? new AnthropicApi_1.AnthropicApi(config)
|
|
243
|
+
: new ClaudeCli_1.ClaudeCli(config, cwd);
|
|
244
|
+
const aiFindings = await (0, lintRuleSourcesWithAi_1.lintRuleSourcesWithAi)(sources, client);
|
|
245
|
+
findings.push(...aiFindings);
|
|
246
|
+
}
|
|
228
247
|
console.log((0, formatFindings_1.formatFindings)(findings));
|
|
229
248
|
const hasError = findings.some((f) => f.severity === 'error');
|
|
230
249
|
if (hasError) {
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Light-weight bash analysis utilities used by deterministic rules to
|
|
3
|
+
* see past common obfuscation patterns. This is intentionally not a
|
|
4
|
+
* full shell parser; it handles the cases that matter for guardrails
|
|
5
|
+
* (separators, quoting, heredoc redirects, command substitution
|
|
6
|
+
* markers) and stays small.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Split a command line into top-level statements separated by `;`,
|
|
10
|
+
* `&&`, `||`, `|`, or newline. Respects single- and double-quoted
|
|
11
|
+
* regions so separators inside strings are preserved as part of the
|
|
12
|
+
* statement.
|
|
13
|
+
*
|
|
14
|
+
* Trims and drops empty results.
|
|
15
|
+
*/
|
|
16
|
+
export declare function splitStatements(command: string): string[];
|
|
17
|
+
/**
|
|
18
|
+
* Return any redirect targets that follow a heredoc operator. Each
|
|
19
|
+
* `cat <<EOF > target` (or `>> target`) anywhere in the command
|
|
20
|
+
* contributes one entry. Returns the raw target token without quote
|
|
21
|
+
* stripping.
|
|
22
|
+
*/
|
|
23
|
+
export declare function extractHeredocTargets(command: string): string[];
|
|
24
|
+
/**
|
|
25
|
+
* True when the command uses command substitution `$(...)` / backticks,
|
|
26
|
+
* or a non-literal variable reference (anything other than the well-
|
|
27
|
+
* known `$HOME` / `$USER` / `$PWD` which the catastrophic-path rule
|
|
28
|
+
* already understands).
|
|
29
|
+
*/
|
|
30
|
+
export declare function hasObfuscation(command: string): boolean;
|
|
31
|
+
//# sourceMappingURL=bashAnalysis.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bashAnalysis.d.ts","sourceRoot":"","sources":["../../src/deterministic/bashAnalysis.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CA2CzD;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAS/D;AAWD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAYvD"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Light-weight bash analysis utilities used by deterministic rules to
|
|
4
|
+
* see past common obfuscation patterns. This is intentionally not a
|
|
5
|
+
* full shell parser; it handles the cases that matter for guardrails
|
|
6
|
+
* (separators, quoting, heredoc redirects, command substitution
|
|
7
|
+
* markers) and stays small.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.splitStatements = splitStatements;
|
|
11
|
+
exports.extractHeredocTargets = extractHeredocTargets;
|
|
12
|
+
exports.hasObfuscation = hasObfuscation;
|
|
13
|
+
/**
|
|
14
|
+
* Split a command line into top-level statements separated by `;`,
|
|
15
|
+
* `&&`, `||`, `|`, or newline. Respects single- and double-quoted
|
|
16
|
+
* regions so separators inside strings are preserved as part of the
|
|
17
|
+
* statement.
|
|
18
|
+
*
|
|
19
|
+
* Trims and drops empty results.
|
|
20
|
+
*/
|
|
21
|
+
function splitStatements(command) {
|
|
22
|
+
const out = [];
|
|
23
|
+
let buf = '';
|
|
24
|
+
let i = 0;
|
|
25
|
+
let quote = null;
|
|
26
|
+
while (i < command.length) {
|
|
27
|
+
const c = command[i];
|
|
28
|
+
if (quote) {
|
|
29
|
+
buf += c;
|
|
30
|
+
if (c === quote)
|
|
31
|
+
quote = null;
|
|
32
|
+
i++;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (c === '"' || c === "'") {
|
|
36
|
+
quote = c;
|
|
37
|
+
buf += c;
|
|
38
|
+
i++;
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
if (c === ';' || c === '\n' || c === '|') {
|
|
42
|
+
// `||` collapses with `|`; `&&` handled below.
|
|
43
|
+
out.push(buf);
|
|
44
|
+
buf = '';
|
|
45
|
+
i++;
|
|
46
|
+
// collapse a trailing | of `||`
|
|
47
|
+
if (c === '|' && command[i] === '|')
|
|
48
|
+
i++;
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (c === '&' && command[i + 1] === '&') {
|
|
52
|
+
out.push(buf);
|
|
53
|
+
buf = '';
|
|
54
|
+
i += 2;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
buf += c;
|
|
58
|
+
i++;
|
|
59
|
+
}
|
|
60
|
+
out.push(buf);
|
|
61
|
+
return out.map((s) => s.trim()).filter((s) => s.length > 0);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Return any redirect targets that follow a heredoc operator. Each
|
|
65
|
+
* `cat <<EOF > target` (or `>> target`) anywhere in the command
|
|
66
|
+
* contributes one entry. Returns the raw target token without quote
|
|
67
|
+
* stripping.
|
|
68
|
+
*/
|
|
69
|
+
function extractHeredocTargets(command) {
|
|
70
|
+
const targets = [];
|
|
71
|
+
// `<<` or `<<-`, optional `'TAG'` or `"TAG"` or bare TAG, then a redirect.
|
|
72
|
+
// We are permissive about whitespace.
|
|
73
|
+
const re = /<<-?\s*(?:['"]?\w+['"]?)\s*(?:>>?)\s*([^\s;|&<>]+)/g;
|
|
74
|
+
for (const m of command.matchAll(re)) {
|
|
75
|
+
if (m[1])
|
|
76
|
+
targets.push(m[1]);
|
|
77
|
+
}
|
|
78
|
+
return targets;
|
|
79
|
+
}
|
|
80
|
+
const KNOWN_LITERAL_VARS = new Set([
|
|
81
|
+
'$HOME',
|
|
82
|
+
'${HOME}',
|
|
83
|
+
'$PWD',
|
|
84
|
+
'${PWD}',
|
|
85
|
+
'$USER',
|
|
86
|
+
'${USER}',
|
|
87
|
+
]);
|
|
88
|
+
/**
|
|
89
|
+
* True when the command uses command substitution `$(...)` / backticks,
|
|
90
|
+
* or a non-literal variable reference (anything other than the well-
|
|
91
|
+
* known `$HOME` / `$USER` / `$PWD` which the catastrophic-path rule
|
|
92
|
+
* already understands).
|
|
93
|
+
*/
|
|
94
|
+
function hasObfuscation(command) {
|
|
95
|
+
if (/\$\([^)]*\)/.test(command))
|
|
96
|
+
return true;
|
|
97
|
+
if (/`[^`]*`/.test(command))
|
|
98
|
+
return true;
|
|
99
|
+
// Match each $VAR / ${VAR} occurrence and decide whether it is one
|
|
100
|
+
// of the literal allowlist.
|
|
101
|
+
const re = /\$\{?[A-Za-z_][A-Za-z0-9_]*\}?/g;
|
|
102
|
+
for (const m of command.matchAll(re)) {
|
|
103
|
+
const tok = m[0];
|
|
104
|
+
if (!KNOWN_LITERAL_VARS.has(tok))
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preventBashSecretWrite.d.ts","sourceRoot":"","sources":["../../../src/deterministic/rules/preventBashSecretWrite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAe,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"preventBashSecretWrite.d.ts","sourceRoot":"","sources":["../../../src/deterministic/rules/preventBashSecretWrite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAe,MAAM,UAAU,CAAA;AA6DzD,eAAO,MAAM,sBAAsB,EAAE,iBAsBpC,CAAA"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.preventBashSecretWrite = void 0;
|
|
4
|
+
const bashAnalysis_1 = require("../bashAnalysis");
|
|
4
5
|
const TEMPLATE_SUFFIXES = ['.example', '.sample', '.template', '.dist'];
|
|
5
6
|
function basename(path) {
|
|
6
7
|
const cleaned = path.replace(/[\s'"]+$/, '');
|
|
@@ -30,18 +31,18 @@ function isSecretTargetPath(rawPath) {
|
|
|
30
31
|
return false;
|
|
31
32
|
}
|
|
32
33
|
/**
|
|
33
|
-
* Extracts
|
|
34
|
-
*
|
|
34
|
+
* Extracts every file the command writes to:
|
|
35
|
+
* 1. Standard redirects (`>`, `>>`, `1>`, `2>`, `&>`)
|
|
36
|
+
* 2. `tee [-a] FILE [FILE ...]`
|
|
37
|
+
* 3. Heredoc redirects (`cat <<EOF > file`)
|
|
35
38
|
*/
|
|
36
39
|
function extractWriteTargets(command) {
|
|
37
40
|
const targets = [];
|
|
38
|
-
// Redirect operators: >, >>, &>, &>>, 1>, 2> etc.
|
|
39
41
|
const redirectRe = /[12&]?>>?\s*([^\s;|&<>]+)/g;
|
|
40
42
|
for (const m of command.matchAll(redirectRe)) {
|
|
41
43
|
if (m[1])
|
|
42
44
|
targets.push(m[1]);
|
|
43
45
|
}
|
|
44
|
-
// tee [-a] FILE [FILE ...]
|
|
45
46
|
const teeRe = /\btee\b(?:\s+-[A-Za-z]+)*\s+([^\s;|&<>]+(?:\s+[^\s;|&<>]+)*)/g;
|
|
46
47
|
for (const m of command.matchAll(teeRe)) {
|
|
47
48
|
if (m[1]) {
|
|
@@ -51,6 +52,9 @@ function extractWriteTargets(command) {
|
|
|
51
52
|
}
|
|
52
53
|
}
|
|
53
54
|
}
|
|
55
|
+
for (const t of (0, bashAnalysis_1.extractHeredocTargets)(command)) {
|
|
56
|
+
targets.push(t);
|
|
57
|
+
}
|
|
54
58
|
return targets;
|
|
55
59
|
}
|
|
56
60
|
exports.preventBashSecretWrite = {
|
|
@@ -61,13 +65,17 @@ exports.preventBashSecretWrite = {
|
|
|
61
65
|
const command = toolInput.command;
|
|
62
66
|
if (typeof command !== 'string')
|
|
63
67
|
return { kind: 'allow' };
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
// Inspect each top-level statement; heredoc spans newlines so the
|
|
69
|
+
// statement splitter preserves the heredoc body inside its segment.
|
|
70
|
+
for (const stmt of (0, bashAnalysis_1.splitStatements)(command)) {
|
|
71
|
+
const targets = extractWriteTargets(stmt);
|
|
72
|
+
for (const target of targets) {
|
|
73
|
+
if (isSecretTargetPath(target)) {
|
|
74
|
+
return {
|
|
75
|
+
kind: 'block',
|
|
76
|
+
reason: `Refusing to write to a likely secret/credential file via shell redirect: ${target}. If this is intentional, run the command manually outside of the agent.`,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
71
79
|
}
|
|
72
80
|
}
|
|
73
81
|
return { kind: 'allow' };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"preventRmRfRoot.d.ts","sourceRoot":"","sources":["../../../src/deterministic/rules/preventRmRfRoot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAe,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"preventRmRfRoot.d.ts","sourceRoot":"","sources":["../../../src/deterministic/rules/preventRmRfRoot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAe,MAAM,UAAU,CAAA;AA0EzD,eAAO,MAAM,eAAe,EAAE,iBAa7B,CAAA"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.preventRmRfRoot = void 0;
|
|
4
|
+
const bashAnalysis_1 = require("../bashAnalysis");
|
|
4
5
|
const CATASTROPHIC_TARGETS = new Set([
|
|
5
6
|
'/',
|
|
6
7
|
'$HOME',
|
|
@@ -44,6 +45,29 @@ function extractTargets(command) {
|
|
|
44
45
|
const tokens = trimmed.split(/\s+/);
|
|
45
46
|
return tokens.slice(1).filter((t) => !t.startsWith('-'));
|
|
46
47
|
}
|
|
48
|
+
function evaluateStatement(stmt) {
|
|
49
|
+
if (!isRecursiveForceRm(stmt))
|
|
50
|
+
return { kind: 'allow' };
|
|
51
|
+
// Substitution / unresolved variable targets cannot be evaluated
|
|
52
|
+
// statically. Treat them as suspicious: we cannot prove they are not
|
|
53
|
+
// catastrophic, so block.
|
|
54
|
+
if ((0, bashAnalysis_1.hasObfuscation)(stmt)) {
|
|
55
|
+
return {
|
|
56
|
+
kind: 'block',
|
|
57
|
+
reason: 'Refusing recursive rm whose target is a command substitution or unresolved variable. The target cannot be evaluated statically, so the operation is rejected as a safety precaution.',
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
const targets = extractTargets(stmt);
|
|
61
|
+
for (const target of targets) {
|
|
62
|
+
if (CATASTROPHIC_TARGETS.has(target)) {
|
|
63
|
+
return {
|
|
64
|
+
kind: 'block',
|
|
65
|
+
reason: `Refusing to run recursive rm on a catastrophic path: ${target}. If this is genuinely intended, run the command manually outside of the agent.`,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return { kind: 'allow' };
|
|
70
|
+
}
|
|
47
71
|
exports.preventRmRfRoot = {
|
|
48
72
|
id: 'prevent-rm-rf-root',
|
|
49
73
|
check(toolName, toolInput) {
|
|
@@ -52,16 +76,10 @@ exports.preventRmRfRoot = {
|
|
|
52
76
|
const command = toolInput.command;
|
|
53
77
|
if (typeof command !== 'string')
|
|
54
78
|
return { kind: 'allow' };
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if (CATASTROPHIC_TARGETS.has(target)) {
|
|
60
|
-
return {
|
|
61
|
-
kind: 'block',
|
|
62
|
-
reason: `Refusing to run recursive rm on a catastrophic path: ${target}. If this is genuinely intended, run the command manually outside of the agent.`,
|
|
63
|
-
};
|
|
64
|
-
}
|
|
79
|
+
for (const stmt of (0, bashAnalysis_1.splitStatements)(command)) {
|
|
80
|
+
const v = evaluateStatement(stmt);
|
|
81
|
+
if (v.kind === 'block')
|
|
82
|
+
return v;
|
|
65
83
|
}
|
|
66
84
|
return { kind: 'allow' };
|
|
67
85
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { RuleSourceKind } from '../contracts/types/RuleSource';
|
|
2
2
|
export type Severity = 'info' | 'warning' | 'error';
|
|
3
|
-
export type FindingCode = 'empty-file' | 'ambiguous-modifier' | 'no-concrete-rules';
|
|
3
|
+
export type FindingCode = 'empty-file' | 'ambiguous-modifier' | 'no-concrete-rules' | 'ambiguity' | 'contradiction' | 'missing-imperative';
|
|
4
4
|
export interface Finding {
|
|
5
5
|
ruleSourcePath: string;
|
|
6
6
|
ruleSourceKind: RuleSourceKind;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"findings.d.ts","sourceRoot":"","sources":["../../src/doctor/findings.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AAE9D,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,CAAA;AAEnD,MAAM,MAAM,WAAW,GACnB,YAAY,GACZ,oBAAoB,GACpB,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"findings.d.ts","sourceRoot":"","sources":["../../src/doctor/findings.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AAE9D,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,CAAA;AAEnD,MAAM,MAAM,WAAW,GACnB,YAAY,GACZ,oBAAoB,GACpB,mBAAmB,GACnB,WAAW,GACX,eAAe,GACf,oBAAoB,CAAA;AAExB,MAAM,WAAW,OAAO;IACtB,cAAc,EAAE,MAAM,CAAA;IACtB,cAAc,EAAE,cAAc,CAAA;IAC9B,QAAQ,EAAE,QAAQ,CAAA;IAClB,IAAI,EAAE,WAAW,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,+DAA+D;IAC/D,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,4DAA4D;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { RuleSource } from '../contracts/types/RuleSource';
|
|
2
|
+
import { IModelClient } from '../contracts/types/ModelClient';
|
|
3
|
+
import { Finding } from './findings';
|
|
4
|
+
export declare function lintRuleSourcesWithAi(sources: RuleSource[], client: IModelClient): Promise<Finding[]>;
|
|
5
|
+
//# sourceMappingURL=lintRuleSourcesWithAi.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lintRuleSourcesWithAi.d.ts","sourceRoot":"","sources":["../../src/doctor/lintRuleSourcesWithAi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAkB,MAAM,+BAA+B,CAAA;AAC1E,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAA;AAC7D,OAAO,EAAE,OAAO,EAAyB,MAAM,YAAY,CAAA;AA8E3D,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,UAAU,EAAE,EACrB,MAAM,EAAE,YAAY,GACnB,OAAO,CAAC,OAAO,EAAE,CAAC,CA4CpB"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.lintRuleSourcesWithAi = lintRuleSourcesWithAi;
|
|
4
|
+
const PROMPT_HEADER = `You are auditing AI agent instruction files for issues that
|
|
5
|
+
make rules hard for an AI to enforce reliably. Look at the sources below
|
|
6
|
+
and report any of the following:
|
|
7
|
+
|
|
8
|
+
- "contradiction": two or more rules across one or more files that
|
|
9
|
+
conflict. Cite both/all sides in the excerpt.
|
|
10
|
+
- "ambiguity": a rule that uses vague language (e.g. "where possible",
|
|
11
|
+
"as needed", "appropriately") with no concrete threshold or condition.
|
|
12
|
+
- "missing-imperative": a rule expressed as a wish or description rather
|
|
13
|
+
than an imperative the AI can act on.
|
|
14
|
+
|
|
15
|
+
Respond as a JSON array of objects with this shape:
|
|
16
|
+
[
|
|
17
|
+
{
|
|
18
|
+
"code": "contradiction" | "ambiguity" | "missing-imperative",
|
|
19
|
+
"ruleSourcePath": "<one of the paths shown>",
|
|
20
|
+
"line": <1-indexed line number in that file, or null>,
|
|
21
|
+
"message": "<concise explanation>",
|
|
22
|
+
"excerpt": "<short literal text from the file>"
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
If there are no issues, respond with []. Output ONLY the JSON array. No
|
|
27
|
+
markdown, no prose, no commentary.`;
|
|
28
|
+
const ALLOWED_CODES = [
|
|
29
|
+
'ambiguity',
|
|
30
|
+
'contradiction',
|
|
31
|
+
'missing-imperative',
|
|
32
|
+
];
|
|
33
|
+
const CODE_SEVERITY = {
|
|
34
|
+
'empty-file': 'warning',
|
|
35
|
+
'ambiguous-modifier': 'info',
|
|
36
|
+
'no-concrete-rules': 'warning',
|
|
37
|
+
ambiguity: 'info',
|
|
38
|
+
contradiction: 'warning',
|
|
39
|
+
'missing-imperative': 'info',
|
|
40
|
+
};
|
|
41
|
+
function buildPrompt(sources) {
|
|
42
|
+
const blocks = sources.map((s) => `--- path: ${s.path} (kind: ${s.kind}) ---\n${s.content}`);
|
|
43
|
+
return `${PROMPT_HEADER}\n\n${blocks.join('\n\n')}`;
|
|
44
|
+
}
|
|
45
|
+
function extractJsonArray(raw) {
|
|
46
|
+
const trimmed = raw.trim();
|
|
47
|
+
if (trimmed.startsWith('['))
|
|
48
|
+
return trimmed;
|
|
49
|
+
// Code fence variants
|
|
50
|
+
const fenced = trimmed.match(/```(?:json)?\s*\n([\s\S]*?)\n```/);
|
|
51
|
+
if (fenced)
|
|
52
|
+
return fenced[1].trim();
|
|
53
|
+
// Plain extraction: first [ to last ]
|
|
54
|
+
const start = trimmed.indexOf('[');
|
|
55
|
+
const end = trimmed.lastIndexOf(']');
|
|
56
|
+
if (start !== -1 && end > start)
|
|
57
|
+
return trimmed.slice(start, end + 1);
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
function pathToKind(path, sources) {
|
|
61
|
+
const match = sources.find((s) => s.path === path);
|
|
62
|
+
return match ? match.kind : null;
|
|
63
|
+
}
|
|
64
|
+
async function lintRuleSourcesWithAi(sources, client) {
|
|
65
|
+
if (sources.length === 0)
|
|
66
|
+
return [];
|
|
67
|
+
let response;
|
|
68
|
+
try {
|
|
69
|
+
response = await client.ask(buildPrompt(sources));
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return [];
|
|
73
|
+
}
|
|
74
|
+
const jsonStr = extractJsonArray(response);
|
|
75
|
+
if (!jsonStr)
|
|
76
|
+
return [];
|
|
77
|
+
let parsed;
|
|
78
|
+
try {
|
|
79
|
+
parsed = JSON.parse(jsonStr);
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return [];
|
|
83
|
+
}
|
|
84
|
+
if (!Array.isArray(parsed))
|
|
85
|
+
return [];
|
|
86
|
+
const findings = [];
|
|
87
|
+
for (const raw of parsed) {
|
|
88
|
+
if (!raw || typeof raw !== 'object')
|
|
89
|
+
continue;
|
|
90
|
+
const code = raw.code;
|
|
91
|
+
if (!code || !ALLOWED_CODES.includes(code))
|
|
92
|
+
continue;
|
|
93
|
+
if (typeof raw.ruleSourcePath !== 'string')
|
|
94
|
+
continue;
|
|
95
|
+
const kind = pathToKind(raw.ruleSourcePath, sources);
|
|
96
|
+
if (!kind)
|
|
97
|
+
continue;
|
|
98
|
+
findings.push({
|
|
99
|
+
ruleSourcePath: raw.ruleSourcePath,
|
|
100
|
+
ruleSourceKind: kind,
|
|
101
|
+
severity: CODE_SEVERITY[code],
|
|
102
|
+
code,
|
|
103
|
+
message: typeof raw.message === 'string' ? raw.message : '',
|
|
104
|
+
line: typeof raw.line === 'number' && Number.isFinite(raw.line)
|
|
105
|
+
? raw.line
|
|
106
|
+
: undefined,
|
|
107
|
+
excerpt: typeof raw.excerpt === 'string' ? raw.excerpt : undefined,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
return findings;
|
|
111
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -23,6 +23,7 @@ export type { CompositeModelClientOptions } from './validation/models/CompositeM
|
|
|
23
23
|
export { AgentSdkClient } from './validation/models/AgentSdkClient';
|
|
24
24
|
export type { AgentSdkClientOptions, AgentSdkQueryFn, } from './validation/models/AgentSdkClient';
|
|
25
25
|
export { lintRuleSources } from './doctor/lintRuleSources';
|
|
26
|
+
export { lintRuleSourcesWithAi } from './doctor/lintRuleSourcesWithAi';
|
|
26
27
|
export { formatFindings } from './doctor/formatFindings';
|
|
27
28
|
export type { Finding, FindingCode, Severity, } from './doctor/findings';
|
|
28
29
|
export { DecisionCache } from './cache/DecisionCache';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.processHookData = exports.validator = exports.collectRuleSources = exports.JsonlFileSink = exports.EventBus = exports.defaultDaemonSocketPath = exports.sendToDaemon = exports.DaemonServer = exports.DecisionCache = exports.formatFindings = exports.lintRuleSources = exports.AgentSdkClient = exports.CompositeModelClient = exports.cursorAdapter = exports.claudeCodeAdapter = exports.buildDefaultDeterministicRules = exports.defaultDeterministicRules = exports.forbidFilePathPattern = exports.forbidContentPattern = exports.forbidCommandPattern = exports.HookDataSchema = exports.loadPluginConfig = exports.loadAgentGateConfig = exports.defineConfig = exports.Config = void 0;
|
|
3
|
+
exports.processHookData = exports.validator = exports.collectRuleSources = exports.JsonlFileSink = exports.EventBus = exports.defaultDaemonSocketPath = exports.sendToDaemon = exports.DaemonServer = exports.DecisionCache = exports.formatFindings = exports.lintRuleSourcesWithAi = exports.lintRuleSources = exports.AgentSdkClient = exports.CompositeModelClient = exports.cursorAdapter = exports.claudeCodeAdapter = exports.buildDefaultDeterministicRules = exports.defaultDeterministicRules = exports.forbidFilePathPattern = exports.forbidContentPattern = exports.forbidCommandPattern = exports.HookDataSchema = exports.loadPluginConfig = exports.loadAgentGateConfig = exports.defineConfig = exports.Config = void 0;
|
|
4
4
|
// Config
|
|
5
5
|
var Config_1 = require("./config/Config");
|
|
6
6
|
Object.defineProperty(exports, "Config", { enumerable: true, get: function () { return Config_1.Config; } });
|
|
@@ -33,6 +33,8 @@ Object.defineProperty(exports, "AgentSdkClient", { enumerable: true, get: functi
|
|
|
33
33
|
// Doctor (CLAUDE.md linter)
|
|
34
34
|
var lintRuleSources_1 = require("./doctor/lintRuleSources");
|
|
35
35
|
Object.defineProperty(exports, "lintRuleSources", { enumerable: true, get: function () { return lintRuleSources_1.lintRuleSources; } });
|
|
36
|
+
var lintRuleSourcesWithAi_1 = require("./doctor/lintRuleSourcesWithAi");
|
|
37
|
+
Object.defineProperty(exports, "lintRuleSourcesWithAi", { enumerable: true, get: function () { return lintRuleSourcesWithAi_1.lintRuleSourcesWithAi; } });
|
|
36
38
|
var formatFindings_1 = require("./doctor/formatFindings");
|
|
37
39
|
Object.defineProperty(exports, "formatFindings", { enumerable: true, get: function () { return formatFindings_1.formatFindings; } });
|
|
38
40
|
// Cache
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hiro-c/agent-gate",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Runtime rule enforcer for AI coding agents. Reads CLAUDE.md / AGENTS.md / .cursorrules and enforces them via Claude Code and Cursor hooks, with a deterministic safety baseline.",
|
|
5
5
|
"author": "Hiro-Chiba",
|
|
6
6
|
"license": "MIT",
|