@kodrunhq/opencode-autopilot 1.16.0 → 1.18.0

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 (61) hide show
  1. package/assets/commands/oc-doctor.md +17 -0
  2. package/bin/configure-tui.ts +1 -1
  3. package/bin/inspect.ts +2 -2
  4. package/package.json +1 -1
  5. package/src/config/index.ts +29 -0
  6. package/src/config/migrations.ts +196 -0
  7. package/src/config/v7.ts +45 -0
  8. package/src/config.ts +108 -24
  9. package/src/health/checks.ts +165 -0
  10. package/src/health/runner.ts +8 -2
  11. package/src/health/types.ts +1 -1
  12. package/src/index.ts +25 -2
  13. package/src/kernel/transaction.ts +48 -0
  14. package/src/kernel/types.ts +1 -2
  15. package/src/logging/domains.ts +39 -0
  16. package/src/logging/forensic-writer.ts +177 -0
  17. package/src/logging/index.ts +4 -0
  18. package/src/logging/logger.ts +44 -0
  19. package/src/logging/performance.ts +59 -0
  20. package/src/logging/rotation.ts +261 -0
  21. package/src/logging/types.ts +33 -0
  22. package/src/memory/capture-utils.ts +149 -0
  23. package/src/memory/capture.ts +16 -197
  24. package/src/memory/decay.ts +11 -2
  25. package/src/memory/injector.ts +4 -1
  26. package/src/memory/lessons.ts +85 -0
  27. package/src/memory/observations.ts +177 -0
  28. package/src/memory/preferences.ts +718 -0
  29. package/src/memory/projects.ts +83 -0
  30. package/src/memory/repository.ts +46 -1001
  31. package/src/memory/retrieval.ts +5 -1
  32. package/src/observability/context-display.ts +8 -0
  33. package/src/observability/event-handlers.ts +44 -6
  34. package/src/observability/forensic-log.ts +10 -2
  35. package/src/observability/forensic-schemas.ts +9 -1
  36. package/src/observability/log-reader.ts +20 -1
  37. package/src/orchestrator/error-context.ts +24 -0
  38. package/src/orchestrator/handlers/build-utils.ts +118 -0
  39. package/src/orchestrator/handlers/build.ts +13 -148
  40. package/src/orchestrator/handlers/retrospective.ts +0 -1
  41. package/src/orchestrator/lesson-memory.ts +7 -2
  42. package/src/orchestrator/orchestration-logger.ts +46 -31
  43. package/src/orchestrator/progress.ts +63 -0
  44. package/src/review/memory.ts +11 -3
  45. package/src/review/parse-findings.ts +116 -0
  46. package/src/review/pipeline.ts +3 -107
  47. package/src/review/selection.ts +38 -4
  48. package/src/scoring/time-provider.ts +23 -0
  49. package/src/tools/configure.ts +1 -1
  50. package/src/tools/doctor.ts +2 -2
  51. package/src/tools/logs.ts +32 -6
  52. package/src/tools/orchestrate.ts +11 -9
  53. package/src/tools/replay.ts +42 -0
  54. package/src/tools/review.ts +8 -2
  55. package/src/tools/summary.ts +43 -0
  56. package/src/types/background.ts +51 -0
  57. package/src/types/mcp.ts +27 -0
  58. package/src/types/recovery.ts +39 -0
  59. package/src/types/routing.ts +39 -0
  60. package/src/utils/random.ts +33 -0
  61. package/src/ux/session-summary.ts +56 -0
