@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.
Files changed (30) hide show
  1. package/package.json +1 -1
  2. package/packages/cli/dist/index.js +317 -338
  3. package/packages/cli/package.json +1 -1
  4. package/packages/core/package.json +1 -1
  5. package/packages/core/src/catalog/catalog.spec.ts +1 -10
  6. package/packages/core/src/catalog/facets/autonomy.ts +4 -62
  7. package/packages/core/src/index.ts +1 -4
  8. package/packages/core/src/resolver.spec.ts +4 -22
  9. package/packages/core/src/resolver.ts +1 -5
  10. package/packages/core/src/types.ts +0 -20
  11. package/packages/harnesses/package.json +1 -1
  12. package/packages/harnesses/src/permission-policy.ts +1 -165
  13. package/packages/harnesses/src/util.ts +11 -0
  14. package/packages/harnesses/src/writers/claude-code.spec.ts +14 -46
  15. package/packages/harnesses/src/writers/claude-code.ts +33 -16
  16. package/packages/harnesses/src/writers/cline.spec.ts +1 -41
  17. package/packages/harnesses/src/writers/copilot.spec.ts +2 -42
  18. package/packages/harnesses/src/writers/copilot.ts +19 -32
  19. package/packages/harnesses/src/writers/cursor.spec.ts +1 -41
  20. package/packages/harnesses/src/writers/cursor.ts +28 -40
  21. package/packages/harnesses/src/writers/kiro.spec.ts +1 -41
  22. package/packages/harnesses/src/writers/kiro.ts +23 -24
  23. package/packages/harnesses/src/writers/opencode.spec.ts +1 -41
  24. package/packages/harnesses/src/writers/opencode.ts +157 -10
  25. package/packages/harnesses/src/writers/roo-code.spec.ts +2 -42
  26. package/packages/harnesses/src/writers/roo-code.ts +25 -10
  27. package/packages/harnesses/src/writers/universal.spec.ts +1 -41
  28. package/packages/harnesses/src/writers/universal.ts +45 -31
  29. package/packages/harnesses/src/writers/windsurf.spec.ts +5 -42
  30. package/packages/harnesses/src/writers/windsurf.ts +30 -47
