@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 { parse as parseYaml } from "yaml";
|
|
|
11
11
|
import { opencodeWriter } from "./opencode.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("opencodeWriter", () => {
|
|
@@ -142,17 +102,16 @@ describe("opencodeWriter", () => {
|
|
|
142
102
|
expect(defaultsAgent).toContain('grep: "allow"');
|
|
143
103
|
expect(defaultsAgent).toContain('list: "allow"');
|
|
144
104
|
expect(defaultsAgent).toContain('lsp: "allow"');
|
|
145
|
-
expect(defaultsAgent).toContain('task: "
|
|
105
|
+
expect(defaultsAgent).toContain('task: "deny"');
|
|
146
106
|
expect(defaultsAgent).toContain('skill: "deny"');
|
|
147
107
|
expect(defaultsAgent).toContain('todoread: "deny"');
|
|
148
108
|
expect(defaultsAgent).toContain('todowrite: "deny"');
|
|
149
109
|
expect(defaultsAgent).toContain('webfetch: "ask"');
|
|
150
110
|
expect(defaultsAgent).toContain('websearch: "ask"');
|
|
151
111
|
expect(defaultsAgent).toContain('codesearch: "ask"');
|
|
152
|
-
expect(defaultsAgent).toContain('external_directory: "
|
|
112
|
+
expect(defaultsAgent).toContain('external_directory: "ask"');
|
|
153
113
|
expect(defaultsAgent).toContain('doom_loop: "deny"');
|
|
154
114
|
expect(defaultsAgent).toContain('"grep *": "allow"');
|
|
155
|
-
expect(defaultsAgent).toContain('"cp *": "ask"');
|
|
156
115
|
expect(defaultsAgent).toContain('"rm *": "deny"');
|
|
157
116
|
expect(defaultsFrontmatter.permission).toMatchObject({
|
|
158
117
|
edit: "allow",
|
|
@@ -160,21 +119,20 @@ describe("opencodeWriter", () => {
|
|
|
160
119
|
grep: "allow",
|
|
161
120
|
list: "allow",
|
|
162
121
|
lsp: "allow",
|
|
163
|
-
task: "
|
|
122
|
+
task: "deny",
|
|
164
123
|
skill: "deny",
|
|
165
124
|
todoread: "deny",
|
|
166
125
|
todowrite: "deny",
|
|
167
126
|
webfetch: "ask",
|
|
168
127
|
websearch: "ask",
|
|
169
128
|
codesearch: "ask",
|
|
170
|
-
external_directory: "
|
|
129
|
+
external_directory: "ask",
|
|
171
130
|
doom_loop: "deny"
|
|
172
131
|
});
|
|
173
132
|
const defaultsPermission = defaultsFrontmatter.permission as {
|
|
174
133
|
bash: Record<string, string>;
|
|
175
134
|
};
|
|
176
135
|
expect(defaultsPermission.bash["grep *"]).toBe("allow");
|
|
177
|
-
expect(defaultsPermission.bash["cp *"]).toBe("ask");
|
|
178
136
|
expect(defaultsPermission.bash["rm *"]).toBe("deny");
|
|
179
137
|
|
|
180
138
|
expect(maxAgent).toContain('"*": "allow"');
|
|
@@ -1,8 +1,157 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
|
-
import type {
|
|
2
|
+
import type { AutonomyProfile, LogicalConfig } from "@codemcp/ade-core";
|
|
3
3
|
import type { HarnessWriter } from "../types.js";
|
|
4
|
-
import {
|
|
5
|
-
|
|
4
|
+
import {
|
|
5
|
+
writeAgentMd,
|
|
6
|
+
writeGitHooks,
|
|
7
|
+
writeMcpServers,
|
|
8
|
+
formatYamlKey
|
|
9
|
+
} from "../util.js";
|
|
10
|
+
import { getAutonomyProfile } from "../permission-policy.js";
|
|
11
|
+
|
|
12
|
+
type PermissionDecision = "ask" | "allow" | "deny";
|
|
13
|
+
type PermissionRule = PermissionDecision | Record<string, PermissionDecision>;
|
|
14
|
+
|
|
15
|
+
const APPLICABLE_TO_ALL: Record<string, PermissionRule> = {
|
|
16
|
+
read: {
|
|
17
|
+
"*": "allow",
|
|
18
|
+
"*.env": "deny",
|
|
19
|
+
"*.env.*": "deny",
|
|
20
|
+
"*.env.example": "allow"
|
|
21
|
+
},
|
|
22
|
+
skill: "deny", //we're using an own skills-mcp
|
|
23
|
+
todoread: "deny", //no agent-proprieatry todo tools
|
|
24
|
+
todowrite: "deny",
|
|
25
|
+
task: "deny",
|
|
26
|
+
lsp: "allow",
|
|
27
|
+
glob: "allow",
|
|
28
|
+
grep: "allow",
|
|
29
|
+
list: "allow",
|
|
30
|
+
external_directory: "ask"
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const RIGID_RULES: Record<string, PermissionRule> = {
|
|
34
|
+
...APPLICABLE_TO_ALL,
|
|
35
|
+
"*": "ask",
|
|
36
|
+
webfetch: "ask",
|
|
37
|
+
websearch: "ask",
|
|
38
|
+
codesearch: "ask",
|
|
39
|
+
external_directory: "deny",
|
|
40
|
+
doom_loop: "deny"
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const SENSIBLE_DEFAULTS_RULES: Record<string, PermissionRule> = {
|
|
44
|
+
...APPLICABLE_TO_ALL,
|
|
45
|
+
edit: "allow",
|
|
46
|
+
webfetch: "ask",
|
|
47
|
+
websearch: "ask",
|
|
48
|
+
codesearch: "ask",
|
|
49
|
+
bash: {
|
|
50
|
+
"*": "ask",
|
|
51
|
+
"grep *": "allow",
|
|
52
|
+
"rg *": "allow",
|
|
53
|
+
"find *": "allow",
|
|
54
|
+
"fd *": "allow",
|
|
55
|
+
"ls *": "allow",
|
|
56
|
+
"cat *": "allow",
|
|
57
|
+
"head *": "allow",
|
|
58
|
+
"tail *": "allow",
|
|
59
|
+
"wc *": "allow",
|
|
60
|
+
"sort *": "allow",
|
|
61
|
+
"uniq *": "allow",
|
|
62
|
+
"diff *": "allow",
|
|
63
|
+
"echo *": "allow",
|
|
64
|
+
"printf *": "allow",
|
|
65
|
+
pwd: "allow",
|
|
66
|
+
"which *": "allow",
|
|
67
|
+
"type *": "allow",
|
|
68
|
+
whoami: "allow",
|
|
69
|
+
date: "allow",
|
|
70
|
+
"date *": "allow",
|
|
71
|
+
env: "allow",
|
|
72
|
+
"tree *": "allow",
|
|
73
|
+
"file *": "allow",
|
|
74
|
+
"stat *": "allow",
|
|
75
|
+
"readlink *": "allow",
|
|
76
|
+
"realpath *": "allow",
|
|
77
|
+
"dirname *": "allow",
|
|
78
|
+
"basename *": "allow",
|
|
79
|
+
"sed *": "allow",
|
|
80
|
+
"awk *": "allow",
|
|
81
|
+
"cut *": "allow",
|
|
82
|
+
"tr *": "allow",
|
|
83
|
+
"tee *": "allow",
|
|
84
|
+
"xargs *": "allow",
|
|
85
|
+
"jq *": "allow",
|
|
86
|
+
"yq *": "allow",
|
|
87
|
+
"mkdir *": "allow",
|
|
88
|
+
"touch *": "allow",
|
|
89
|
+
"kill *": "ask",
|
|
90
|
+
"rm *": "deny",
|
|
91
|
+
"rmdir *": "deny",
|
|
92
|
+
"curl *": "deny",
|
|
93
|
+
"wget *": "deny",
|
|
94
|
+
"chmod *": "deny",
|
|
95
|
+
"chown *": "deny",
|
|
96
|
+
"sudo *": "deny",
|
|
97
|
+
"su *": "deny",
|
|
98
|
+
"sh *": "deny",
|
|
99
|
+
"bash *": "deny",
|
|
100
|
+
"zsh *": "deny",
|
|
101
|
+
"eval *": "deny",
|
|
102
|
+
"exec *": "deny",
|
|
103
|
+
"source *": "deny",
|
|
104
|
+
". *": "deny",
|
|
105
|
+
"nohup *": "deny",
|
|
106
|
+
"dd *": "deny",
|
|
107
|
+
"mkfs *": "deny",
|
|
108
|
+
"mount *": "deny",
|
|
109
|
+
"umount *": "deny",
|
|
110
|
+
"killall *": "deny",
|
|
111
|
+
"pkill *": "deny",
|
|
112
|
+
"nc *": "deny",
|
|
113
|
+
"ncat *": "deny",
|
|
114
|
+
"ssh *": "deny",
|
|
115
|
+
"scp *": "deny",
|
|
116
|
+
"rsync *": "deny",
|
|
117
|
+
"docker *": "deny",
|
|
118
|
+
"kubectl *": "deny",
|
|
119
|
+
"systemctl *": "deny",
|
|
120
|
+
"service *": "deny",
|
|
121
|
+
"crontab *": "deny",
|
|
122
|
+
reboot: "deny",
|
|
123
|
+
"shutdown *": "deny",
|
|
124
|
+
"passwd *": "deny",
|
|
125
|
+
"useradd *": "deny",
|
|
126
|
+
"userdel *": "deny",
|
|
127
|
+
"iptables *": "deny"
|
|
128
|
+
},
|
|
129
|
+
doom_loop: "deny"
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const MAX_AUTONOMY_RULES: Record<string, PermissionRule> = {
|
|
133
|
+
...APPLICABLE_TO_ALL,
|
|
134
|
+
"*": "allow",
|
|
135
|
+
webfetch: "ask",
|
|
136
|
+
websearch: "ask",
|
|
137
|
+
codesearch: "ask",
|
|
138
|
+
doom_loop: "deny"
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
function getPermissionRules(
|
|
142
|
+
profile: AutonomyProfile | undefined
|
|
143
|
+
): Record<string, PermissionRule> | undefined {
|
|
144
|
+
switch (profile) {
|
|
145
|
+
case "rigid":
|
|
146
|
+
return RIGID_RULES;
|
|
147
|
+
case "sensible-defaults":
|
|
148
|
+
return SENSIBLE_DEFAULTS_RULES;
|
|
149
|
+
case "max-autonomy":
|
|
150
|
+
return MAX_AUTONOMY_RULES;
|
|
151
|
+
default:
|
|
152
|
+
return undefined;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
6
155
|
|
|
7
156
|
export const opencodeWriter: HarnessWriter = {
|
|
8
157
|
id: "opencode",
|
|
@@ -20,7 +169,7 @@ export const opencodeWriter: HarnessWriter = {
|
|
|
20
169
|
defaults: { $schema: "https://opencode.ai/config.json" }
|
|
21
170
|
});
|
|
22
171
|
|
|
23
|
-
const permission =
|
|
172
|
+
const permission = getPermissionRules(getAutonomyProfile(config));
|
|
24
173
|
|
|
25
174
|
await writeAgentMd(config, {
|
|
26
175
|
path: join(projectRoot, ".opencode", "agents", "ade.md"),
|
|
@@ -59,9 +208,3 @@ function renderYamlMapping(
|
|
|
59
208
|
|
|
60
209
|
return lines;
|
|
61
210
|
}
|
|
62
|
-
|
|
63
|
-
function formatYamlKey(value: string): string {
|
|
64
|
-
return /^[A-Za-z_][A-Za-z0-9_-]*$/.test(value)
|
|
65
|
-
? value
|
|
66
|
-
: JSON.stringify(value);
|
|
67
|
-
}
|
|
@@ -10,47 +10,7 @@ import type {
|
|
|
10
10
|
import { rooCodeWriter } from "./roo-code.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("rooCodeWriter", () => {
|
|
@@ -174,7 +134,7 @@ describe("rooCodeWriter", () => {
|
|
|
174
134
|
await readFile(join(rigidRoot, ".roo", "mcp.json"), "utf-8")
|
|
175
135
|
);
|
|
176
136
|
|
|
177
|
-
expect(rigidModes.customModes.ade.groups).toEqual(["mcp"]);
|
|
137
|
+
expect(rigidModes.customModes.ade.groups).toEqual(["read", "mcp"]);
|
|
178
138
|
expect(defaultsModes.customModes.ade.groups).toEqual([
|
|
179
139
|
"read",
|
|
180
140
|
"edit",
|
|
@@ -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,
|
|
@@ -9,7 +9,10 @@ import {
|
|
|
9
9
|
writeGitHooks,
|
|
10
10
|
writeJson
|
|
11
11
|
} from "../util.js";
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
getAutonomyProfile,
|
|
14
|
+
hasPermissionPolicy
|
|
15
|
+
} from "../permission-policy.js";
|
|
13
16
|
|
|
14
17
|
export const rooCodeWriter: HarnessWriter = {
|
|
15
18
|
id: "roo-code",
|
|
@@ -48,7 +51,10 @@ async function writeRooModes(
|
|
|
48
51
|
name: "ADE",
|
|
49
52
|
roleDefinition:
|
|
50
53
|
"ADE — Agentic Development Environment mode generated by ADE.",
|
|
51
|
-
groups: getRooModeGroups(
|
|
54
|
+
groups: getRooModeGroups(
|
|
55
|
+
getAutonomyProfile(config),
|
|
56
|
+
config.mcp_servers.length > 0
|
|
57
|
+
),
|
|
52
58
|
source: "project"
|
|
53
59
|
}
|
|
54
60
|
}
|
|
@@ -61,11 +67,20 @@ function asRecord(value: unknown): Record<string, unknown> {
|
|
|
61
67
|
: {};
|
|
62
68
|
}
|
|
63
69
|
|
|
64
|
-
function getRooModeGroups(
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
70
|
+
function getRooModeGroups(
|
|
71
|
+
profile: AutonomyProfile | undefined,
|
|
72
|
+
hasMcpServers: boolean
|
|
73
|
+
): string[] {
|
|
74
|
+
const mcpGroup = hasMcpServers ? ["mcp"] : [];
|
|
75
|
+
|
|
76
|
+
switch (profile) {
|
|
77
|
+
case "rigid":
|
|
78
|
+
return ["read", ...mcpGroup];
|
|
79
|
+
case "sensible-defaults":
|
|
80
|
+
return ["read", "edit", ...mcpGroup];
|
|
81
|
+
case "max-autonomy":
|
|
82
|
+
return ["read", "edit", "command", ...mcpGroup];
|
|
83
|
+
default:
|
|
84
|
+
return ["read", "edit", "command", ...mcpGroup];
|
|
85
|
+
}
|
|
71
86
|
}
|
|
@@ -10,47 +10,7 @@ import type {
|
|
|
10
10
|
import { universalWriter } from "./universal.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("universalWriter", () => {
|
|
@@ -1,40 +1,16 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
2
|
import { writeFile } from "node:fs/promises";
|
|
3
|
-
import type {
|
|
4
|
-
AutonomyCapability,
|
|
5
|
-
LogicalConfig,
|
|
6
|
-
PermissionDecision
|
|
7
|
-
} from "@codemcp/ade-core";
|
|
3
|
+
import type { AutonomyProfile, LogicalConfig } from "@codemcp/ade-core";
|
|
8
4
|
import type { HarnessWriter } from "../types.js";
|
|
9
5
|
import { writeMcpServers, writeGitHooks } from "../util.js";
|
|
10
|
-
|
|
11
|
-
const CAPABILITY_ORDER: AutonomyCapability[] = [
|
|
12
|
-
"read",
|
|
13
|
-
"edit_write",
|
|
14
|
-
"search_list",
|
|
15
|
-
"bash_safe",
|
|
16
|
-
"bash_unsafe",
|
|
17
|
-
"web",
|
|
18
|
-
"task_agent"
|
|
19
|
-
];
|
|
20
|
-
|
|
21
|
-
function formatCapabilityGuidance(
|
|
22
|
-
capability: AutonomyCapability,
|
|
23
|
-
decision: PermissionDecision
|
|
24
|
-
): string {
|
|
25
|
-
return `- \`${capability}\`: ${decision}`;
|
|
26
|
-
}
|
|
6
|
+
import { getAutonomyProfile } from "../permission-policy.js";
|
|
27
7
|
|
|
28
8
|
function renderAutonomyGuidance(config: LogicalConfig): string | undefined {
|
|
29
|
-
const
|
|
30
|
-
if (!
|
|
9
|
+
const profile = getAutonomyProfile(config);
|
|
10
|
+
if (!profile) {
|
|
31
11
|
return undefined;
|
|
32
12
|
}
|
|
33
13
|
|
|
34
|
-
const capabilityLines = CAPABILITY_ORDER.map((capability) =>
|
|
35
|
-
formatCapabilityGuidance(capability, policy.capabilities[capability])
|
|
36
|
-
);
|
|
37
|
-
|
|
38
14
|
return [
|
|
39
15
|
"## Autonomy",
|
|
40
16
|
"",
|
|
@@ -42,15 +18,53 @@ function renderAutonomyGuidance(config: LogicalConfig): string | undefined {
|
|
|
42
18
|
"",
|
|
43
19
|
"Treat this autonomy profile as documentation-only guidance for built-in/basic operations.",
|
|
44
20
|
"",
|
|
45
|
-
`Profile: \`${
|
|
21
|
+
`Profile: \`${profile}\``,
|
|
46
22
|
"",
|
|
47
|
-
|
|
48
|
-
...capabilityLines,
|
|
23
|
+
...getUniversalProfileGuidance(profile),
|
|
49
24
|
"",
|
|
50
25
|
"MCP permissions are not re-modeled by autonomy here; any MCP approvals must come from provisioning-aware consuming harnesses rather than the Universal writer."
|
|
51
26
|
].join("\n");
|
|
52
27
|
}
|
|
53
28
|
|
|
29
|
+
function getUniversalProfileGuidance(profile: AutonomyProfile): string[] {
|
|
30
|
+
const header = "Built-in/basic capability guidance:";
|
|
31
|
+
switch (profile) {
|
|
32
|
+
case "rigid":
|
|
33
|
+
return [
|
|
34
|
+
header,
|
|
35
|
+
"- `read`: allow",
|
|
36
|
+
"- `edit_write`: ask",
|
|
37
|
+
"- `search_list`: ask",
|
|
38
|
+
"- `bash_safe`: ask",
|
|
39
|
+
"- `bash_unsafe`: ask",
|
|
40
|
+
"- `web`: ask",
|
|
41
|
+
"- `task_agent`: ask"
|
|
42
|
+
];
|
|
43
|
+
case "sensible-defaults":
|
|
44
|
+
return [
|
|
45
|
+
header,
|
|
46
|
+
"- `read`: allow",
|
|
47
|
+
"- `edit_write`: allow",
|
|
48
|
+
"- `search_list`: allow",
|
|
49
|
+
"- `bash_safe`: allow",
|
|
50
|
+
"- `bash_unsafe`: ask",
|
|
51
|
+
"- `web`: ask",
|
|
52
|
+
"- `task_agent`: allow"
|
|
53
|
+
];
|
|
54
|
+
case "max-autonomy":
|
|
55
|
+
return [
|
|
56
|
+
header,
|
|
57
|
+
"- `read`: allow",
|
|
58
|
+
"- `edit_write`: allow",
|
|
59
|
+
"- `search_list`: allow",
|
|
60
|
+
"- `bash_safe`: allow",
|
|
61
|
+
"- `bash_unsafe`: allow",
|
|
62
|
+
"- `web`: ask",
|
|
63
|
+
"- `task_agent`: allow"
|
|
64
|
+
];
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
54
68
|
export const universalWriter: HarnessWriter = {
|
|
55
69
|
id: "universal",
|
|
56
70
|
label: "Universal (AGENTS.md + .mcp.json)",
|
|
@@ -95,7 +95,10 @@ describe("windsurfWriter", () => {
|
|
|
95
95
|
expect(rigidRules).toContain("Windsurf limitation:");
|
|
96
96
|
expect(rigidRules).toContain("advisory only");
|
|
97
97
|
expect(rigidRules).toContain(
|
|
98
|
-
"
|
|
98
|
+
"May proceed without extra approval: read files."
|
|
99
|
+
);
|
|
100
|
+
expect(rigidRules).toContain(
|
|
101
|
+
"Ask before: edit and write files, search and list files, safe local shell commands, unsafe local shell commands, web and network access, task or agent delegation."
|
|
99
102
|
);
|
|
100
103
|
|
|
101
104
|
expect(sensibleRules).toContain("Windsurf limitation:");
|
|
@@ -134,45 +137,5 @@ describe("windsurfWriter", () => {
|
|
|
134
137
|
function autonomyPolicy(
|
|
135
138
|
profile: "rigid" | "sensible-defaults" | "max-autonomy"
|
|
136
139
|
): LogicalConfig["permission_policy"] {
|
|
137
|
-
|
|
138
|
-
case "rigid":
|
|
139
|
-
return {
|
|
140
|
-
profile,
|
|
141
|
-
capabilities: {
|
|
142
|
-
read: "ask",
|
|
143
|
-
edit_write: "ask",
|
|
144
|
-
search_list: "ask",
|
|
145
|
-
bash_safe: "ask",
|
|
146
|
-
bash_unsafe: "ask",
|
|
147
|
-
web: "ask",
|
|
148
|
-
task_agent: "ask"
|
|
149
|
-
}
|
|
150
|
-
};
|
|
151
|
-
case "sensible-defaults":
|
|
152
|
-
return {
|
|
153
|
-
profile,
|
|
154
|
-
capabilities: {
|
|
155
|
-
read: "allow",
|
|
156
|
-
edit_write: "allow",
|
|
157
|
-
search_list: "allow",
|
|
158
|
-
bash_safe: "allow",
|
|
159
|
-
bash_unsafe: "ask",
|
|
160
|
-
web: "ask",
|
|
161
|
-
task_agent: "allow"
|
|
162
|
-
}
|
|
163
|
-
};
|
|
164
|
-
case "max-autonomy":
|
|
165
|
-
return {
|
|
166
|
-
profile,
|
|
167
|
-
capabilities: {
|
|
168
|
-
read: "allow",
|
|
169
|
-
edit_write: "allow",
|
|
170
|
-
search_list: "allow",
|
|
171
|
-
bash_safe: "allow",
|
|
172
|
-
bash_unsafe: "allow",
|
|
173
|
-
web: "ask",
|
|
174
|
-
task_agent: "allow"
|
|
175
|
-
}
|
|
176
|
-
};
|
|
177
|
-
}
|
|
140
|
+
return { profile };
|
|
178
141
|
}
|