@@ -0,0 +1,17 @@
1
+ ---
2
+ # opencode-autopilot
3
+ description: Run plugin health diagnostics — config validity, agent injection, native suppression, assets, memory, commands, and v7 config fields (background, routing, recovery, mcp)
4
+ ---
5
+
6
+ Invoke the `oc_doctor` tool to run a full health check on the opencode-autopilot plugin.
7
+
8
+ `oc_doctor` runs the current built-in health checks and reports the results by diagnostic area. These checks cover:
9
+
10
+ - **Config health** — The plugin config exists, parses correctly, and required modern config sections such as `background`, `routing`, `recovery`, and `mcp` are present or reported as needing migration.
11
+ - **Agent setup** — Expected autopilot agents are present in the OpenCode config, and native `plan`/`build` agents are suppressed as subagents.
12
+ - **Assets and installation paths** — Bundled asset directories and the global `~/.config/opencode/` target are accessible.
13
+ - **Skill loading** — Skills load correctly and are filtered against the detected project stack.
14
+ - **Memory storage** — The memory SQLite database is available, readable, or cleanly reported as not yet initialized on first install.
15
+ - **Command files** — Expected slash command files exist and have valid YAML frontmatter.
16
+
17
+ Each failing check includes a **Fix** suggestion. Run this after installation, after upgrades, or whenever something feels off.
@@ -307,7 +307,7 @@ export async function runConfigure(configPath: string = CONFIG_PATH): Promise<vo
307
307
 
308
308
  const newConfig = {
309
309
  ...baseConfig,
310
- version: 6 as const,
310
+ version: 7 as const,
311
311
  configured: true,
312
312
  groups: groupsRecord,
313
313
  overrides: baseConfig.overrides ?? {},
package/bin/inspect.ts CHANGED
@@ -249,7 +249,7 @@ export async function inspectCliCore(
249
249
  );
250
250
  }
251
251
  case "project": {
252
- const details = getProjectDetails(parsed.projectRef!, dbInput);
252
+ const details = getProjectDetails(parsed.projectRef ?? "", dbInput);
253
253
  if (details === null) {
254
254
  return makeError(`Project not found: ${parsed.projectRef}`, parsed.json);
255
255
  }
@@ -260,7 +260,7 @@ export async function inspectCliCore(
260
260
  );
261
261
  }