@@ -10,47 +10,7 @@ import type {
10
10
  import { copilotWriter } from "./copilot.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("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).not.toContain(" - read");
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 { LogicalConfig, McpServerEntry } from "@codemcp/ade-core";
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(config: LogicalConfig): string[] {
45
- if (!hasPermissionPolicy(config)) {
46
- return ["read", "edit", "search", "execute", "agent", "web"];
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
- 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("cursorWriter", () => {
@@ -1,34 +1,13 @@
1
1
  import { mkdir, writeFile } from "node:fs/promises";
2
2
  import { join } from "node:path";
3
- import type { AutonomyCapability, LogicalConfig } from "@codemcp/ade-core";
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 allowedCapabilities = CURSOR_CAPABILITY_ORDER.filter(
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): ${getAutonomyProfile(config) ?? "custom"}.`,
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
- ...(allowedCapabilities.length > 0
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
- 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("kiroWriter", () => {
@@ -1,5 +1,9 @@
1
1
  import { join } from "node:path";
2
- import type { LogicalConfig, McpServerEntry } from "@codemcp/ade-core";
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: getKiroTools(config),
38
- allowedTools: getKiroAllowedTools(config),
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(config: LogicalConfig): string[] {
47
- const mcpTools = getKiroForwardedMcpTools(config.mcp_servers);
47
+ function getKiroTools(
48
+ profile: AutonomyProfile | undefined,
49
+ servers: McpServerEntry[]
50
+ ): string[] {
51
+ const mcpTools = getKiroForwardedMcpTools(servers);
48
52
 
49
- if (!hasPermissionPolicy(config)) {
50
- return ["read", "write", "shell", "spec", ...mcpTools];
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[] {
@@ -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
- switch (profile) {
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", () => {
@@ -1,8 +1,161 @@
1
1
  import { join } from "node:path";
2
- import type { LogicalConfig, PermissionRule } from "@codemcp/ade-core";
2
+ import type { AutonomyProfile, LogicalConfig } from "@codemcp/ade-core";
3
3
  import type { HarnessWriter } from "../types.js";
4
- import { writeAgentMd, writeGitHooks, writeMcpServers } from "../util.js";
5
- import { getHarnessPermissionRules } from "../permission-policy.js";
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 RIGID_RULES: Record<string, PermissionRule> = {
16
+ "*": "ask",
17
+ webfetch: "ask",
18
+ websearch: "ask",
19
+ codesearch: "ask",
20
+ external_directory: "deny",
21
+ doom_loop: "deny"
22
+ };
23
+
24
+ const SENSIBLE_DEFAULTS_RULES: Record<string, PermissionRule> = {
25
+ read: {
26
+ "*": "allow",
27
+ "*.env": "deny",
28
+ "*.env.*": "deny",
29
+ "*.env.example": "allow"
30
+ },
31
+ edit: "allow",
32
+ glob: "allow",
33
+ grep: "allow",
34
+ list: "allow",
35
+ lsp: "allow",
36
+ task: "allow",
37
+ todoread: "deny",
38
+ todowrite: "deny",
39
+ skill: "deny",
40
+ webfetch: "ask",
41
+ websearch: "ask",
42
+ codesearch: "ask",
43
+ bash: {
44
+ "*": "deny",
45
+ "grep *": "allow",
46
+ "rg *": "allow",
47
+ "find *": "allow",
48
+ "fd *": "allow",
49
+ ls: "allow",
50
+ "ls *": "allow",
51
+ "cat *": "allow",
52
+ "head *": "allow",
53
+ "tail *": "allow",
54
+ "wc *": "allow",
55
+ "sort *": "allow",
56
+ "uniq *": "allow",
57
+ "diff *": "allow",
58
+ "echo *": "allow",
59
+ "printf *": "allow",
60
+ pwd: "allow",
61
+ "which *": "allow",
62
+ "type *": "allow",
63
+ whoami: "allow",
64
+ date: "allow",
65
+ "date *": "allow",
66
+ env: "allow",
67
+ "tree *": "allow",
68
+ "file *": "allow",
69
+ "stat *": "allow",
70
+ "readlink *": "allow",
71
+ "realpath *": "allow",
72
+ "dirname *": "allow",
73
+ "basename *": "allow",
74
+ "sed *": "allow",
75
+ "awk *": "allow",
76
+ "cut *": "allow",
77
+ "tr *": "allow",
78
+ "tee *": "allow",
79
+ "xargs *": "allow",
80
+ "jq *": "allow",
81
+ "yq *": "allow",
82
+ "mkdir *": "allow",
83
+ "touch *": "allow",
84
+ "cp *": "ask",
85
+ "mv *": "ask",
86
+ "ln *": "ask",
87
+ "npm *": "ask",
88
+ "node *": "ask",
89
+ "pip *": "ask",
90
+ "python *": "ask",
91
+ "python3 *": "ask",
92
+ "rm *": "deny",
93
+ "rmdir *": "deny",
94
+ "curl *": "deny",
95
+ "wget *": "deny",
96
+ "chmod *": "deny",
97
+ "chown *": "deny",
98
+ "sudo *": "deny",
99
+ "su *": "deny",
100
+ "sh *": "deny",
101
+ "bash *": "deny",
102
+ "zsh *": "deny",
103
+ "eval *": "deny",
104
+ "exec *": "deny",
105
+ "source *": "deny",
106
+ ". *": "deny",
107
+ "nohup *": "deny",
108
+ "dd *": "deny",
109
+ "mkfs *": "deny",
110
+ "mount *": "deny",
111
+ "umount *": "deny",
112
+ "kill *": "deny",
113
+ "killall *": "deny",
114
+ "pkill *": "deny",
115
+ "nc *": "deny",
116
+ "ncat *": "deny",
117
+ "ssh *": "deny",
118
+ "scp *": "deny",
119
+ "rsync *": "deny",
120
+ "docker *": "deny",
121
+ "kubectl *": "deny",
122
+ "systemctl *": "deny",
123
+ "service *": "deny",
124
+ "crontab *": "deny",
125
+ reboot: "deny",
126
+ "shutdown *": "deny",
127
+ "passwd *": "deny",
128
+ "useradd *": "deny",
129
+ "userdel *": "deny",
130
+ "iptables *": "deny"
131
+ },
132
+ external_directory: "deny",
133
+ doom_loop: "deny"
134
+ };
135
+
136
+ const MAX_AUTONOMY_RULES: Record<string, PermissionRule> = {
137
+ "*": "allow",
138
+ webfetch: "ask",
139
+ websearch: "ask",
140
+ codesearch: "ask",
141
+ external_directory: "deny",
142
+ doom_loop: "deny"
143
+ };
144
+
145
+ function getPermissionRules(
146
+ profile: AutonomyProfile | undefined
147
+ ): Record<string, PermissionRule> | undefined {
148
+ switch (profile) {
149
+ case "rigid":
150
+ return RIGID_RULES;
151
+ case "sensible-defaults":
152
+ return SENSIBLE_DEFAULTS_RULES;
153
+ case "max-autonomy":
154
+ return MAX_AUTONOMY_RULES;
155
+ default:
156
+ return undefined;
157
+ }
158
+ }
6
159
 
7
160
  export const opencodeWriter: HarnessWriter = {
8
161
  id: "opencode",
@@ -20,7 +173,7 @@ export const opencodeWriter: HarnessWriter = {
20
173
  defaults: { $schema: "https://opencode.ai/config.json" }
21
174
  });
22
175
 
23
- const permission = getHarnessPermissionRules(config);
176
+ const permission = getPermissionRules(getAutonomyProfile(config));
24
177
 
25
178
  await writeAgentMd(config, {
26
179
  path: join(projectRoot, ".opencode", "agents", "ade.md"),
@@ -59,9 +212,3 @@ function renderYamlMapping(
59
212
 
60
213
  return lines;
61
214
  }
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
- }