opencode-conductor-cdd-plugin 1.0.0-beta.19 → 1.0.0-beta.20

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/README.md CHANGED
@@ -92,18 +92,31 @@ We highly recommend pinning the `@cdd` agent to a "flash" model for optimal perf
92
92
 
93
93
  ### oh-my-opencode-slim Config
94
94
  **File:** `~/.config/opencode/oh-my-opencode-slim.json`
95
+
96
+ **⚠️ Important**: For synergy to activate with oh-my-opencode-slim, you **must** configure a `cdd` agent in the config file. The presence of the file alone is not sufficient.
97
+
95
98
  ```json
96
99
  {
97
100
  "agents": {
98
101
  "cdd": {
99
102
  "model": "anthropic/claude-3-5-sonnet"
103
+ },
104
+ "designer": {
105
+ "model": "google/gemini-flash-1.5"
106
+ },
107
+ "explorer": {
108
+ "model": "google/gemini-flash-1.5"
100
109
  }
101
110
  }
102
111
  }
103
112
  ```
104
113
 
105
114
  **Framework Detection Priority:**
106
- When multiple synergy frameworks are detected, Conductor CDD prioritizes oh-my-opencode-slim over oh-my-opencode. If neither framework config is found, Conductor operates in manual mode.
115
+ When multiple synergy frameworks are detected, Conductor CDD prioritizes oh-my-opencode-slim over oh-my-opencode. However, synergy will **only activate** if the selected framework has a `cdd` agent explicitly configured:
116
+
117
+ 1. **Check slim**: If `~/.config/opencode/oh-my-opencode-slim.json` exists **and** has `agents.cdd` → use slim (highest priority)
118
+ 2. **Check OMO**: If `~/.config/opencode/oh-my-opencode.json` exists **and** has `agents.cdd` → use OMO (fallback)
119
+ 3. **No synergy**: If neither config has a `cdd` agent → Conductor operates in manual mode
107
120
 
108
121
  **Agent Mappings for oh-my-opencode-slim:**
109
122
  Conductor CDD automatically maps generic agent names to slim-specific agent names:
@@ -140,9 +153,12 @@ When using **OhMyOpenCode**, `@cdd` acts as your Technical Lead. While **Sisyphu
140
153
  ### oh-my-opencode-slim Integration
141
154
  When using **oh-my-opencode-slim**, `@cdd` integrates with the lightweight agent framework, automatically mapping to slim-specific agents like `explorer`, `designer`, and `librarian` for specialized tasks.
142
155
 
156
+ **Requirements**: You **must** configure a `cdd` agent in your `oh-my-opencode-slim.json` for synergy to activate. Simply having the file present is not sufficient.
157
+
143
158
  ### Key Features
144
- - **Automatic Detection**: Conductor CDD automatically detects which framework you're using (if any)
145
- - **Priority Resolution**: When both frameworks are present, oh-my-opencode-slim takes priority
159
+ - **Automatic Detection**: Conductor CDD automatically detects which framework you're using based on the presence of a `cdd` agent in the config
160
+ - **Strict CDD Requirement**: Synergy only activates if the framework config explicitly includes a `cdd` agent (file presence alone is insufficient)
161
+ - **Priority Resolution**: When both frameworks have a `cdd` agent configured, oh-my-opencode-slim takes priority
146
162
  - **Agent Mapping**: Generic agent names are automatically mapped to framework-specific names
147
163
  - **Graceful Fallback**: If a requested agent is unavailable or disabled, tasks fall back to `@cdd`
148
164
  - **Loop Protection**: Built-in safeguards ensure no conflicts with framework continuation enforcers during interactive Q&A
@@ -1,10 +1,22 @@
1
1
  export type SynergyFramework = 'none' | 'oh-my-opencode' | 'oh-my-opencode-slim';
2
+ /**
3
+ * Result of CDD configuration detection across multiple config files.
4
+ * Checks ~/.config/opencode/{opencode.json, oh-my-opencode.json, oh-my-opencode-slim.json}
5
+ */
2
6
  export interface ConfigDetectionResult {
7
+ /** Whether CDD agent is configured in opencode.json */
3
8
  hasCDDInOpenCode: boolean;
9
+ /** Whether CDD agent is configured in oh-my-opencode.json */
4
10
  hasCDDInOMO: boolean;
11
+ /** Whether CDD agent is configured in oh-my-opencode-slim.json */
12
+ hasCDDInSlim: boolean;
13
+ /** Whether synergy mode should be activated (true if any synergy framework detected) */
5
14
  synergyActive: boolean;
15
+ /** The CDD model string extracted from configs (priority: slim > OMO > opencode) */
6
16
  cddModel?: string;
17
+ /** Which synergy framework to use (priority: slim > OMO > none) */
7
18
  synergyFramework: SynergyFramework;
19
+ /** Available agents from slim config (filtered by disabled_agents) */
8
20
  slimAgents?: string[];
9
21
  }
