@cortexkit/magic-context 0.42.5 → 0.42.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 (2) hide show
  1. package/dist/index.js +550 -129
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -20477,7 +20477,7 @@ function expandConfigPath(value) {
20477
20477
  return `${homedir8()}/${trimmed.slice(2)}`;
20478
20478
  return trimmed;
20479
20479
  }
20480
- var DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE = 65, EXECUTE_THRESHOLD_CAP_MESSAGE = "execute_threshold is capped at 90% for cache safety: output capacity is reserved from the usable context window, and the remaining 10% absorbs mid-turn growth before the absolute 95% emergency wall. Use a value between 20 and 90.", DEFAULT_HISTORIAN_TIMEOUT_MS = 600000, DEFAULT_HISTORY_BUDGET_PERCENTAGE = 0.15, DEFAULT_LOCAL_EMBEDDING_MODEL = "Xenova/all-MiniLM-L6-v2", PiThinkingLevelSchema, OmpThinkingLevelSchema, PiConfigSchema, PromptSurfacePresetSchema, PromptSurfaceModelKeySchema, PromptSurfaceToolKeySchema, PromptSurfaceConfigSchema, PER_HARNESS_MIGRATION_INVENTORY, PER_HARNESS_MODEL_KEYS, OcEntryObjectSchema, OcEntrySchema, PiEntryObjectSchema, PiEntrySchema, OmpEntryObjectSchema, OmpEntrySchema, OpenCodeHarnessBlockSchema, PiHarnessBlockSchema, OmpHarnessBlockSchema, OpenCodeTaskExecutionSchema, PiTaskExecutionSchema, OmpTaskExecutionSchema, DreamerOpenCodeHarnessBlockSchema, DreamerPiHarnessBlockSchema, DreamerOmpHarnessBlockSchema, ProfileOpenCodeModelBlockSchema, ProfilePiModelBlockSchema, ProfileOmpModelBlockSchema, ProfileHistorianSchema, ProfileDreamerSchema, ConfigProfileSchema, ConfigProfilesSchema, CronScheduleSchema, DreamTaskBaseConfigSchema, PromotionThresholdSchema, PrimerPromotionThresholdSchema, DreamTaskConfigSchema, ReviewUserMemoriesTaskConfigSchema, PromotePrimersTaskConfigSchema, DEFAULT_TASK_SCHEDULES2, DreamTasksSchema, AgentMetadataSchema, DreamerConfigSchema, HistorianConfigSchema, EmbeddingFallbackProviderSchema, BaseEmbeddingConfigSchema, EmbeddingConfigSchema, MagicContextConfigSchema;
20480
+ var DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE = 65, EXECUTE_THRESHOLD_CAP_MESSAGE = "execute_threshold is capped at 90% for cache safety: output capacity is reserved from the usable context window, and the remaining 10% absorbs mid-turn growth before the absolute 95% emergency wall. Use a value between 20 and 90.", DEFAULT_HISTORIAN_TIMEOUT_MS = 600000, DEFAULT_HISTORY_BUDGET_PERCENTAGE = 0.15, PROTECTED_TOKENS_MIN = 4000, DEFAULT_LOCAL_EMBEDDING_MODEL = "Xenova/all-MiniLM-L6-v2", PiThinkingLevelSchema, OmpThinkingLevelSchema, PiConfigSchema, PromptSurfacePresetSchema, PromptSurfaceModelKeySchema, PromptSurfaceToolKeySchema, PromptSurfaceConfigSchema, PER_HARNESS_MIGRATION_INVENTORY, PER_HARNESS_MODEL_KEYS, OcEntryObjectSchema, OcEntrySchema, PiEntryObjectSchema, PiEntrySchema, OmpEntryObjectSchema, OmpEntrySchema, OpenCodeHarnessBlockSchema, PiHarnessBlockSchema, OmpHarnessBlockSchema, OpenCodeTaskExecutionSchema, PiTaskExecutionSchema, OmpTaskExecutionSchema, DreamerOpenCodeHarnessBlockSchema, DreamerPiHarnessBlockSchema, DreamerOmpHarnessBlockSchema, ProfileOpenCodeModelBlockSchema, ProfilePiModelBlockSchema, ProfileOmpModelBlockSchema, ProfileHistorianSchema, ProfileDreamerSchema, ConfigProfileSchema, ConfigProfilesSchema, CronScheduleSchema, DreamTaskBaseConfigSchema, PromotionThresholdSchema, PrimerPromotionThresholdSchema, DreamTaskConfigSchema, ReviewUserMemoriesTaskConfigSchema, PromotePrimersTaskConfigSchema, DEFAULT_TASK_SCHEDULES2, DreamTasksSchema, AgentMetadataSchema, DreamerConfigSchema, HistorianConfigSchema, EmbeddingFallbackProviderSchema, BaseEmbeddingConfigSchema, EmbeddingConfigSchema, MagicContextConfigSchema;
20481
20481
  var init_magic_context = __esm(() => {
20482
20482
  init_zod();
20483
20483
  init_language_directive();
@@ -20836,8 +20836,8 @@ var init_magic_context = __esm(() => {
20836
20836
  smart_notes: object({
20837
20837
  retina_handoff: boolean2().default(false).describe("When true, dreamer skips smart notes whose surface conditions compiled to retina provider configs at authoring time. Default false keeps both paths active until the retina consumer is deployed.")
20838
20838
  }).default({ retina_handoff: false }).describe("Smart-note ownership transition controls."),
20839
- cache_ttl: union([string2(), object({ default: string2() }).catchall(string2())]).default("5m").describe(`How long Magic Context assumes the provider's cached prefix stays valid. This is MC's own deferral gate — it does not change the provider's actual cache lifetime. String (e.g. "5m", "1h", "30s") or per-model object ({ default: "5m", "model-id": "10m" }). Set to "never" to mean MC never assumes expiry (for lanes kept warm externally by a cache-keep tool) — disables the idle-TTL heuristic so MC never initiates a rebuild based on elapsed time. Provider-side extended TTL is a separate request-level concern (cache_control: { ttl } in the request body).`),
20840
- prompt_surface: PromptSurfaceConfigSchema.default({ default: "full" }).describe("Prompt-surface presets: default is full; models use bare model IDs, provider/model, or provider/* routing keys. Guidance and tool-description overrides are user-level only. On OpenCode and Pi, per-model routing applies to the guidance block only: tool descriptions are registered once per process, so they follow the default preset (a v1 plugin-surface limitation; per-model tool descriptions are planned for the OpenCode v2 plugin API once the SDK stabilizes)."),
20839
+ cache_ttl: union([string2(), object({ default: string2() }).catchall(string2())]).default("5m").describe(`How long Magic Context assumes the provider's cached prefix stays valid. This is MC's own deferral gate — it does not change the provider's actual cache lifetime. String (e.g. "5m", "1h", "30s") or per-model object ({ default: "5m", "provider/model": "1h", "provider/*": "never" }); keys resolve most-specific first (exact provider/model, bare model ID, shorter dash-prefixes, then the provider/* wildcard, then default). Set to "never" to mean MC never assumes expiry (for lanes kept warm externally by a cache-keep tool) — disables the idle-TTL heuristic so MC never initiates a rebuild based on elapsed time. Provider-side extended TTL is a separate request-level concern (cache_control: { ttl } in the request body).`),
20840
+ prompt_surface: PromptSurfaceConfigSchema.default({ default: "full" }).describe("Prompt-surface presets: default is full; models use bare model IDs, provider/model, or provider/* routing keys. Guidance and tool-description overrides are user-level only. OpenCode 1.x, Pi, and OMP register tool descriptions once per process (they follow the default preset). OpenCode 2 rewrites the five ctx_* descriptions per request from the draft model."),
20841
20841
  output_reserve: union([
20842
20842
  number2().min(0),
20843
20843
  object({ default: number2().min(0) }).catchall(number2().min(0))
@@ -20853,7 +20853,7 @@ var init_magic_context = __esm(() => {
20853
20853
  execute_threshold_tokens: object({
20854
20854
  default: number2().min(5000).max(2000000).optional()
20855
20855
  }).catchall(number2().min(5000).max(2000000)).optional().describe("Absolute token thresholds per model. When matched, overrides execute_threshold_percentage for that model. Accepts `default` for all models or per-model keys. Values above 90% × context_limit are clamped with a warning log. Min 5_000, max 2_000_000."),
20856
- protected_tokens: number2().int().min(4000).max(1e6).optional().describe("Positive integer token floor to protect from automatic reclaim (min: 4_000, max: 1_000_000). When omitted, the derived default is clamp(round(0.05 × usableSoft), min(16_000, round(0.08 × usableSoft)), 64_000)."),
20856
+ protected_tokens: number2().int().min(PROTECTED_TOKENS_MIN).max(1e6).optional().describe("Positive integer token floor to protect from automatic reclaim (min: 4_000, max: 1_000_000). When omitted, the derived default is clamp(round(0.05 × usableSoft), min(16_000, round(0.08 × usableSoft)), 64_000)."),
20857
20857
  protected_tags: unknown().optional().describe("Deprecated: number of recent tags to protect. Ignored for behaviour; use protected_tokens instead.").meta({ deprecated: true }),
20858
20858
  clear_reasoning_age: number2().min(10).default(50).describe("Clear reasoning/thinking blocks older than N tags (default: 50)"),
20859
20859
  history_budget_percentage: number2().min(0.05).max(0.5).default(DEFAULT_HISTORY_BUDGET_PERCENTAGE).describe("Fraction of usable context (context_limit × execute_threshold) reserved for the session history block (default: 0.15)"),
@@ -21786,6 +21786,9 @@ function redactConfigValue(value) {
21786
21786
  }
21787
21787
  return typeof value;
21788
21788
  }
21789
+ function formatProtectedTokensBelowMinWarning(value) {
21790
+ return `protected_tokens is a token floor (minimum ${PROTECTED_TOKENS_MIN}, default derived from the context window); ${value} looks like the old protected_tags count. Remove the key to use the default, or set a token count such as 16000.`;
21791
+ }
21789
21792
  function warnProtectedTagsDeprecationOnce() {
21790
21793
  if (!warnedProtectedTagsDeprecation) {
21791
21794
  warnedProtectedTagsDeprecation = true;
@@ -21876,6 +21879,11 @@ function parsePluginConfig(rawConfig, recoveredTopLevelKeys = []) {
21876
21879
  delete patched[key];
21877
21880
  const defaultVal = defaults[key];
21878
21881
  const reason = customMessagesByKey.get(key);
21882
+ const invalidRawValue = rawConfig[key];
21883
+ if (key === "protected_tokens" && typeof invalidRawValue === "number" && invalidRawValue < PROTECTED_TOKENS_MIN) {
21884
+ warnings.push(formatProtectedTokensBelowMinWarning(invalidRawValue));
21885
+ continue;
21886
+ }
21879
21887
  warnings.push(`"${key}": invalid value (${redactConfigValue(rawConfig[key])}), using default ${JSON.stringify(defaultVal)}.${reason ? ` ${reason}` : ""}`);
21880
21888
  }
21881
21889
  const retryMigrated = migrateLegacyAgentEnabledInMemory(migrateDreamerV2(migrateLegacyExperimental(patched, preMigrationWarnings), preMigrationWarnings), preMigrationWarnings);
@@ -22122,6 +22130,7 @@ import { homedir as homedir11 } from "node:os";
22122
22130
  import { join as join13 } from "node:path";
22123
22131
  function detectConflicts(directory, options) {
22124
22132
  const compactionEnabled = options?.compactionEnabled ?? true;
22133
+ const hostGeneration = options?.hostGeneration ?? "v1";
22125
22134
  const conflicts = {
22126
22135
  compactionAuto: false,
22127
22136
  compactionPrune: false,
@@ -22131,15 +22140,15 @@ function detectConflicts(directory, options) {
22131
22140
  omoAnthropicRecovery: false
22132
22141
  };
22133
22142
  const reasons = [];
22134
- let compactionResult = options?.resolvedCompaction ?? checkCompaction(directory);
22143
+ let compactionResult = options?.resolvedCompaction ?? checkCompaction(directory, hostGeneration);
22135
22144
  if (process.env.OPENCODE_DISABLE_AUTOCOMPACT) {
22136
22145
  compactionResult = { auto: false, prune: false };
22137
22146
  }
22138
- if (compactionEnabled && compactionResult.auto) {
22147
+ if (hostGeneration === "v1" && compactionEnabled && compactionResult.auto) {
22139
22148
  conflicts.compactionAuto = true;
22140
22149
  reasons.push(options?.resolvedCompaction ? "OpenCode auto-compaction is enabled (compaction.auto=true) (resolved config)" : "OpenCode auto-compaction is enabled (compaction.auto=true)");
22141
22150
  }
22142
- if (compactionEnabled && compactionResult.prune) {
22151
+ if (hostGeneration === "v1" && compactionEnabled && compactionResult.prune) {
22143
22152
  conflicts.compactionPrune = true;
22144
22153
  reasons.push(options?.resolvedCompaction ? "OpenCode prune is enabled (compaction.prune=true) (resolved config)" : "OpenCode prune is enabled (compaction.prune=true)");
22145
22154
  }
@@ -22165,29 +22174,32 @@ function detectConflicts(directory, options) {
22165
22174
  hasConflict: reasons.length > 0,
22166
22175
  reasons,
22167
22176
  conflicts,
22168
- nativeCompaction: { auto: compactionResult.auto, prune: compactionResult.prune }
22177
+ nativeCompaction: {
22178
+ auto: compactionResult.auto,
22179
+ prune: hostGeneration === "v1" ? compactionResult.prune : false
22180
+ }
22169
22181
  };
22170
22182
  }
22171
- function checkCompaction(directory) {
22183
+ function checkCompaction(directory, hostGeneration) {
22172
22184
  if (process.env.OPENCODE_DISABLE_AUTOCOMPACT) {
22173
22185
  return { auto: false, prune: false };
22174
22186
  }
22175
- const projectResult = readProjectCompaction(directory);
22187
+ const projectResult = readProjectCompaction(directory, hostGeneration);
22176
22188
  if (projectResult.resolved)
22177
22189
  return projectResult;
22178
- const userResult = readUserCompaction();
22190
+ const userResult = readUserCompaction(hostGeneration);
22179
22191
  if (userResult.resolved)
22180
22192
  return userResult;
22181
22193
  return { auto: true, prune: false };
22182
22194
  }
22183
- function readProjectCompaction(directory) {
22195
+ function readProjectCompaction(directory, hostGeneration) {
22184
22196
  const dotOcJsonc = join13(directory, ".opencode", "opencode.jsonc");
22185
22197
  const dotOcJson = join13(directory, ".opencode", "opencode.json");
22186
22198
  const dotOcConfig = readJsoncFile(dotOcJsonc) ?? readJsoncFile(dotOcJson);
22187
22199
  if (dotOcConfig?.compaction) {
22188
22200
  const c = dotOcConfig.compaction;
22189
- if (c.auto !== undefined || c.prune !== undefined) {
22190
- return { auto: c.auto === true, prune: c.prune === true, resolved: true };
22201
+ if (c.auto !== undefined || hostGeneration === "v1" && c.prune !== undefined || hostGeneration === "v2" && (c.keep?.tokens !== undefined || c.buffer !== undefined)) {
22202
+ return resolvedCompactionBlock(c, hostGeneration);
22191
22203
  }
22192
22204
  }
22193
22205
  const rootJsonc = join13(directory, "opencode.jsonc");
@@ -22195,25 +22207,37 @@ function readProjectCompaction(directory) {
22195
22207
  const rootConfig = readJsoncFile(rootJsonc) ?? readJsoncFile(rootJson);
22196
22208
  if (rootConfig?.compaction) {
22197
22209
  const c = rootConfig.compaction;
22198
- if (c.auto !== undefined || c.prune !== undefined) {
22199
- return { auto: c.auto === true, prune: c.prune === true, resolved: true };
22210
+ if (c.auto !== undefined || hostGeneration === "v1" && c.prune !== undefined || hostGeneration === "v2" && (c.keep?.tokens !== undefined || c.buffer !== undefined)) {
22211
+ return resolvedCompactionBlock(c, hostGeneration);
22200
22212
  }
22201
22213
  }
22202
22214
  return { auto: false, prune: false, resolved: false };
22203
22215
  }
22204
- function readUserCompaction() {
22216
+ function readUserCompaction(hostGeneration) {
22205
22217
  try {
22206
22218
  const paths = getOpenCodeConfigPaths({ binary: "opencode" });
22207
22219
  const config = readJsoncFile(paths.configJsonc) ?? readJsoncFile(paths.configJson);
22208
22220
  if (config?.compaction) {
22209
22221
  const c = config.compaction;
22210
- if (c.auto !== undefined || c.prune !== undefined) {
22211
- return { auto: c.auto === true, prune: c.prune === true, resolved: true };
22222
+ if (c.auto !== undefined || hostGeneration === "v1" && c.prune !== undefined || hostGeneration === "v2" && (c.keep?.tokens !== undefined || c.buffer !== undefined)) {
22223
+ return resolvedCompactionBlock(c, hostGeneration);
22212
22224
  }
22213
22225
  }
22214
22226
  } catch {}
22215
22227
  return { auto: false, prune: false, resolved: false };
22216
22228
  }
22229
+ function resolvedCompactionBlock(block, hostGeneration) {
22230
+ if (hostGeneration === "v2") {
22231
+ return {
22232
+ auto: block.auto !== false,
22233
+ prune: false,
22234
+ resolved: true,
22235
+ ...typeof block.keep?.tokens === "number" ? { keepTokens: block.keep.tokens } : {},
22236
+ ...typeof block.buffer === "number" ? { buffer: block.buffer } : {}
22237
+ };
22238
+ }
22239
+ return { auto: block.auto === true, prune: block.prune === true, resolved: true };
22240
+ }
22217
22241
  function checkDcpPlugin(directory) {
22218
22242
  const plugins = collectPluginEntries(directory);
22219
22243
  return plugins.some((p) => matchesPackageName(p, DCP_PACKAGE_NAMES));
@@ -26263,9 +26287,11 @@ class SubcModuleTransport {
26263
26287
  this.wrapupSessions.delete(args.sessionId);
26264
26288
  };
26265
26289
  const laneDeadlineMs = Date.now() + attemptTimeoutMs;
26266
- let releaseLane;
26290
+ let releaseLane = () => {};
26267
26291
  try {
26268
- releaseLane = await this.acquireCorrectnessLane(args.sessionId, args.signal, laneDeadlineMs);
26292
+ if (!args.bypassSessionLane) {
26293
+ releaseLane = await this.acquireCorrectnessLane(args.sessionId, args.signal, laneDeadlineMs);
26294
+ }
26269
26295
  } catch (error) {
26270
26296
  finishWrapupTracking();
26271
26297
  if (args.method === "state_sync" && isDeadlineFailure(error)) {
@@ -26367,12 +26393,13 @@ class SubcModuleTransport {
26367
26393
  args.onTimings?.(timings);
26368
26394
  }
26369
26395
  }
26370
- async authorityRequest(sessionId, projectRoot, method, body) {
26396
+ async authorityRequest(sessionId, projectRoot, method, body, timeoutMs) {
26371
26397
  const response = await this.call({
26372
26398
  sessionId,
26373
26399
  projectRoot,
26374
26400
  method,
26375
- body: { ...body, method, v: 1 }
26401
+ body: { ...body, method, v: 1 },
26402
+ timeoutMs
26376
26403
  });
26377
26404
  if (isRecord3(response) && isRecord3(response.result))
26378
26405
  return response.result;
@@ -26432,6 +26459,20 @@ class SubcModuleTransport {
26432
26459
  throw new Error("mirror.pull omitted page");
26433
26460
  return { page: response.page };
26434
26461
  }
26462
+ async mirrorMemory(args) {
26463
+ const { projectRoot, ...body } = args;
26464
+ const response = await this.authorityRequest(`mirror-memory:${args.module_row_id}`, projectRoot ?? this.bindRootForAuthority(), "mirror.memory", body, 1900);
26465
+ return {
26466
+ row: isRecord3(response.row) ? response.row : null
26467
+ };
26468
+ }
26469
+ async memoryIdentityAck(args) {
26470
+ const { projectRoot, ...body } = args;
26471
+ const response = await this.authorityRequest(`memory-identity:${args.project}`, projectRoot ?? this.bindRootForAuthority(), "memory.identity.ack", body);
26472
+ return {
26473
+ acknowledged: typeof response.acknowledged === "number" ? response.acknowledged : 0
26474
+ };
26475
+ }
26435
26476
  async deleteSession(sessionId, projectRoot) {
26436
26477
  await this.call({
26437
26478
  sessionId,
@@ -27700,6 +27741,90 @@ function isSqliteLockError(error) {
27700
27741
  function tableExists(db, name) {
27701
27742
  return Boolean(db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name = ?").get(name));
27702
27743
  }
27744
+ function tableHasHarnessColumn(db, name) {
27745
+ if (!tableExists(db, name))
27746
+ return false;
27747
+ return db.prepare(`PRAGMA table_info(${name})`).all().some((column) => column.name === "harness");
27748
+ }
27749
+ function deleteLosingOpenCode2Twin(db, table, joinColumns, newerPredicate) {
27750
+ if (!tableHasHarnessColumn(db, table))
27751
+ return;
27752
+ const naturalJoin = joinColumns.map((column) => `oc.${column} = o2.${column}`).join(" AND ");
27753
+ const o2On = naturalJoin ? `${naturalJoin} AND oc.harness = 'opencode'` : `oc.harness = 'opencode'`;
27754
+ const ocOn = naturalJoin ? `${naturalJoin} AND o2.harness = 'opencode2'` : `o2.harness = 'opencode2'`;
27755
+ db.exec(`
27756
+ DELETE FROM ${table}
27757
+ WHERE rowid IN (
27758
+ SELECT o2.rowid
27759
+ FROM ${table} AS o2
27760
+ JOIN ${table} AS oc
27761
+ ON ${o2On}
27762
+ WHERE o2.harness = 'opencode2'
27763
+ AND NOT (${newerPredicate})
27764
+ );
27765
+ DELETE FROM ${table}
27766
+ WHERE rowid IN (
27767
+ SELECT oc.rowid
27768
+ FROM ${table} AS oc
27769
+ JOIN ${table} AS o2
27770
+ ON ${ocOn}
27771
+ WHERE oc.harness = 'opencode'
27772
+ AND (${newerPredicate})
27773
+ );
27774
+ `);
27775
+ }
27776
+ function relabelOpenCode2HarnessRows(db) {
27777
+ deleteLosingOpenCode2Twin(db, "session_projects", ["session_id"], "o2.updated_at > oc.updated_at");
27778
+ deleteLosingOpenCode2Twin(db, "primer_candidates", ["project_path", "session_id", "source_start_message_id", "source_end_message_id"], "o2.created_at > oc.created_at");
27779
+ deleteLosingOpenCode2Twin(db, "transform_decisions", ["session_id", "message_id"], "o2.ts_ms > oc.ts_ms");
27780
+ deleteLosingOpenCode2Twin(db, "message_history_orphan_sweep", [], "COALESCE(o2.last_swept_at, -1) > COALESCE(oc.last_swept_at, -1)");
27781
+ if (tableHasHarnessColumn(db, "session_project_backfill_state")) {
27782
+ db.exec(`
27783
+ DELETE FROM session_project_backfill_state
27784
+ WHERE harness = 'opencode2'
27785
+ AND EXISTS (
27786
+ SELECT 1 FROM session_project_backfill_state WHERE harness = 'opencode'
27787
+ )
27788
+ AND NOT (
27789
+ (status = 'completed'
27790
+ AND (SELECT status FROM session_project_backfill_state WHERE harness = 'opencode')
27791
+ != 'completed')
27792
+ OR (
27793
+ status = (SELECT status FROM session_project_backfill_state WHERE harness = 'opencode')
27794
+ AND COALESCE(started_at, -1) > COALESCE(
27795
+ (SELECT started_at FROM session_project_backfill_state WHERE harness = 'opencode'),
27796
+ -1
27797
+ )
27798
+ )
27799
+ );
27800
+ DELETE FROM session_project_backfill_state
27801
+ WHERE harness = 'opencode'
27802
+ AND EXISTS (
27803
+ SELECT 1 FROM session_project_backfill_state WHERE harness = 'opencode2'
27804
+ )
27805
+ AND (
27806
+ ((SELECT status FROM session_project_backfill_state WHERE harness = 'opencode2') = 'completed'
27807
+ AND status != 'completed')
27808
+ OR (
27809
+ status = (SELECT status FROM session_project_backfill_state WHERE harness = 'opencode2')
27810
+ AND COALESCE(
27811
+ (SELECT started_at FROM session_project_backfill_state WHERE harness = 'opencode2'),
27812
+ -1
27813
+ ) > COALESCE(started_at, -1)
27814
+ )
27815
+ );
27816
+ `);
27817
+ }
27818
+ const tables = new Set([
27819
+ ...V85_OPENCODE2_RELABEL_TABLES,
27820
+ ...V85_OPTIONAL_OPENCODE2_RELABEL_TABLES
27821
+ ]);
27822
+ for (const table of tables) {
27823
+ if (!tableHasHarnessColumn(db, table))
27824
+ continue;
27825
+ db.exec(`UPDATE ${table} SET harness = 'opencode' WHERE harness = 'opencode2'`);
27826
+ }
27827
+ }
27703
27828
  function healMismatchedTierClose(db, table, hasLegacy) {
27704
27829
  if (!tableExists(db, table))
27705
27830
  return;
@@ -27901,7 +28026,7 @@ function runMigrations(db) {
27901
28026
  log3(`[migrations] upstream migration lane now: ${MIGRATIONS[MIGRATIONS.length - 1].version}`);
27902
28027
  }
27903
28028
  }
27904
- var FORK_MIGRATION_VERSION_FLOOR = 1e4, MigrationLockBusyError, MIGRATIONS, LATEST_MIGRATION_VERSION;
28029
+ var FORK_MIGRATION_VERSION_FLOOR = 1e4, MigrationLockBusyError, V85_OPENCODE2_RELABEL_TABLES, V85_OPTIONAL_OPENCODE2_RELABEL_TABLES, MIGRATIONS, LATEST_MIGRATION_VERSION;
27905
28030
  var init_migrations = __esm(() => {
27906
28031
  init_compartment_parser();
27907
28032
  init_logger();
@@ -27913,6 +28038,30 @@ var init_migrations = __esm(() => {
27913
28038
  this.name = "MigrationLockBusyError";
27914
28039
  }
27915
28040
  };
28041
+ V85_OPENCODE2_RELABEL_TABLES = [
28042
+ "tags",
28043
+ "pending_ops",
28044
+ "source_contents",
28045
+ "compartments",
28046
+ "compartment_chunk_embeddings",
28047
+ "session_projects",
28048
+ "compartment_events",
28049
+ "compression_depth",
28050
+ "session_facts",
28051
+ "primer_candidates",
28052
+ "notes",
28053
+ "message_history_index",
28054
+ "message_history_source",
28055
+ "pending_session_cleanup",
28056
+ "message_history_orphan_sweep",
28057
+ "session_meta",
28058
+ "subagent_invocations",
28059
+ "historian_runs",
28060
+ "transform_decisions",
28061
+ "recomp_compartments",
28062
+ "recomp_facts"
28063
+ ];
28064
+ V85_OPTIONAL_OPENCODE2_RELABEL_TABLES = ["session_project_backfill_state"];
27916
28065
  MIGRATIONS = [
27917
28066
  {
27918
28067
  version: 1,
@@ -29975,6 +30124,13 @@ var init_migrations = __esm(() => {
29975
30124
  ensureColumn(db, "session_meta", "protected_tokens_effective", "INTEGER");
29976
30125
  ensureColumn(db, "session_meta", "protected_tokens_pre_snapshot", "TEXT");
29977
30126
  }
30127
+ },
30128
+ {
30129
+ version: 85,
30130
+ description: "relabel OpenCode 1.x mis-tagged opencode2 session rows",
30131
+ up(db) {
30132
+ relabelOpenCode2HarnessRows(db);
30133
+ }
29978
30134
  }
29979
30135
  ];
29980
30136
  LATEST_MIGRATION_VERSION = MIGRATIONS.reduce((max, m) => Math.max(max, m.version), 0);
@@ -30054,15 +30210,20 @@ var init_tool_definition_tokens = __esm(() => {
30054
30210
  import { existsSync as existsSync19, readdirSync as readdirSync2, statSync as statSync9 } from "node:fs";
30055
30211
  import { homedir as homedir13 } from "node:os";
30056
30212
  import { isAbsolute as isAbsolute6, join as join16 } from "node:path";
30057
- function openCodeDataDir() {
30058
- return join16(process.env.XDG_DATA_HOME ?? join16(homedir13(), ".local", "share"), "opencode");
30213
+ function openCodeHostGenerationFromVersion(version) {
30214
+ const major = Number.parseInt(version?.match(/\d+/)?.[0] ?? "", 10);
30215
+ return Number.isFinite(major) && major >= 2 ? "v2" : "v1";
30216
+ }
30217
+ function openCodeDataDir(env = process.env, dataHome) {
30218
+ return join16(dataHome ?? env.XDG_DATA_HOME ?? join16(homedir13(), ".local", "share"), "opencode");
30059
30219
  }
30060
- function environmentKey(dataDir) {
30220
+ function environmentKey(dataDir, hostGeneration, channel, env) {
30061
30221
  return [
30222
+ hostGeneration,
30062
30223
  dataDir,
30063
- process.env.OPENCODE_DB ?? "",
30064
- process.env.OPENCODE_DISABLE_CHANNEL_DB ?? "",
30065
- process.env.OPENCODE_CHANNEL ?? ""
30224
+ env.OPENCODE_DB ?? "",
30225
+ env.OPENCODE_DISABLE_CHANNEL_DB ?? "",
30226
+ channel ?? env.OPENCODE_CHANNEL ?? ""
30066
30227
  ].join("\x00");
30067
30228
  }
30068
30229
  function channelPath(dataDir, channel) {
@@ -30094,8 +30255,8 @@ function discoverOpenCodeDb(dataDir) {
30094
30255
  const channel = name === "opencode.db" ? null : name.slice("opencode-".length, -".db".length) || null;
30095
30256
  return { path: existing.path, source: "discovered", channel };
30096
30257
  }
30097
- function resolveFresh(dataDir) {
30098
- const explicit = process.env.OPENCODE_DB;
30258
+ function resolveV1Fresh(dataDir, env = process.env) {
30259
+ const explicit = env.OPENCODE_DB;
30099
30260
  if (explicit !== undefined && explicit.length > 0) {
30100
30261
  if (explicit === ":memory:") {
30101
30262
  return { path: explicit, source: "OPENCODE_DB", channel: null };
@@ -30106,24 +30267,47 @@ function resolveFresh(dataDir) {
30106
30267
  channel: null
30107
30268
  };
30108
30269
  }
30109
- const disableChannelDb = process.env.OPENCODE_DISABLE_CHANNEL_DB;
30270
+ const disableChannelDb = env.OPENCODE_DISABLE_CHANNEL_DB;
30110
30271
  if (disableChannelDb === "1" || disableChannelDb === "true") {
30111
30272
  return { path: join16(dataDir, "opencode.db"), source: "default", channel: null };
30112
30273
  }
30113
- const channel = process.env.OPENCODE_CHANNEL;
30274
+ const channel = env.OPENCODE_CHANNEL;
30114
30275
  if (channel !== undefined && channel.length > 0) {
30115
30276
  return { path: channelPath(dataDir, channel), source: "channel", channel };
30116
30277
  }
30117
30278
  return discoverOpenCodeDb(dataDir);
30118
30279
  }
30119
- function resolveOpenCodeDbPath() {
30120
- const dataDir = openCodeDataDir();
30121
- const key = environmentKey(dataDir);
30280
+ function sourceOpenCodeDatabaseFilename(hostGeneration, channel, env = process.env) {
30281
+ if (hostGeneration === "v1") {
30282
+ const explicit = env.OPENCODE_DB;
30283
+ if (explicit !== undefined && explicit.length > 0)
30284
+ return explicit;
30285
+ if (env.OPENCODE_DISABLE_CHANNEL_DB === "1" || env.OPENCODE_DISABLE_CHANNEL_DB === "true") {
30286
+ return "opencode.db";
30287
+ }
30288
+ return ["latest", "beta", "prod"].includes(channel) ? "opencode.db" : `opencode-${channel}.db`;
30289
+ }
30290
+ return env.OPENCODE_DB ?? (["latest", "dev", "beta", "next", "prod"].includes(channel) || env.OPENCODE_DISABLE_CHANNEL_DB === "1" || env.OPENCODE_DISABLE_CHANNEL_DB === "true" ? "opencode.db" : `opencode-${channel.replace(/[^a-zA-Z0-9._-]/g, "")}.db`);
30291
+ }
30292
+ function resolveV2Fresh(dataDir, channel, env) {
30293
+ const filename = sourceOpenCodeDatabaseFilename("v2", channel, env);
30294
+ const explicit = env.OPENCODE_DB !== undefined;
30295
+ return {
30296
+ path: filename === ":memory:" ? filename : join16(dataDir, filename),
30297
+ source: explicit ? "OPENCODE_DB" : env.OPENCODE_CHANNEL ? "channel" : "default",
30298
+ channel: explicit ? null : channel
30299
+ };
30300
+ }
30301
+ function resolveOpenCodeDbPath(hostGeneration = "v1", options = {}) {
30302
+ const env = options.env ?? process.env;
30303
+ const dataDir = openCodeDataDir(env, options.dataHome);
30304
+ const channel = options.channel ?? env.OPENCODE_CHANNEL;
30305
+ const key = environmentKey(dataDir, hostGeneration, channel, env);
30122
30306
  if (cachedResolution?.key === key && (!cachedResolution.existed || existsSync19(cachedResolution.resolution.path))) {
30123
30307
  if (cachedResolution.existed)
30124
30308
  return cachedResolution.resolution;
30125
30309
  }
30126
- const resolution = resolveFresh(dataDir);
30310
+ const resolution = hostGeneration === "v2" ? resolveV2Fresh(dataDir, channel ?? "latest", env) : resolveV1Fresh(dataDir, env);
30127
30311
  cachedResolution = {
30128
30312
  key,
30129
30313
  resolution,
@@ -30131,6 +30315,29 @@ function resolveOpenCodeDbPath() {
30131
30315
  };
30132
30316
  return resolution;
30133
30317
  }
30318
+ function schemaTableNames(db, schema = "main") {
30319
+ const rows = db.prepare(`SELECT name FROM ${schema}.sqlite_master WHERE type = 'table' AND name IN ('message', 'part', 'session', 'project', 'session_message')`).all();
30320
+ return new Set(rows.flatMap((row) => typeof row.name === "string" ? [row.name] : []));
30321
+ }
30322
+ function detectOpenCodeStoreGeneration(db, schema = "main") {
30323
+ const tables = schemaTableNames(db, schema);
30324
+ const hasV1Messages = tables.has("message") && tables.has("part");
30325
+ if (hasV1Messages)
30326
+ return "v1";
30327
+ if (tables.has("session_message"))
30328
+ return "v2";
30329
+ if (tables.has("session") || tables.has("project"))
30330
+ return "v1";
30331
+ return "unknown";
30332
+ }
30333
+ function assertOpenCodeStoreGeneration(db, expected, path, schema = "main") {
30334
+ const actual = detectOpenCodeStoreGeneration(db, schema);
30335
+ if (actual === expected)
30336
+ return;
30337
+ if (actual === "unknown")
30338
+ return;
30339
+ throw new Error(`OpenCode store generation mismatch at ${path}: expected ${expected}, found ${actual}; refusing generation-specific database access`);
30340
+ }
30134
30341
  function openCodeDbPathExists(resolution = resolveOpenCodeDbPath()) {
30135
30342
  return resolution.path !== ":memory:" && existsSync19(resolution.path);
30136
30343
  }
@@ -30415,7 +30622,7 @@ function initializeDatabase(db, busyTimeoutMs = BOOT_SQLITE_BUSY_TIMEOUT_MS) {
30415
30622
  tag_id INTEGER,
30416
30623
  session_id TEXT,
30417
30624
  content TEXT,
30418
- created_at INTEGER,
30625
+ created_at INTEGER, -- epoch ms; Date.now() on source writes, preserved on session clones
30419
30626
  harness TEXT NOT NULL DEFAULT 'opencode',
30420
30627
  PRIMARY KEY(session_id, tag_id)
30421
30628
  );
@@ -30439,7 +30646,7 @@ function initializeDatabase(db, busyTimeoutMs = BOOT_SQLITE_BUSY_TIMEOUT_MS) {
30439
30646
  p1_embedding BLOB,
30440
30647
  p1_embedding_model_id TEXT,
30441
30648
  legacy INTEGER NOT NULL DEFAULT 0,
30442
- created_at INTEGER NOT NULL,
30649
+ created_at INTEGER NOT NULL, -- epoch ms (Date.now())
30443
30650
  harness TEXT NOT NULL DEFAULT 'opencode',
30444
30651
  UNIQUE(session_id, sequence)
30445
30652
  );
@@ -30458,7 +30665,7 @@ function initializeDatabase(db, busyTimeoutMs = BOOT_SQLITE_BUSY_TIMEOUT_MS) {
30458
30665
  model_id TEXT NOT NULL,
30459
30666
  dims INTEGER NOT NULL,
30460
30667
  vector BLOB NOT NULL,
30461
- created_at INTEGER NOT NULL,
30668
+ created_at INTEGER NOT NULL, -- epoch ms (Date.now())
30462
30669
  UNIQUE(compartment_id, model_id, window_index)
30463
30670
  );
30464
30671
  CREATE INDEX IF NOT EXISTS idx_cce_session ON compartment_chunk_embeddings(session_id);
@@ -30481,7 +30688,7 @@ function initializeDatabase(db, busyTimeoutMs = BOOT_SQLITE_BUSY_TIMEOUT_MS) {
30481
30688
  kind TEXT NOT NULL,
30482
30689
  at_compartment INTEGER,
30483
30690
  fields_json TEXT NOT NULL DEFAULT '{}',
30484
- created_at INTEGER NOT NULL,
30691
+ created_at INTEGER NOT NULL, -- epoch ms (Date.now())
30485
30692
  harness TEXT NOT NULL DEFAULT 'opencode'
30486
30693
  );
30487
30694
  CREATE INDEX IF NOT EXISTS idx_compartment_events_session
@@ -30510,7 +30717,7 @@ function initializeDatabase(db, busyTimeoutMs = BOOT_SQLITE_BUSY_TIMEOUT_MS) {
30510
30717
  session_id TEXT NOT NULL,
30511
30718
  category TEXT NOT NULL,
30512
30719
  content TEXT NOT NULL,
30513
- created_at INTEGER NOT NULL,
30720
+ created_at INTEGER NOT NULL, -- epoch ms (Date.now())
30514
30721
  updated_at INTEGER NOT NULL,
30515
30722
  harness TEXT NOT NULL DEFAULT 'opencode'
30516
30723
  );
@@ -30529,7 +30736,7 @@ function initializeDatabase(db, busyTimeoutMs = BOOT_SQLITE_BUSY_TIMEOUT_MS) {
30529
30736
  source_message_time INTEGER NOT NULL,
30530
30737
  question_embedding BLOB,
30531
30738
  question_embedding_model_id TEXT,
30532
- created_at INTEGER NOT NULL,
30739
+ created_at INTEGER NOT NULL, -- epoch ms (Date.now())
30533
30740
  UNIQUE(project_path, harness, session_id, source_start_message_id, source_end_message_id)
30534
30741
  );
30535
30742
  CREATE INDEX IF NOT EXISTS idx_primer_candidates_project_time
@@ -30552,7 +30759,7 @@ function initializeDatabase(db, busyTimeoutMs = BOOT_SQLITE_BUSY_TIMEOUT_MS) {
30552
30759
  answer_refreshed_at INTEGER,
30553
30760
  source_candidate_ids TEXT NOT NULL DEFAULT '[]',
30554
30761
  source_candidate_provenance TEXT,
30555
- created_at INTEGER NOT NULL,
30762
+ created_at INTEGER NOT NULL, -- epoch ms (Date.now())
30556
30763
  updated_at INTEGER NOT NULL
30557
30764
  );
30558
30765
  CREATE INDEX IF NOT EXISTS idx_primers_project_status_observed
@@ -30665,7 +30872,7 @@ function initializeDatabase(db, busyTimeoutMs = BOOT_SQLITE_BUSY_TIMEOUT_MS) {
30665
30872
  job_id TEXT,
30666
30873
  cursor TEXT,
30667
30874
  status TEXT NOT NULL DEFAULT 'pending',
30668
- created_at INTEGER NOT NULL DEFAULT 0,
30875
+ created_at INTEGER NOT NULL DEFAULT 0, -- epoch ms (Date.now())
30669
30876
  updated_at INTEGER NOT NULL DEFAULT 0,
30670
30877
  UNIQUE(session_id, request_key)
30671
30878
  );
@@ -30706,7 +30913,7 @@ function initializeDatabase(db, busyTimeoutMs = BOOT_SQLITE_BUSY_TIMEOUT_MS) {
30706
30913
  shadow_epoch INTEGER NOT NULL DEFAULT 0,
30707
30914
  corpus_hash TEXT NOT NULL DEFAULT '',
30708
30915
  coverage_json TEXT NOT NULL DEFAULT '{}',
30709
- created_at INTEGER NOT NULL DEFAULT 0,
30916
+ created_at INTEGER NOT NULL DEFAULT 0, -- epoch ms (Date.now())
30710
30917
  UNIQUE(dedup_key, cohort_key)
30711
30918
  );
30712
30919
  CREATE INDEX IF NOT EXISTS idx_embedding_measurement_session
@@ -31129,7 +31336,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
31129
31336
  importance_avg REAL,
31130
31337
  discarded_last INTEGER NOT NULL DEFAULT 0,
31131
31338
  legacy INTEGER NOT NULL DEFAULT 0,
31132
- created_at INTEGER NOT NULL
31339
+ created_at INTEGER NOT NULL -- epoch ms (Date.now())
31133
31340
  );
31134
31341
  CREATE INDEX IF NOT EXISTS idx_historian_runs_session
31135
31342
  ON historian_runs(session_id, created_at DESC);
@@ -31182,7 +31389,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
31182
31389
  importance INTEGER NOT NULL DEFAULT 50,
31183
31390
  episode_type TEXT,
31184
31391
  pass_number INTEGER NOT NULL,
31185
- created_at INTEGER NOT NULL,
31392
+ created_at INTEGER NOT NULL, -- epoch ms (Date.now())
31186
31393
  harness TEXT NOT NULL DEFAULT 'opencode',
31187
31394
  UNIQUE(session_id, sequence)
31188
31395
  );
@@ -31193,7 +31400,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
31193
31400
  category TEXT NOT NULL,
31194
31401
  content TEXT NOT NULL,
31195
31402
  pass_number INTEGER NOT NULL,
31196
- created_at INTEGER NOT NULL,
31403
+ created_at INTEGER NOT NULL, -- epoch ms (Date.now())
31197
31404
  harness TEXT NOT NULL DEFAULT 'opencode'
31198
31405
  );
31199
31406
 
@@ -31526,7 +31733,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
31526
31733
  `);
31527
31734
  ensureColumn(db, "workspaces", "share_categories", `TEXT NOT NULL DEFAULT '["CONSTRAINTS"]'`);
31528
31735
  }
31529
- var databases, pendingAsyncOpens, persistenceByDatabase, persistenceErrorByDatabase, pathByDatabase, LATEST_SUPPORTED_VERSION = 84, BOOT_SQLITE_BUSY_TIMEOUT_MS = 5000, PERMISSIONS_ENFORCEABLE, RPC_DISCOVERY_PARSE_GRACE_MS, defaultRpcDiscoveryFs, rpcDiscoveryFs, sqlitePragmaConfig, CHANNEL2_CLAIM_TTL_MS;
31736
+ var databases, pendingAsyncOpens, persistenceByDatabase, persistenceErrorByDatabase, pathByDatabase, LATEST_SUPPORTED_VERSION = 85, BOOT_SQLITE_BUSY_TIMEOUT_MS = 5000, PERMISSIONS_ENFORCEABLE, RPC_DISCOVERY_PARSE_GRACE_MS, defaultRpcDiscoveryFs, rpcDiscoveryFs, sqlitePragmaConfig, CHANNEL2_CLAIM_TTL_MS;
31530
31737
  var init_storage_db = __esm(async () => {
31531
31738
  init_data_path();
31532
31739
  init_logger();
@@ -32683,6 +32890,81 @@ var init_doctor_repair_db = __esm(async () => {
32683
32890
  ];
32684
32891
  });
32685
32892
 
32893
+ // src/commands/doctor-hidden-sessions.ts
32894
+ function parseMetadata(value) {
32895
+ if (value && typeof value === "object" && !Array.isArray(value)) {
32896
+ return value;
32897
+ }
32898
+ if (typeof value !== "string")
32899
+ return null;
32900
+ try {
32901
+ const parsed = JSON.parse(value);
32902
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
32903
+ } catch {
32904
+ return null;
32905
+ }
32906
+ }
32907
+ function listHiddenSessionsFromDatabase(database) {
32908
+ const columns = new Set(database.prepare("PRAGMA table_info(session)").all().flatMap((row) => row && typeof row === "object" && typeof row.name === "string" ? [row.name] : []));
32909
+ if (!columns.has("metadata"))
32910
+ return [];
32911
+ const title = columns.has("title") ? "title" : "'' AS title";
32912
+ const directory = columns.has("directory") ? "directory" : "'' AS directory";
32913
+ const updatedAt = columns.has("time_updated") ? "time_updated" : columns.has("updated_at") ? "updated_at AS time_updated" : "NULL AS time_updated";
32914
+ const rows = database.prepare(`SELECT id, ${title}, ${directory}, ${updatedAt}, metadata
32915
+ FROM session
32916
+ WHERE metadata IS NOT NULL
32917
+ ORDER BY time_updated DESC, id ASC`).all();
32918
+ return rows.flatMap((row) => {
32919
+ const metadata = parseMetadata(row.metadata);
32920
+ if (metadata?.magic_context !== "hidden-run" || typeof row.id !== "string")
32921
+ return [];
32922
+ const role = metadata.role;
32923
+ return [
32924
+ {
32925
+ id: row.id,
32926
+ title: typeof row.title === "string" ? row.title : "",
32927
+ directory: typeof row.directory === "string" ? row.directory : "",
32928
+ role: role === "historian" || role === "dreamer" ? role : "unknown",
32929
+ updatedAt: typeof row.time_updated === "number" ? row.time_updated : null
32930
+ }
32931
+ ];
32932
+ });
32933
+ }
32934
+ async function runListHiddenSessions() {
32935
+ const resolution = resolveOpenCodeDbPath("v2");
32936
+ if (!openCodeDbPathExists(resolution)) {
32937
+ console.log(`No OpenCode 2 session database found at ${resolution.path}.`);
32938
+ return 0;
32939
+ }
32940
+ const db = openExistingDatabase(resolution.path, { readonly: true });
32941
+ if (!db) {
32942
+ console.log(`No OpenCode 2 session database found at ${resolution.path}.`);
32943
+ return 0;
32944
+ }
32945
+ try {
32946
+ assertOpenCodeStoreGeneration(db, "v2", resolution.path);
32947
+ const sessions = listHiddenSessionsFromDatabase(db);
32948
+ if (sessions.length === 0) {
32949
+ console.log("No Magic Context hidden-run sessions found.");
32950
+ return 0;
32951
+ }
32952
+ console.log(`Magic Context hidden-run sessions (${sessions.length}):`);
32953
+ for (const session of sessions) {
32954
+ const location = session.directory ? ` ${session.directory}` : "";
32955
+ console.log(`- ${session.id} ${session.role} ${session.title}${location}`);
32956
+ }
32957
+ console.log("These are visible OpenCode 2 root sessions and are never deleted by Magic Context. Remove unwanted sessions manually in OpenCode.");
32958
+ return 0;
32959
+ } finally {
32960
+ db.close();
32961
+ }
32962
+ }
32963
+ var init_doctor_hidden_sessions = __esm(async () => {
32964
+ init_opencode_db_path();
32965
+ await init_database_access();
32966
+ });
32967
+
32686
32968
  // src/lib/migration-paths.ts
32687
32969
  function getOpenCodeDatabasePath() {
32688
32970
  return resolveOpenCodeDbPath().path;
@@ -33291,6 +33573,7 @@ function migrateOpenCodeSessionToPi(opts) {
33291
33573
  if (db === null) {
33292
33574
  throw new Error(`OpenCode database not found at ${opencodeDbPath}; nothing to migrate.`);
33293
33575
  }
33576
+ assertOpenCodeStoreGeneration(db, "v1", opencodeDbPath);
33294
33577
  let cortexkitDb;
33295
33578
  let ownsCortexkitDb = false;
33296
33579
  let cortexkitSchemaVersionBefore = null;
@@ -33560,6 +33843,7 @@ var DEFAULT_PROVIDER = "openai-codex", DEFAULT_MODEL = "gpt-5.5", MIGRATION_COMP
33560
33843
  FROM migration_pending WHERE migration_key = ?`;
33561
33844
  var init_migrate = __esm(async () => {
33562
33845
  init_data_path();
33846
+ init_opencode_db_path();
33563
33847
  init_atomic_write();
33564
33848
  init_migration_paths();
33565
33849
  init_paths();
@@ -33969,6 +34253,7 @@ async function runMigrateSessionCli(args) {
33969
34253
  if (opencodeDb === null) {
33970
34254
  throw new Error(`OpenCode database not found at ${opencodeDbPath}; nothing to migrate.`);
33971
34255
  }
34256
+ assertOpenCodeStoreGeneration(opencodeDb, "v1", opencodeDbPath);
33972
34257
  contextDb = dryRun ? openExistingContextDatabase(contextDbPath, { readonly: true }) : openExistingContextDatabaseForMutation(contextDbPath);
33973
34258
  if (contextDb === null) {
33974
34259
  throw new Error(`Magic Context database not found at ${contextDbPath}; nothing to migrate.`);
@@ -34089,6 +34374,7 @@ var init_migrate_session = __esm(async () => {
34089
34374
  init_storage_project_state();
34090
34375
  init_module_transport();
34091
34376
  init_data_path();
34377
+ init_opencode_db_path();
34092
34378
  init_migration_paths();
34093
34379
  init_prompts();
34094
34380
  await __promiseAll([
@@ -34561,6 +34847,11 @@ function parsePiConfig(rawConfig, recoveredTopLevelKeys = []) {
34561
34847
  }
34562
34848
  delete patched[key];
34563
34849
  const defaultValue = defaults[key];
34850
+ const invalidRawValue = rawConfig[key];
34851
+ if (key === "protected_tokens" && typeof invalidRawValue === "number" && invalidRawValue < PROTECTED_TOKENS_MIN) {
34852
+ warnings.push(`protected_tokens is a token floor (minimum ${PROTECTED_TOKENS_MIN}, default derived from the context window); ${invalidRawValue} looks like the old protected_tags count. Remove the key to use the default, or set a token count such as 16000.`);
34853
+ continue;
34854
+ }
34564
34855
  warnings.push(`"${key}": invalid value (${redactConfigValue2(rawConfig[key])}), using default ${JSON.stringify(defaultValue)}.`);
34565
34856
  }
34566
34857
  const retryParsed = MagicContextConfigSchema.safeParse(patched);
@@ -36384,12 +36675,43 @@ function listShadowBackfillStalls(db, projectIdentity) {
36384
36675
  }
36385
36676
  var SHADOW_BACKFILL_PROVENANCE_KEY = "_magicContextShadowBackfill";
36386
36677
 
36678
+ // ../plugin/src/shared/auto-update-provenance.ts
36679
+ import { existsSync as existsSync28, readFileSync as readFileSync17 } from "node:fs";
36680
+ function readAutoUpdateCheckState(path) {
36681
+ if (!existsSync28(path))
36682
+ return null;
36683
+ try {
36684
+ const value = JSON.parse(readFileSync17(path, "utf-8"));
36685
+ if (!value || typeof value !== "object" || Array.isArray(value))
36686
+ return null;
36687
+ const raw = value;
36688
+ const state = {};
36689
+ if (typeof raw.lastCheckedMs === "number" && Number.isFinite(raw.lastCheckedMs)) {
36690
+ state.lastCheckedMs = raw.lastCheckedMs;
36691
+ }
36692
+ if (typeof raw.updaterPinnedSpec === "string" && raw.updaterPinnedSpec.length > 0) {
36693
+ state.updaterPinnedSpec = raw.updaterPinnedSpec;
36694
+ }
36695
+ if (typeof raw.updaterPinnedAt === "number" && Number.isFinite(raw.updaterPinnedAt)) {
36696
+ state.updaterPinnedAt = raw.updaterPinnedAt;
36697
+ }
36698
+ return state;
36699
+ } catch {
36700
+ return null;
36701
+ }
36702
+ }
36703
+ function isUpdaterPinnedSpec(state, configuredSpec) {
36704
+ return state?.updaterPinnedSpec === configuredSpec && typeof state.updaterPinnedAt === "number" && Number.isFinite(state.updaterPinnedAt);
36705
+ }
36706
+ var AUTO_UPDATE_CHECK_STATE_FILENAME = "last-update-check.json";
36707
+ var init_auto_update_provenance = () => {};
36708
+
36387
36709
  // ../plugin/src/shared/tui-config.ts
36388
36710
  import {
36389
36711
  chmodSync as chmodSync5,
36390
- existsSync as existsSync28,
36712
+ existsSync as existsSync29,
36391
36713
  mkdirSync as mkdirSync9,
36392
- readFileSync as readFileSync17,
36714
+ readFileSync as readFileSync18,
36393
36715
  renameSync as renameSync6,
36394
36716
  statSync as statSync13,
36395
36717
  writeFileSync as writeFileSync6
@@ -36437,9 +36759,9 @@ function resolveTuiConfigPath(configDirOverride) {
36437
36759
  const configDir = configDirOverride ?? getOpenCodeConfigPaths({ binary: "opencode" }).configDir;
36438
36760
  const jsoncPath = join24(configDir, "tui.jsonc");
36439
36761
  const jsonPath = join24(configDir, "tui.json");
36440
- if (existsSync28(jsoncPath))
36762
+ if (existsSync29(jsoncPath))
36441
36763
  return jsoncPath;
36442
- if (existsSync28(jsonPath))
36764
+ if (existsSync29(jsonPath))
36443
36765
  return jsonPath;
36444
36766
  return jsoncPath;
36445
36767
  }
@@ -36447,8 +36769,8 @@ function ensureTuiPluginEntry(options = {}) {
36447
36769
  try {
36448
36770
  const configPath = resolveTuiConfigPath(options.configDir);
36449
36771
  let config = {};
36450
- if (existsSync28(configPath)) {
36451
- const raw = readFileSync17(configPath, "utf-8");
36772
+ if (existsSync29(configPath)) {
36773
+ const raw = readFileSync18(configPath, "utf-8");
36452
36774
  config = import_comment_json8.parse(raw) ?? {};
36453
36775
  }
36454
36776
  const plugins = Array.isArray(config.plugin) ? [...config.plugin] : [];
@@ -36500,7 +36822,7 @@ var init_tui_config = __esm(() => {
36500
36822
  });
36501
36823
 
36502
36824
  // src/lib/diagnostics-opencode.ts
36503
- import { existsSync as existsSync29, readdirSync as readdirSync4, readFileSync as readFileSync18, statSync as statSync14 } from "node:fs";
36825
+ import { existsSync as existsSync30, readdirSync as readdirSync4, readFileSync as readFileSync19, statSync as statSync14 } from "node:fs";
36504
36826
  import { createRequire as createRequire4 } from "node:module";
36505
36827
  import { join as join25 } from "node:path";
36506
36828
  function getSelfVersion() {
@@ -36520,8 +36842,8 @@ function getPluginCacheInfo() {
36520
36842
  let cached;
36521
36843
  for (const installedPkgPath of getOpenCodePluginPackageJsonPaths()) {
36522
36844
  try {
36523
- if (existsSync29(installedPkgPath)) {
36524
- const pkg = JSON.parse(readFileSync18(installedPkgPath, "utf-8"));
36845
+ if (existsSync30(installedPkgPath)) {
36846
+ const pkg = JSON.parse(readFileSync19(installedPkgPath, "utf-8"));
36525
36847
  cached = typeof pkg.version === "string" ? pkg.version : undefined;
36526
36848
  if (cached)
36527
36849
  break;
@@ -36537,7 +36859,7 @@ function getStorageResolution() {
36537
36859
  }
36538
36860
  function fileSize(path) {
36539
36861
  try {
36540
- return existsSync29(path) ? statSync14(path).size : 0;
36862
+ return existsSync30(path) ? statSync14(path).size : 0;
36541
36863
  } catch {
36542
36864
  return 0;
36543
36865
  }
@@ -36549,10 +36871,10 @@ function sanitizeValue(value) {
36549
36871
  return sanitizeConfigValue(value);
36550
36872
  }
36551
36873
  function readConfig3(path) {
36552
- if (!existsSync29(path))
36874
+ if (!existsSync30(path))
36553
36875
  return { value: null };
36554
36876
  try {
36555
- const raw = readFileSync18(path, "utf-8");
36877
+ const raw = readFileSync19(path, "utf-8");
36556
36878
  const value = import_comment_json9.parse(raw);
36557
36879
  return { value };
36558
36880
  } catch (error) {
@@ -36577,7 +36899,7 @@ function configHasPluginEntry(config) {
36577
36899
  }
36578
36900
  function parseHistorianDumpMeta(path) {
36579
36901
  try {
36580
- const xml = readFileSync18(path, "utf-8");
36902
+ const xml = readFileSync19(path, "utf-8");
36581
36903
  const parsed = parseCompartmentOutput(xml);
36582
36904
  const factCountByCategory = {};
36583
36905
  for (const fact of parsed.facts) {
@@ -36610,7 +36932,7 @@ function parseHistorianDumpMeta(path) {
36610
36932
  }
36611
36933
  }
36612
36934
  function listDumpsInDir(dir, limit) {
36613
- if (!existsSync29(dir))
36935
+ if (!existsSync30(dir))
36614
36936
  return { count: 0, recent: [] };
36615
36937
  try {
36616
36938
  const entries = readdirSync4(dir).filter((name) => name.endsWith(".xml")).map((name) => {
@@ -36733,7 +37055,7 @@ function collectRecentSessionsFromDatabase(database) {
36733
37055
  return [{ sessionId, title, directory, lastActiveAt, parentSessionId }];
36734
37056
  });
36735
37057
  }
36736
- async function collectRecentSessions(resolution) {
37058
+ async function collectRecentSessions(resolution, hostGeneration) {
36737
37059
  const opencodeDbPath = resolution.path;
36738
37060
  if (!openCodeDbPathExists(resolution))
36739
37061
  return [];
@@ -36750,6 +37072,7 @@ async function collectRecentSessions(resolution) {
36750
37072
  let db = null;
36751
37073
  try {
36752
37074
  db = new DatabaseClass(opencodeDbPath, { readonly: true });
37075
+ assertOpenCodeStoreGeneration(db, hostGeneration, opencodeDbPath);
36753
37076
  return collectRecentSessionsFromDatabase(db);
36754
37077
  } catch {
36755
37078
  return [];
@@ -36761,7 +37084,7 @@ async function collectRecentSessions(resolution) {
36761
37084
  }
36762
37085
  async function collectHistorianFailures(storageDirPath) {
36763
37086
  const contextDbPath = join25(storageDirPath, "context.db");
36764
- if (!existsSync29(contextDbPath))
37087
+ if (!existsSync30(contextDbPath))
36765
37088
  return [];
36766
37089
  if (typeof globalThis.Bun === "undefined") {
36767
37090
  return [];
@@ -36795,7 +37118,7 @@ async function collectHistorianFailures(storageDirPath) {
36795
37118
  }
36796
37119
  async function collectHistorianRuns(storageDirPath) {
36797
37120
  const contextDbPath = join25(storageDirPath, "context.db");
36798
- if (!existsSync29(contextDbPath))
37121
+ if (!existsSync30(contextDbPath))
36799
37122
  return [];
36800
37123
  if (typeof globalThis.Bun === "undefined")
36801
37124
  return [];
@@ -36874,11 +37197,12 @@ async function collectDiagnostics() {
36874
37197
  } catch (error) {
36875
37198
  console.warn(`[magic-context] Could not load Magic Context config to resolve compaction mode; ` + `preserving existing native compaction fields. ` + `(${error instanceof Error ? error.message : String(error)})`);
36876
37199
  }
36877
- const conflictResult = detectConflicts(process.cwd(), { compactionEnabled });
36878
- const openCodeDatabaseResolution = resolveOpenCodeDbPath();
36879
- const recentSessions = await collectRecentSessions(openCodeDatabaseResolution);
36880
37200
  const opencodeInstallations = describeOpenCodeInstallations(detectOpenCodeInstallations());
36881
37201
  const activeInstallation = opencodeInstallations[0];
37202
+ const hostGeneration = openCodeHostGenerationFromVersion(activeInstallation?.version);
37203
+ const conflictResult = detectConflicts(process.cwd(), { compactionEnabled, hostGeneration });
37204
+ const openCodeDatabaseResolution = resolveOpenCodeDbPath(hostGeneration);
37205
+ const recentSessions = await collectRecentSessions(openCodeDatabaseResolution, hostGeneration);
36882
37206
  let openCodeInstallKind = "none";
36883
37207
  if (activeInstallation)
36884
37208
  openCodeInstallKind = activeInstallation.kind;
@@ -36896,7 +37220,7 @@ async function collectDiagnostics() {
36896
37220
  opencodeConfigHasPlugin: configHasPluginEntry(opencodeConfig.value),
36897
37221
  tuiConfigHasPlugin: configHasPluginEntry(tuiConfig.value),
36898
37222
  magicContextConfig: {
36899
- exists: existsSync29(configPaths.magicContextConfig),
37223
+ exists: existsSync30(configPaths.magicContextConfig),
36900
37224
  ...magicContextConfig.error ? { parseError: magicContextConfig.error } : {},
36901
37225
  flags: sanitizeValue(magicContextConfig.value ?? {}) ?? {}
36902
37226
  },
@@ -36904,7 +37228,7 @@ async function collectDiagnostics() {
36904
37228
  storageDir: {
36905
37229
  path: storageDirPath,
36906
37230
  source: storageResolution.source,
36907
- exists: existsSync29(storageDirPath),
37231
+ exists: existsSync30(storageDirPath),
36908
37232
  contextDbSizeBytes: fileSize(contextDbPath)
36909
37233
  },
36910
37234
  openCodeDatabase: {
@@ -37131,7 +37455,7 @@ var init_embedding_local = __esm(() => {
37131
37455
 
37132
37456
  // src/lib/embedding-runtime.ts
37133
37457
  import { spawnSync as spawnSync6 } from "node:child_process";
37134
- import { existsSync as existsSync30, readFileSync as readFileSync19 } from "node:fs";
37458
+ import { existsSync as existsSync31, readFileSync as readFileSync20 } from "node:fs";
37135
37459
  import { createRequire as createRequire5 } from "node:module";
37136
37460
  import { dirname as dirname16, join as join26, sep } from "node:path";
37137
37461
  function describeError(error) {
@@ -37278,7 +37602,7 @@ function expectedBinaryRelPath(platform, arch) {
37278
37602
  }
37279
37603
  function onnxRuntimeNodeVersion(packageDir) {
37280
37604
  try {
37281
- const parsed = JSON.parse(readFileSync19(join26(packageDir, "package.json"), "utf8"));
37605
+ const parsed = JSON.parse(readFileSync20(join26(packageDir, "package.json"), "utf8"));
37282
37606
  return typeof parsed.version === "string" ? parsed.version : undefined;
37283
37607
  } catch {
37284
37608
  return;
@@ -37327,7 +37651,7 @@ function formatLocalEmbeddingRuntimeWasmSelected(status) {
37327
37651
  function requireNodeWasmBundle(probe, candidates) {
37328
37652
  if (probe.state === "failed")
37329
37653
  return probe;
37330
- const bundlePath = candidates.find((candidate) => existsSync30(candidate));
37654
+ const bundlePath = candidates.find((candidate) => existsSync31(candidate));
37331
37655
  return bundlePath ? probe : {
37332
37656
  state: "failed",
37333
37657
  reason: `functional Node WASM Transformers bundle is missing (checked ${candidates.join(", ")})`
@@ -37352,7 +37676,7 @@ function checkLocalEmbeddingRuntimeAt(installRoot, platform = process.platform,
37352
37676
  }
37353
37677
  const packageDir = join26(installRoot, "node_modules", "onnxruntime-node");
37354
37678
  let native;
37355
- if (!existsSync30(join26(packageDir, "package.json"))) {
37679
+ if (!existsSync31(join26(packageDir, "package.json"))) {
37356
37680
  native = { state: "package-missing", packageDir };
37357
37681
  } else {
37358
37682
  const rel = expectedBinaryRelPath(platform, arch);
@@ -37363,7 +37687,7 @@ function checkLocalEmbeddingRuntimeAt(installRoot, platform = process.platform,
37363
37687
  };
37364
37688
  } else {
37365
37689
  const binaryPath = join26(packageDir, rel);
37366
- native = existsSync30(binaryPath) ? probeOnnxRuntimeNodeLoad(packageDir) ?? { state: "ok", binaryPath } : {
37690
+ native = existsSync31(binaryPath) ? probeOnnxRuntimeNodeLoad(packageDir) ?? { state: "ok", binaryPath } : {
37367
37691
  state: "binary-missing",
37368
37692
  packageDir,
37369
37693
  expectedBinary: binaryPath,
@@ -37374,7 +37698,7 @@ function checkLocalEmbeddingRuntimeAt(installRoot, platform = process.platform,
37374
37698
  return withWasmFallback(native, () => probeWasmRuntimeAt(installRoot));
37375
37699
  }
37376
37700
  function checkLocalEmbeddingRuntime(installRoots, platform = process.platform, arch = process.arch, runtimePreference = "auto", host) {
37377
- const existing = installRoots.filter((root) => existsSync30(root));
37701
+ const existing = installRoots.filter((root) => existsSync31(root));
37378
37702
  if (existing.length === 0) {
37379
37703
  return {
37380
37704
  state: "unknown",
@@ -37421,7 +37745,7 @@ function probeWasmRuntimeByResolution(pluginDir) {
37421
37745
  }
37422
37746
  }
37423
37747
  function checkLocalEmbeddingRuntimeByResolution(pluginDir, platform = process.platform, arch = process.arch, runtimePreference = "auto", host) {
37424
- if (!existsSync30(join26(pluginDir, "package.json"))) {
37748
+ if (!existsSync31(join26(pluginDir, "package.json"))) {
37425
37749
  return { state: "unknown", reason: "plugin package dir not found" };
37426
37750
  }
37427
37751
  const selectedRuntime = resolveLocalEmbeddingRuntime(runtimePreference, host);
@@ -37463,7 +37787,7 @@ function checkLocalEmbeddingRuntimeByResolution(pluginDir, platform = process.pl
37463
37787
  native = probeOnnxRuntimeNodeLoad(onnxDir) ?? { state: "ok", binaryPath: onnxDir };
37464
37788
  } else {
37465
37789
  const binaryPath = join26(onnxDir, rel);
37466
- native = existsSync30(binaryPath) ? probeOnnxRuntimeNodeLoad(onnxDir) ?? { state: "ok", binaryPath } : {
37790
+ native = existsSync31(binaryPath) ? probeOnnxRuntimeNodeLoad(onnxDir) ?? { state: "ok", binaryPath } : {
37467
37791
  state: "binary-missing",
37468
37792
  packageDir: onnxDir,
37469
37793
  expectedBinary: binaryPath,
@@ -38023,9 +38347,9 @@ var init_types = __esm(() => {
38023
38347
  // ../plugin/src/hooks/auto-update-checker/checker.ts
38024
38348
  import {
38025
38349
  accessSync as accessSync2,
38026
- existsSync as existsSync31,
38350
+ existsSync as existsSync32,
38027
38351
  constants as fsConstants,
38028
- readFileSync as readFileSync20,
38352
+ readFileSync as readFileSync21,
38029
38353
  renameSync as renameSync7,
38030
38354
  statSync as statSync15,
38031
38355
  writeFileSync as writeFileSync8
@@ -38077,9 +38401,9 @@ function getWinningConfig(directory, surface) {
38077
38401
  let winner = null;
38078
38402
  for (const path of getSurfaceConfigPaths(directory, surface)) {
38079
38403
  try {
38080
- if (!existsSync31(path))
38404
+ if (!existsSync32(path))
38081
38405
  continue;
38082
- const parsed = parseJsonConfig(readFileSync20(path, "utf-8"));
38406
+ const parsed = parseJsonConfig(readFileSync21(path, "utf-8"));
38083
38407
  const entries = getPluginEntries(parsed);
38084
38408
  if (entries.some((entry) => entry === PACKAGE_NAME || entry.startsWith(`${PACKAGE_NAME}@`))) {
38085
38409
  if (winner) {
@@ -38115,14 +38439,14 @@ var init_checker = __esm(() => {
38115
38439
  });
38116
38440
 
38117
38441
  // src/lib/opencode-plugin-schema-fence.ts
38118
- import { existsSync as existsSync32, readdirSync as readdirSync5, readFileSync as readFileSync21 } from "node:fs";
38442
+ import { existsSync as existsSync33, readdirSync as readdirSync5, readFileSync as readFileSync22 } from "node:fs";
38119
38443
  import { join as join30 } from "node:path";
38120
38444
  import { gunzipSync } from "node:zlib";
38121
38445
  function readPackageVersion(packageJsonPath) {
38122
38446
  try {
38123
- if (!existsSync32(packageJsonPath))
38447
+ if (!existsSync33(packageJsonPath))
38124
38448
  return null;
38125
- const packageJson = JSON.parse(readFileSync21(packageJsonPath, "utf-8"));
38449
+ const packageJson = JSON.parse(readFileSync22(packageJsonPath, "utf-8"));
38126
38450
  if (packageJson.name !== OPENCODE_PLUGIN_NAME || typeof packageJson.version !== "string") {
38127
38451
  return null;
38128
38452
  }
@@ -38142,7 +38466,7 @@ function readFenceValue(text) {
38142
38466
  }
38143
38467
  function readFenceFromDist(packageDirectory) {
38144
38468
  const distDirectory = join30(packageDirectory, "dist");
38145
- if (!existsSync32(distDirectory))
38469
+ if (!existsSync33(distDirectory))
38146
38470
  return null;
38147
38471
  const pending = [distDirectory];
38148
38472
  const fenceValues = new Set;
@@ -38159,7 +38483,7 @@ function readFenceFromDist(packageDirectory) {
38159
38483
  }
38160
38484
  if (!entry.isFile() || !/\.(?:[cm]?js|ts)$/.test(entry.name))
38161
38485
  continue;
38162
- const fence = readFenceValue(readFileSync21(path, "utf-8"));
38486
+ const fence = readFenceValue(readFileSync22(path, "utf-8"));
38163
38487
  if (fence !== null)
38164
38488
  fenceValues.add(fence);
38165
38489
  }
@@ -38376,14 +38700,53 @@ var init_storage_versions = __esm(async () => {
38376
38700
  await init_storage_db();
38377
38701
  });
38378
38702
 
38703
+ // src/commands/doctor-compartment-boundaries.ts
38704
+ function listDanglingCompartmentBoundaries(contextDb, openCodeDb) {
38705
+ const generation = detectOpenCodeStoreGeneration(openCodeDb);
38706
+ if (generation === "unknown") {
38707
+ throw new Error("OpenCode session database has an unrecognized schema");
38708
+ }
38709
+ const rows = contextDb.prepare(`SELECT c.session_id, c.sequence, c.start_message_id, c.end_message_id
38710
+ FROM compartments AS c
38711
+ LEFT JOIN session_meta AS sm ON sm.session_id = c.session_id
38712
+ WHERE sm.harness IS NULL OR sm.harness IN ('opencode', 'opencode2')
38713
+ ORDER BY c.session_id ASC, c.sequence ASC`).all();
38714
+ const statement = openCodeDb.prepare(generation === "v2" ? "SELECT 1 AS found FROM session_message WHERE session_id = ? AND id = ? LIMIT 1" : "SELECT 1 AS found FROM message WHERE session_id = ? AND id = ? LIMIT 1");
38715
+ const exists = (sessionId, messageId) => statement.get(sessionId, messageId) != null;
38716
+ return rows.flatMap((row) => {
38717
+ const missingStart = !exists(row.session_id, row.start_message_id);
38718
+ const missingEnd = !exists(row.session_id, row.end_message_id);
38719
+ if (!missingStart && !missingEnd)
38720
+ return [];
38721
+ return [
38722
+ {
38723
+ sessionId: row.session_id,
38724
+ sequence: row.sequence,
38725
+ missingStartMessageId: missingStart ? row.start_message_id : null,
38726
+ missingEndMessageId: missingEnd ? row.end_message_id : null
38727
+ }
38728
+ ];
38729
+ });
38730
+ }
38731
+ function formatDanglingCompartmentBoundary(boundary) {
38732
+ const missing = [
38733
+ boundary.missingStartMessageId ? `start_message_id=${boundary.missingStartMessageId}` : null,
38734
+ boundary.missingEndMessageId ? `end_message_id=${boundary.missingEndMessageId}` : null
38735
+ ].filter((value) => value !== null);
38736
+ return `session=${boundary.sessionId} sequence=${boundary.sequence} missing ${missing.join(" ")}`;
38737
+ }
38738
+ var init_doctor_compartment_boundaries = __esm(() => {
38739
+ init_opencode_db_path();
38740
+ });
38741
+
38379
38742
  // src/commands/doctor-opencode-cache.ts
38380
- import { existsSync as existsSync33, readFileSync as readFileSync22, rmSync as rmSync3 } from "node:fs";
38743
+ import { existsSync as existsSync34, readFileSync as readFileSync23, rmSync as rmSync3 } from "node:fs";
38381
38744
  function readCachedPluginVersion(pluginCacheDir) {
38382
38745
  try {
38383
38746
  const installedPkgPath = getOpenCodePluginPackageJsonPath(pluginCacheDir);
38384
- if (!existsSync33(installedPkgPath))
38747
+ if (!existsSync34(installedPkgPath))
38385
38748
  return;
38386
- const pkg = JSON.parse(readFileSync22(installedPkgPath, "utf-8"));
38749
+ const pkg = JSON.parse(readFileSync23(installedPkgPath, "utf-8"));
38387
38750
  return typeof pkg.version === "string" ? pkg.version : undefined;
38388
38751
  } catch {
38389
38752
  return;
@@ -38392,7 +38755,7 @@ function readCachedPluginVersion(pluginCacheDir) {
38392
38755
  async function clearPluginCache(options = {}, deps = {}) {
38393
38756
  const remove = deps.remove ?? ((path) => rmSync3(path, { recursive: true, force: true }));
38394
38757
  const pluginCacheRoots = getOpenCodePluginCacheRoots();
38395
- const existingRoots = pluginCacheRoots.filter((root) => existsSync33(root));
38758
+ const existingRoots = pluginCacheRoots.filter((root) => existsSync34(root));
38396
38759
  if (existingRoots.length === 0) {
38397
38760
  return { action: "not_found", path: pluginCacheRoots[0] ?? "" };
38398
38761
  }
@@ -38460,7 +38823,7 @@ var init_doctor_opencode_cache = __esm(() => {
38460
38823
 
38461
38824
  // src/commands/doctor-opencode.ts
38462
38825
  import { spawnSync as spawnSync7 } from "node:child_process";
38463
- import { existsSync as existsSync34, readFileSync as readFileSync23 } from "node:fs";
38826
+ import { existsSync as existsSync35, readFileSync as readFileSync24 } from "node:fs";
38464
38827
  import { createRequire as createRequire6 } from "node:module";
38465
38828
  import { homedir as homedir16 } from "node:os";
38466
38829
  import { join as join31 } from "node:path";
@@ -38566,6 +38929,13 @@ function isPinnedOpenCodePluginSpecifier(specifier) {
38566
38929
  return false;
38567
38930
  return specifier.startsWith(`${OPENCODE_PLUGIN_NAME}@`);
38568
38931
  }
38932
+ function describeAutoUpdateStall(specifier, autoUpdateEnabled, storageDir = getMagicContextStorageDir()) {
38933
+ if (!autoUpdateEnabled || !isPinnedOpenCodePluginSpecifier(specifier))
38934
+ return null;
38935
+ const state = readAutoUpdateCheckState(join31(storageDir, AUTO_UPDATE_CHECK_STATE_FILENAME));
38936
+ const owner = isUpdaterPinnedSpec(state, specifier) ? "updater" : "you";
38937
+ return `auto-update: stalled — config pinned to ${specifier} (by ${owner})`;
38938
+ }
38569
38939
  function getUserNpmrcPath() {
38570
38940
  const custom = process.env.NPM_CONFIG_USERCONFIG?.trim();
38571
38941
  if (custom)
@@ -38576,10 +38946,10 @@ function getUserNpmrcPath() {
38576
38946
  function collectNpmReleaseAgeWarnings() {
38577
38947
  const ageWarnings = [];
38578
38948
  const npmrcPath = getUserNpmrcPath();
38579
- if (!existsSync34(npmrcPath))
38949
+ if (!existsSync35(npmrcPath))
38580
38950
  return ageWarnings;
38581
38951
  try {
38582
- const npmrc = readFileSync23(npmrcPath, "utf-8");
38952
+ const npmrc = readFileSync24(npmrcPath, "utf-8");
38583
38953
  for (const line of npmrc.split(`
38584
38954
  `)) {
38585
38955
  const trimmed = line.trim();
@@ -38713,7 +39083,7 @@ function checkLocalEmbeddingRuntimeForDoctor(runtimePreference = "auto") {
38713
39083
  return { issues: 0 };
38714
39084
  }
38715
39085
  async function checkEmbeddingConfig(magicContextConfigPath) {
38716
- if (!existsSync34(magicContextConfigPath)) {
39086
+ if (!existsSync35(magicContextConfigPath)) {
38717
39087
  return checkLocalEmbeddingRuntimeForDoctor();
38718
39088
  }
38719
39089
  let rawText;
@@ -38935,11 +39305,42 @@ async function runDoctor2(options = {}) {
38935
39305
  } else {
38936
39306
  pass(installationReports.length > 1 ? `OpenCode ${activeInstallation.version} installed (active install marked above)` : `OpenCode ${activeInstallation.version} installed`);
38937
39307
  }
38938
- const openCodeDbCheck = describeOpenCodeDatabaseDoctorCheck(resolveOpenCodeDbPath());
39308
+ const hostGeneration = openCodeHostGenerationFromVersion(activeInstallation.version);
39309
+ const openCodeDbResolution = resolveOpenCodeDbPath(hostGeneration);
39310
+ const openCodeDbCheck = describeOpenCodeDatabaseDoctorCheck(openCodeDbResolution);
38939
39311
  if (openCodeDbCheck.ok)
38940
39312
  pass(openCodeDbCheck.message);
38941
39313
  else
38942
39314
  fail(openCodeDbCheck.message);
39315
+ if (openCodeDbCheck.ok) {
39316
+ let contextDb = null;
39317
+ let sessionDb = null;
39318
+ try {
39319
+ contextDb = openExistingContextDatabase(authorityDbPath, { readonly: true });
39320
+ if (contextDb) {
39321
+ sessionDb = new Database(openCodeDbResolution.path, {
39322
+ readonly: true,
39323
+ fileMustExist: true
39324
+ });
39325
+ const dangling = listDanglingCompartmentBoundaries(contextDb, sessionDb);
39326
+ if (dangling.length === 0) {
39327
+ pass("Compartment boundary ids resolve in the OpenCode session store");
39328
+ } else {
39329
+ warn(`${dangling.length} compartment(s) have dangling OpenCode boundary ids`);
39330
+ for (const boundary of dangling) {
39331
+ log2.warn(` ${formatDanglingCompartmentBoundary(boundary)}`);
39332
+ }
39333
+ }
39334
+ } else {
39335
+ log2.info("Compartment boundary check: no context database found");
39336
+ }
39337
+ } catch (error) {
39338
+ warn(`Compartment boundary check unavailable: ${error instanceof Error ? error.message : String(error)}`);
39339
+ } finally {
39340
+ sessionDb?.close();
39341
+ contextDb?.close();
39342
+ }
39343
+ }
38943
39344
  const selfVersion = getSelfVersion2();
38944
39345
  const [npmLatest, pluginNpmLatest] = await Promise.all([
38945
39346
  fetchNpmLatest(CLI_PACKAGE_NAME),
@@ -38958,7 +39359,8 @@ async function runDoctor2(options = {}) {
38958
39359
  } else {
38959
39360
  pass(`OpenCode config: ${paths.opencodeConfig}`);
38960
39361
  }
38961
- if (existsSync34(paths.magicContextConfig)) {
39362
+ let autoUpdateEnabled = true;
39363
+ if (existsSync35(paths.magicContextConfig)) {
38962
39364
  pass(`Magic Context config: ${paths.magicContextConfig}`);
38963
39365
  try {
38964
39366
  const raw = loadRawConfigFile({ configPath: paths.magicContextConfig, tier: "user" });
@@ -38979,6 +39381,7 @@ async function runDoctor2(options = {}) {
38979
39381
  }
38980
39382
  try {
38981
39383
  const result = loadPluginConfig(process.cwd());
39384
+ autoUpdateEnabled = result.auto_update !== false;
38982
39385
  const warnings = result.configWarnings ?? [];
38983
39386
  if (warnings.length > 0) {
38984
39387
  warn(`Magic Context config has ${warnings.length} warning(s) — see 'magic-context doctor --issue' for details`);
@@ -38992,7 +39395,7 @@ async function runDoctor2(options = {}) {
38992
39395
  warn(`No magic-context.jsonc found — using defaults`);
38993
39396
  log2.info(" Run 'setup' to create one with model recommendations");
38994
39397
  }
38995
- if (existsSync34(paths.magicContextConfig)) {
39398
+ if (existsSync35(paths.magicContextConfig)) {
38996
39399
  try {
38997
39400
  const raw = loadRawConfigFile({ configPath: paths.magicContextConfig, tier: "user" });
38998
39401
  if (!raw)
@@ -39112,9 +39515,17 @@ async function runDoctor2(options = {}) {
39112
39515
  log2.warn("Could not migrate deprecated config keys in magic-context.jsonc");
39113
39516
  }
39114
39517
  }
39518
+ const reportedAutoUpdateStalls = new Set;
39519
+ const reportAutoUpdateStall = (specifier) => {
39520
+ const message = describeAutoUpdateStall(specifier, autoUpdateEnabled);
39521
+ if (!message || reportedAutoUpdateStalls.has(message))
39522
+ return;
39523
+ reportedAutoUpdateStalls.add(message);
39524
+ warn(message);
39525
+ };
39115
39526
  if (paths.opencodeConfigFormat !== "none") {
39116
39527
  try {
39117
- const raw = readFileSync23(paths.opencodeConfig, "utf-8");
39528
+ const raw = readFileSync24(paths.opencodeConfig, "utf-8");
39118
39529
  const config = import_comment_json11.parse(raw);
39119
39530
  const rawPlugins = Array.isArray(config?.plugin) ? config.plugin : [];
39120
39531
  const existingIdx = rawPlugins.findIndex((entry) => matchesPluginEntry(entry, OPENCODE_PLUGIN_NAME) || isDevPathPluginEntry(entry));
@@ -39139,6 +39550,7 @@ async function runDoctor2(options = {}) {
39139
39550
  } else {
39140
39551
  const isPinned = isPinnedOpenCodePluginSpecifier(oldEntryStr);
39141
39552
  if (isPinned && !options.force) {
39553
+ reportAutoUpdateStall(oldEntryStr);
39142
39554
  warn(`Plugin pinned to ${oldEntryStr} in ${configName} — use 'doctor --force' to upgrade`);
39143
39555
  } else {
39144
39556
  if (Array.isArray(oldEntry) && oldEntry.length >= 1) {
@@ -39199,9 +39611,9 @@ async function runDoctor2(options = {}) {
39199
39611
  pass("Added TUI sidebar plugin to tui.json");
39200
39612
  warn("Restart OpenCode to see the sidebar");
39201
39613
  fixed++;
39202
- } else if (existsSync34(paths.tuiConfig)) {
39614
+ } else if (existsSync35(paths.tuiConfig)) {
39203
39615
  try {
39204
- const tuiRaw = readFileSync23(paths.tuiConfig, "utf-8");
39616
+ const tuiRaw = readFileSync24(paths.tuiConfig, "utf-8");
39205
39617
  const tuiConfig = import_comment_json11.parse(tuiRaw);
39206
39618
  const tuiRawPlugins = Array.isArray(tuiConfig?.plugin) ? tuiConfig.plugin : [];
39207
39619
  const tuiIdx = tuiRawPlugins.findIndex((entry) => matchesPluginEntry(entry, OPENCODE_PLUGIN_NAME) || isDevPathPluginEntry(entry));
@@ -39223,6 +39635,7 @@ async function runDoctor2(options = {}) {
39223
39635
  } else {
39224
39636
  const tuiPinned = isPinnedOpenCodePluginSpecifier(tuiEntryStr);
39225
39637
  if (tuiPinned && !options.force) {
39638
+ reportAutoUpdateStall(tuiEntryStr);
39226
39639
  warn(`TUI plugin pinned to ${tuiEntryStr} — use 'doctor --force' to upgrade`);
39227
39640
  } else if (tuiPinned && options.force) {
39228
39641
  if (Array.isArray(tuiEntry) && tuiEntry.length >= 1) {
@@ -39250,7 +39663,7 @@ async function runDoctor2(options = {}) {
39250
39663
  } else {
39251
39664
  fail("Could not create or verify the TUI sidebar config");
39252
39665
  }
39253
- if (existsSync34(paths.magicContextConfig)) {
39666
+ if (existsSync35(paths.magicContextConfig)) {
39254
39667
  try {
39255
39668
  const raw = loadRawConfigFile({ configPath: paths.magicContextConfig, tier: "user" });
39256
39669
  if (!raw)
@@ -39274,7 +39687,7 @@ async function runDoctor2(options = {}) {
39274
39687
  const storage = getMagicContextStorageResolution();
39275
39688
  const dbPath = join31(storage.path, "context.db");
39276
39689
  log2.info(`Shared storage: ${storage.path} (source: ${storage.source})`);
39277
- if (!existsSync34(dbPath)) {
39690
+ if (!existsSync35(dbPath)) {
39278
39691
  log2.info(`Shared context DB not yet created at ${dbPath} (will be created on first run)`);
39279
39692
  } else {
39280
39693
  log2.info(`Shared context DB exists at ${dbPath}`);
@@ -39454,6 +39867,7 @@ var init_doctor_opencode = __esm(async () => {
39454
39867
  init_removed_agent_config();
39455
39868
  init_variable();
39456
39869
  init_embedding_synapse();
39870
+ init_auto_update_provenance();
39457
39871
  init_conflict_detector();
39458
39872
  init_conflict_fixer();
39459
39873
  init_data_path();
@@ -39476,9 +39890,11 @@ var init_doctor_opencode = __esm(async () => {
39476
39890
  init_paths();
39477
39891
  init_prompts();
39478
39892
  init_redaction2();
39893
+ init_doctor_compartment_boundaries();
39479
39894
  init_doctor_opencode_cache();
39480
39895
  await __promiseAll([
39481
39896
  init_storage_db(),
39897
+ init_sqlite(),
39482
39898
  init_database_access(),
39483
39899
  init_storage_versions(),
39484
39900
  init_v22_backfill_commands(),
@@ -39488,7 +39904,7 @@ var init_doctor_opencode = __esm(async () => {
39488
39904
  });
39489
39905
 
39490
39906
  // src/lib/diagnostics-pi.ts
39491
- import { existsSync as existsSync35, readdirSync as readdirSync6, readFileSync as readFileSync24, statSync as statSync16 } from "node:fs";
39907
+ import { existsSync as existsSync36, readdirSync as readdirSync6, readFileSync as readFileSync25, statSync as statSync16 } from "node:fs";
39492
39908
  import { createRequire as createRequire7 } from "node:module";
39493
39909
  import { join as join32 } from "node:path";
39494
39910
  function getSelfVersion3() {
@@ -39505,7 +39921,7 @@ function getSelfVersion3() {
39505
39921
  }
39506
39922
  function fileSize2(path) {
39507
39923
  try {
39508
- return existsSync35(path) ? statSync16(path).size : 0;
39924
+ return existsSync36(path) ? statSync16(path).size : 0;
39509
39925
  } catch {
39510
39926
  return 0;
39511
39927
  }
@@ -39517,11 +39933,11 @@ function sanitizeValue2(value) {
39517
39933
  return sanitizeConfigValue(value);
39518
39934
  }
39519
39935
  function readJsonc(path) {
39520
- if (!existsSync35(path))
39936
+ if (!existsSync36(path))
39521
39937
  return { value: {} };
39522
39938
  try {
39523
39939
  return {
39524
- value: import_comment_json12.parse(readFileSync24(path, "utf-8"))
39940
+ value: import_comment_json12.parse(readFileSync25(path, "utf-8"))
39525
39941
  };
39526
39942
  } catch (error) {
39527
39943
  return {
@@ -39537,7 +39953,7 @@ function readConfigDiagnostic(path) {
39537
39953
  const parsed = readJsonc(path);
39538
39954
  return {
39539
39955
  path,
39540
- exists: existsSync35(path),
39956
+ exists: existsSync36(path),
39541
39957
  ...parsed.parseError ? { parseError: parsed.parseError } : {},
39542
39958
  flags: sanitizeValue2(parsed.value)
39543
39959
  };
@@ -39555,7 +39971,7 @@ function reverseSlugToDirectory(slug) {
39555
39971
  }
39556
39972
  function collectPiRecentSessions() {
39557
39973
  const sessionsRoot = getPiSessionsRoot();
39558
- if (!existsSync35(sessionsRoot))
39974
+ if (!existsSync36(sessionsRoot))
39559
39975
  return [];
39560
39976
  try {
39561
39977
  const slugs = readdirSync6(sessionsRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
@@ -39591,7 +40007,7 @@ function collectPiRecentSessions() {
39591
40007
  }
39592
40008
  function parseHistorianDumpMeta2(path) {
39593
40009
  try {
39594
- const xml = readFileSync24(path, "utf-8");
40010
+ const xml = readFileSync25(path, "utf-8");
39595
40011
  const parsed = parseCompartmentOutput(xml);
39596
40012
  const factCountByCategory = {};
39597
40013
  for (const fact of parsed.facts) {
@@ -39624,7 +40040,7 @@ function parseHistorianDumpMeta2(path) {
39624
40040
  }
39625
40041
  }
39626
40042
  function listDumpsInDir2(dir, limit) {
39627
- if (!existsSync35(dir))
40043
+ if (!existsSync36(dir))
39628
40044
  return { count: 0, recent: [] };
39629
40045
  try {
39630
40046
  const entries = readdirSync6(dir).filter((name) => name.endsWith(".xml")).map((name) => {
@@ -39718,7 +40134,7 @@ async function collectDiagnostics2(cwd = process.cwd()) {
39718
40134
  piVersion: pi ? getPiVersion(pi.path) : null,
39719
40135
  settings: {
39720
40136
  path: settingsPath,
39721
- exists: existsSync35(settingsPath),
40137
+ exists: existsSync36(settingsPath),
39722
40138
  ...settingsParsed.parseError ? { parseError: settingsParsed.parseError } : {},
39723
40139
  hasMagicContextPackage: hasPiMagicContextPackage(packages),
39724
40140
  packages: sanitizeValue2(packages)
@@ -39735,7 +40151,7 @@ async function collectDiagnostics2(cwd = process.cwd()) {
39735
40151
  storageDir: {
39736
40152
  path: storageDirPath,
39737
40153
  source: storageResolution.source,
39738
- exists: existsSync35(storageDirPath),
40154
+ exists: existsSync36(storageDirPath),
39739
40155
  contextDbSizeBytes: fileSize2(dbPath)
39740
40156
  },
39741
40157
  conflicts: {
@@ -39929,7 +40345,7 @@ var init_logs_pi = __esm(() => {
39929
40345
 
39930
40346
  // src/commands/doctor-pi.ts
39931
40347
  import { execFileSync as execFileSync6, spawnSync as spawnSync8 } from "node:child_process";
39932
- import { existsSync as existsSync36, mkdirSync as mkdirSync11, readdirSync as readdirSync7, readFileSync as readFileSync25, rmSync as rmSync4, statSync as statSync17 } from "node:fs";
40348
+ import { existsSync as existsSync37, mkdirSync as mkdirSync11, readdirSync as readdirSync7, readFileSync as readFileSync26, rmSync as rmSync4, statSync as statSync17 } from "node:fs";
39933
40349
  import { createRequire as createRequire8 } from "node:module";
39934
40350
  import { homedir as homedir17 } from "node:os";
39935
40351
  import { dirname as dirname19, isAbsolute as isAbsolute8, join as join34 } from "node:path";
@@ -40023,7 +40439,7 @@ function summarize(results) {
40023
40439
  function readJsonc2(path) {
40024
40440
  try {
40025
40441
  return {
40026
- value: import_comment_json13.parse(readFileSync25(path, "utf-8"))
40442
+ value: import_comment_json13.parse(readFileSync26(path, "utf-8"))
40027
40443
  };
40028
40444
  } catch (error) {
40029
40445
  return {
@@ -40075,13 +40491,13 @@ function piPluginDirCandidates(packages, cwd) {
40075
40491
  }
40076
40492
  dirs.push(join34(agentDir, "npm", "node_modules", PACKAGE_NAME2));
40077
40493
  dirs.push(join34(cwd, ".pi", "npm", "node_modules", PACKAGE_NAME2));
40078
- return dirs.filter((dir) => existsSync36(join34(dir, "package.json")));
40494
+ return dirs.filter((dir) => existsSync37(join34(dir, "package.json")));
40079
40495
  }
40080
40496
  function projectConfigPath(cwd) {
40081
40497
  return resolveCortexKitProjectConfigPath(cwd);
40082
40498
  }
40083
40499
  function readConfigForEmbedding(path, isProjectConfig) {
40084
- if (!existsSync36(path))
40500
+ if (!existsSync37(path))
40085
40501
  return null;
40086
40502
  try {
40087
40503
  const raw = loadRawConfigFile({
@@ -40182,7 +40598,7 @@ function cacheRoots(cwd) {
40182
40598
  function findPiMagicContextCacheDirs(cwd, expectedVersion, force = false) {
40183
40599
  const found = new Map;
40184
40600
  const visit = (path, depth) => {
40185
- if (depth < 0 || !existsSync36(path))
40601
+ if (depth < 0 || !existsSync37(path))
40186
40602
  return;
40187
40603
  let stat;
40188
40604
  try {
@@ -40193,9 +40609,9 @@ function findPiMagicContextCacheDirs(cwd, expectedVersion, force = false) {
40193
40609
  if (!stat.isDirectory())
40194
40610
  return;
40195
40611
  const packageJson = join34(path, "package.json");
40196
- if (existsSync36(packageJson)) {
40612
+ if (existsSync37(packageJson)) {
40197
40613
  try {
40198
- const pkg = JSON.parse(readFileSync25(packageJson, "utf-8"));
40614
+ const pkg = JSON.parse(readFileSync26(packageJson, "utf-8"));
40199
40615
  const name = typeof pkg.name === "string" ? pkg.name : "";
40200
40616
  const version = typeof pkg.version === "string" ? pkg.version : undefined;
40201
40617
  if (name === PACKAGE_NAME2) {
@@ -40260,7 +40676,7 @@ async function runHealthChecks2(options) {
40260
40676
  }
40261
40677
  const settingsPath = getPiUserExtensionsPath();
40262
40678
  let packages = [];
40263
- if (!existsSync36(settingsPath)) {
40679
+ if (!existsSync37(settingsPath)) {
40264
40680
  add2(results, "fail", `Pi settings not found at ${settingsPath}`);
40265
40681
  repairPlan.addPackageEntry = true;
40266
40682
  } else {
@@ -40284,7 +40700,7 @@ async function runHealthChecks2(options) {
40284
40700
  ["user", userConfigPath, true],
40285
40701
  ["project", projectPath, false]
40286
40702
  ]) {
40287
- if (!existsSync36(path)) {
40703
+ if (!existsSync37(path)) {
40288
40704
  if (required) {
40289
40705
  add2(results, "warn", `No ${label} magic-context.jsonc found at ${path}`);
40290
40706
  if (userConfigMigrationRefused) {
@@ -40326,7 +40742,7 @@ async function runHealthChecks2(options) {
40326
40742
  const storageDir = storage.path;
40327
40743
  const dbPath = join34(storageDir, "context.db");
40328
40744
  add2(results, "info", `Shared storage: ${storageDir} (source: ${storage.source})`);
40329
- const existedBeforeOpen = existsSync36(dbPath);
40745
+ const existedBeforeOpen = existsSync37(dbPath);
40330
40746
  if (existedBeforeOpen)
40331
40747
  add2(results, "pass", `Shared context DB exists at ${dbPath}`);
40332
40748
  else
@@ -40561,7 +40977,7 @@ function repair2(plan, prompts) {
40561
40977
  }
40562
40978
  if (plan.writeUserConfig) {
40563
40979
  const configPath = getPiUserConfigPath();
40564
- if (!existsSync36(configPath)) {
40980
+ if (!existsSync37(configPath)) {
40565
40981
  try {
40566
40982
  writeDefaultMagicContextConfig(configPath);
40567
40983
  prompts.log.success(`Wrote default Magic Context config to ${configPath}`);
@@ -40812,7 +41228,7 @@ var init_doctor_pi = __esm(async () => {
40812
41228
  });
40813
41229
 
40814
41230
  // src/commands/doctor.ts
40815
- import { existsSync as existsSync37, rmSync as rmSync5 } from "node:fs";
41231
+ import { existsSync as existsSync38, rmSync as rmSync5 } from "node:fs";
40816
41232
  import { join as join35 } from "node:path";
40817
41233
  async function runDoctor4(options) {
40818
41234
  if (options.clear)
@@ -40943,7 +41359,7 @@ async function runClear() {
40943
41359
  const s = spinner2();
40944
41360
  s.start(`Clearing ${item.path}`);
40945
41361
  try {
40946
- if (existsSync37(item.path)) {
41362
+ if (existsSync38(item.path)) {
40947
41363
  rmSync5(item.path, { recursive: true, force: true });
40948
41364
  }
40949
41365
  s.stop(`Cleared ${item.path}`);
@@ -41049,6 +41465,7 @@ function printUsage() {
41049
41465
  console.log(" doctor migrate-session Re-home an OpenCode session to another directory");
41050
41466
  console.log(" doctor merge-identity Merge project rows (--from ID --to ID [--dry-run] [--yes])");
41051
41467
  console.log(" doctor repair-db Back up and salvage a corrupted shared database");
41468
+ console.log(" doctor list-hidden-sessions List Magic Context OpenCode 2 roots");
41052
41469
  console.log("");
41053
41470
  console.log(" Harness selection:");
41054
41471
  console.log(" --harness opencode Target OpenCode only");
@@ -41105,6 +41522,10 @@ async function main(argv = process.argv.slice(2)) {
41105
41522
  await init_doctor_repair_db();
41106
41523
  return runRepairDbCli(rest.slice(1));
41107
41524
  }
41525
+ if (rest[0] === "list-hidden-sessions") {
41526
+ await init_doctor_hidden_sessions();
41527
+ return runListHiddenSessions();
41528
+ }
41108
41529
  if (rest[0] === "migrate") {
41109
41530
  await init_migrate();
41110
41531
  return runMigrateCli(rest.slice(1));