262
262
  case "paths": {
263
- const details = getProjectDetails(parsed.projectRef!, dbInput);
263
+ const details = getProjectDetails(parsed.projectRef ?? "", dbInput);
264
264
  if (details === null) {
265
265
  return makeError(`Project not found: ${parsed.projectRef}`, parsed.json);
266
266
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kodrunhq/opencode-autopilot",
3
- "version": "1.16.0",
3
+ "version": "1.18.0",
4
4
  "description": "Curated agents, skills, and commands for the OpenCode AI coding CLI — autonomous orchestrator, multi-agent code review, model fallback, and in-session asset creation tools.",
5
5
  "main": "src/index.ts",
6
6
  "keywords": [
@@ -0,0 +1,29 @@
1
+ export {
2
+ CONFIG_PATH,
3
+ confidenceConfigSchema,
4
+ confidenceDefaults,
5
+ createDefaultConfig,
6
+ isFirstLoad,
7
+ loadConfig,
8
+ memoryConfigSchema,
9
+ memoryDefaults,
10
+ orchestratorConfigSchema,
11
+ orchestratorDefaults,
12
+ type PluginConfig,
13
+ pluginConfigSchema,
14
+ saveConfig,
15
+ } from "../config";
16
+ // Re-export migration schemas and functions for backward compatibility
17
+ export {
18
+ migrateV1toV2,
19
+ migrateV2toV3,
20
+ migrateV3toV4,
21
+ migrateV4toV5,
22
+ migrateV5toV6,
23
+ pluginConfigSchemaV1,
24
+ pluginConfigSchemaV2,
25
+ pluginConfigSchemaV3,
26
+ pluginConfigSchemaV4,
27
+ pluginConfigSchemaV5,
28
+ } from "./migrations";
29
+ export { migrateV6toV7, type PluginConfigV7, v7ConfigDefaults } from "./v7";
@@ -0,0 +1,196 @@
1
+ import { z } from "zod";
2
+ import {
3
+ confidenceConfigSchema,
4
+ confidenceDefaults,
5
+ memoryConfigSchema,
6
+ memoryDefaults,
7
+ orchestratorConfigSchema,
8
+ orchestratorDefaults,
9
+ } from "../config";
10
+ import {
11
+ fallbackConfigSchema,
12
+ fallbackDefaults,
13
+ testModeDefaults,
14
+ } from "../orchestrator/fallback/fallback-config";
15
+ import { AGENT_REGISTRY, ALL_GROUP_IDS } from "../registry/model-groups";
16
+
17
+ export const pluginConfigSchemaV1 = z.object({
18
+ version: z.literal(1),
19
+ configured: z.boolean(),
20
+ models: z.record(z.string(), z.string()),
21
+ });
22
+
23
+ export type PluginConfigV1 = z.infer<typeof pluginConfigSchemaV1>;
24
+
25
+ export const pluginConfigSchemaV2 = z.object({
26
+ version: z.literal(2),
27
+ configured: z.boolean(),
28
+ models: z.record(z.string(), z.string()),
29
+ orchestrator: orchestratorConfigSchema.default(orchestratorDefaults),
30
+ confidence: confidenceConfigSchema.default(confidenceDefaults),
31
+ });
32
+
33
+ export type PluginConfigV2 = z.infer<typeof pluginConfigSchemaV2>;
34
+
35
+ export const pluginConfigSchemaV3 = z.object({
36
+ version: z.literal(3),
37
+ configured: z.boolean(),
38
+ models: z.record(z.string(), z.string()),
39
+ orchestrator: orchestratorConfigSchema.default(orchestratorDefaults),
40
+ confidence: confidenceConfigSchema.default(confidenceDefaults),
41
+ fallback: fallbackConfigSchema.default(fallbackDefaults),
42
+ fallback_models: z.union([z.string(), z.array(z.string())]).optional(),
43
+ });
44
+
45
+ export type PluginConfigV3 = z.infer<typeof pluginConfigSchemaV3>;
46
+
47
+ const groupModelAssignmentSchema = z.object({
48
+ primary: z.string().min(1),
49
+ fallbacks: z.array(z.string().min(1)).default([]),
50
+ });
51
+
52
+ const agentOverrideSchema = z.object({
53
+ primary: z.string().min(1),
54
+ fallbacks: z.array(z.string().min(1)).optional(),
55
+ });
56
+
57
+ export const pluginConfigSchemaV4 = z
58
+ .object({
59
+ version: z.literal(4),
60
+ configured: z.boolean(),
61
+ groups: z.record(z.string(), groupModelAssignmentSchema).default({}),
62
+ overrides: z.record(z.string(), agentOverrideSchema).default({}),
63
+ orchestrator: orchestratorConfigSchema.default(orchestratorDefaults),
64
+ confidence: confidenceConfigSchema.default(confidenceDefaults),
65
+ fallback: fallbackConfigSchema.default(fallbackDefaults),
66
+ })
67
+ .superRefine((config, ctx) => {
68
+ for (const groupId of Object.keys(config.groups)) {
69
+ if (!ALL_GROUP_IDS.includes(groupId as (typeof ALL_GROUP_IDS)[number])) {
70
+ ctx.addIssue({
71
+ code: z.ZodIssueCode.custom,
72
+ path: ["groups", groupId],
73
+ message: `Unknown group id "${groupId}". Expected one of: ${ALL_GROUP_IDS.join(", ")}`,
74
+ });
75
+ }
76
+ }
77
+ });
78
+
79
+ export type PluginConfigV4 = z.infer<typeof pluginConfigSchemaV4>;
80
+
81
+ export const pluginConfigSchemaV5 = z
82
+ .object({
83
+ version: z.literal(5),
84
+ configured: z.boolean(),
85
+ groups: z.record(z.string(), groupModelAssignmentSchema).default({}),
86
+ overrides: z.record(z.string(), agentOverrideSchema).default({}),
87
+ orchestrator: orchestratorConfigSchema.default(orchestratorDefaults),
88
+ confidence: confidenceConfigSchema.default(confidenceDefaults),
89
+ fallback: fallbackConfigSchema.default(fallbackDefaults),
90
+ memory: memoryConfigSchema.default(memoryDefaults),
91
+ })
92
+ .superRefine((config, ctx) => {
93
+ for (const groupId of Object.keys(config.groups)) {
94
+ if (!ALL_GROUP_IDS.includes(groupId as (typeof ALL_GROUP_IDS)[number])) {
95
+ ctx.addIssue({
96
+ code: z.ZodIssueCode.custom,
97
+ path: ["groups", groupId],
98
+ message: `Unknown group id "${groupId}". Expected one of: ${ALL_GROUP_IDS.join(", ")}`,
99
+ });
100
+ }
101
+ }
102
+ });
103
+
104
+ export type PluginConfigV5 = z.infer<typeof pluginConfigSchemaV5>;
105
+
106
+ export function migrateV1toV2(v1Config: PluginConfigV1): PluginConfigV2 {
107
+ return {
108
+ version: 2 as const,
109
+ configured: v1Config.configured,
110
+ models: v1Config.models,
111
+ orchestrator: orchestratorDefaults,
112
+ confidence: confidenceDefaults,
113
+ };
114
+ }
115
+
116
+ export function migrateV2toV3(v2Config: PluginConfigV2): PluginConfigV3 {
117
+ return {
118
+ version: 3 as const,
119
+ configured: v2Config.configured,
120
+ models: v2Config.models,
121
+ orchestrator: v2Config.orchestrator,
122
+ confidence: v2Config.confidence,
123
+ fallback: fallbackDefaults,
124
+ };
125
+ }
126
+
127
+ export function migrateV3toV4(v3Config: PluginConfigV3): PluginConfigV4 {
128
+ const groups: Record<string, { primary: string; fallbacks: string[] }> = {};
129
+ const overrides: Record<string, { primary: string }> = {};
130
+
131
+ for (const [agentName, modelId] of Object.entries(v3Config.models)) {
132
+ const entry = AGENT_REGISTRY[agentName];
133
+ if (!entry) {
134
+ overrides[agentName] = { primary: modelId };
135
+ continue;
136
+ }
137
+
138
+ const groupId = entry.group;
139
+ if (!groups[groupId]) {
140
+ groups[groupId] = { primary: modelId, fallbacks: [] };
141
+ } else if (groups[groupId].primary !== modelId) {
142
+ overrides[agentName] = { primary: modelId };
143
+ }
144
+ }
145
+
146
+ const globalFallbacks = v3Config.fallback_models
147
+ ? typeof v3Config.fallback_models === "string"
148
+ ? [v3Config.fallback_models]
149
+ : [...v3Config.fallback_models]
150
+ : [];
151
+
152
+ for (const group of Object.values(groups)) {
153
+ if (group.fallbacks.length === 0 && globalFallbacks.length > 0) {
154
+ group.fallbacks = [...globalFallbacks];
155
+ }
156
+ }
157
+
158
+ return {
159
+ version: 4 as const,
160
+ configured: v3Config.configured,
161
+ groups,
162
+ overrides,
163
+ orchestrator: v3Config.orchestrator,
164
+ confidence: v3Config.confidence,
165
+ fallback: v3Config.fallback,
166
+ };
167
+ }
168
+
169
+ export function migrateV4toV5(v4Config: PluginConfigV4): PluginConfigV5 {
170
+ return {
171
+ version: 5 as const,
172
+ configured: v4Config.configured,
173
+ groups: v4Config.groups,
174
+ overrides: v4Config.overrides,
175
+ orchestrator: v4Config.orchestrator,
176
+ confidence: v4Config.confidence,
177
+ fallback: v4Config.fallback,
178
+ memory: memoryDefaults,
179
+ };
180
+ }
181
+
182
+ export function migrateV5toV6(
183
+ v5Config: PluginConfigV5,
184
+ _fallbackDefaultsV6: typeof fallbackDefaults,
185
+ ) {
186
+ return {
187
+ version: 6 as const,
188
+ configured: v5Config.configured,
189
+ groups: v5Config.groups,
190
+ overrides: v5Config.overrides,
191
+ orchestrator: v5Config.orchestrator,
192
+ confidence: v5Config.confidence,
193
+ fallback: { ...v5Config.fallback, testMode: testModeDefaults },
194
+ memory: v5Config.memory,
195
+ };
196
+ }
@@ -0,0 +1,45 @@
1
+ import type { PluginConfig } from "../config";
2
+
3
+ export type PluginConfigV7 = Omit<PluginConfig, "version"> & {
4
+ readonly version: 7;
5
+ readonly background?: {
6
+ readonly enabled: boolean;
7
+ readonly maxConcurrent: number;
8
+ readonly persistence: boolean;
9
+ };
10
+ readonly autonomy?: {
11
+ readonly enabled: boolean;
12
+ readonly verification: "strict" | "normal" | "lenient";
13
+ readonly maxIterations: number;
14
+ };
15
+ };
16
+
17
+ export function migrateV6toV7(v6Config: PluginConfig): PluginConfigV7 {
18
+ return {
19
+ ...v6Config,
20
+ version: 7,
21
+ background: {
22
+ enabled: true,
23
+ maxConcurrent: 5,
24
+ persistence: true,
25
+ },
26
+ autonomy: {
27
+ enabled: false,
28
+ verification: "normal",
29
+ maxIterations: 10,
30
+ },
31
+ };
32
+ }
33
+
34
+ export const v7ConfigDefaults = {
35
+ background: {
36
+ enabled: true,
37
+ maxConcurrent: 5,
38
+ persistence: true,
39
+ },
40
+ autonomy: {
41
+ enabled: false,
42
+ verification: "normal",
43
+ maxIterations: 10,
44
+ },
45
+ } as const;
package/src/config.ts CHANGED
@@ -10,6 +10,10 @@ import {
10
10
  testModeDefaults,
11
11
  } from "./orchestrator/fallback/fallback-config";
12
12
  import { AGENT_REGISTRY, ALL_GROUP_IDS } from "./registry/model-groups";
13
+ import { backgroundConfigSchema, backgroundDefaults } from "./types/background";
14
+ import { mcpConfigSchema, mcpDefaults } from "./types/mcp";
15
+ import { recoveryConfigSchema, recoveryDefaults } from "./types/recovery";
16
+ import { routingConfigSchema, routingDefaults } from "./types/routing";
13
17
  import { ensureDir, isEnoentError } from "./utils/fs-helpers";
14
18
  import { getGlobalConfigDir } from "./utils/paths";
15
19
 
@@ -53,8 +57,8 @@ export const confidenceConfigSchema = z.object({
53
57
  });
54
58
 
55
59
  // Pre-compute full defaults for nested schema defaults
56
- const orchestratorDefaults = orchestratorConfigSchema.parse({});
57
- const confidenceDefaults = confidenceConfigSchema.parse({});
60
+ export const orchestratorDefaults = orchestratorConfigSchema.parse({});
61
+ export const confidenceDefaults = confidenceConfigSchema.parse({});
58
62
 
59
63
  // --- V2 schema (internal, for migration) ---
60
64
 
@@ -90,7 +94,7 @@ export const memoryConfigSchema = z.object({
90
94
  decayHalfLifeDays: z.number().min(7).max(365).default(90),
91
95
  });
92
96
 
93
- const memoryDefaults = memoryConfigSchema.parse({});
97
+ export const memoryDefaults = memoryConfigSchema.parse({});
94
98
 
95
99
  // --- V4 sub-schemas ---
96
100
 
@@ -182,14 +186,47 @@ const pluginConfigSchemaV6 = z
182
186
  }
183
187
  });
