@codemcp/ade 0.2.5 → 0.3.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/.agentskills/skills/conventional-commits/SKILL.md +36 -0
- package/.beads/issues.jsonl +6 -0
- package/.beads/last-touched +1 -1
- package/.kiro/agents/ade.json +9 -2
- package/.opencode/agents/ade.md +9 -18
- package/.vibe/beads-state-ade-fix-no-git-k396xs.json +34 -0
- package/.vibe/development-plan-fix-no-git.md +76 -0
- package/AGENTS.md +27 -0
- package/config.lock.yaml +33 -9
- package/config.yaml +3 -0
- package/package.json +1 -1
- package/packages/cli/dist/index.js +404 -343
- package/packages/cli/package.json +1 -1
- package/packages/cli/src/commands/conventions.integration.spec.ts +7 -1
- package/packages/cli/src/commands/install.ts +19 -1
- package/packages/cli/src/commands/setup.ts +19 -1
- package/packages/core/package.json +1 -1
- package/packages/core/src/catalog/catalog.spec.ts +1 -10
- package/packages/core/src/catalog/facets/autonomy.ts +4 -62
- package/packages/core/src/index.ts +1 -4
- package/packages/core/src/resolver.spec.ts +4 -22
- package/packages/core/src/resolver.ts +1 -5
- package/packages/core/src/types.ts +0 -20
- package/packages/harnesses/package.json +2 -1
- package/packages/harnesses/src/permission-policy.ts +1 -165
- package/packages/harnesses/src/util.spec.ts +97 -0
- package/packages/harnesses/src/util.ts +32 -4
- package/packages/harnesses/src/writers/claude-code.spec.ts +14 -46
- package/packages/harnesses/src/writers/claude-code.ts +33 -16
- package/packages/harnesses/src/writers/cline.spec.ts +1 -41
- package/packages/harnesses/src/writers/copilot.spec.ts +2 -42
- package/packages/harnesses/src/writers/copilot.ts +19 -32
- package/packages/harnesses/src/writers/cursor.spec.ts +1 -41
- package/packages/harnesses/src/writers/cursor.ts +28 -40
- package/packages/harnesses/src/writers/kiro.spec.ts +1 -41
- package/packages/harnesses/src/writers/kiro.ts +23 -24
- package/packages/harnesses/src/writers/opencode.spec.ts +5 -47
- package/packages/harnesses/src/writers/opencode.ts +153 -10
- package/packages/harnesses/src/writers/roo-code.spec.ts +2 -42
- package/packages/harnesses/src/writers/roo-code.ts +25 -10
- package/packages/harnesses/src/writers/universal.spec.ts +1 -41
- package/packages/harnesses/src/writers/universal.ts +45 -31
- package/packages/harnesses/src/writers/windsurf.spec.ts +5 -42
- package/packages/harnesses/src/writers/windsurf.ts +30 -47
- package/skills-lock.json +6 -1
|
@@ -11,47 +11,7 @@ import { claudeCodeWriter } from "./claude-code.js";
|
|
|
11
11
|
import { writeInlineSkills } from "../util.js";
|
|
12
12
|
|
|
13
13
|
function autonomyPolicy(profile: AutonomyProfile): PermissionPolicy {
|
|
14
|
-
|
|
15
|
-
case "rigid":
|
|
16
|
-
return {
|
|
17
|
-
profile,
|
|
18
|
-
capabilities: {
|
|
19
|
-
read: "ask",
|
|
20
|
-
edit_write: "ask",
|
|
21
|
-
search_list: "ask",
|
|
22
|
-
bash_safe: "ask",
|
|
23
|
-
bash_unsafe: "ask",
|
|
24
|
-
web: "ask",
|
|
25
|
-
task_agent: "ask"
|
|
26
|
-
}
|
|
27
|
-
};
|
|
28
|
-
case "sensible-defaults":
|
|
29
|
-
return {
|
|
30
|
-
profile,
|
|
31
|
-
capabilities: {
|
|
32
|
-
read: "allow",
|
|
33
|
-
edit_write: "allow",
|
|
34
|
-
search_list: "allow",
|
|
35
|
-
bash_safe: "allow",
|
|
36
|
-
bash_unsafe: "ask",
|
|
37
|
-
web: "ask",
|
|
38
|
-
task_agent: "allow"
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
case "max-autonomy":
|
|
42
|
-
return {
|
|
43
|
-
profile,
|
|
44
|
-
capabilities: {
|
|
45
|
-
read: "allow",
|
|
46
|
-
edit_write: "allow",
|
|
47
|
-
search_list: "allow",
|
|
48
|
-
bash_safe: "allow",
|
|
49
|
-
bash_unsafe: "allow",
|
|
50
|
-
web: "ask",
|
|
51
|
-
task_agent: "allow"
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
}
|
|
14
|
+
return { profile };
|
|
55
15
|
}
|
|
56
16
|
|
|
57
17
|
describe("claudeCodeWriter", () => {
|
|
@@ -160,7 +120,7 @@ describe("claudeCodeWriter", () => {
|
|
|
160
120
|
);
|
|
161
121
|
});
|
|
162
122
|
|
|
163
|
-
it("
|
|
123
|
+
it("forwards wildcard MCP permission rules for servers without explicit allowedTools", async () => {
|
|
164
124
|
const config: LogicalConfig = {
|
|
165
125
|
mcp_servers: [
|
|
166
126
|
{
|
|
@@ -182,10 +142,10 @@ describe("claudeCodeWriter", () => {
|
|
|
182
142
|
|
|
183
143
|
const raw = await readFile(join(dir, ".claude", "settings.json"), "utf-8");
|
|
184
144
|
const settings = JSON.parse(raw);
|
|
185
|
-
expect(settings.permissions.allow
|
|
145
|
+
expect(settings.permissions.allow).toContain("mcp__workflows__*");
|
|
186
146
|
});
|
|
187
147
|
|
|
188
|
-
it("
|
|
148
|
+
it("allows only Read for rigid autonomy while asking for everything else", async () => {
|
|
189
149
|
const config: LogicalConfig = {
|
|
190
150
|
mcp_servers: [],
|
|
191
151
|
instructions: [],
|
|
@@ -201,9 +161,17 @@ describe("claudeCodeWriter", () => {
|
|
|
201
161
|
|
|
202
162
|
const raw = await readFile(join(dir, ".claude", "settings.json"), "utf-8");
|
|
203
163
|
const settings = JSON.parse(raw);
|
|
204
|
-
expect(settings.permissions.allow
|
|
164
|
+
expect(settings.permissions.allow).toEqual(["Read"]);
|
|
205
165
|
expect(settings.permissions.ask).toEqual(
|
|
206
|
-
expect.arrayContaining([
|
|
166
|
+
expect.arrayContaining([
|
|
167
|
+
"Edit",
|
|
168
|
+
"Glob",
|
|
169
|
+
"Grep",
|
|
170
|
+
"Bash",
|
|
171
|
+
"WebFetch",
|
|
172
|
+
"WebSearch",
|
|
173
|
+
"TodoWrite"
|
|
174
|
+
])
|
|
207
175
|
);
|
|
208
176
|
});
|
|
209
177
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
|
-
import type { LogicalConfig } from "@codemcp/ade-core";
|
|
2
|
+
import type { AutonomyProfile, LogicalConfig } from "@codemcp/ade-core";
|
|
3
3
|
import type { HarnessWriter } from "../types.js";
|
|
4
4
|
import {
|
|
5
5
|
readJsonOrEmpty,
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
writeAgentMd,
|
|
9
9
|
writeGitHooks
|
|
10
10
|
} from "../util.js";
|
|
11
|
-
import {
|
|
11
|
+
import { getAutonomyProfile } from "../permission-policy.js";
|
|
12
12
|
|
|
13
13
|
export const claudeCodeWriter: HarnessWriter = {
|
|
14
14
|
id: "claude-code",
|
|
@@ -40,7 +40,7 @@ async function writeClaudeSettings(
|
|
|
40
40
|
const existingAllow = asStringArray(existingPerms.allow);
|
|
41
41
|
const existingAsk = asStringArray(existingPerms.ask);
|
|
42
42
|
|
|
43
|
-
const autonomyRules = getClaudeAutonomyRules(config);
|
|
43
|
+
const autonomyRules = getClaudeAutonomyRules(getAutonomyProfile(config));
|
|
44
44
|
const mcpRules = getClaudeMcpAllowRules(config);
|
|
45
45
|
const allowRules = [
|
|
46
46
|
...new Set([...existingAllow, ...autonomyRules.allow, ...mcpRules])
|
|
@@ -77,6 +77,7 @@ function getClaudeMcpAllowRules(config: LogicalConfig): string[] {
|
|
|
77
77
|
for (const server of config.mcp_servers) {
|
|
78
78
|
const allowedTools = server.allowedTools;
|
|
79
79
|
if (!allowedTools || allowedTools.includes("*")) {
|
|
80
|
+
allowRules.push(`mcp__${server.ref}__*`);
|
|
80
81
|
continue;
|
|
81
82
|
}
|
|
82
83
|
|
|
@@ -88,20 +89,36 @@ function getClaudeMcpAllowRules(config: LogicalConfig): string[] {
|
|
|
88
89
|
return allowRules;
|
|
89
90
|
}
|
|
90
91
|
|
|
91
|
-
function getClaudeAutonomyRules(
|
|
92
|
+
function getClaudeAutonomyRules(profile: AutonomyProfile | undefined): {
|
|
92
93
|
allow: string[];
|
|
93
94
|
ask: string[];
|
|
94
95
|
} {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
96
|
+
switch (profile) {
|
|
97
|
+
case "rigid":
|
|
98
|
+
return {
|
|
99
|
+
allow: ["Read"],
|
|
100
|
+
ask: [
|
|
101
|
+
"Edit",
|
|
102
|
+
"Write",
|
|
103
|
+
"Glob",
|
|
104
|
+
"Grep",
|
|
105
|
+
"Bash",
|
|
106
|
+
"WebFetch",
|
|
107
|
+
"WebSearch",
|
|
108
|
+
"TodoWrite"
|
|
109
|
+
]
|
|
110
|
+
};
|
|
111
|
+
case "sensible-defaults":
|
|
112
|
+
return {
|
|
113
|
+
allow: ["Read", "Edit", "Write", "Glob", "Grep", "TodoWrite"],
|
|
114
|
+
ask: ["WebFetch", "WebSearch"]
|
|
115
|
+
};
|
|
116
|
+
case "max-autonomy":
|
|
117
|
+
return {
|
|
118
|
+
allow: ["Read", "Edit", "Write", "Glob", "Grep", "Bash", "TodoWrite"],
|
|
119
|
+
ask: ["WebFetch", "WebSearch"]
|
|
120
|
+
};
|
|
121
|
+
default:
|
|
122
|
+
return { allow: [], ask: [] };
|
|
123
|
+
}
|
|
107
124
|
}
|
|
@@ -10,47 +10,7 @@ import type {
|
|
|
10
10
|
import { clineWriter } from "./cline.js";
|
|
11
11
|
|
|
12
12
|
function autonomyPolicy(profile: AutonomyProfile): PermissionPolicy {
|
|
13
|
-
|
|
14
|
-
case "rigid":
|
|
15
|
-
return {
|
|
16
|
-
profile,
|
|
17
|
-
capabilities: {
|
|
18
|
-
read: "ask",
|
|
19
|
-
edit_write: "ask",
|
|
20
|
-
search_list: "ask",
|
|
21
|
-
bash_safe: "ask",
|
|
22
|
-
bash_unsafe: "ask",
|
|
23
|
-
web: "ask",
|
|
24
|
-
task_agent: "ask"
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
case "sensible-defaults":
|
|
28
|
-
return {
|
|
29
|
-
profile,
|
|
30
|
-
capabilities: {
|
|
31
|
-
read: "allow",
|
|
32
|
-
edit_write: "allow",
|
|
33
|
-
search_list: "allow",
|
|
34
|
-
bash_safe: "allow",
|
|
35
|
-
bash_unsafe: "ask",
|
|
36
|
-
web: "ask",
|
|
37
|
-
task_agent: "allow"
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
case "max-autonomy":
|
|
41
|
-
return {
|
|
42
|
-
profile,
|
|
43
|
-
capabilities: {
|
|
44
|
-
read: "allow",
|
|
45
|
-
edit_write: "allow",
|
|
46
|
-
search_list: "allow",
|
|
47
|
-
bash_safe: "allow",
|
|
48
|
-
bash_unsafe: "allow",
|
|
49
|
-
web: "ask",
|
|
50
|
-
task_agent: "allow"
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
}
|
|
13
|
+
return { profile };
|
|
54
14
|
}
|
|
55
15
|
|
|
56
16
|
describe("clineWriter", () => {
|
|
@@ -10,47 +10,7 @@ import type {
|
|
|
10
10
|
import { copilotWriter } from "./copilot.js";
|
|
11
11
|
|
|
12
12
|
function autonomyPolicy(profile: AutonomyProfile): PermissionPolicy {
|
|
13
|
-
|
|
14
|
-
case "rigid":
|
|
15
|
-
return {
|
|
16
|
-
profile,
|
|
17
|
-
capabilities: {
|
|
18
|
-
read: "ask",
|
|
19
|
-
edit_write: "ask",
|
|
20
|
-
search_list: "ask",
|
|
21
|
-
bash_safe: "ask",
|
|
22
|
-
bash_unsafe: "ask",
|
|
23
|
-
web: "ask",
|
|
24
|
-
task_agent: "ask"
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
case "sensible-defaults":
|
|
28
|
-
return {
|
|
29
|
-
profile,
|
|
30
|
-
capabilities: {
|
|
31
|
-
read: "allow",
|
|
32
|
-
edit_write: "allow",
|
|
33
|
-
search_list: "allow",
|
|
34
|
-
bash_safe: "allow",
|
|
35
|
-
bash_unsafe: "ask",
|
|
36
|
-
web: "ask",
|
|
37
|
-
task_agent: "allow"
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
case "max-autonomy":
|
|
41
|
-
return {
|
|
42
|
-
profile,
|
|
43
|
-
capabilities: {
|
|
44
|
-
read: "allow",
|
|
45
|
-
edit_write: "allow",
|
|
46
|
-
search_list: "allow",
|
|
47
|
-
bash_safe: "allow",
|
|
48
|
-
bash_unsafe: "allow",
|
|
49
|
-
web: "ask",
|
|
50
|
-
task_agent: "allow"
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
}
|
|
13
|
+
return { profile };
|
|
54
14
|
}
|
|
55
15
|
|
|
56
16
|
describe("copilotWriter", () => {
|
|
@@ -224,7 +184,7 @@ describe("copilotWriter", () => {
|
|
|
224
184
|
|
|
225
185
|
expect(rigidAgent).not.toContain(" - server/workflows/*");
|
|
226
186
|
expect(rigidAgent).toContain(" - workflows/*");
|
|
227
|
-
expect(rigidAgent).
|
|
187
|
+
expect(rigidAgent).toContain(" - read");
|
|
228
188
|
expect(rigidAgent).not.toContain(" - edit");
|
|
229
189
|
expect(rigidAgent).not.toContain(" - search");
|
|
230
190
|
expect(rigidAgent).not.toContain(" - execute");
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
AutonomyProfile,
|
|
4
|
+
LogicalConfig,
|
|
5
|
+
McpServerEntry
|
|
6
|
+
} from "@codemcp/ade-core";
|
|
3
7
|
import type { HarnessWriter } from "../types.js";
|
|
4
8
|
import {
|
|
5
9
|
writeMcpServers,
|
|
6
10
|
stdioEntry,
|
|
7
11
|
writeAgentMd,
|
|
8
|
-
writeGitHooks
|
|
12
|
+
writeGitHooks,
|
|
13
|
+
formatYamlKey
|
|
9
14
|
} from "../util.js";
|
|
10
|
-
import {
|
|
11
|
-
allowsCapability,
|
|
12
|
-
hasPermissionPolicy,
|
|
13
|
-
keepsWebOnAsk
|
|
14
|
-
} from "../permission-policy.js";
|
|
15
|
+
import { getAutonomyProfile } from "../permission-policy.js";
|
|
15
16
|
|
|
16
17
|
export const copilotWriter: HarnessWriter = {
|
|
17
18
|
id: "copilot",
|
|
@@ -25,7 +26,7 @@ export const copilotWriter: HarnessWriter = {
|
|
|
25
26
|
});
|
|
26
27
|
|
|
27
28
|
const tools = [
|
|
28
|
-
...getBuiltInTools(config),
|
|
29
|
+
...getBuiltInTools(getAutonomyProfile(config)),
|
|
29
30
|
...getForwardedMcpTools(config.mcp_servers)
|
|
30
31
|
];
|
|
31
32
|
|
|
@@ -41,25 +42,17 @@ export const copilotWriter: HarnessWriter = {
|
|
|
41
42
|
}
|
|
42
43
|
};
|
|
43
44
|
|
|
44
|
-
function getBuiltInTools(
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
function getBuiltInTools(profile: AutonomyProfile | undefined): string[] {
|
|
46
|
+
switch (profile) {
|
|
47
|
+
case "rigid":
|
|
48
|
+
return ["read"];
|
|
49
|
+
case "sensible-defaults":
|
|
50
|
+
return ["read", "edit", "search", "agent"];
|
|
51
|
+
case "max-autonomy":
|
|
52
|
+
return ["read", "edit", "search", "execute", "agent", "todo"];
|
|
53
|
+
default:
|
|
54
|
+
return ["read", "edit", "search", "execute", "agent", "web"];
|
|
47
55
|
}
|
|
48
|
-
|
|
49
|
-
return [
|
|
50
|
-
...(allowsCapability(config, "read") ? ["read"] : []),
|
|
51
|
-
...(allowsCapability(config, "edit_write") ? ["edit"] : []),
|
|
52
|
-
...(allowsCapability(config, "search_list") ? ["search"] : []),
|
|
53
|
-
...(allowsCapability(config, "bash_unsafe") ? ["execute"] : []),
|
|
54
|
-
...(allowsCapability(config, "task_agent") ? ["agent"] : []),
|
|
55
|
-
...(allowsCapability(config, "task_agent") &&
|
|
56
|
-
allowsCapability(config, "bash_unsafe")
|
|
57
|
-
? ["todo"]
|
|
58
|
-
: []),
|
|
59
|
-
...(!keepsWebOnAsk(config) && allowsCapability(config, "web")
|
|
60
|
-
? ["web"]
|
|
61
|
-
: [])
|
|
62
|
-
];
|
|
63
56
|
}
|
|
64
57
|
|
|
65
58
|
function getForwardedMcpTools(servers: McpServerEntry[]): string[] {
|
|
@@ -97,9 +90,3 @@ function renderCopilotAgentMcpServers(servers: McpServerEntry[]): string[] {
|
|
|
97
90
|
|
|
98
91
|
return lines;
|
|
99
92
|
}
|
|
100
|
-
|
|
101
|
-
function formatYamlKey(value: string): string {
|
|
102
|
-
return /^[A-Za-z_][A-Za-z0-9_-]*$/.test(value)
|
|
103
|
-
? value
|
|
104
|
-
: JSON.stringify(value);
|
|
105
|
-
}
|
|
@@ -10,47 +10,7 @@ import type {
|
|
|
10
10
|
import { cursorWriter } from "./cursor.js";
|
|
11
11
|
|
|
12
12
|
function autonomyPolicy(profile: AutonomyProfile): PermissionPolicy {
|
|
13
|
-
|
|
14
|
-
case "rigid":
|
|
15
|
-
return {
|
|
16
|
-
profile,
|
|
17
|
-
capabilities: {
|
|
18
|
-
read: "ask",
|
|
19
|
-
edit_write: "ask",
|
|
20
|
-
search_list: "ask",
|
|
21
|
-
bash_safe: "ask",
|
|
22
|
-
bash_unsafe: "ask",
|
|
23
|
-
web: "ask",
|
|
24
|
-
task_agent: "ask"
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
case "sensible-defaults":
|
|
28
|
-
return {
|
|
29
|
-
profile,
|
|
30
|
-
capabilities: {
|
|
31
|
-
read: "allow",
|
|
32
|
-
edit_write: "allow",
|
|
33
|
-
search_list: "allow",
|
|
34
|
-
bash_safe: "allow",
|
|
35
|
-
bash_unsafe: "ask",
|
|
36
|
-
web: "ask",
|
|
37
|
-
task_agent: "allow"
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
case "max-autonomy":
|
|
41
|
-
return {
|
|
42
|
-
profile,
|
|
43
|
-
capabilities: {
|
|
44
|
-
read: "allow",
|
|
45
|
-
edit_write: "allow",
|
|
46
|
-
search_list: "allow",
|
|
47
|
-
bash_safe: "allow",
|
|
48
|
-
bash_unsafe: "allow",
|
|
49
|
-
web: "ask",
|
|
50
|
-
task_agent: "allow"
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
}
|
|
13
|
+
return { profile };
|
|
54
14
|
}
|
|
55
15
|
|
|
56
16
|
describe("cursorWriter", () => {
|
|
@@ -1,34 +1,13 @@
|
|
|
1
1
|
import { mkdir, writeFile } from "node:fs/promises";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
-
import type {
|
|
3
|
+
import type { AutonomyProfile, LogicalConfig } from "@codemcp/ade-core";
|
|
4
4
|
import type { HarnessWriter } from "../types.js";
|
|
5
5
|
import { writeMcpServers, writeGitHooks } from "../util.js";
|
|
6
6
|
import {
|
|
7
7
|
getAutonomyProfile,
|
|
8
|
-
getCapabilityDecision,
|
|
9
8
|
hasPermissionPolicy
|
|
10
9
|
} from "../permission-policy.js";
|
|
11
10
|
|
|
12
|
-
const CURSOR_CAPABILITY_ORDER: AutonomyCapability[] = [
|
|
13
|
-
"read",
|
|
14
|
-
"edit_write",
|
|
15
|
-
"search_list",
|
|
16
|
-
"bash_safe",
|
|
17
|
-
"bash_unsafe",
|
|
18
|
-
"web",
|
|
19
|
-
"task_agent"
|
|
20
|
-
];
|
|
21
|
-
|
|
22
|
-
const CURSOR_CAPABILITY_LABELS: Record<AutonomyCapability, string> = {
|
|
23
|
-
read: "read project files",
|
|
24
|
-
edit_write: "edit and write project files",
|
|
25
|
-
search_list: "search and list project contents",
|
|
26
|
-
bash_safe: "run safe local shell commands",
|
|
27
|
-
bash_unsafe: "run high-impact shell commands",
|
|
28
|
-
web: "use web or network access",
|
|
29
|
-
task_agent: "delegate or decompose work into agent tasks"
|
|
30
|
-
};
|
|
31
|
-
|
|
32
11
|
export const cursorWriter: HarnessWriter = {
|
|
33
12
|
id: "cursor",
|
|
34
13
|
label: "Cursor",
|
|
@@ -68,28 +47,37 @@ function getCursorAutonomyNotes(config: LogicalConfig): string[] {
|
|
|
68
47
|
return [];
|
|
69
48
|
}
|
|
70
49
|
|
|
71
|
-
const
|
|
72
|
-
(capability) => getCapabilityDecision(config, capability) === "allow"
|
|
73
|
-
).map((capability) => CURSOR_CAPABILITY_LABELS[capability]);
|
|
74
|
-
|
|
75
|
-
const approvalGatedCapabilities = CURSOR_CAPABILITY_ORDER.filter(
|
|
76
|
-
(capability) => getCapabilityDecision(config, capability) === "ask"
|
|
77
|
-
).map((capability) => CURSOR_CAPABILITY_LABELS[capability]);
|
|
50
|
+
const profile = getAutonomyProfile(config);
|
|
78
51
|
|
|
79
52
|
return [
|
|
80
|
-
`Cursor autonomy note (documented, not enforced): ${
|
|
53
|
+
`Cursor autonomy note (documented, not enforced): ${profile ?? "custom"}.`,
|
|
81
54
|
"Cursor has no verified committed project-local built-in ask/allow/deny config surface, so ADE documents autonomy intent here instead of writing unsupported permission config.",
|
|
82
|
-
...(
|
|
83
|
-
? [
|
|
84
|
-
`Prefer handling these built-in capabilities without extra approval when Cursor permits it: ${allowedCapabilities.join(", ")}.`
|
|
85
|
-
]
|
|
86
|
-
: []),
|
|
87
|
-
...(approvalGatedCapabilities.length > 0
|
|
88
|
-
? [
|
|
89
|
-
`Request approval before these capabilities: ${approvalGatedCapabilities.join(", ")}.`
|
|
90
|
-
]
|
|
91
|
-
: []),
|
|
55
|
+
...getCursorProfileGuidance(profile),
|
|
92
56
|
"Web and network access must remain approval-gated.",
|
|
93
57
|
"MCP server registration stays in .cursor/mcp.json; MCP tool approvals remain owned by provisioning and are not enforced or re-modeled in this rules file."
|
|
94
58
|
];
|
|
95
59
|
}
|
|
60
|
+
|
|
61
|
+
function getCursorProfileGuidance(
|
|
62
|
+
profile: AutonomyProfile | undefined
|
|
63
|
+
): string[] {
|
|
64
|
+
switch (profile) {
|
|
65
|
+
case "rigid":
|
|
66
|
+
return [
|
|
67
|
+
"Prefer handling these built-in capabilities without extra approval when Cursor permits it: read project files.",
|
|
68
|
+
"Request approval before these capabilities: edit and write project files, search and list project contents, run safe local shell commands, run high-impact shell commands, use web or network access, delegate or decompose work into agent tasks."
|
|
69
|
+
];
|
|
70
|
+
case "sensible-defaults":
|
|
71
|
+
return [
|
|
72
|
+
"Prefer handling these built-in capabilities without extra approval when Cursor permits it: read project files, edit and write project files, search and list project contents, run safe local shell commands, delegate or decompose work into agent tasks.",
|
|
73
|
+
"Request approval before these capabilities: run high-impact shell commands, use web or network access."
|
|
74
|
+
];
|
|
75
|
+
case "max-autonomy":
|
|
76
|
+
return [
|
|
77
|
+
"Prefer handling these built-in capabilities without extra approval when Cursor permits it: read project files, edit and write project files, search and list project contents, run safe local shell commands, run high-impact shell commands, delegate or decompose work into agent tasks.",
|
|
78
|
+
"Request approval before these capabilities: use web or network access."
|
|
79
|
+
];
|
|
80
|
+
default:
|
|
81
|
+
return [];
|
|
82
|
+
}
|
|
83
|
+
}
|
|
@@ -10,47 +10,7 @@ import type {
|
|
|
10
10
|
import { kiroWriter } from "./kiro.js";
|
|
11
11
|
|
|
12
12
|
function autonomyPolicy(profile: AutonomyProfile): PermissionPolicy {
|
|
13
|
-
|
|
14
|
-
case "rigid":
|
|
15
|
-
return {
|
|
16
|
-
profile,
|
|
17
|
-
capabilities: {
|
|
18
|
-
read: "ask",
|
|
19
|
-
edit_write: "ask",
|
|
20
|
-
search_list: "ask",
|
|
21
|
-
bash_safe: "ask",
|
|
22
|
-
bash_unsafe: "ask",
|
|
23
|
-
web: "ask",
|
|
24
|
-
task_agent: "ask"
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
case "sensible-defaults":
|
|
28
|
-
return {
|
|
29
|
-
profile,
|
|
30
|
-
capabilities: {
|
|
31
|
-
read: "allow",
|
|
32
|
-
edit_write: "allow",
|
|
33
|
-
search_list: "allow",
|
|
34
|
-
bash_safe: "allow",
|
|
35
|
-
bash_unsafe: "ask",
|
|
36
|
-
web: "ask",
|
|
37
|
-
task_agent: "allow"
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
case "max-autonomy":
|
|
41
|
-
return {
|
|
42
|
-
profile,
|
|
43
|
-
capabilities: {
|
|
44
|
-
read: "allow",
|
|
45
|
-
edit_write: "allow",
|
|
46
|
-
search_list: "allow",
|
|
47
|
-
bash_safe: "allow",
|
|
48
|
-
bash_unsafe: "allow",
|
|
49
|
-
web: "ask",
|
|
50
|
-
task_agent: "allow"
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
}
|
|
13
|
+
return { profile };
|
|
54
14
|
}
|
|
55
15
|
|
|
56
16
|
describe("kiroWriter", () => {
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
AutonomyProfile,
|
|
4
|
+
LogicalConfig,
|
|
5
|
+
McpServerEntry
|
|
6
|
+
} from "@codemcp/ade-core";
|
|
3
7
|
import type { HarnessWriter } from "../types.js";
|
|
4
8
|
import {
|
|
5
9
|
standardEntry,
|
|
@@ -7,11 +11,7 @@ import {
|
|
|
7
11
|
writeJson,
|
|
8
12
|
writeMcpServers
|
|
9
13
|
} from "../util.js";
|
|
10
|
-
import {
|
|
11
|
-
allowsCapability,
|
|
12
|
-
getCapabilityDecision,
|
|
13
|
-
hasPermissionPolicy
|
|
14
|
-
} from "../permission-policy.js";
|
|
14
|
+
import { getAutonomyProfile } from "../permission-policy.js";
|
|
15
15
|
|
|
16
16
|
export const kiroWriter: HarnessWriter = {
|
|
17
17
|
id: "kiro",
|
|
@@ -26,6 +26,7 @@ export const kiroWriter: HarnessWriter = {
|
|
|
26
26
|
})
|
|
27
27
|
});
|
|
28
28
|
|
|
29
|
+
const tools = getKiroTools(getAutonomyProfile(config), config.mcp_servers);
|
|
29
30
|
await writeJson(join(projectRoot, ".kiro", "agents", "ade.json"), {
|
|
30
31
|
name: "ade",
|
|
31
32
|
description:
|
|
@@ -34,8 +35,8 @@ export const kiroWriter: HarnessWriter = {
|
|
|
34
35
|
config.instructions.join("\n\n") ||
|
|
35
36
|
"ADE — Agentic Development Environment agent.",
|
|
36
37
|
mcpServers: getKiroAgentMcpServers(config.mcp_servers),
|
|
37
|
-
tools
|
|
38
|
-
allowedTools:
|
|
38
|
+
tools,
|
|
39
|
+
allowedTools: tools,
|
|
39
40
|
useLegacyMcpJson: true
|
|
40
41
|
});
|
|
41
42
|
|
|
@@ -43,24 +44,22 @@ export const kiroWriter: HarnessWriter = {
|
|
|
43
44
|
}
|
|
44
45
|
};
|
|
45
46
|
|
|
46
|
-
function getKiroTools(
|
|
47
|
-
|
|
47
|
+
function getKiroTools(
|
|
48
|
+
profile: AutonomyProfile | undefined,
|
|
49
|
+
servers: McpServerEntry[]
|
|
50
|
+
): string[] {
|
|
51
|
+
const mcpTools = getKiroForwardedMcpTools(servers);
|
|
48
52
|
|
|
49
|
-
|
|
50
|
-
|
|
53
|
+
switch (profile) {
|
|
54
|
+
case "rigid":
|
|
55
|
+
return ["read", "shell", "spec", ...mcpTools];
|
|
56
|
+
case "sensible-defaults":
|
|
57
|
+
return ["read", "write", "shell", "spec", ...mcpTools];
|
|
58
|
+
case "max-autonomy":
|
|
59
|
+
return ["read", "write", "shell(*)", "spec", ...mcpTools];
|
|
60
|
+
default:
|
|
61
|
+
return ["read", "write", "shell", "spec", ...mcpTools];
|
|
51
62
|
}
|
|
52
|
-
|
|
53
|
-
return [
|
|
54
|
-
...(getCapabilityDecision(config, "read") !== "deny" ? ["read"] : []),
|
|
55
|
-
...(allowsCapability(config, "edit_write") ? ["write"] : []),
|
|
56
|
-
...(allowsCapability(config, "bash_unsafe") ? ["shell(*)"] : ["shell"]),
|
|
57
|
-
"spec",
|
|
58
|
-
...mcpTools
|
|
59
|
-
];
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function getKiroAllowedTools(config: LogicalConfig): string[] {
|
|
63
|
-
return getKiroTools(config);
|
|
64
63
|
}
|
|
65
64
|
|
|
66
65
|
function getKiroForwardedMcpTools(servers: McpServerEntry[]): string[] {
|