gsd-opencode 1.20.2 → 1.20.4
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/commands/gsd/gsd-check-profile.md +30 -0
- package/get-shit-done/bin/gsd-oc-commands/allow-read-config.cjs +235 -0
- package/get-shit-done/bin/gsd-oc-commands/check-oc-config-json.cjs +169 -0
- package/get-shit-done/bin/gsd-oc-commands/check-opencode-json.cjs +86 -0
- package/get-shit-done/bin/gsd-oc-commands/get-profile.cjs +117 -0
- package/get-shit-done/bin/gsd-oc-commands/set-profile.cjs +357 -0
- package/get-shit-done/bin/gsd-oc-commands/update-opencode-json.cjs +199 -0
- package/get-shit-done/bin/gsd-oc-commands/validate-models.cjs +75 -0
- package/get-shit-done/bin/gsd-oc-lib/oc-config.cjs +205 -0
- package/get-shit-done/bin/gsd-oc-lib/oc-core.cjs +113 -0
- package/get-shit-done/bin/gsd-oc-lib/oc-models.cjs +133 -0
- package/get-shit-done/bin/gsd-oc-lib/oc-profile-config.cjs +409 -0
- package/get-shit-done/bin/gsd-oc-tools.cjs +136 -0
- package/get-shit-done/bin/lib/oc-config.cjs +200 -0
- package/get-shit-done/bin/lib/oc-core.cjs +114 -0
- package/get-shit-done/bin/lib/oc-models.cjs +133 -0
- package/get-shit-done/bin/test/allow-read-config.test.cjs +262 -0
- package/get-shit-done/bin/test/fixtures/oc-config-invalid.json +14 -0
- package/get-shit-done/bin/test/fixtures/oc-config-valid.json +22 -0
- package/get-shit-done/bin/test/get-profile.test.cjs +447 -0
- package/get-shit-done/bin/test/oc-profile-config.test.cjs +377 -0
- package/get-shit-done/bin/test/pivot-profile.test.cjs +276 -0
- package/get-shit-done/bin/test/set-profile.test.cjs +301 -0
- package/get-shit-done/workflows/oc-check-profile.md +181 -0
- package/get-shit-done/workflows/oc-set-profile.md +98 -234
- package/get-shit-done/workflows/settings.md +4 -3
- package/package.json +2 -2
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for set-profile.cjs
|
|
3
|
+
*
|
|
4
|
+
* Tests for profile switching, validation, and the three operation modes:
|
|
5
|
+
* 1. Mode 1 (no profile name): Validate and apply current profile
|
|
6
|
+
* 2. Mode 2 (profile name): Switch to specified profile
|
|
7
|
+
* 3. Mode 3 (inline JSON): Create new profile from definition
|
|
8
|
+
*
|
|
9
|
+
* Includes validation checks, dry-run functionality, and rollback mechanisms.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
13
|
+
import fs from 'fs';
|
|
14
|
+
import path from 'path';
|
|
15
|
+
import os from 'os';
|
|
16
|
+
|
|
17
|
+
// Mock console.log and console.error to capture output
|
|
18
|
+
const originalLog = console.log;
|
|
19
|
+
const originalError = console.error;
|
|
20
|
+
const originalExit = process.exit;
|
|
21
|
+
|
|
22
|
+
// Test fixtures
|
|
23
|
+
const VALID_CONFIG = {
|
|
24
|
+
current_oc_profile: 'smart',
|
|
25
|
+
profiles: {
|
|
26
|
+
presets: {
|
|
27
|
+
simple: {
|
|
28
|
+
planning: 'bailian-coding-plan/qwen3.5-plus',
|
|
29
|
+
execution: 'bailian-coding-plan/qwen3.5-plus',
|
|
30
|
+
verification: 'bailian-coding-plan/qwen3.5-plus'
|
|
31
|
+
},
|
|
32
|
+
smart: {
|
|
33
|
+
planning: 'bailian-coding-plan/qwen3.5-plus',
|
|
34
|
+
execution: 'bailian-coding-plan/qwen3.5-plus',
|
|
35
|
+
verification: 'bailian-coding-plan/qwen3.5-plus'
|
|
36
|
+
},
|
|
37
|
+
genius: {
|
|
38
|
+
planning: 'bailian-coding-plan/qwen3.5-plus',
|
|
39
|
+
execution: 'bailian-coding-plan/qwen3.5-plus',
|
|
40
|
+
verification: 'bailian-coding-plan/qwen3.5-plus'
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
describe('set-profile.cjs', () => {
|
|
47
|
+
let testDir;
|
|
48
|
+
let planningDir;
|
|
49
|
+
let configPath;
|
|
50
|
+
let opencodePath;
|
|
51
|
+
let capturedLog;
|
|
52
|
+
let capturedError;
|
|
53
|
+
let exitCode;
|
|
54
|
+
let allLogs;
|
|
55
|
+
let allErrors;
|
|
56
|
+
|
|
57
|
+
beforeEach(() => {
|
|
58
|
+
// Create isolated test directory
|
|
59
|
+
testDir = fs.mkdtempSync(path.join(os.tmpdir(), 'set-profile-test-'));
|
|
60
|
+
planningDir = path.join(testDir, '.planning');
|
|
61
|
+
configPath = path.join(planningDir, 'oc_config.json');
|
|
62
|
+
opencodePath = path.join(testDir, 'opencode.json');
|
|
63
|
+
|
|
64
|
+
fs.mkdirSync(planningDir, { recursive: true });
|
|
65
|
+
|
|
66
|
+
// Reset captured output
|
|
67
|
+
capturedLog = null;
|
|
68
|
+
capturedError = null;
|
|
69
|
+
exitCode = null;
|
|
70
|
+
allLogs = [];
|
|
71
|
+
allErrors = [];
|
|
72
|
+
|
|
73
|
+
// Mock console.log to capture all output
|
|
74
|
+
console.log = (msg) => {
|
|
75
|
+
allLogs.push(msg);
|
|
76
|
+
capturedLog = msg;
|
|
77
|
+
};
|
|
78
|
+
console.error = (msg) => {
|
|
79
|
+
allErrors.push(msg);
|
|
80
|
+
capturedError = msg;
|
|
81
|
+
};
|
|
82
|
+
process.exit = (code) => {
|
|
83
|
+
exitCode = code;
|
|
84
|
+
throw new Error(`process.exit(${code})`);
|
|
85
|
+
};
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
afterEach(() => {
|
|
89
|
+
// Restore original functions
|
|
90
|
+
console.log = originalLog;
|
|
91
|
+
console.error = originalError;
|
|
92
|
+
process.exit = originalExit;
|
|
93
|
+
|
|
94
|
+
// Cleanup test directory
|
|
95
|
+
try {
|
|
96
|
+
fs.rmSync(testDir, { recursive: true, force: true });
|
|
97
|
+
} catch (err) {
|
|
98
|
+
// Ignore cleanup errors
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// Import setProfile inside tests to use mocked functions
|
|
103
|
+
const importSetProfile = () => {
|
|
104
|
+
const modulePath = '../gsd-oc-commands/set-profile.cjs';
|
|
105
|
+
delete require.cache[require.resolve(modulePath)];
|
|
106
|
+
return require(modulePath);
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
describe('Export verification', () => {
|
|
110
|
+
it('exports setProfile function', () => {
|
|
111
|
+
const setProfile = importSetProfile();
|
|
112
|
+
expect(typeof setProfile).toBe('function');
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('function name is setProfile', () => {
|
|
116
|
+
const setProfile = importSetProfile();
|
|
117
|
+
expect(setProfile.name).toBe('setProfilePhase16'); // Function was renamed from phase16
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
describe('Basic functionality', () => {
|
|
122
|
+
function writeOpencodeJson() {
|
|
123
|
+
const opencode = {
|
|
124
|
+
$schema: 'https://opencode.ai/schema.json',
|
|
125
|
+
agent: {
|
|
126
|
+
'gsd-planner': {
|
|
127
|
+
model: 'bailian-coding-plan/qwen3.5-plus',
|
|
128
|
+
tools: ['*']
|
|
129
|
+
},
|
|
130
|
+
'gsd-executor': {
|
|
131
|
+
model: 'bailian-coding-plan/qwen3.5-plus',
|
|
132
|
+
tools: ['*']
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
fs.writeFileSync(opencodePath, JSON.stringify(opencode, null, 2) + '\n', 'utf8');
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
beforeEach(() => {
|
|
140
|
+
fs.writeFileSync(configPath, JSON.stringify(VALID_CONFIG, null, 2) + '\n', 'utf8');
|
|
141
|
+
writeOpencodeJson();
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it('setProfile updates profile when profile name provided', () => {
|
|
145
|
+
const setProfile = importSetProfile();
|
|
146
|
+
|
|
147
|
+
try {
|
|
148
|
+
setProfile(testDir, ['genius']);
|
|
149
|
+
} catch (err) {
|
|
150
|
+
// Expected to throw due to process.exit mock
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
expect(exitCode).toBe(0);
|
|
154
|
+
const output = JSON.parse(capturedLog);
|
|
155
|
+
expect(output.success).toBe(true);
|
|
156
|
+
expect(output.data.profile).toBe('genius');
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it('setProfile processes dry-run flag', () => {
|
|
160
|
+
const setProfile = importSetProfile();
|
|
161
|
+
|
|
162
|
+
try {
|
|
163
|
+
setProfile(testDir, ['smart', '--dry-run']);
|
|
164
|
+
} catch (err) {
|
|
165
|
+
// Expected
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
expect(exitCode).toBe(0);
|
|
169
|
+
const output = JSON.parse(capturedLog);
|
|
170
|
+
expect(output.success).toBe(true);
|
|
171
|
+
expect(output.data.dryRun).toBe(true);
|
|
172
|
+
expect(output.data.action).toBe('switch_profile');
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
it('setProfile validates required keys for inline profiles', () => {
|
|
176
|
+
const setProfile = importSetProfile();
|
|
177
|
+
const inlineProfile = 'test_profile:{"planning":"bailian-coding-plan/qwen3.5-plus","execution":"bailian-coding-plan/qwen3.5-plus","verification":"bailian-coding-plan/qwen3.5-plus"}';
|
|
178
|
+
|
|
179
|
+
try {
|
|
180
|
+
setProfile(testDir, [inlineProfile]);
|
|
181
|
+
} catch (err) {
|
|
182
|
+
// Expected
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const output = JSON.parse(capturedLog);
|
|
186
|
+
expect(output.success).toBe(true);
|
|
187
|
+
expect(output.data.profile).toBe('test_profile');
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it('setProfile handles Mode 1 (no profile name) scenario', () => {
|
|
191
|
+
const setProfile = importSetProfile();
|
|
192
|
+
|
|
193
|
+
try {
|
|
194
|
+
setProfile(testDir, []);
|
|
195
|
+
} catch (err) {
|
|
196
|
+
// Expected
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
expect(exitCode).toBe(0);
|
|
200
|
+
const output = JSON.parse(capturedLog);
|
|
201
|
+
expect(output.success).toBe(true);
|
|
202
|
+
expect(output.data.profile).toBe('smart'); // From initial current_oc_profile
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
it('setProfile validates invalid models before modification', () => {
|
|
206
|
+
const setProfile = importSetProfile();
|
|
207
|
+
const inlineProfile = 'bad_profile:{"planning":"bad_model","execution":"bad_model","verification":"bad_model"}';
|
|
208
|
+
|
|
209
|
+
try {
|
|
210
|
+
setProfile(testDir, [inlineProfile]);
|
|
211
|
+
} catch (err) {
|
|
212
|
+
// Expected - should error
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
expect(exitCode).toBe(1);
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
it('setProfile rejects invalid inline profile definitions', () => {
|
|
219
|
+
const setProfile = importSetProfile();
|
|
220
|
+
// Invalid JSON
|
|
221
|
+
const badDef = 'bad_profile:{"planning:"model","execution":"model","verification":"model"}';
|
|
222
|
+
|
|
223
|
+
try {
|
|
224
|
+
setProfile(testDir, [badDef]);
|
|
225
|
+
} catch (err) {
|
|
226
|
+
// Expected - should error
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
expect(exitCode).toBe(1);
|
|
230
|
+
const error = JSON.parse(capturedError);
|
|
231
|
+
expect(error.error.code).toBe('INVALID_SYNTAX');
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
it('setProfile rejects incomplete profile definitions', () => {
|
|
235
|
+
const setProfile = importSetProfile();
|
|
236
|
+
// Missing verification property
|
|
237
|
+
const badDef = 'bad_profile:{"planning":"bailian-coding-plan/qwen3.5-plus","execution":"bailian-coding-plan/qwen3.5-plus"}';
|
|
238
|
+
|
|
239
|
+
try {
|
|
240
|
+
setProfile(testDir, [badDef]);
|
|
241
|
+
} catch (err) {
|
|
242
|
+
// Expected - should error
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
expect(exitCode).toBe(1);
|
|
246
|
+
const error = JSON.parse(capturedError);
|
|
247
|
+
expect(error.error.code).toBe('INCOMPLETE_PROFILE');
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
describe('Error handling', () => {
|
|
252
|
+
it('handles missing config.json gracefully', () => {
|
|
253
|
+
const setProfile = importSetProfile();
|
|
254
|
+
|
|
255
|
+
try {
|
|
256
|
+
setProfile(testDir, ['test']);
|
|
257
|
+
} catch (err) {
|
|
258
|
+
// Expected to throw
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
expect(exitCode).toBe(1);
|
|
262
|
+
const error = JSON.parse(capturedError);
|
|
263
|
+
expect(error.error.code).toBe('CONFIG_NOT_FOUND');
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
it('sets exit code 1 for invalid profile', () => {
|
|
267
|
+
const setProfile = importSetProfile();
|
|
268
|
+
|
|
269
|
+
// Set up a valid config with presets
|
|
270
|
+
const configData = {...VALID_CONFIG};
|
|
271
|
+
fs.writeFileSync(configPath, JSON.stringify(configData, null, 2) + '\n', 'utf8');
|
|
272
|
+
const opencodeData = {
|
|
273
|
+
$schema: 'https://opencode.ai/schema.json',
|
|
274
|
+
agent: {}
|
|
275
|
+
};
|
|
276
|
+
fs.writeFileSync(opencodePath, JSON.stringify(opencodeData, null, 2) + '\n', 'utf8');
|
|
277
|
+
|
|
278
|
+
try {
|
|
279
|
+
setProfile(testDir, ['non-existent-profile']);
|
|
280
|
+
} catch (err) {
|
|
281
|
+
// Expected
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
expect(exitCode).toBe(1);
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
it('rejects too many arguments', () => {
|
|
288
|
+
const setProfile = importSetProfile();
|
|
289
|
+
|
|
290
|
+
try {
|
|
291
|
+
setProfile(testDir, ['profile1', 'profile2']);
|
|
292
|
+
} catch (err) {
|
|
293
|
+
// Expected
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
expect(exitCode).toBe(1);
|
|
297
|
+
const error = JSON.parse(capturedError);
|
|
298
|
+
expect(error.error.code).toBe('INVALID_ARGS');
|
|
299
|
+
});
|
|
300
|
+
});
|
|
301
|
+
});
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
<role>
|
|
2
|
+
You are executing the `/gsd-check-profile` command. Validate gsd-opencode profile configuration across both `opencode.json` and `.planning/oc_config.json`, then report results.
|
|
3
|
+
|
|
4
|
+
This is a **read-only diagnostic**. Do NOT modify any files or attempt to fix issues. When problems are found, recommend `/gsd-set-profile` and stop.
|
|
5
|
+
</role>
|
|
6
|
+
|
|
7
|
+
<required_reading>
|
|
8
|
+
read all files referenced by the invoking prompt's execution_context before starting.
|
|
9
|
+
</required_reading>
|
|
10
|
+
|
|
11
|
+
<context>
|
|
12
|
+
## What Gets Validated
|
|
13
|
+
|
|
14
|
+
| Check | File | Validates |
|
|
15
|
+
|-------|------|-----------|
|
|
16
|
+
| `check-opencode-json` | `opencode.json` | All agent model IDs exist in the opencode models catalog |
|
|
17
|
+
| `check-config-json` | `.planning/oc_config.json` | gsd-opencode profile structure is valid, current profile exists in presets, all stage model IDs exist in catalog |
|
|
18
|
+
|
|
19
|
+
## CLI Tool
|
|
20
|
+
|
|
21
|
+
All validation runs through `gsd-oc-tools.cjs`. Both commands output a JSON envelope with `success`, `data`, and optional `error` fields. Exit code 0 = valid, exit code 1 = issues found.
|
|
22
|
+
|
|
23
|
+
## JSON Response Shapes
|
|
24
|
+
|
|
25
|
+
**check-opencode-json** (exit 0 or 1):
|
|
26
|
+
```json
|
|
27
|
+
{
|
|
28
|
+
"success": true,
|
|
29
|
+
"data": { "valid": true|false, "total": N, "validCount": N, "invalidCount": N, "issues": [{ "agent": "...", "model": "...", "reason": "..." }] },
|
|
30
|
+
"error": { "code": "INVALID_MODEL_ID", "message": "..." }
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Note: When `opencode.json` does not exist, the tool returns exit 1 with `error.code = "CONFIG_NOT_FOUND"`. This is **not** an error for gsd-opencode profile validation — see Step 2 for handling.
|
|
35
|
+
|
|
36
|
+
**check-config-json** (exit 0 or 1):
|
|
37
|
+
```json
|
|
38
|
+
{
|
|
39
|
+
"success": true|false,
|
|
40
|
+
"data": { "passed": true|false, "current_oc_profile": "...", "profile_data": {...}, "issues": [{ "field": "...", "value": "...", "reason": "..." }] },
|
|
41
|
+
"error": { "code": "INVALID_PROFILE|CONFIG_NOT_FOUND|INVALID_JSON", "message": "..." }
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
</context>
|
|
45
|
+
|
|
46
|
+
<behavior>
|
|
47
|
+
|
|
48
|
+
## Step 1: Run both validations
|
|
49
|
+
|
|
50
|
+
Execute both checks and capture their output and exit codes:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
node ~/.config/opencode/get-shit-done/bin/gsd-oc-tools.cjs check-opencode-json
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
node ~/.config/opencode/get-shit-done/bin/gsd-oc-tools.cjs check-config-json
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Parse both JSON responses.
|
|
61
|
+
|
|
62
|
+
## Step 2: Classify results by severity
|
|
63
|
+
|
|
64
|
+
### opencode.json classification
|
|
65
|
+
|
|
66
|
+
| Tool result | Severity | Meaning |
|
|
67
|
+
|-------------|----------|---------|
|
|
68
|
+
| exit 0, `data.valid = true` | OK | All model IDs valid |
|
|
69
|
+
| exit 1, `error.code = "CONFIG_NOT_FOUND"` | WARNING | No `opencode.json` — agents will use the default/current model. This is acceptable. |
|
|
70
|
+
| exit 1, `error.code = "INVALID_MODEL_ID"` | ERROR | One or more model IDs are invalid. Must be fixed. |
|
|
71
|
+
| exit 1, `error.code = "INVALID_JSON"` | ERROR | File is malformed JSON. Must be fixed. |
|
|
72
|
+
|
|
73
|
+
### .planning/oc_config.json classification
|
|
74
|
+
|
|
75
|
+
| Tool result | Severity | Meaning |
|
|
76
|
+
|-------------|----------|---------|
|
|
77
|
+
| exit 0, `data.passed = true` | OK | gsd-opencode profile configuration valid |
|
|
78
|
+
| exit 1, `error.code = "CONFIG_NOT_FOUND"` | ERROR | No gsd-opencode profile configured yet |
|
|
79
|
+
| exit 1, `error.code = "INVALID_PROFILE"` | ERROR | gsd-opencode profile structure is invalid |
|
|
80
|
+
| exit 1, `error.code = "INVALID_JSON"` | ERROR | File is malformed JSON |
|
|
81
|
+
|
|
82
|
+
## Step 3: Report results
|
|
83
|
+
|
|
84
|
+
Determine the overall status:
|
|
85
|
+
- **All OK (no ERRORs, no WARNINGs)**: report success
|
|
86
|
+
- **WARNINGs only (no ERRORs)**: report success with warnings
|
|
87
|
+
- **Any ERRORs**: report errors with fix instructions
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
### All OK — no errors, no warnings
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
gsd-opencode profile: OK
|
|
95
|
+
|
|
96
|
+
opencode.json All model IDs valid
|
|
97
|
+
.planning/oc_config.json gsd-opencode profile valid
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**Stop here.**
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
### OK with warnings (opencode.json missing, but oc_config.json is valid)
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
gsd-opencode profile: OK
|
|
108
|
+
|
|
109
|
+
opencode.json Not found (agents will use the default/current model)
|
|
110
|
+
.planning/oc_config.json gsd-opencode profile valid
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**Stop here.**
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
### Errors found
|
|
118
|
+
|
|
119
|
+
Display a structured diagnostic. Use the severity labels (WARNING / ERROR) to make the impact clear.
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
gsd-opencode profile: ERRORS FOUND
|
|
123
|
+
|
|
124
|
+
--- opencode.json ---
|
|
125
|
+
|
|
126
|
+
[If OK]
|
|
127
|
+
All model IDs valid
|
|
128
|
+
|
|
129
|
+
[If WARNING — CONFIG_NOT_FOUND]
|
|
130
|
+
WARNING: opencode.json not found. Agents will use the default/current model.
|
|
131
|
+
|
|
132
|
+
[If ERROR — INVALID_MODEL_ID — iterate over data.issues]
|
|
133
|
+
ERROR: {N} invalid model ID(s):
|
|
134
|
+
|
|
135
|
+
Agent: {issue.agent}
|
|
136
|
+
Model: {issue.model}
|
|
137
|
+
Reason: {issue.reason}
|
|
138
|
+
|
|
139
|
+
(repeat for each issue)
|
|
140
|
+
|
|
141
|
+
[If ERROR — INVALID_JSON]
|
|
142
|
+
ERROR: opencode.json is not valid JSON.
|
|
143
|
+
|
|
144
|
+
--- .planning/oc_config.json ---
|
|
145
|
+
|
|
146
|
+
[If OK]
|
|
147
|
+
gsd-opencode profile valid
|
|
148
|
+
|
|
149
|
+
[If ERROR — CONFIG_NOT_FOUND]
|
|
150
|
+
ERROR: .planning/oc_config.json not found — no gsd-opencode profile configured.
|
|
151
|
+
|
|
152
|
+
[If ERROR — INVALID_PROFILE — iterate over data.issues]
|
|
153
|
+
ERROR: {N} gsd-opencode profile issue(s):
|
|
154
|
+
|
|
155
|
+
Field: {issue.field}
|
|
156
|
+
Value: {issue.value}
|
|
157
|
+
Reason: {issue.reason}
|
|
158
|
+
|
|
159
|
+
(repeat for each issue)
|
|
160
|
+
|
|
161
|
+
[If ERROR — INVALID_JSON]
|
|
162
|
+
ERROR: .planning/oc_config.json is not valid JSON.
|
|
163
|
+
|
|
164
|
+
--- Fix ---
|
|
165
|
+
|
|
166
|
+
Run /gsd-set-profile or /gsd-set-profile <simple|smart|genius> to fix gsd-opencode profile configuration.
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
**Stop here.** Do not offer to fix anything. Do not edit files.
|
|
170
|
+
|
|
171
|
+
</behavior>
|
|
172
|
+
|
|
173
|
+
<notes>
|
|
174
|
+
- This workflow is strictly diagnostic — never modify `opencode.json`, `.planning/oc_config.json`, or any other file.
|
|
175
|
+
- When errors are found, always recommend `/gsd-set-profile` or `/gsd-set-profile <simple|smart|genius>` as the resolution path. Do not suggest manual editing.
|
|
176
|
+
- Always display full model IDs (e.g., `bailian-coding-plan/qwen3-coder-plus`), never abbreviate.
|
|
177
|
+
- Missing `opencode.json` is a WARNING, not an error. The user simply hasn't customized agent models — agents fall back to the default/current model. Do not include it in the "Fix" section.
|
|
178
|
+
- Missing `.planning/oc_config.json` IS an error — it means no gsd-opencode profile has been set up.
|
|
179
|
+
- Always use the term "gsd-opencode profile" (not just "profile") when referring to the profile system.
|
|
180
|
+
- Both `check-config-json` and `check-oc-config-json` route to the same validator. Use `check-config-json` (shorter).
|
|
181
|
+
</notes>
|