184
188
 
185
- // Export aliases updated to v6
186
- export const pluginConfigSchema = pluginConfigSchemaV6;
189
+ type PluginConfigV6 = z.infer<typeof pluginConfigSchemaV6>;
187
190
 
188
- export type PluginConfig = z.infer<typeof pluginConfigSchemaV6>;
191
+ const pluginConfigSchemaV7 = z
192
+ .object({
193
+ version: z.literal(7),
194
+ configured: z.boolean(),
195
+ groups: z.record(z.string(), groupModelAssignmentSchema).default({}),
196
+ overrides: z.record(z.string(), agentOverrideSchema).default({}),
197
+ orchestrator: orchestratorConfigSchema.default(orchestratorDefaults),
198
+ confidence: confidenceConfigSchema.default(confidenceDefaults),
199
+ fallback: fallbackConfigSchemaV6.default(fallbackDefaultsV6),
200
+ memory: memoryConfigSchema.default(memoryDefaults),
201
+ background: backgroundConfigSchema.default(backgroundDefaults),
202
+ autonomy: z
203
+ .object({
204
+ enabled: z.boolean().default(false),
205
+ verification: z.enum(["strict", "normal", "lenient"]).default("normal"),
206
+ maxIterations: z.number().int().min(1).max(50).default(10),
207
+ })
208
+ .default({ enabled: false, verification: "normal", maxIterations: 10 }),
209
+ routing: routingConfigSchema.default(routingDefaults),
210
+ recovery: recoveryConfigSchema.default(recoveryDefaults),
211
+ mcp: mcpConfigSchema.default(mcpDefaults),
212
+ })
213
+ .superRefine((config, ctx) => {
214
+ for (const groupId of Object.keys(config.groups)) {
215
+ if (!ALL_GROUP_IDS.includes(groupId as (typeof ALL_GROUP_IDS)[number])) {
216
+ ctx.addIssue({
217
+ code: z.ZodIssueCode.custom,
218
+ path: ["groups", groupId],
219
+ message: `Unknown group id "${groupId}". Expected one of: ${ALL_GROUP_IDS.join(", ")}`,
220
+ });
221
+ }
222
+ }
223
+ });
189
224
 
