@codemcp/ade 0.2.4 → 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.
Files changed (31) hide show
  1. package/package.json +1 -1
  2. package/packages/cli/dist/index.js +394 -7703
  3. package/packages/cli/package.json +3 -2
  4. package/packages/cli/tsup.config.ts +6 -1
  5. package/packages/core/package.json +1 -1
  6. package/packages/core/src/catalog/catalog.spec.ts +1 -10
  7. package/packages/core/src/catalog/facets/autonomy.ts +4 -62
  8. package/packages/core/src/index.ts +1 -4
  9. package/packages/core/src/resolver.spec.ts +4 -22
  10. package/packages/core/src/resolver.ts +1 -5
  11. package/packages/core/src/types.ts +0 -20
  12. package/packages/harnesses/package.json +1 -1
  13. package/packages/harnesses/src/permission-policy.ts +1 -165
  14. package/packages/harnesses/src/util.ts +11 -0
  15. package/packages/harnesses/src/writers/claude-code.spec.ts +14 -46
  16. package/packages/harnesses/src/writers/claude-code.ts +33 -16
  17. package/packages/harnesses/src/writers/cline.spec.ts +1 -41
  18. package/packages/harnesses/src/writers/copilot.spec.ts +2 -42
  19. package/packages/harnesses/src/writers/copilot.ts +19 -32
  20. package/packages/harnesses/src/writers/cursor.spec.ts +1 -41
  21. package/packages/harnesses/src/writers/cursor.ts +28 -40
  22. package/packages/harnesses/src/writers/kiro.spec.ts +1 -41
  23. package/packages/harnesses/src/writers/kiro.ts +23 -24
  24. package/packages/harnesses/src/writers/opencode.spec.ts +1 -41
  25. package/packages/harnesses/src/writers/opencode.ts +157 -10
  26. package/packages/harnesses/src/writers/roo-code.spec.ts +2 -42
  27. package/packages/harnesses/src/writers/roo-code.ts +25 -10
  28. package/packages/harnesses/src/writers/universal.spec.ts +1 -41
  29. package/packages/harnesses/src/writers/universal.ts +45 -31
  30. package/packages/harnesses/src/writers/windsurf.spec.ts +5 -42
  31. package/packages/harnesses/src/writers/windsurf.ts +30 -47
@@ -10,47 +10,7 @@ import type {
10
10
  import { rooCodeWriter } from "./roo-code.js";
11
11
 
12
12
  function autonomyPolicy(profile: AutonomyProfile): PermissionPolicy {
13
- switch (profile) {
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 { allowsCapability, hasPermissionPolicy } from "../permission-policy.js";
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(config),
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(config: LogicalConfig): string[] {
65
- return [
66
- ...(allowsCapability(config, "read") ? ["read"] : []),
67
- ...(allowsCapability(config, "edit_write") ? ["edit"] : []),
68
- ...(allowsCapability(config, "bash_unsafe") ? ["command"] : []),
69
- ...(config.mcp_servers.length > 0 ? ["mcp"] : [])
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
- switch (profile) {
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 policy = config.permission_policy;
30
- if (!policy) {
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: \`${policy.profile}\``,
21
+ `Profile: \`${profile}\``,
46
22
  "",
47
- "Built-in/basic capability guidance:",
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
- "Ask before: read files, edit and write files, search and list files, safe local shell commands, unsafe local shell commands, web and network access, task or agent delegation."
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
- switch (profile) {
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
  }
@@ -1,5 +1,5 @@
1
1
  import { join } from "node:path";
2
- import type { AutonomyCapability, 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
  writeMcpServers,
@@ -7,7 +7,10 @@ import {
7
7
  writeRulesFile,
8
8
  writeGitHooks
9
9
  } from "../util.js";
10
- import { hasPermissionPolicy } from "../permission-policy.js";
10
+ import {
11
+ getAutonomyProfile,
12
+ hasPermissionPolicy
13
+ } from "../permission-policy.js";
11
14
 
12
15
  export const windsurfWriter: HarnessWriter = {
13
16
  id: "windsurf",
@@ -32,58 +35,38 @@ function getWindsurfRules(config: LogicalConfig): string[] {
32
35
  return config.instructions;
33
36
  }
34
37
 
35
- const { capabilities } = config.permission_policy!;
36
- const allow = listCapabilities(capabilities, "allow");
37
- const ask = listCapabilities(capabilities, "ask");
38
- const deny = listCapabilities(capabilities, "deny");
39
-
40
38
  const autonomyGuidance = [
41
39
  "Windsurf limitation: ADE could not verify a stable committed project-local permission schema for Windsurf built-in tools, so this autonomy policy is advisory only and should be applied conservatively.",
42
- formatGuidance(allow, ask, deny)
40
+ getWindsurfProfileGuidance(getAutonomyProfile(config))
43
41
  ];
44
42
 
45
43
  return [...autonomyGuidance, ...config.instructions];
46
44
  }
47
45
 
48
- function listCapabilities(
49
- capabilities: NonNullable<LogicalConfig["permission_policy"]>["capabilities"],
50
- decision: "ask" | "allow" | "deny"
51
- ): string[] {
52
- return (Object.entries(capabilities) as Array<[AutonomyCapability, string]>)
53
- .filter(([, value]) => value === decision)
54
- .map(([capability]) => CAPABILITY_LABELS[capability]);
55
- }
56
-
57
- function formatGuidance(
58
- allow: string[],
59
- ask: string[],
60
- deny: string[]
46
+ function getWindsurfProfileGuidance(
47
+ profile: AutonomyProfile | undefined
61
48
  ): string {
62
- const lines = ["Autonomy guidance for Windsurf built-in capabilities:"];
63
-
64
- if (allow.length > 0) {
65
- lines.push(`- May proceed without extra approval: ${allow.join(", ")}.`);
66
- }
67
-
68
- if (ask.length > 0) {
69
- lines.push(`- Ask before: ${ask.join(", ")}.`);
49
+ const header = "Autonomy guidance for Windsurf built-in capabilities:";
50
+ switch (profile) {
51
+ case "rigid":
52
+ return [
53
+ header,
54
+ "- May proceed without extra approval: read files.",
55
+ "- 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."
56
+ ].join("\n");
57
+ case "sensible-defaults":
58
+ return [
59
+ header,
60
+ "- May proceed without extra approval: read files, edit and write files, search and list files, safe local shell commands, task or agent delegation.",
61
+ "- Ask before: unsafe local shell commands, web and network access."
62
+ ].join("\n");
63
+ case "max-autonomy":
64
+ return [
65
+ header,
66
+ "- May proceed without extra approval: read files, edit and write files, search and list files, safe local shell commands, unsafe local shell commands, task or agent delegation.",
67
+ "- Ask before: web and network access."
68
+ ].join("\n");
69
+ default:
70
+ return `${header} follow project conventions.`;
70
71
  }
71
-
72
- if (deny.length > 0) {
73
- lines.push(
74
- `- Do not use unless the user explicitly overrides: ${deny.join(", ")}.`
75
- );
76
- }
77
-
78
- return lines.join("\n");
79
72
  }
80
-
81
- const CAPABILITY_LABELS: Record<AutonomyCapability, string> = {
82
- read: "read files",
83
- edit_write: "edit and write files",
84
- search_list: "search and list files",
85
- bash_safe: "safe local shell commands",
86
- bash_unsafe: "unsafe local shell commands",
87
- web: "web and network access",
88
- task_agent: "task or agent delegation"
89
- };