@dotdotgod/opencode 0.0.0-stage → 0.6.7

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 (52) hide show
  1. package/LICENSE +94 -0
  2. package/README.md +84 -2
  3. package/commands/impact.md +26 -0
  4. package/commands/init.md +38 -0
  5. package/commands/load.md +28 -0
  6. package/index.js +1 -0
  7. package/mcp/cli.mjs +7161 -0
  8. package/mcp/impact-state.mjs +133 -0
  9. package/mcp/parsers/IGNORE_LICENSE +21 -0
  10. package/mcp/parsers/LICENSE +21 -0
  11. package/mcp/parsers/TYPESCRIPT_LICENSE +21 -0
  12. package/mcp/parsers/tree-sitter-bash.wasm +0 -0
  13. package/mcp/parsers/tree-sitter-c-sharp.wasm +0 -0
  14. package/mcp/parsers/tree-sitter-cpp.wasm +0 -0
  15. package/mcp/parsers/tree-sitter-css.wasm +0 -0
  16. package/mcp/parsers/tree-sitter-go.wasm +0 -0
  17. package/mcp/parsers/tree-sitter-ini.wasm +0 -0
  18. package/mcp/parsers/tree-sitter-java.wasm +0 -0
  19. package/mcp/parsers/tree-sitter-javascript.wasm +0 -0
  20. package/mcp/parsers/tree-sitter-php.wasm +0 -0
  21. package/mcp/parsers/tree-sitter-powershell.wasm +0 -0
  22. package/mcp/parsers/tree-sitter-python.wasm +0 -0
  23. package/mcp/parsers/tree-sitter-regex.wasm +0 -0
  24. package/mcp/parsers/tree-sitter-ruby.wasm +0 -0
  25. package/mcp/parsers/tree-sitter-rust.wasm +0 -0
  26. package/mcp/parsers/tree-sitter-tsx.wasm +0 -0
  27. package/mcp/parsers/tree-sitter-typescript.wasm +0 -0
  28. package/mcp/parsers/tree-sitter.cjs +4075 -0
  29. package/mcp/parsers/tree-sitter.wasm +0 -0
  30. package/mcp/server.mjs +23716 -0
  31. package/package.json +41 -3
  32. package/server.js +1 -0
  33. package/skills/doc-first-planning/SKILL.md +30 -0
  34. package/skills/document-clarify/SKILL.md +41 -0
  35. package/skills/impact-review/SKILL.md +25 -0
  36. package/skills/project-initializer/SKILL.md +37 -0
  37. package/skills/project-initializer/references/agent-docs.md +42 -0
  38. package/skills/project-initializer/scripts/init_project.sh +525 -0
  39. package/skills/project-initializer/templates/case-and-evidence.json +219 -0
  40. package/skills/project-initializer/templates/dotdotgod.config.json +234 -0
  41. package/skills/project-initializer/templates/policy.json +241 -0
  42. package/skills/project-initializer/templates/portfolio.json +255 -0
  43. package/skills/project-initializer/templates/publication.json +265 -0
  44. package/skills/project-initializer/templates/research.json +287 -0
  45. package/skills/project-initializer/templates/software.json +234 -0
  46. package/skills/project-load/SKILL.md +27 -0
  47. package/src/impact.mjs +25 -0
  48. package/src/index.mjs +17 -0
  49. package/src/location.mjs +7 -0
  50. package/src/mcp.mjs +37 -0
  51. package/src/plan.mjs +65 -0
  52. package/src/resources.mjs +28 -0