190
- export const CONFIG_PATH = join(getGlobalConfigDir(), "opencode-autopilot.json");
225
+ export const pluginConfigSchema = pluginConfigSchemaV7;
226
+
227
+ export type PluginConfig = z.infer<typeof pluginConfigSchemaV7>;
191
228
 
192
- // --- Migration ---
229
+ export const CONFIG_PATH = join(getGlobalConfigDir(), "opencode-autopilot.json");
193
230
 
194
231
  function migrateV1toV2(v1Config: PluginConfigV1): PluginConfigV2 {
195
232
  return {
@@ -274,7 +311,7 @@ function migrateV4toV5(v4Config: PluginConfigV4): PluginConfigV5 {
274
311
  };
275
312
  }
276
313
 
277
- function migrateV5toV6(v5Config: PluginConfigV5): PluginConfig {
314
+ function migrateV5toV6(v5Config: PluginConfigV5): PluginConfigV6 {
278
315
  return {
279
316
  version: 6 as const,
280
317
  configured: v5Config.configured,
@@ -287,68 +324,106 @@ function migrateV5toV6(v5Config: PluginConfigV5): PluginConfig {
287
324
  };
288
325
  }
289
326
 
290
- // --- Public API ---
327
+ export const v7ConfigDefaults = {
328
+ background: backgroundDefaults,
329
+ autonomy: {
330
+ enabled: false,
331
+ verification: "normal" as const,
332
+ maxIterations: 10,
333
+ },
334
+ routing: routingDefaults,
335
+ recovery: recoveryDefaults,
336
+ mcp: mcpDefaults,
337
+ } as const;
338
+
339
+ export function migrateV6toV7(v6Config: PluginConfigV6): PluginConfig {
340
+ return {
341
+ version: 7 as const,
342
+ configured: v6Config.configured,
343
+ groups: v6Config.groups,
344
+ overrides: v6Config.overrides,
345
+ orchestrator: v6Config.orchestrator,
346
+ confidence: v6Config.confidence,
347
+ fallback: v6Config.fallback,
348
+ memory: v6Config.memory,
349
+ background: backgroundDefaults,
350
+ autonomy: {
351
+ enabled: false,
352
+ verification: "normal",
353
+ maxIterations: 10,
354
+ },
355
+ routing: routingDefaults,
356
+ recovery: recoveryDefaults,
357
+ mcp: mcpDefaults,
358
+ };
359
+ }
291
360
 
292
361
  export async function loadConfig(configPath: string = CONFIG_PATH): Promise<PluginConfig | null> {
293
362
  try {
294
363
  const raw = await readFile(configPath, "utf-8");
295
364
  const parsed = JSON.parse(raw);
296
365
 
297
- // Try v6 first
366
+ const v7Result = pluginConfigSchemaV7.safeParse(parsed);
367
+ if (v7Result.success) return v7Result.data;
368
+
298
369
  const v6Result = pluginConfigSchemaV6.safeParse(parsed);
299
- if (v6Result.success) return v6Result.data;
370
+ if (v6Result.success) {
371
+ const migrated = migrateV6toV7(v6Result.data);
372
+ await saveConfig(migrated, configPath);
373
+ return migrated;
374
+ }
300
375
 
301
- // Try v5 and migrate to v6
302
376
  const v5Result = pluginConfigSchemaV5.safeParse(parsed);
303
377
  if (v5Result.success) {
304
- const migrated = migrateV5toV6(v5Result.data);
378
+ const v6 = migrateV5toV6(v5Result.data);
379
+ const migrated = migrateV6toV7(v6);
305
380
  await saveConfig(migrated, configPath);
306
381
  return migrated;
307
382
  }
308
383
 
309
- // Try v4 → v5 → v6
310
384
  const v4Result = pluginConfigSchemaV4.safeParse(parsed);
311
385
  if (v4Result.success) {
312
386
  const v5 = migrateV4toV5(v4Result.data);
313
- const migrated = migrateV5toV6(v5);
387
+ const v6 = migrateV5toV6(v5);
388
+ const migrated = migrateV6toV7(v6);
314
389
  await saveConfig(migrated, configPath);
315
390
  return migrated;
316
391
  }
317
392
 
318
- // Try v3 → v4 → v5 → v6
319
393
  const v3Result = pluginConfigSchemaV3.safeParse(parsed);
320
394
  if (v3Result.success) {
321
395
  const v4 = migrateV3toV4(v3Result.data);
322
396
  const v5 = migrateV4toV5(v4);
323
- const migrated = migrateV5toV6(v5);
397
+ const v6 = migrateV5toV6(v5);
398
+ const migrated = migrateV6toV7(v6);
324
399
  await saveConfig(migrated, configPath);
325
400
  return migrated;
326
401
  }
327
402
 
328
- // Try v2 → v3 → v4 → v5 → v6
329
403
  const v2Result = pluginConfigSchemaV2.safeParse(parsed);
330
404
  if (v2Result.success) {
331
405
  const v3 = migrateV2toV3(v2Result.data);
332
406
  const v4 = migrateV3toV4(v3);
333
407
  const v5 = migrateV4toV5(v4);
334
- const migrated = migrateV5toV6(v5);
408
+ const v6 = migrateV5toV6(v5);
409
+ const migrated = migrateV6toV7(v6);
335
410
  await saveConfig(migrated, configPath);
336
411
  return migrated;
337
412
  }
338
413
 
339
- // Try v1 → v2 → v3 → v4 → v5 → v6
340
414
  const v1Result = pluginConfigSchemaV1.safeParse(parsed);
341
415
  if (v1Result.success) {
342
416
  const v2 = migrateV1toV2(v1Result.data);
343
417
  const v3 = migrateV2toV3(v2);
344
418
  const v4 = migrateV3toV4(v3);
345
419
  const v5 = migrateV4toV5(v4);
346
- const migrated = migrateV5toV6(v5);
420
+ const v6 = migrateV5toV6(v5);
421
+ const migrated = migrateV6toV7(v6);
347
422
  await saveConfig(migrated, configPath);
348
423
  return migrated;
349
424
  }
350
425
 
351
- return pluginConfigSchemaV6.parse(parsed); // throw with proper error
426
+ return pluginConfigSchemaV7.parse(parsed);
352
427
  } catch (error: unknown) {
353
428
  if (isEnoentError(error)) return null;
354
429
  throw error;
@@ -371,7 +446,7 @@ export function isFirstLoad(config: PluginConfig | null): boolean {
371
446
 
372
447
  export function createDefaultConfig(): PluginConfig {
373
448
  return {
374
- version: 6 as const,
449
+ version: 7 as const,
375
450
  configured: false,
376
451
  groups: {},
377
452
  overrides: {},
@@ -379,5 +454,14 @@ export function createDefaultConfig(): PluginConfig {
379
454
  confidence: confidenceDefaults,
380
455
  fallback: fallbackDefaultsV6,
381
456
  memory: memoryDefaults,
457
+ background: backgroundDefaults,
458
+ autonomy: {
459
+ enabled: false,
460
+ verification: "normal",
461
+ maxIterations: 10,
462
+ },
463
+ routing: routingDefaults,
464
+ recovery: recoveryDefaults,
465
+ mcp: mcpDefaults,
382
466
  };
383
467
  }