10
22
  export declare function detectCDDConfig(): ConfigDetectionResult;
@@ -8,6 +8,7 @@ export function detectCDDConfig() {
8
8
  const slimJsonPath = join(opencodeConfigDir, "oh-my-opencode-slim.json");
9
9
  let hasCDDInOpenCode = false;
10
10
  let hasCDDInOMO = false;
11
+ let hasCDDInSlim = false;
11
12
  let cddModel;
12
13
  let synergyFramework = 'none';
13
14
  let slimAgents;
@@ -17,8 +18,16 @@ export function detectCDDConfig() {
17
18
  const config = JSON.parse(readFileSync(slimJsonPath, "utf-8"));
18
19
  // Check if config is not empty and has actual content
19
20
  if (config && Object.keys(config).length > 0) {
20
- synergyFramework = 'oh-my-opencode-slim';
21
- // Extract available agents (filter out disabled ones)
21
+ // Check for CDD agent in slim config (strict detection)
22
+ if (config.agents && config.agents.cdd) {
23
+ hasCDDInSlim = true;
24
+ synergyFramework = 'oh-my-opencode-slim';
25
+ // Extract model from slim config (priority over OMO and opencode.json)
26
+ if (config.agents.cdd.model) {
27
+ cddModel = config.agents.cdd.model;
28
+ }
29
+ }
30
+ // Extract available agents (filter out disabled ones) regardless of CDD presence
22
31
  const coreAgents = ['explorer', 'librarian', 'oracle', 'designer'];
23
32
  const disabledAgents = new Set(config.disabled_agents ?? []);
24
33
  slimAgents = coreAgents.filter(agent => !disabledAgents.has(agent));
@@ -28,15 +37,19 @@ export function detectCDDConfig() {
28
37
  // Silently fail on parse errors
29
38
  }
30
39
  }
31
- // Check oh-my-opencode.json (only if slim is not active)
32
- if (synergyFramework === 'none' && existsSync(omoJsonPath)) {
40
+ // Check oh-my-opencode.json (only if slim doesn't have CDD)
41
+ // NOTE: We still check OMO to set hasCDDInOMO flag even if slim has priority
42
+ if (existsSync(omoJsonPath)) {
33
43
  try {
34
44
  const config = JSON.parse(readFileSync(omoJsonPath, "utf-8"));
35
45
  if (config.agents && config.agents.cdd) {
36
46
  hasCDDInOMO = true;
37
- synergyFramework = 'oh-my-opencode';
38
- // Extract model from oh-my-opencode.json
39
- if (config.agents.cdd.model) {
47
+ // Only activate OMO synergy if slim doesn't have CDD (slim takes priority)
48
+ if (synergyFramework === 'none') {
49
+ synergyFramework = 'oh-my-opencode';
50
+ }
51
+ // Extract model from oh-my-opencode.json (only if not already set by slim)
52
+ if (!cddModel && config.agents.cdd.model) {
40
53
  cddModel = config.agents.cdd.model;
41
54
  }
42
55
  }
@@ -45,13 +58,13 @@ export function detectCDDConfig() {
45
58
  // Silently fail on parse errors
46
59
  }
47
60
  }
48
- // Check opencode.json (fallback if model not found in OMO)
61
+ // Check opencode.json (fallback if model not found in slim or OMO)
49
62
  if (existsSync(opencodeJsonPath)) {
50
63
  try {
51
64
  const config = JSON.parse(readFileSync(opencodeJsonPath, "utf-8"));
52
65
  if (config.agent && config.agent.cdd) {
53
66
  hasCDDInOpenCode = true;
54
- // Only use this model if we didn't find one in oh-my-opencode.json
67
+ // Only use this model if we didn't find one in slim or oh-my-opencode.json
55
68
  if (!cddModel && config.agent.cdd.model) {
56
69
  cddModel = config.agent.cdd.model;
57
70
  }
@@ -64,6 +77,7 @@ export function detectCDDConfig() {
64
77
  return {
65
78
  hasCDDInOpenCode,
66
79
  hasCDDInOMO,
80
+ hasCDDInSlim,
67
81
  synergyActive: synergyFramework !== 'none',
68
82
  cddModel,
69
83
  synergyFramework,
@@ -119,7 +119,7 @@ describe("configDetection", () => {
119
119
  });
120
120
  // New tests for oh-my-opencode-slim detection
121
121
  describe("oh-my-opencode-slim detection", () => {
122
- it("should detect oh-my-opencode-slim when only slim config is present", () => {
122
+ it("should NOT detect synergy when slim config has no cdd agent", () => {
123
123
  vi.mocked(existsSync).mockImplementation((path) => path === slimJsonPath);
124
124
  vi.mocked(readFileSync).mockImplementation((path) => {
125
125
  if (path === slimJsonPath) {
@@ -130,11 +130,11 @@ describe("configDetection", () => {
130
130
  return "";
131
131
  });
132
132
  const result = detectCDDConfig();
133
- expect(result.synergyActive).toBe(true);
134
- expect(result.synergyFramework).toBe('oh-my-opencode-slim');
133
+ expect(result.synergyActive).toBe(false);
134
+ expect(result.synergyFramework).toBe('none');
135
135
  expect(result.slimAgents).toEqual(['explorer', 'librarian', 'oracle', 'designer']);
136
136
  });
137
- it("should prioritize oh-my-opencode-slim over oh-my-opencode when both present", () => {
137
+ it("should prioritize oh-my-opencode over slim when slim has no cdd agent", () => {
138
138
  vi.mocked(existsSync).mockReturnValue(true);
139
139
  vi.mocked(readFileSync).mockImplementation((path) => {
140
140
  if (path === slimJsonPath) {
@@ -146,10 +146,11 @@ describe("configDetection", () => {
146
146
  return "";
147
147
  });
148
148
  const result = detectCDDConfig();
149
- expect(result.synergyFramework).toBe('oh-my-opencode-slim');
149
+ expect(result.synergyFramework).toBe('oh-my-opencode');
150
150
  expect(result.synergyActive).toBe(true);
151
+ expect(result.cddModel).toBe('model-from-omo');
151
152
  });
152
- it("should filter out disabled agents from slim config", () => {
153
+ it("should filter out disabled agents from slim config (but require cdd for synergy)", () => {
153
154
  vi.mocked(existsSync).mockImplementation((path) => path === slimJsonPath);
154
155
  vi.mocked(readFileSync).mockImplementation((path) => {
155
156
  if (path === slimJsonPath) {
@@ -160,7 +161,8 @@ describe("configDetection", () => {
160
161
  return "";
161
162
  });
162
163
  const result = detectCDDConfig();
163
- expect(result.synergyFramework).toBe('oh-my-opencode-slim');
164
+ expect(result.synergyFramework).toBe('none');
165
+ expect(result.synergyActive).toBe(false);
164
166
  expect(result.slimAgents).toEqual(['explorer', 'librarian']);
165
167
  });
166
168
  it("should handle empty oh-my-opencode-slim config", () => {
@@ -203,4 +205,199 @@ describe("configDetection", () => {
203
205
  expect(result.synergyActive).toBe(false);
204
206
  });
205
207
  });
208
+ // New tests for CDD agent detection in oh-my-opencode-slim
209
+ describe("CDD agent detection in oh-my-opencode-slim", () => {
210
+ it("should detect cdd agent in slim config and activate synergy", () => {
211
+ vi.mocked(existsSync).mockImplementation((path) => path === slimJsonPath);
212
+ vi.mocked(readFileSync).mockImplementation((path) => {
213
+ if (path === slimJsonPath) {
214
+ return JSON.stringify({
215
+ agents: {
216
+ cdd: { model: "anthropic/claude-3-5-sonnet" },
217
+ designer: { model: "google/gemini-3-flash" }
218
+ }
219
+ });
220
+ }
221
+ return "";
222
+ });
223
+ const result = detectCDDConfig();
224
+ expect(result.hasCDDInSlim).toBe(true);
225
+ expect(result.synergyFramework).toBe('oh-my-opencode-slim');
226
+ expect(result.synergyActive).toBe(true);
227
+ expect(result.cddModel).toBe("anthropic/claude-3-5-sonnet");
228
+ });
229
+ it("should not activate synergy when slim config exists but no cdd agent", () => {
230
+ vi.mocked(existsSync).mockImplementation((path) => path === slimJsonPath);
231
+ vi.mocked(readFileSync).mockImplementation((path) => {
232
+ if (path === slimJsonPath) {
233
+ return JSON.stringify({
234
+ agents: {
235
+ designer: { model: "google/gemini-3-flash" }
236
+ }
237
+ });
238
+ }
239
+ return "";
240
+ });
241
+ const result = detectCDDConfig();
242
+ expect(result.hasCDDInSlim).toBe(false);
243
+ expect(result.synergyFramework).toBe('none');
244
+ expect(result.synergyActive).toBe(false);
245
+ });
246
+ it("should not activate synergy when slim config has empty agents object", () => {
247
+ vi.mocked(existsSync).mockImplementation((path) => path === slimJsonPath);
248
+ vi.mocked(readFileSync).mockImplementation((path) => {
249
+ if (path === slimJsonPath) {
250
+ return JSON.stringify({ agents: {} });
251
+ }
252
+ return "";
253
+ });
254
+ const result = detectCDDConfig();
255
+ expect(result.hasCDDInSlim).toBe(false);
256
+ expect(result.synergyFramework).toBe('none');
257
+ expect(result.synergyActive).toBe(false);
258
+ });
259
+ it("should handle malformed slim config gracefully with hasCDDInSlim false", () => {
260
+ vi.mocked(existsSync).mockImplementation((path) => path === slimJsonPath);
261
+ vi.mocked(readFileSync).mockImplementation((path) => {
262
+ if (path === slimJsonPath) {
263
+ return "invalid json";
264
+ }
265
+ return "";
266
+ });
267
+ const result = detectCDDConfig();
268
+ expect(result.hasCDDInSlim).toBe(false);
269
+ expect(result.synergyFramework).toBe('none');
270
+ expect(result.synergyActive).toBe(false);
271
+ });
272
+ it("should extract cdd model from slim config when present", () => {
273
+ vi.mocked(existsSync).mockImplementation((path) => path === slimJsonPath);
274
+ vi.mocked(readFileSync).mockImplementation((path) => {
275
+ if (path === slimJsonPath) {
276
+ return JSON.stringify({
277
+ agents: {
278
+ cdd: { model: "anthropic/claude-3-5-haiku" }
279
+ }
280
+ });
281
+ }
282
+ return "";
283
+ });
284
+ const result = detectCDDConfig();
285
+ expect(result.cddModel).toBe("anthropic/claude-3-5-haiku");
286
+ expect(result.hasCDDInSlim).toBe(true);
287
+ });
288
+ it("should handle cdd agent without model field in slim", () => {
289
+ vi.mocked(existsSync).mockImplementation((path) => path === slimJsonPath);
290
+ vi.mocked(readFileSync).mockImplementation((path) => {
291
+ if (path === slimJsonPath) {
292
+ return JSON.stringify({
293
+ agents: {
294
+ cdd: {}
295
+ }
296
+ });
297
+ }
298
+ return "";
299
+ });
300
+ const result = detectCDDConfig();
301
+ expect(result.hasCDDInSlim).toBe(true);
302
+ expect(result.cddModel).toBeUndefined();
303
+ });
304
+ it("should prioritize slim model over oh-my-opencode model when both have cdd", () => {
305
+ vi.mocked(existsSync).mockReturnValue(true);
306
+ vi.mocked(readFileSync).mockImplementation((path) => {
307
+ if (path === slimJsonPath) {
308
+ return JSON.stringify({
309
+ agents: {
310
+ cdd: { model: "model-from-slim" }
311
+ }
312
+ });
313
+ }
314
+ if (path === omoJsonPath) {
315
+ return JSON.stringify({
316
+ agents: {
317
+ cdd: { model: "model-from-omo" }
318
+ }
319
+ });
320
+ }
321
+ return "";
322
+ });
323
+ const result = detectCDDConfig();
324
+ expect(result.cddModel).toBe("model-from-slim");
325
+ expect(result.synergyFramework).toBe('oh-my-opencode-slim');
326
+ expect(result.hasCDDInSlim).toBe(true);
327
+ expect(result.hasCDDInOMO).toBe(true);
328
+ });
329
+ it("should select oh-my-opencode when only OMO has cdd", () => {
330
+ vi.mocked(existsSync).mockReturnValue(true);
331
+ vi.mocked(readFileSync).mockImplementation((path) => {
332
+ if (path === slimJsonPath) {
333
+ return JSON.stringify({
334
+ agents: {
335
+ designer: { model: "google/gemini-3-flash" }
336
+ }
337
+ });
338
+ }
339
+ if (path === omoJsonPath) {
340
+ return JSON.stringify({
341
+ agents: {
342
+ cdd: { model: "model-from-omo" }
343
+ }
344
+ });
345
+ }
346
+ return "";
347
+ });
348
+ const result = detectCDDConfig();
349
+ expect(result.hasCDDInSlim).toBe(false);
350
+ expect(result.hasCDDInOMO).toBe(true);
351
+ expect(result.synergyFramework).toBe('oh-my-opencode');
352
+ });
353
+ it("should select slim when only slim has cdd", () => {
354
+ vi.mocked(existsSync).mockReturnValue(true);
355
+ vi.mocked(readFileSync).mockImplementation((path) => {
356
+ if (path === slimJsonPath) {
357
+ return JSON.stringify({
358
+ agents: {
359
+ cdd: { model: "model-from-slim" }
360
+ }
361
+ });
362
+ }
363
+ if (path === omoJsonPath) {
364
+ return JSON.stringify({
365
+ agents: {
366
+ sisyphus: { model: "google/gemini-3-flash" }
367
+ }
368
+ });
369
+ }
370
+ return "";
371
+ });
372
+ const result = detectCDDConfig();
373
+ expect(result.hasCDDInSlim).toBe(true);
374
+ expect(result.hasCDDInOMO).toBe(false);
375
+ expect(result.synergyFramework).toBe('oh-my-opencode-slim');
376
+ });
377
+ it("should not activate synergy when neither framework has cdd", () => {
378
+ vi.mocked(existsSync).mockReturnValue(true);
379
+ vi.mocked(readFileSync).mockImplementation((path) => {
380
+ if (path === slimJsonPath) {
381
+ return JSON.stringify({
382
+ agents: {
383
+ designer: { model: "google/gemini-3-flash" }
384
+ }
385
+ });
386
+ }
387
+ if (path === omoJsonPath) {
388
+ return JSON.stringify({
389
+ agents: {
390
+ sisyphus: { model: "google/gemini-3-flash" }
391
+ }
392
+ });
393
+ }
394
+ return "";
395
+ });
396
+ const result = detectCDDConfig();
397
+ expect(result.hasCDDInSlim).toBe(false);
398
+ expect(result.hasCDDInOMO).toBe(false);
399
+ expect(result.synergyFramework).toBe('none');
400
+ expect(result.synergyActive).toBe(false);
401
+ });
402
+ });
206
403
  });
@@ -15,6 +15,7 @@ describe("synergyState", () => {
15
15
  vi.mocked(detectCDDConfig).mockReturnValue({
16
16
  hasCDDInOpenCode: false,
17
17
  hasCDDInOMO: false,
18
+ hasCDDInSlim: true,
18
19
  synergyActive: true,
19
20
  synergyFramework: 'oh-my-opencode-slim',
20
21
  slimAgents: ['explorer', 'librarian', 'oracle', 'designer'],
@@ -28,6 +29,7 @@ describe("synergyState", () => {
28
29
  vi.mocked(detectCDDConfig).mockReturnValue({
29
30
  hasCDDInOpenCode: false,
30
31
  hasCDDInOMO: false,
32
+ hasCDDInSlim: true,
31
33
  synergyActive: true,
32
34
  synergyFramework: 'oh-my-opencode-slim',
33
35
  slimAgents: ['explorer', 'librarian'],
@@ -42,6 +44,7 @@ describe("synergyState", () => {
42
44
  .mockReturnValueOnce({
43
45
  hasCDDInOpenCode: false,
44
46
  hasCDDInOMO: false,
47
+ hasCDDInSlim: true,
45
48
  synergyActive: true,
46
49
  synergyFramework: 'oh-my-opencode-slim',
47
50
  slimAgents: ['explorer'],
@@ -49,6 +52,7 @@ describe("synergyState", () => {
49
52
  .mockReturnValueOnce({
50
53
  hasCDDInOpenCode: false,
51
54
  hasCDDInOMO: true,
55
+ hasCDDInSlim: false,
52
56
  synergyActive: true,
53
57
  synergyFramework: 'oh-my-opencode',
54
58
  cddModel: 'model-1',
@@ -64,13 +68,15 @@ describe("synergyState", () => {
64
68
  .mockReturnValueOnce({
65
69
  hasCDDInOpenCode: false,
66
70
  hasCDDInOMO: false,
71
+ hasCDDInSlim: true,
67
72
  synergyActive: true,
68
73
  synergyFramework: 'oh-my-opencode-slim',
69
74
  slimAgents: ['explorer'],
70
75
  })
71
76
  .mockReturnValueOnce({
72
77
  hasCDDInOpenCode: false,
73
- hasCDDInOMO: false,
78
+ hasCDDInOMO: true,
79
+ hasCDDInSlim: false,
74
80
  synergyActive: true,
75
81
  synergyFramework: 'oh-my-opencode',
76
82
  cddModel: 'model-changed',
@@ -85,6 +91,7 @@ describe("synergyState", () => {
85
91
  vi.mocked(detectCDDConfig).mockReturnValue({
86
92
  hasCDDInOpenCode: true,
87
93
  hasCDDInOMO: false,
94
+ hasCDDInSlim: false,
88
95
  synergyActive: false,
89
96
  synergyFramework: 'none',
90
97
  cddModel: 'model-1',
@@ -99,13 +106,15 @@ describe("synergyState", () => {
99
106
  .mockReturnValueOnce({
100
107
  hasCDDInOpenCode: false,
101
108
  hasCDDInOMO: false,
109
+ hasCDDInSlim: true,
102
110
  synergyActive: true,
103
111
  synergyFramework: 'oh-my-opencode-slim',
104
112
  slimAgents: ['explorer'],
105
113
  })
106
114
  .mockReturnValueOnce({
107
115
  hasCDDInOpenCode: false,
108
- hasCDDInOMO: false,
116
+ hasCDDInOMO: true,
117
+ hasCDDInSlim: false,
109
118
  synergyActive: true,
110
119
  synergyFramework: 'oh-my-opencode',
111
120
  cddModel: 'model-1',
@@ -124,6 +133,7 @@ describe("synergyState", () => {
124
133
  vi.mocked(detectCDDConfig).mockReturnValue({
125
134
  hasCDDInOpenCode: false,
126
135
  hasCDDInOMO: false,
136
+ hasCDDInSlim: false,
127
137
  synergyActive: false,
128
138
  synergyFramework: 'none',
129
139
  });
@@ -136,6 +146,7 @@ describe("synergyState", () => {
136
146
  vi.mocked(detectCDDConfig).mockReturnValue({
137
147
  hasCDDInOpenCode: false,
138
148
  hasCDDInOMO: false,
149
+ hasCDDInSlim: true,
139
150
  synergyActive: true,
140
151
  synergyFramework: 'oh-my-opencode-slim',
141
152
  slimAgents: ['explorer', 'oracle'],
@@ -147,6 +158,7 @@ describe("synergyState", () => {
147
158
  vi.mocked(detectCDDConfig).mockReturnValue({
148
159
  hasCDDInOpenCode: false,
149
160
  hasCDDInOMO: true,
161
+ hasCDDInSlim: false,
150
162
  synergyActive: true,
151
163
  synergyFramework: 'oh-my-opencode',
152
164
  cddModel: 'model-1',
@@ -163,13 +175,15 @@ describe("synergyState", () => {
163
175
  .mockReturnValueOnce({
164
176
  hasCDDInOpenCode: false,
165
177
  hasCDDInOMO: false,
178
+ hasCDDInSlim: true,
166
179
  synergyActive: true,
167
180
  synergyFramework: 'oh-my-opencode-slim',
168
181
  slimAgents: ['explorer'],
169
182
  })
170
183
  .mockReturnValueOnce({
171
184
  hasCDDInOpenCode: false,
172
- hasCDDInOMO: false,
185
+ hasCDDInOMO: true,
186
+ hasCDDInSlim: false,
173
187
  synergyActive: true,
174
188
  synergyFramework: 'oh-my-opencode',
175
189
  cddModel: 'changed',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-conductor-cdd-plugin",
3
- "version": "1.0.0-beta.19",
3
+ "version": "1.0.0-beta.20",
4
4
  "description": "Context-Driven Development (CDD) plugin for OpenCode - Transform your AI coding workflow with structured specifications, plans, and implementation tracking",
5
5
  "type": "module",
6
6
  "repository": {
@@ -53,6 +53,7 @@
53
53
  "@semantic-release/npm": "^12.0.1",
54
54
  "@semantic-release/release-notes-generator": "^14.0.0",
55
55
  "@types/node": "^20.0.0",
56
+ "@vitest/coverage-v8": "^4.0.17",
56
57
  "semantic-release": "^24.2.1",
57
58
  "typescript": "^5.0.0",
58
59
  "vitest": "^4.0.16"