@@ -0,0 +1,287 @@
1
+ {
2
+ "documentation": {
3
+ "root": "docs"
4
+ },
5
+ "memory": {
6
+ "areas": [
7
+ {
8
+ "id": "rules",
9
+ "label": "Agent Rules",
10
+ "paths": [
11
+ "AGENTS.md"
12
+ ],
13
+ "excludePaths": [],
14
+ "scope": "shared",
15
+ "freshness": "fresh",
16
+ "role": "agent-working-rules",
17
+ "priority": 100,
18
+ "includeBodiesByDefault": true
19
+ },
20
+ {
21
+ "id": "agent-entrypoint",
22
+ "label": "Agent Entrypoints",
23
+ "paths": [
24
+ "CLAUDE.md",
25
+ "CODEX.md"
26
+ ],
27
+ "excludePaths": [],
28
+ "scope": "shared",
29
+ "freshness": "fresh",
30
+ "role": "agent-specific-entrypoint",
31
+ "priority": 85,
32
+ "includeBodiesByDefault": true
33
+ },
34
+ {
35
+ "id": "project-overview",
36
+ "label": "Project Overview",
37
+ "paths": [
38
+ "README.md"
39
+ ],
40
+ "excludePaths": [],
41
+ "scope": "shared",
42
+ "freshness": "fresh",
43
+ "role": "project-map",
44
+ "priority": 85,
45
+ "includeBodiesByDefault": true
46
+ },
47
+ {
48
+ "id": "docs-index",
49
+ "label": "Docs Index",
50
+ "paths": [
51
+ "docs/README.md"
52
+ ],
53
+ "excludePaths": [],
54
+ "scope": "shared",
55
+ "freshness": "fresh",
56
+ "role": "documentation-routing-map",
57
+ "priority": 90,
58
+ "includeBodiesByDefault": true
59
+ },
60
+ {
61
+ "id": "spec",
62
+ "label": "Research Specifications",
63
+ "paths": [
64
+ "docs/spec/**"
65
+ ],
66
+ "excludePaths": [],
67
+ "scope": "shared",
68
+ "freshness": "fresh",
69
+ "role": "research-contract",
70
+ "priority": 85,
71
+ "includeBodiesByDefault": true
72
+ },
73
+ {
74
+ "id": "architecture",
75
+ "label": "Architecture",
76
+ "paths": [
77
+ "docs/arch/**"
78
+ ],
79
+ "excludePaths": [],
80
+ "scope": "shared",
81
+ "freshness": "fresh",
82
+ "role": "architecture-rationale",
83
+ "priority": 82,
84
+ "includeBodiesByDefault": true
85
+ },
86
+ {
87
+ "id": "test",
88
+ "label": "Verification",
89
+ "paths": [
90
+ "docs/test/**"
91
+ ],
92
+ "excludePaths": [],
93
+ "scope": "shared",
94
+ "freshness": "fresh",
95
+ "role": "test-strategy",
96
+ "priority": 78,
97
+ "includeBodiesByDefault": true
98
+ },
99
+ {
100
+ "id": "research",
101
+ "label": "Research Notes",
102
+ "paths": [
103
+ "docs/research/**"
104
+ ],
105
+ "excludePaths": [],
106
+ "scope": "shared",
107
+ "freshness": "fresh",
108
+ "role": "research-diary",
109
+ "priority": 70,
110
+ "includeBodiesByDefault": true
111
+ },
112
+ {
113
+ "id": "record",
114
+ "label": "Research Records",
115
+ "paths": [
116
+ "docs/record/**"
117
+ ],
118
+ "excludePaths": [],
119
+ "scope": "shared",
120
+ "freshness": "fresh",
121
+ "role": "research-record",
122
+ "priority": 68,
123
+ "includeBodiesByDefault": true
124
+ },
125
+ {
126
+ "id": "report",
127
+ "label": "Reports",
128
+ "paths": [
129
+ "docs/report/**"
130
+ ],
131
+ "excludePaths": [],
132
+ "scope": "shared",
133
+ "freshness": "stale",
134
+ "role": "report-background",
135
+ "priority": 60,
136
+ "includeBodiesByDefault": true
137
+ },
138
+ {
139
+ "id": "artifacts",
140
+ "label": "Generated Artifacts",
141
+ "paths": [
142
+ "outputs/**"
143
+ ],
144
+ "excludePaths": [],
145
+ "scope": "local",
146
+ "freshness": "stale",
147
+ "role": "artifact-body",
148
+ "priority": 10,
149
+ "includeBodiesByDefault": false
150
+ },
151
+ {
152
+ "id": "active-plan",
153
+ "label": "Active Plans",
154
+ "paths": [
155
+ "docs/plan/**"
156
+ ],
157
+ "excludePaths": [],
158
+ "scope": "local",
159
+ "freshness": "fresh",
160
+ "role": "active-task-intent",
161
+ "priority": 95,
162
+ "includeBodiesByDefault": true
163
+ },
164
+ {
165
+ "id": "archive-map",
166
+ "label": "Archive Map",
167
+ "paths": [
168
+ "docs/archive/README.md"
169
+ ],
170
+ "excludePaths": [],
171
+ "scope": "local",
172
+ "freshness": "stale",
173
+ "role": "historical-memory-map",
174
+ "priority": 65,
175
+ "includeBodiesByDefault": true
176
+ },
177
+ {
178
+ "id": "archive-body",
179
+ "label": "Archive Body",
180
+ "paths": [
181
+ "docs/archive/**"
182
+ ],
183
+ "excludePaths": [
184
+ "docs/archive/README.md"
185
+ ],
186
+ "scope": "local",
187
+ "freshness": "stale",
188
+ "role": "historical-memory-body",
189
+ "priority": 20,
190
+ "includeBodiesByDefault": false
191
+ },
192
+ {
193
+ "id": "docs",
194
+ "label": "Project Documentation",
195
+ "paths": [
196
+ "docs/**"
197
+ ],
198
+ "excludePaths": [],
199
+ "scope": "shared",
200
+ "freshness": "fresh",
201
+ "role": "project-documentation",
202
+ "priority": 60,
203
+ "includeBodiesByDefault": true
204
+ }
205
+ ]
206
+ },
207
+ "traceability": {
208
+ "required": [
209
+ "docs/spec/**",
210
+ "docs/report/**"
211
+ ],
212
+ "exclude": [
213
+ "**/README.md"
214
+ ],
215
+ "keys": [
216
+ {
217
+ "key": "informedBy",
218
+ "label": "Informed by",
219
+ "description": "Research sources or prior findings that justify the direction.",
220
+ "target": "path",
221
+ "relation": "informed_by",
222
+ "weight": 4
223
+ },
224
+ {
225
+ "key": "assumptionsDefinedIn",
226
+ "label": "Assumptions defined in",
227
+ "description": "Documents defining assumptions that bound the claim.",
228
+ "target": "path",
229
+ "relation": "assumptions_defined_in",
230
+ "weight": 4
231
+ },
232
+ {
233
+ "key": "evaluatedBy",
234
+ "label": "Evaluated by",
235
+ "description": "Evaluation protocols or measurement methods.",
236
+ "target": "path",
237
+ "relation": "evaluated_by",
238
+ "weight": 4
239
+ },
240
+ {
241
+ "key": "evidenceRecordedIn",
242
+ "label": "Evidence recorded in",
243
+ "description": "Dated experiment, dataset, or validation records.",
244
+ "target": "path",
245
+ "relation": "evidence_recorded_in",
246
+ "weight": 4
247
+ }
248
+ ]
249
+ },
250
+ "validation": {
251
+ "markdown": {
252
+ "maxLines": 200,
253
+ "maxChars": 10000,
254
+ "exclude": [],
255
+ "filename": {
256
+ "warnNumberedSeries": true,
257
+ "allow": []
258
+ }
259
+ }
260
+ },
261
+ "impactRanking": {
262
+ "semantic": {
263
+ "enabled": true,
264
+ "threshold": 0.5,
265
+ "topKPerFile": 5
266
+ }
267
+ },
268
+ "referenceExpansion": {
269
+ "fuzzy": {
270
+ "lowSignal": {
271
+ "add": [],
272
+ "remove": []
273
+ }
274
+ }
275
+ },
276
+ "load": {
277
+ "pinnedPaths": [],
278
+ "pinnedBodies": [],
279
+ "documentationSummary": {
280
+ "exclude": [
281
+ "docs/plan",
282
+ "docs/archive"
283
+ ]
284
+ }
285
+ },
286
+ "planMode": {}
287
+ }
@@ -0,0 +1,234 @@
1
+ {
2
+ "documentation": {
3
+ "root": "docs"
4
+ },
5
+ "memory": {
6
+ "areas": [
7
+ {
8
+ "id": "rules",
9
+ "label": "Agent Rules",
10
+ "paths": [
11
+ "AGENTS.md"
12
+ ],
13
+ "excludePaths": [],
14
+ "scope": "shared",
15
+ "freshness": "fresh",
16
+ "role": "agent-working-rules",
17
+ "priority": 100,
18
+ "includeBodiesByDefault": true
19
+ },
20
+ {
21
+ "id": "agent-entrypoint",
22
+ "label": "Agent Entrypoints",
23
+ "paths": [
24
+ "CLAUDE.md",
25
+ "CODEX.md"
26
+ ],
27
+ "excludePaths": [],
28
+ "scope": "shared",
29
+ "freshness": "fresh",
30
+ "role": "agent-specific-entrypoint",
31
+ "priority": 85,
32
+ "includeBodiesByDefault": true
33
+ },
34
+ {
35
+ "id": "project-overview",
36
+ "label": "Project Overview",
37
+ "paths": [
38
+ "README.md"
39
+ ],
40
+ "excludePaths": [],
41
+ "scope": "shared",
42
+ "freshness": "fresh",
43
+ "role": "project-map",
44
+ "priority": 85,
45
+ "includeBodiesByDefault": true
46
+ },
47
+ {
48
+ "id": "docs-index",
49
+ "label": "Docs Index",
50
+ "paths": [
51
+ "docs/README.md"
52
+ ],
53
+ "excludePaths": [],
54
+ "scope": "shared",
55
+ "freshness": "fresh",
56
+ "role": "documentation-routing-map",
57
+ "priority": 90,
58
+ "includeBodiesByDefault": true
59
+ },
60
+ {
61
+ "id": "spec",
62
+ "label": "Product Specs",
63
+ "paths": [
64
+ "docs/spec/**"
65
+ ],
66
+ "excludePaths": [],
67
+ "scope": "shared",
68
+ "freshness": "fresh",
69
+ "role": "behavior-truth",
70
+ "priority": 80,
71
+ "includeBodiesByDefault": true
72
+ },
73
+ {
74
+ "id": "architecture",
75
+ "label": "Architecture",
76
+ "paths": [
77
+ "docs/arch/**"
78
+ ],
79
+ "excludePaths": [],
80
+ "scope": "shared",
81
+ "freshness": "fresh",
82
+ "role": "architecture-rationale",
83
+ "priority": 75,
84
+ "includeBodiesByDefault": true
85
+ },
86
+ {
87
+ "id": "test",
88
+ "label": "Tests",
89
+ "paths": [
90
+ "docs/test/**"
91
+ ],
92
+ "excludePaths": [],
93
+ "scope": "shared",
94
+ "freshness": "fresh",
95
+ "role": "verification-knowledge",
96
+ "priority": 70,
97
+ "includeBodiesByDefault": true
98
+ },
99
+ {
100
+ "id": "active-plan",
101
+ "label": "Active Plans",
102
+ "paths": [
103
+ "docs/plan/**"
104
+ ],
105
+ "excludePaths": [],
106
+ "scope": "local",
107
+ "freshness": "fresh",
108
+ "role": "active-task-intent",
109
+ "priority": 95,
110
+ "includeBodiesByDefault": true
111
+ },
112
+ {
113
+ "id": "archive-map",
114
+ "label": "Archive Map",
115
+ "paths": [
116
+ "docs/archive/README.md"
117
+ ],
118
+ "excludePaths": [],
119
+ "scope": "local",
120
+ "freshness": "stale",
121
+ "role": "historical-memory-map",
122
+ "priority": 65,
123
+ "includeBodiesByDefault": true
124
+ },
125
+ {
126
+ "id": "archive-body",
127
+ "label": "Archive Body",
128
+ "paths": [
129
+ "docs/archive/**"
130
+ ],
131
+ "excludePaths": [
132
+ "docs/archive/README.md"
133
+ ],
134
+ "scope": "local",
135
+ "freshness": "stale",
136
+ "role": "historical-memory-body",
137
+ "priority": 20,
138
+ "includeBodiesByDefault": false
139
+ },
140
+ {
141
+ "id": "docs",
142
+ "label": "Project Documentation",
143
+ "paths": [
144
+ "docs/**"
145
+ ],
146
+ "excludePaths": [],
147
+ "scope": "shared",
148
+ "freshness": "fresh",
149
+ "role": "project-documentation",
150
+ "priority": 60,
151
+ "includeBodiesByDefault": true
152
+ }
153
+ ]
154
+ },
155
+ "traceability": {
156
+ "required": [
157
+ "docs/spec/**"
158
+ ],
159
+ "exclude": [
160
+ "**/README.md"
161
+ ],
162
+ "keys": [
163
+ {
164
+ "key": "implementedBy",
165
+ "label": "Implemented by",
166
+ "description": "Files that implement the behavior.",
167
+ "target": "path",
168
+ "relation": "implemented_by",
169
+ "weight": 4
170
+ },
171
+ {
172
+ "key": "verifiedBy",
173
+ "label": "Verified by",
174
+ "description": "Tests or maintained verification documents.",
175
+ "target": "path",
176
+ "relation": "verified_by",
177
+ "weight": 4
178
+ },
179
+ {
180
+ "key": "relatedDocs",
181
+ "label": "Related docs",
182
+ "description": "Documents needed to interpret the behavior.",
183
+ "target": "path",
184
+ "relation": "related_doc",
185
+ "weight": 3
186
+ },
187
+ {
188
+ "key": "designDecisions",
189
+ "label": "Design decisions",
190
+ "description": "Maintained architecture or design decision documents that constrain the behavior.",
191
+ "target": "path",
192
+ "relation": "design_decision",
193
+ "weight": 3
194
+ }
195
+ ]
196
+ },
197
+ "validation": {
198
+ "markdown": {
199
+ "maxLines": 200,
200
+ "maxChars": 10000,
201
+ "exclude": [],
202
+ "filename": {
203
+ "warnNumberedSeries": true,
204
+ "allow": []
205
+ }
206
+ }
207
+ },
208
+ "impactRanking": {
209
+ "semantic": {
210
+ "enabled": true,
211
+ "threshold": 0.5,
212
+ "topKPerFile": 5
213
+ }
214
+ },
215
+ "referenceExpansion": {
216
+ "fuzzy": {
217
+ "lowSignal": {
218
+ "add": [],
219
+ "remove": []
220
+ }
221
+ }
222
+ },
223
+ "load": {
224
+ "pinnedPaths": [],
225
+ "pinnedBodies": [],
226
+ "documentationSummary": {
227
+ "exclude": [
228
+ "docs/plan",
229
+ "docs/archive"
230
+ ]
231
+ }
232
+ },
233
+ "planMode": {}
234
+ }
@@ -0,0 +1,27 @@
1
+ ---
2
+ name: project-load
3
+ description: Load or refresh project memory and focused documentation/code search.
4
+ ---
5
+
6
+ <!-- Generated from packages/shared resources by scripts/generate-adapters.mjs. Do not edit this file directly; edit the shared source and run `pnpm run generate`. -->
7
+
8
+ # Project Load
9
+
10
+ Use the dotdotgod_context MCP server for project load, initialization, graph impact, execution and indexed retrieval. Discover its exact tool names in OpenCode Code Mode; inspect MCP isError and structuredContent and every execution results entry. For unknown output size use execute with a commands array and outputMode auto; search indexed.id with bounded source-scoped search. Run ancillary CLI checks through MCP execute rather than a duplicate native service. Keep direct read for short located source and images. Pending impact is advisory, never an execution gate. Preserve host permissions. Use the native plan agent, not dd:plan; concrete plans are automatically maintained in docs/plan/<task-slug>/README.md without a separate save request.
11
+
12
+ ## Goal
13
+
14
+ Load the repository's dotdotgod project memory without modifying maintained files. Treat free-form arguments as query text, not mode switches.
15
+
16
+ ## Workflow
17
+
18
+ 1. Identify the repository root. Expose `Help: dotdotgod --help` as optional CLI discovery guidance without checking or reporting installation status, and do not require Help execution for Load to continue.
19
+ 2. When baseline context is missing, read `AGENTS.md`, the adapter entrypoint, `README.md`, and `docs/README.md` when present.
20
+ 3. Without arguments, call the shared MCP project_load tool with an empty focus and maxDepth 5. Its configured map owns documentation-root resolution, exclusions and boundary summaries.
21
+ 4. With arguments, call project_load with the arguments as focus, limit 30 and maxDepth 3. It returns the configured map plus documentation/code query results and retrieval warnings.
22
+ 5. If the CLI or shell execution is unavailable, preserve Load behavior by building the same tree from the configured documentation root when known, excluding local memory, and using README routing. At the depth boundary, list every direct Markdown file and immediate child directory, then summarize hidden descendants separately under each named child with exact recursive directory and Markdown-file counts.
23
+ 6. Query searches full documentation content and code outlines/comments, not implementation bodies. Preserve result kind, source ranges and retrieval warnings; verify source freshness before reading a symbol's implementation. Read bodies selectively from query results, explicit paths, and README indexes. Read relevant active plans only when needed, use `docs/archive/README.md` (or the configured archive `README.md` under an alternate documentation root) as the history map, and avoid broad generated, dependency, cache, or secret reads.
24
+
25
+ ## Output
26
+
27
+ Report the project purpose, key rules, relevant documentation routes, and only the active-plan or next-read hints needed for the request. Keep compact loads to a brief refresh.
package/src/impact.mjs ADDED
@@ -0,0 +1,25 @@
1
+ import { ImpactState, impactReminder } from '../mcp/impact-state.mjs';
2
+ import { isLocalSession } from './location.mjs';
3
+
4
+ export function editedPaths(tool, input) {
5
+ if (!input || typeof input !== 'object') return [];
6
+ if (['write', 'edit'].includes(tool)) return [input.path ?? input.filePath ?? input.file_path].filter(path => typeof path === 'string');
7
+ if (tool === 'patch' || tool === 'apply_patch') {
8
+ const patch = input.patch ?? input.patchText;
9
+ return typeof patch === 'string' ? [...patch.matchAll(/^\*\*\* (?:Add File|Update File|Delete File|Move to): (.+)$/gm)].map(match => match[1]) : [];
10
+ }
11
+ return [];
12
+ }
13
+
14
+ export async function registerImpact(ctx, root) {
15
+ await ctx.tool.hook('execute.after', async event => {
16
+ if (event.status !== 'completed' || !await isLocalSession(ctx, event.sessionID)) return;
17
+ const paths = editedPaths(event.tool, event.input);
18
+ if (paths.length) new ImpactState(root, event.sessionID).mark(paths);
19
+ });
20
+ await ctx.session.hook('context', async event => {
21
+ if (!await isLocalSession(ctx, event.sessionID)) return;
22
+ const reminder = impactReminder(new ImpactState(root, event.sessionID).status());
23
+ if (reminder) event.system.push({ type: 'text', text: reminder });
24
+ });
25
+ }
package/src/index.mjs ADDED
@@ -0,0 +1,17 @@
1
+ import { resolve } from 'node:path';
2
+ import { registerResources } from './resources.mjs';
3
+ import { registerMcp } from './mcp.mjs';
4
+ import { registerPlan } from './plan.mjs';
5
+ import { registerImpact } from './impact.mjs';
6
+
7
+ export default {
8
+ id: 'dotdotgod',
9
+ async setup(ctx) {
10
+ // Use the active checkout, never the canonical checkout of another worktree.
11
+ const root = resolve(ctx.location.project.directory ?? ctx.location.directory);
12
+ await registerResources(ctx);
13
+ await registerMcp(ctx, root);
14
+ await registerPlan(ctx, root);
15
+ await registerImpact(ctx, root);
16
+ },
17
+ };
@@ -0,0 +1,7 @@
1
+ import { realpathSync } from 'node:fs';
2
+
3
+ // Server-wide hooks can see sessions from other loaded locations.
4
+ export async function isLocalSession(ctx, sessionID) {
5
+ const session = await ctx.session.get({ sessionID });
6
+ return realpathSync(session.location.directory) === realpathSync(ctx.location.directory);
7
+ }
package/src/mcp.mjs ADDED
@@ -0,0 +1,37 @@
1
+ import { fileURLToPath } from 'node:url';
2
+
3
+ const prefix = 'dotdotgod_context_';
4
+ const readOnly = new Set(['project_load', 'project_impact', 'impact_status', 'embedding_status', 'index', 'search', 'fetch_and_index', 'stats', 'doctor', 'session_resume', 'ingestion_job_start', 'ingestion_job_status']);
5
+ const quote = value => /^[\w./:-]+$/.test(String(value)) ? String(value) : `'${String(value).replaceAll("'", "'\\''")}'`;
6
+
7
+ export async function registerMcp(ctx, root) {
8
+ await ctx.mcp.transform(editor => {
9
+ if (editor.get('dotdotgod_context')) return;
10
+ editor.set('dotdotgod_context', {
11
+ type: 'local', command: ['node', fileURLToPath(new URL('../mcp/server.mjs', import.meta.url))],
12
+ cwd: root, environment: { DOTDOTGOD_PROJECT_ROOT: root }, codemode: true,
13
+ });
14
+ });
15
+ await ctx.tool.transform(editor => {
16
+ for (const tool of editor.list()) {
17
+ if (!tool.id.startsWith(prefix)) continue;
18
+ editor.update(tool.id, draft => {
19
+ const execute = draft.execute;
20
+ const name = tool.id.slice(prefix.length);
21
+ draft.execute = async (input, context) => {
22
+ // Actual executor context, not model-selected session identity. This
23
+ // wrapper also runs when the tool is called through Code Mode.
24
+ if (context.agent === 'plan' && !readOnly.has(name)) throw new Error('Plan mode: this write-capable MCP operation requires switching agents.');
25
+ if (name === 'execute') {
26
+ for (const entry of input.commands ?? []) await ctx.permission.assert({
27
+ sessionID: context.sessionID, agent: context.agent,
28
+ source: { type: 'tool', messageID: context.messageID, id: context.id },
29
+ action: 'shell', resources: [entry.executable ? [entry.executable, ...(entry.args ?? [])].map(quote).join(' ') : entry.command ?? ''],
30
+ });
31
+ }
32
+ return execute({ ...input, contextSessionId: context.sessionID }, context);
33
+ };
34
+ });
35
+ }
36
+ });
37
+ }