@codemcp/ade 0.2.5 → 0.2.6
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/package.json +1 -1
- package/packages/cli/dist/index.js +317 -338
- package/packages/cli/package.json +1 -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 +1 -1
- package/packages/harnesses/src/permission-policy.ts +1 -165
- package/packages/harnesses/src/util.ts +11 -0
- 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 +1 -41
- package/packages/harnesses/src/writers/opencode.ts +157 -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
|
@@ -486,16 +486,7 @@ describe("catalog", () => {
|
|
|
486
486
|
|
|
487
487
|
expect(provision).toBeDefined();
|
|
488
488
|
expect(provision!.config).toEqual({
|
|
489
|
-
profile: "sensible-defaults"
|
|
490
|
-
capabilities: {
|
|
491
|
-
read: "allow",
|
|
492
|
-
edit_write: "allow",
|
|
493
|
-
search_list: "allow",
|
|
494
|
-
bash_safe: "allow",
|
|
495
|
-
bash_unsafe: "ask",
|
|
496
|
-
web: "ask",
|
|
497
|
-
task_agent: "allow"
|
|
498
|
-
}
|
|
489
|
+
profile: "sensible-defaults"
|
|
499
490
|
});
|
|
500
491
|
});
|
|
501
492
|
});
|
|
@@ -1,62 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
AutonomyCapability,
|
|
3
|
-
Facet,
|
|
4
|
-
PermissionDecision,
|
|
5
|
-
PermissionPolicy
|
|
6
|
-
} from "../../types.js";
|
|
7
|
-
|
|
8
|
-
const ALL_CAPABILITIES: AutonomyCapability[] = [
|
|
9
|
-
"read",
|
|
10
|
-
"edit_write",
|
|
11
|
-
"search_list",
|
|
12
|
-
"bash_safe",
|
|
13
|
-
"bash_unsafe",
|
|
14
|
-
"web",
|
|
15
|
-
"task_agent"
|
|
16
|
-
];
|
|
17
|
-
|
|
18
|
-
function capabilityMap(
|
|
19
|
-
defaultDecision: PermissionDecision,
|
|
20
|
-
overrides: Partial<Record<AutonomyCapability, PermissionDecision>> = {}
|
|
21
|
-
): Record<AutonomyCapability, PermissionDecision> {
|
|
22
|
-
return Object.fromEntries(
|
|
23
|
-
ALL_CAPABILITIES.map((capability) => [
|
|
24
|
-
capability,
|
|
25
|
-
overrides[capability] ?? defaultDecision
|
|
26
|
-
])
|
|
27
|
-
) as Record<AutonomyCapability, PermissionDecision>;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function autonomyPolicy(
|
|
31
|
-
profile: PermissionPolicy["profile"]
|
|
32
|
-
): PermissionPolicy {
|
|
33
|
-
switch (profile) {
|
|
34
|
-
case "rigid":
|
|
35
|
-
return {
|
|
36
|
-
profile,
|
|
37
|
-
capabilities: capabilityMap("ask")
|
|
38
|
-
};
|
|
39
|
-
case "sensible-defaults":
|
|
40
|
-
return {
|
|
41
|
-
profile,
|
|
42
|
-
capabilities: capabilityMap("ask", {
|
|
43
|
-
read: "allow",
|
|
44
|
-
edit_write: "allow",
|
|
45
|
-
search_list: "allow",
|
|
46
|
-
bash_safe: "allow",
|
|
47
|
-
task_agent: "allow",
|
|
48
|
-
web: "ask"
|
|
49
|
-
})
|
|
50
|
-
};
|
|
51
|
-
case "max-autonomy":
|
|
52
|
-
return {
|
|
53
|
-
profile,
|
|
54
|
-
capabilities: capabilityMap("allow", {
|
|
55
|
-
web: "ask"
|
|
56
|
-
})
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
}
|
|
1
|
+
import type { Facet } from "../../types.js";
|
|
60
2
|
|
|
61
3
|
export const autonomyFacet: Facet = {
|
|
62
4
|
id: "autonomy",
|
|
@@ -74,7 +16,7 @@ export const autonomyFacet: Facet = {
|
|
|
74
16
|
recipe: [
|
|
75
17
|
{
|
|
76
18
|
writer: "permission-policy",
|
|
77
|
-
config:
|
|
19
|
+
config: { profile: "rigid" }
|
|
78
20
|
}
|
|
79
21
|
]
|
|
80
22
|
},
|
|
@@ -86,7 +28,7 @@ export const autonomyFacet: Facet = {
|
|
|
86
28
|
recipe: [
|
|
87
29
|
{
|
|
88
30
|
writer: "permission-policy",
|
|
89
|
-
config:
|
|
31
|
+
config: { profile: "sensible-defaults" }
|
|
90
32
|
}
|
|
91
33
|
]
|
|
92
34
|
},
|
|
@@ -98,7 +40,7 @@ export const autonomyFacet: Facet = {
|
|
|
98
40
|
recipe: [
|
|
99
41
|
{
|
|
100
42
|
writer: "permission-policy",
|
|
101
|
-
config:
|
|
43
|
+
config: { profile: "max-autonomy" }
|
|
102
44
|
}
|
|
103
45
|
]
|
|
104
46
|
}
|
|
@@ -15,10 +15,7 @@ export {
|
|
|
15
15
|
type ExternalSkill,
|
|
16
16
|
type GitHook,
|
|
17
17
|
type PermissionPolicy,
|
|
18
|
-
type AutonomyProfile
|
|
19
|
-
type AutonomyCapability,
|
|
20
|
-
type PermissionDecision,
|
|
21
|
-
type PermissionRule
|
|
18
|
+
type AutonomyProfile
|
|
22
19
|
} from "./types.js";
|
|
23
20
|
export { type ResolutionContext, type ResolvedFacet } from "./types.js";
|
|
24
21
|
export { type UserConfig, type LockFile } from "./types.js";
|
|
@@ -580,7 +580,7 @@ describe("resolve", () => {
|
|
|
580
580
|
});
|
|
581
581
|
|
|
582
582
|
describe("autonomy permission policy", () => {
|
|
583
|
-
it("adds a
|
|
583
|
+
it("adds a profile-based permission policy to LogicalConfig", async () => {
|
|
584
584
|
const userConfig: UserConfig = {
|
|
585
585
|
choices: { autonomy: "rigid" }
|
|
586
586
|
};
|
|
@@ -589,20 +589,11 @@ describe("resolve", () => {
|
|
|
589
589
|
|
|
590
590
|
expect(result).toHaveProperty("permission_policy");
|
|
591
591
|
expect((result as Record<string, unknown>).permission_policy).toEqual({
|
|
592
|
-
profile: "rigid"
|
|
593
|
-
capabilities: {
|
|
594
|
-
read: "ask",
|
|
595
|
-
edit_write: "ask",
|
|
596
|
-
search_list: "ask",
|
|
597
|
-
bash_safe: "ask",
|
|
598
|
-
bash_unsafe: "ask",
|
|
599
|
-
web: "ask",
|
|
600
|
-
task_agent: "ask"
|
|
601
|
-
}
|
|
592
|
+
profile: "rigid"
|
|
602
593
|
});
|
|
603
594
|
});
|
|
604
595
|
|
|
605
|
-
it("uses
|
|
596
|
+
it("uses the sensible-defaults autonomy profile", async () => {
|
|
606
597
|
const userConfig: UserConfig = {
|
|
607
598
|
choices: { autonomy: "sensible-defaults" }
|
|
608
599
|
};
|
|
@@ -610,16 +601,7 @@ describe("resolve", () => {
|
|
|
610
601
|
const result = await resolve(userConfig, catalog, registry);
|
|
611
602
|
|
|
612
603
|
expect(result.permission_policy).toEqual({
|
|
613
|
-
profile: "sensible-defaults"
|
|
614
|
-
capabilities: {
|
|
615
|
-
read: "allow",
|
|
616
|
-
edit_write: "allow",
|
|
617
|
-
search_list: "allow",
|
|
618
|
-
bash_safe: "allow",
|
|
619
|
-
bash_unsafe: "ask",
|
|
620
|
-
web: "ask",
|
|
621
|
-
task_agent: "allow"
|
|
622
|
-
}
|
|
604
|
+
profile: "sensible-defaults"
|
|
623
605
|
});
|
|
624
606
|
});
|
|
625
607
|
});
|
|
@@ -68,28 +68,8 @@ export interface GitHook {
|
|
|
68
68
|
|
|
69
69
|
export type AutonomyProfile = "rigid" | "sensible-defaults" | "max-autonomy";
|
|
70
70
|
|
|
71
|
-
export type PermissionDecision = "ask" | "allow" | "deny";
|
|
72
|
-
|
|
73
|
-
export type AutonomyCapability =
|
|
74
|
-
| "read"
|
|
75
|
-
| "edit_write"
|
|
76
|
-
| "search_list"
|
|
77
|
-
| "bash_safe"
|
|
78
|
-
| "bash_unsafe"
|
|
79
|
-
| "web"
|
|
80
|
-
| "task_agent";
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* @deprecated Harness-specific tool-level rules are no longer produced by core.
|
|
84
|
-
* Kept temporarily as a compatibility type for downstream packages.
|
|
85
|
-
*/
|
|
86
|
-
export type PermissionRule =
|
|
87
|
-
| PermissionDecision
|
|
88
|
-
| Record<string, PermissionDecision>;
|
|
89
|
-
|
|
90
71
|
export interface PermissionPolicy extends Record<string, unknown> {
|
|
91
72
|
profile: AutonomyProfile;
|
|
92
|
-
capabilities: Record<AutonomyCapability, PermissionDecision>;
|
|
93
73
|
}
|
|
94
74
|
|
|
95
75
|
export interface LogicalConfig extends Record<string, unknown> {
|
|
@@ -1,121 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
AutonomyCapability,
|
|
3
|
-
LogicalConfig,
|
|
4
|
-
PermissionDecision,
|
|
5
|
-
PermissionRule
|
|
6
|
-
} from "@codemcp/ade-core";
|
|
7
|
-
|
|
8
|
-
const SENSIBLE_DEFAULTS_RULES: Record<string, PermissionRule> = {
|
|
9
|
-
read: {
|
|
10
|
-
"*": "allow",
|
|
11
|
-
"*.env": "deny",
|
|
12
|
-
"*.env.*": "deny",
|
|
13
|
-
"*.env.example": "allow"
|
|
14
|
-
},
|
|
15
|
-
edit: "allow",
|
|
16
|
-
glob: "allow",
|
|
17
|
-
grep: "allow",
|
|
18
|
-
list: "allow",
|
|
19
|
-
lsp: "allow",
|
|
20
|
-
task: "allow",
|
|
21
|
-
todoread: "deny",
|
|
22
|
-
todowrite: "deny",
|
|
23
|
-
skill: "deny",
|
|
24
|
-
webfetch: "ask",
|
|
25
|
-
websearch: "ask",
|
|
26
|
-
codesearch: "ask",
|
|
27
|
-
bash: {
|
|
28
|
-
"*": "deny",
|
|
29
|
-
"grep *": "allow",
|
|
30
|
-
"rg *": "allow",
|
|
31
|
-
"find *": "allow",
|
|
32
|
-
"fd *": "allow",
|
|
33
|
-
ls: "allow",
|
|
34
|
-
"ls *": "allow",
|
|
35
|
-
"cat *": "allow",
|
|
36
|
-
"head *": "allow",
|
|
37
|
-
"tail *": "allow",
|
|
38
|
-
"wc *": "allow",
|
|
39
|
-
"sort *": "allow",
|
|
40
|
-
"uniq *": "allow",
|
|
41
|
-
"diff *": "allow",
|
|
42
|
-
"echo *": "allow",
|
|
43
|
-
"printf *": "allow",
|
|
44
|
-
pwd: "allow",
|
|
45
|
-
"which *": "allow",
|
|
46
|
-
"type *": "allow",
|
|
47
|
-
whoami: "allow",
|
|
48
|
-
date: "allow",
|
|
49
|
-
"date *": "allow",
|
|
50
|
-
env: "allow",
|
|
51
|
-
"tree *": "allow",
|
|
52
|
-
"file *": "allow",
|
|
53
|
-
"stat *": "allow",
|
|
54
|
-
"readlink *": "allow",
|
|
55
|
-
"realpath *": "allow",
|
|
56
|
-
"dirname *": "allow",
|
|
57
|
-
"basename *": "allow",
|
|
58
|
-
"sed *": "allow",
|
|
59
|
-
"awk *": "allow",
|
|
60
|
-
"cut *": "allow",
|
|
61
|
-
"tr *": "allow",
|
|
62
|
-
"tee *": "allow",
|
|
63
|
-
"xargs *": "allow",
|
|
64
|
-
"jq *": "allow",
|
|
65
|
-
"yq *": "allow",
|
|
66
|
-
"mkdir *": "allow",
|
|
67
|
-
"touch *": "allow",
|
|
68
|
-
"cp *": "ask",
|
|
69
|
-
"mv *": "ask",
|
|
70
|
-
"ln *": "ask",
|
|
71
|
-
"npm *": "ask",
|
|
72
|
-
"node *": "ask",
|
|
73
|
-
"pip *": "ask",
|
|
74
|
-
"python *": "ask",
|
|
75
|
-
"python3 *": "ask",
|
|
76
|
-
"rm *": "deny",
|
|
77
|
-
"rmdir *": "deny",
|
|
78
|
-
"curl *": "deny",
|
|
79
|
-
"wget *": "deny",
|
|
80
|
-
"chmod *": "deny",
|
|
81
|
-
"chown *": "deny",
|
|
82
|
-
"sudo *": "deny",
|
|
83
|
-
"su *": "deny",
|
|
84
|
-
"sh *": "deny",
|
|
85
|
-
"bash *": "deny",
|
|
86
|
-
"zsh *": "deny",
|
|
87
|
-
"eval *": "deny",
|
|
88
|
-
"exec *": "deny",
|
|
89
|
-
"source *": "deny",
|
|
90
|
-
". *": "deny",
|
|
91
|
-
"nohup *": "deny",
|
|
92
|
-
"dd *": "deny",
|
|
93
|
-
"mkfs *": "deny",
|
|
94
|
-
"mount *": "deny",
|
|
95
|
-
"umount *": "deny",
|
|
96
|
-
"kill *": "deny",
|
|
97
|
-
"killall *": "deny",
|
|
98
|
-
"pkill *": "deny",
|
|
99
|
-
"nc *": "deny",
|
|
100
|
-
"ncat *": "deny",
|
|
101
|
-
"ssh *": "deny",
|
|
102
|
-
"scp *": "deny",
|
|
103
|
-
"rsync *": "deny",
|
|
104
|
-
"docker *": "deny",
|
|
105
|
-
"kubectl *": "deny",
|
|
106
|
-
"systemctl *": "deny",
|
|
107
|
-
"service *": "deny",
|
|
108
|
-
"crontab *": "deny",
|
|
109
|
-
reboot: "deny",
|
|
110
|
-
"shutdown *": "deny",
|
|
111
|
-
"passwd *": "deny",
|
|
112
|
-
"useradd *": "deny",
|
|
113
|
-
"userdel *": "deny",
|
|
114
|
-
"iptables *": "deny"
|
|
115
|
-
},
|
|
116
|
-
external_directory: "deny",
|
|
117
|
-
doom_loop: "deny"
|
|
118
|
-
};
|
|
1
|
+
import type { LogicalConfig } from "@codemcp/ade-core";
|
|
119
2
|
|
|
120
3
|
export function getAutonomyProfile(config: LogicalConfig) {
|
|
121
4
|
return config.permission_policy?.profile;
|
|
@@ -124,50 +7,3 @@ export function getAutonomyProfile(config: LogicalConfig) {
|
|
|
124
7
|
export function hasPermissionPolicy(config: LogicalConfig): boolean {
|
|
125
8
|
return config.permission_policy !== undefined;
|
|
126
9
|
}
|
|
127
|
-
|
|
128
|
-
export function getCapabilityDecision(
|
|
129
|
-
config: LogicalConfig,
|
|
130
|
-
capability: AutonomyCapability
|
|
131
|
-
): PermissionDecision | undefined {
|
|
132
|
-
return config.permission_policy?.capabilities?.[capability];
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
export function allowsCapability(
|
|
136
|
-
config: LogicalConfig,
|
|
137
|
-
capability: AutonomyCapability
|
|
138
|
-
): boolean {
|
|
139
|
-
return getCapabilityDecision(config, capability) === "allow";
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
export function keepsWebOnAsk(config: LogicalConfig): boolean {
|
|
143
|
-
return getCapabilityDecision(config, "web") === "ask";
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
export function getHarnessPermissionRules(
|
|
147
|
-
config: LogicalConfig
|
|
148
|
-
): Record<string, PermissionRule> | undefined {
|
|
149
|
-
switch (config.permission_policy?.profile) {
|
|
150
|
-
case "rigid":
|
|
151
|
-
return {
|
|
152
|
-
"*": "ask",
|
|
153
|
-
webfetch: "ask",
|
|
154
|
-
websearch: "ask",
|
|
155
|
-
codesearch: "ask",
|
|
156
|
-
external_directory: "deny",
|
|
157
|
-
doom_loop: "deny"
|
|
158
|
-
};
|
|
159
|
-
case "sensible-defaults":
|
|
160
|
-
return SENSIBLE_DEFAULTS_RULES;
|
|
161
|
-
case "max-autonomy":
|
|
162
|
-
return {
|
|
163
|
-
"*": "allow",
|
|
164
|
-
webfetch: "ask",
|
|
165
|
-
websearch: "ask",
|
|
166
|
-
codesearch: "ask",
|
|
167
|
-
external_directory: "deny",
|
|
168
|
-
doom_loop: "deny"
|
|
169
|
-
};
|
|
170
|
-
default:
|
|
171
|
-
return undefined;
|
|
172
|
-
}
|
|
173
|
-
}
|
|
@@ -219,3 +219,14 @@ export async function writeInlineSkills(
|
|
|
219
219
|
|
|
220
220
|
return modified;
|
|
221
221
|
}
|
|
222
|
+
|
|
223
|
+
// ---------------------------------------------------------------------------
|
|
224
|
+
// YAML helpers
|
|
225
|
+
// ---------------------------------------------------------------------------
|
|
226
|
+
|
|
227
|
+
/** Quote a YAML key only when it contains characters that require quoting. */
|
|
228
|
+
export function formatYamlKey(value: string): string {
|
|
229
|
+
return /^[A-Za-z_][A-Za-z0-9_-]*$/.test(value)
|
|
230
|
+
? value
|
|
231
|
+
: JSON.stringify(value);
|
|
232
|
+
}
|
|
@@ -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", () => {
|