@cortexkit/magic-context 0.40.1 → 0.41.1

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 +783 -421
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2253,6 +2253,7 @@ __export(exports_data_path, {
2253
2253
  getMagicContextHistorianDir: () => getMagicContextHistorianDir,
2254
2254
  getMagicContextLogPath: () => getMagicContextLogPath,
2255
2255
  getMagicContextStorageDir: () => getMagicContextStorageDir,
2256
+ getMagicContextStorageResolution: () => getMagicContextStorageResolution,
2256
2257
  getMagicContextTempDir: () => getMagicContextTempDir,
2257
2258
  getOpenCodeCacheDir: () => getOpenCodeCacheDir,
2258
2259
  getOpenCodeStorageDir: () => getOpenCodeStorageDir,
@@ -2308,15 +2309,43 @@ function getProjectMagicContextHistorianDir(directory) {
2308
2309
  function getOpenCodeStorageDir() {
2309
2310
  return path.join(getDataDir(), "opencode", "storage");
2310
2311
  }
2311
- function getMagicContextStorageDir() {
2312
- if (!process.env.XDG_DATA_HOME) {
2313
- const testDataDir = process.env.MAGIC_CONTEXT_TEST_DATA_DIR;
2314
- if (testDataDir) {
2315
- return path.join(testDataDir, "cortexkit", "magic-context");
2312
+ function getMagicContextStorageResolution() {
2313
+ const testDataDir = process.env.MAGIC_CONTEXT_TEST_DATA_DIR?.trim();
2314
+ if (testDataDir) {
2315
+ const perTestDataHome = process.env.XDG_DATA_HOME?.trim();
2316
+ if (perTestDataHome && path.resolve(perTestDataHome) !== path.resolve(testDataDir)) {
2317
+ return {
2318
+ path: path.join(perTestDataHome, "cortexkit", "magic-context"),
2319
+ source: "test isolation"
2320
+ };
2316
2321
  }
2317
- if (false) {}
2322
+ return {
2323
+ path: path.join(testDataDir, "cortexkit", "magic-context"),
2324
+ source: "test isolation"
2325
+ };
2318
2326
  }
2319
- return path.join(getDataDir(), "cortexkit", "magic-context");
2327
+ if (false) {}
2328
+ const explicitStorageDir = process.env.MAGIC_CONTEXT_STORAGE_DIR?.trim();
2329
+ if (explicitStorageDir) {
2330
+ if (!path.isAbsolute(explicitStorageDir)) {
2331
+ throw new Error("MAGIC_CONTEXT_STORAGE_DIR must be an absolute path");
2332
+ }
2333
+ return { path: explicitStorageDir, source: "environment override" };
2334
+ }
2335
+ const xdgDataHome = process.env.XDG_DATA_HOME?.trim();
2336
+ if (xdgDataHome) {
2337
+ return {
2338
+ path: path.join(xdgDataHome, "cortexkit", "magic-context"),
2339
+ source: "XDG_DATA_HOME"
2340
+ };
2341
+ }
2342
+ return {
2343
+ path: path.join(os.homedir(), ".local", "share", "cortexkit", "magic-context"),
2344
+ source: "platform default"
2345
+ };
2346
+ }
2347
+ function getMagicContextStorageDir() {
2348
+ return getMagicContextStorageResolution().path;
2320
2349
  }
2321
2350
  function getLegacyOpenCodeMagicContextStorageDir() {
2322
2351
  return path.join(getOpenCodeStorageDir(), "plugin", "magic-context");
@@ -2333,7 +2362,7 @@ var init_data_path = () => {};
2333
2362
  // src/lib/paths.ts
2334
2363
  import { existsSync as existsSync4, readdirSync, statSync as statSync3 } from "node:fs";
2335
2364
  import { homedir as homedir3 } from "node:os";
2336
- import { delimiter as delimiter2, dirname as dirname2, join as join4, resolve } from "node:path";
2365
+ import { delimiter as delimiter2, dirname as dirname2, join as join4, resolve as resolve2 } from "node:path";
2337
2366
  function getOpenCodeConfigDir() {
2338
2367
  const envDir = process.env.OPENCODE_CONFIG_DIR?.trim();
2339
2368
  if (envDir)
@@ -2431,7 +2460,7 @@ function resolveOmpPaths() {
2431
2460
  const configRoot = profile ? join4(baseConfigRoot, "profiles", profile) : baseConfigRoot;
2432
2461
  const defaultAgentDir = join4(configRoot, "agent");
2433
2462
  const override = profile ? undefined : process.env.PI_CODING_AGENT_DIR?.trim();
2434
- const agentDir = override ? resolve(override) : defaultAgentDir;
2463
+ const agentDir = override ? resolve2(override) : defaultAgentDir;
2435
2464
  const canUseXdg = (process.platform === "linux" || process.platform === "darwin") && agentDir === defaultAgentDir;
2436
2465
  let dataRoot = configRoot;
2437
2466
  if (canUseXdg) {
@@ -2469,18 +2498,18 @@ function getOmpPackageDir() {
2469
2498
  if (value === "~")
2470
2499
  return envFirstHomeDir();
2471
2500
  if (value.startsWith("~/") || value.startsWith("~\\")) {
2472
- return resolve(envFirstHomeDir(), value.slice(2));
2501
+ return resolve2(envFirstHomeDir(), value.slice(2));
2473
2502
  }
2474
- return resolve(value);
2503
+ return resolve2(value);
2475
2504
  }
2476
2505
  function getOmpNonGlobalConfigSources(cwd = process.cwd()) {
2477
2506
  const sources = process.env.PI_CONFIG_FILES?.split(delimiter2).map((entry) => entry.trim()).filter(Boolean).map((entry) => {
2478
2507
  if (entry === "~")
2479
2508
  return envFirstHomeDir();
2480
2509
  const expanded = entry.startsWith("~/") || entry.startsWith("~\\") ? join4(envFirstHomeDir(), entry.slice(2)) : entry;
2481
- return resolve(cwd, expanded);
2510
+ return resolve2(cwd, expanded);
2482
2511
  }) ?? [];
2483
- const projectConfig = resolve(cwd, ".omp", "config.yml");
2512
+ const projectConfig = resolve2(cwd, ".omp", "config.yml");
2484
2513
  if (existsSync4(projectConfig))
2485
2514
  sources.push(projectConfig);
2486
2515
  return [...new Set(sources)];
@@ -10959,7 +10988,7 @@ var init_opencode_plugin_cache = __esm(() => {
10959
10988
 
10960
10989
  // src/adapters/opencode.ts
10961
10990
  import { existsSync as existsSync8, readFileSync as readFileSync5, statSync as statSync5 } from "node:fs";
10962
- import { dirname as dirname4, isAbsolute as isAbsolute2, parse as parsePath, resolve as resolve2 } from "node:path";
10991
+ import { dirname as dirname4, isAbsolute as isAbsolute3, parse as parsePath, resolve as resolve3 } from "node:path";
10963
10992
  import { fileURLToPath } from "node:url";
10964
10993
 
10965
10994
  class OpenCodeAdapter {
@@ -11157,7 +11186,7 @@ function isLocalPathPluginEntry(entry) {
11157
11186
  const candidate = typeof entry === "string" ? entry : Array.isArray(entry) && typeof entry[0] === "string" ? entry[0] : null;
11158
11187
  if (!candidate)
11159
11188
  return false;
11160
- return candidate.startsWith("file://") || isAbsolute2(candidate) || candidate.startsWith("./") || candidate.startsWith("../");
11189
+ return candidate.startsWith("file://") || isAbsolute3(candidate) || candidate.startsWith("./") || candidate.startsWith("../");
11161
11190
  }
11162
11191
  function isDevPathPluginEntry(entry) {
11163
11192
  const candidate = typeof entry === "string" ? entry : Array.isArray(entry) && typeof entry[0] === "string" ? entry[0] : null;
@@ -11168,13 +11197,13 @@ function isDevPathPluginEntry(entry) {
11168
11197
  if (candidate.startsWith("file://")) {
11169
11198
  localPath = fileURLToPath(candidate);
11170
11199
  } else {
11171
- localPath = resolve2(candidate);
11200
+ localPath = resolve3(candidate);
11172
11201
  }
11173
11202
  if (statSync5(localPath).isFile())
11174
11203
  localPath = dirname4(localPath);
11175
11204
  const root = parsePath(localPath).root;
11176
11205
  while (localPath !== root) {
11177
- const packagePath = resolve2(localPath, "package.json");
11206
+ const packagePath = resolve3(localPath, "package.json");
11178
11207
  if (existsSync8(packagePath)) {
11179
11208
  const pkg = JSON.parse(readFileSync5(packagePath, "utf8"));
11180
11209
  return pkg.name === OPENCODE_PLUGIN_NAME;
@@ -14480,19 +14509,272 @@ var init_setup_omp = __esm(() => {
14480
14509
  OMP_HOST = createOmpHost(DEFAULT_DEPS2);
14481
14510
  });
14482
14511
 
14512
+ // ../plugin/src/shared/redaction.ts
14513
+ import { homedir as homedir7, userInfo } from "node:os";
14514
+ function escapeRegex(value) {
14515
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
14516
+ }
14517
+ function redactionTypeForKey(key) {
14518
+ const normalized = key.trim().toLowerCase().replace(/[^a-z0-9_.-]+/g, "_");
14519
+ const suffix = normalized.split(".").filter(Boolean).at(-1) ?? normalized;
14520
+ return suffix || "secret";
14521
+ }
14522
+ function isNonSecretScalarValue(value) {
14523
+ const v = value.trim();
14524
+ if (v === "true" || v === "false" || v === "null" || v === "undefined")
14525
+ return true;
14526
+ return /^[+-]?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?$/.test(v);
14527
+ }
14528
+ function isSecretKey(key) {
14529
+ const segments = key.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase().split(/[._-]+/).filter(Boolean);
14530
+ if (segments.length === 0)
14531
+ return false;
14532
+ if (segments.length === 1) {
14533
+ const first = segments[0];
14534
+ return Boolean(first && SECRET_SEGMENT_PATTERN.test(first));
14535
+ }
14536
+ for (let i2 = 0;i2 < segments.length; i2++) {
14537
+ const seg = segments[i2];
14538
+ if (!seg || !SECRET_SEGMENT_PATTERN.test(seg))
14539
+ continue;
14540
+ let trailingOk = true;
14541
+ for (let j = i2 + 1;j < segments.length; j++) {
14542
+ const tail = segments[j];
14543
+ if (!tail)
14544
+ continue;
14545
+ if (TRAILING_DESCRIPTORS.has(tail))
14546
+ continue;
14547
+ if (SECRET_SEGMENT_PATTERN.test(tail))
14548
+ continue;
14549
+ trailingOk = false;
14550
+ break;
14551
+ }
14552
+ if (!trailingOk)
14553
+ continue;
14554
+ for (let k = i2 - 1;k >= 0; k--) {
14555
+ const lead = segments[k];
14556
+ if (lead && SECRET_QUALIFIERS.has(lead))
14557
+ return true;
14558
+ }
14559
+ }
14560
+ return false;
14561
+ }
14562
+ function sanitizePathString(value) {
14563
+ const home = process.env.HOME || process.env.USERPROFILE || homedir7();
14564
+ const username = userInfo().username;
14565
+ let sanitized = value;
14566
+ if (home) {
14567
+ sanitized = sanitized.replace(new RegExp(escapeRegex(home), "g"), "~");
14568
+ }
14569
+ sanitized = sanitized.replace(/\/Users\/[^/]+\//g, "/Users/<USER>/");
14570
+ sanitized = sanitized.replace(/\/home\/[^/]+\//g, "/home/<USER>/");
14571
+ sanitized = sanitized.replace(/C:\\Users\\[^\\]+\\/g, "C:\\Users\\<USER>\\");
14572
+ if (username) {
14573
+ sanitized = sanitized.replace(new RegExp(escapeRegex(username), "g"), "<USER>");
14574
+ }
14575
+ return sanitized;
14576
+ }
14577
+ function redactSecretText(value) {
14578
+ let redacted = value;
14579
+ for (const { pattern, replacement } of SECRET_TEXT_PATTERNS) {
14580
+ if (typeof replacement === "string") {
14581
+ redacted = redacted.replace(pattern, replacement);
14582
+ } else {
14583
+ redacted = redacted.replace(pattern, replacement);
14584
+ }
14585
+ }
14586
+ return redacted;
14587
+ }
14588
+ function sanitizeDiagnosticText(value) {
14589
+ return redactSecretText(sanitizePathString(value));
14590
+ }
14591
+ function sanitizeConfigValue(value, keyPath = []) {
14592
+ if (value === null || typeof value === "number" || typeof value === "boolean")
14593
+ return value;
14594
+ const key = keyPath.at(-1) ?? "";
14595
+ if (key && isSecretKey(key)) {
14596
+ return `<REDACTED:${redactionTypeForKey(key)}>`;
14597
+ }
14598
+ if (typeof value === "string")
14599
+ return sanitizeDiagnosticText(value);
14600
+ if (Array.isArray(value)) {
14601
+ return value.map((entry, index) => sanitizeConfigValue(entry, [...keyPath, String(index)]));
14602
+ }
14603
+ if (value && typeof value === "object") {
14604
+ return Object.fromEntries(Object.entries(value).map(([entryKey, entry]) => [
14605
+ entryKey,
14606
+ sanitizeConfigValue(entry, [...keyPath, entryKey])
14607
+ ]));
14608
+ }
14609
+ return value;
14610
+ }
14611
+ var SECRET_WORDS, SECRET_SEGMENT_PATTERN, TRAILING_DESCRIPTORS, SECRET_QUALIFIERS, SECRET_TEXT_PATTERNS;
14612
+ var init_redaction = __esm(() => {
14613
+ SECRET_WORDS = [
14614
+ "key",
14615
+ "token",
14616
+ "secret",
14617
+ "password",
14618
+ "auth",
14619
+ "authorization",
14620
+ "bearer",
14621
+ "credential"
14622
+ ];
14623
+ SECRET_SEGMENT_PATTERN = new RegExp(`^(?:${SECRET_WORDS.map((w) => `${w}s?`).join("|")})$`, "i");
14624
+ TRAILING_DESCRIPTORS = new Set(["id", "ids", "value", "values", "header", "headers"]);
14625
+ SECRET_QUALIFIERS = new Set([
14626
+ "api",
14627
+ "access",
14628
+ "private",
14629
+ "client",
14630
+ "auth",
14631
+ "authorization",
14632
+ "secret",
14633
+ "bearer",
14634
+ "session",
14635
+ "refresh",
14636
+ "service",
14637
+ "x",
14638
+ "openai",
14639
+ "anthropic",
14640
+ "google",
14641
+ "github",
14642
+ "huggingface",
14643
+ "aws",
14644
+ "azure"
14645
+ ]);
14646
+ SECRET_TEXT_PATTERNS = [
14647
+ {
14648
+ pattern: /\bsk-ant-(?:api03-)?[A-Za-z0-9_-]{32,}/g,
14649
+ replacement: "<ANTHROPIC_API_KEY_REDACTED>"
14650
+ },
14651
+ {
14652
+ pattern: /\bsk-(?:proj-)?[A-Za-z0-9_-]{12,}/g,
14653
+ replacement: "<OPENAI_API_KEY_REDACTED>"
14654
+ },
14655
+ {
14656
+ pattern: /\bgithub_pat_[A-Za-z0-9_]{20,}/g,
14657
+ replacement: "<GITHUB_PAT_REDACTED>"
14658
+ },
14659
+ {
14660
+ pattern: /\b(?:gh[opsu]|ghr)_[A-Za-z0-9]{30,}/g,
14661
+ replacement: "<GITHUB_TOKEN_REDACTED>"
14662
+ },
14663
+ {
14664
+ pattern: /\bhf_[A-Za-z0-9]{30,}/g,
14665
+ replacement: "<HUGGINGFACE_TOKEN_REDACTED>"
14666
+ },
14667
+ {
14668
+ pattern: /\b(?:AKIA|ASIA)[0-9A-Z]{16}\b/g,
14669
+ replacement: "<AWS_ACCESS_KEY_ID_REDACTED>"
14670
+ },
14671
+ {
14672
+ pattern: /\bxox[abprsuvc]-[A-Za-z0-9-]{10,}/g,
14673
+ replacement: "<SLACK_TOKEN_REDACTED>"
14674
+ },
14675
+ {
14676
+ pattern: /\bAIza[A-Za-z0-9_-]{35}\b/g,
14677
+ replacement: "<GOOGLE_API_KEY_REDACTED>"
14678
+ },
14679
+ {
14680
+ pattern: /\b(Authorization\s*:\s*Bearer\s+)([A-Za-z0-9._~+/=-]{8,})/gi,
14681
+ replacement: (_full, prefix) => `${prefix}<REDACTED:bearer>`
14682
+ },
14683
+ {
14684
+ pattern: /\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g,
14685
+ replacement: "<JWT_REDACTED>"
14686
+ },
14687
+ {
14688
+ pattern: /(["'])([^"']*(?:key|token|secret|password|auth|bearer|credential)[^"']*)\1(\s*:\s*)(["'])([^"']*)\4/gi,
14689
+ replacement: (full, quote, key, separator, valueQuote, value) => isNonSecretScalarValue(value) ? full : `${quote}${key}${quote}${separator}${valueQuote}<REDACTED:${redactionTypeForKey(key)}>${valueQuote}`
14690
+ },
14691
+ {
14692
+ pattern: /\b([A-Za-z0-9_.-]*(?:key|token|secret|password|auth|bearer|credential)[A-Za-z0-9_.-]*)\s*=\s*([^\s'"`]+)/gi,
14693
+ replacement: (full, key, value) => isNonSecretScalarValue(value) ? full : `${key}=<REDACTED:${redactionTypeForKey(key)}>`
14694
+ }
14695
+ ];
14696
+ });
14697
+
14483
14698
  // ../plugin/src/shared/logger.ts
14484
14699
  import * as fs from "node:fs";
14485
14700
  import * as path2 from "node:path";
14486
14701
  function recordSwallowedWrite(error) {
14487
14702
  try {
14488
14703
  swallowedWriteCount++;
14489
- lastErrorMessage = error instanceof Error ? error.message : String(error);
14704
+ lastErrorMessage = sanitizeDiagnosticText(error instanceof Error ? error.message : String(error));
14490
14705
  lastErrorTime = new Date().toISOString();
14491
14706
  } catch {}
14492
14707
  }
14493
14708
  function ensureDir4(filePath) {
14494
14709
  fs.mkdirSync(path2.dirname(filePath), { recursive: true });
14495
14710
  }
14711
+ function isMissingFile(error) {
14712
+ return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
14713
+ }
14714
+ function getCurrentLogSize(logFile) {
14715
+ if (activeLogFile === logFile && activeLogSize !== null && flushesSinceSizeCheck < SIZE_CHECK_INTERVAL_FLUSHES) {
14716
+ return activeLogSize;
14717
+ }
14718
+ try {
14719
+ const stat = fs.statSync(logFile);
14720
+ if (!stat.isFile()) {
14721
+ throw new Error(`Magic Context log path is not a regular file: ${logFile}`);
14722
+ }
14723
+ fs.chmodSync(logFile, 384);
14724
+ activeLogFile = logFile;
14725
+ activeLogSize = stat.size;
14726
+ flushesSinceSizeCheck = 0;
14727
+ return stat.size;
14728
+ } catch (error) {
14729
+ if (!isMissingFile(error))
14730
+ throw error;
14731
+ activeLogFile = logFile;
14732
+ activeLogSize = 0;
14733
+ flushesSinceSizeCheck = 0;
14734
+ return 0;
14735
+ }
14736
+ }
14737
+ function capLogData(data) {
14738
+ if (Buffer.byteLength(data) <= MAX_LOG_FILE_BYTES)
14739
+ return data;
14740
+ let bounded = Buffer.from(data).subarray(0, MAX_LOG_FILE_BYTES).toString("utf8");
14741
+ while (Buffer.byteLength(bounded) > MAX_LOG_FILE_BYTES) {
14742
+ bounded = bounded.slice(0, -1);
14743
+ }
14744
+ return bounded;
14745
+ }
14746
+ function writeBoundedPredecessor(logFile, predecessorPath, size) {
14747
+ const predecessorFd = fs.openSync(predecessorPath, "w", 384);
14748
+ try {
14749
+ fs.fchmodSync(predecessorFd, 384);
14750
+ const bytesToCopy = Math.min(size, MAX_LOG_FILE_BYTES);
14751
+ const sourceFd = fs.openSync(logFile, "r");
14752
+ try {
14753
+ const chunk = Buffer.allocUnsafe(Math.min(64 * 1024, bytesToCopy));
14754
+ let remaining = bytesToCopy;
14755
+ let position = Math.max(0, size - bytesToCopy);
14756
+ while (remaining > 0) {
14757
+ const bytesRead = fs.readSync(sourceFd, chunk, 0, Math.min(chunk.length, remaining), position);
14758
+ if (bytesRead === 0)
14759
+ break;
14760
+ fs.writeSync(predecessorFd, chunk, 0, bytesRead);
14761
+ remaining -= bytesRead;
14762
+ position += bytesRead;
14763
+ }
14764
+ } finally {
14765
+ fs.closeSync(sourceFd);
14766
+ }
14767
+ } finally {
14768
+ fs.closeSync(predecessorFd);
14769
+ }
14770
+ }
14771
+ function rotateLogFile(logFile, size) {
14772
+ const predecessorPath = `${logFile}.1`;
14773
+ writeBoundedPredecessor(logFile, predecessorPath, size);
14774
+ fs.truncateSync(logFile, 0);
14775
+ activeLogSize = 0;
14776
+ flushesSinceSizeCheck = 0;
14777
+ }
14496
14778
  function flush() {
14497
14779
  if (flushTimer) {
14498
14780
  clearTimeout(flushTimer);
@@ -14500,13 +14782,26 @@ function flush() {
14500
14782
  }
14501
14783
  if (buffer.length === 0)
14502
14784
  return;
14503
- const data = buffer.join("");
14785
+ const bufferedData = buffer.join("");
14504
14786
  buffer = [];
14505
14787
  try {
14788
+ const data = capLogData(bufferedData);
14506
14789
  const logFile = getMagicContextLogPath();
14507
14790
  ensureDir4(logFile);
14508
- fs.appendFileSync(logFile, data);
14791
+ let currentSize = getCurrentLogSize(logFile);
14792
+ const dataSize = Buffer.byteLength(data);
14793
+ if (currentSize > 0 && currentSize + dataSize > MAX_LOG_FILE_BYTES) {
14794
+ rotateLogFile(logFile, currentSize);
14795
+ currentSize = 0;
14796
+ }
14797
+ fs.appendFileSync(logFile, data, { encoding: "utf8", mode: 384 });
14798
+ activeLogFile = logFile;
14799
+ activeLogSize = currentSize + dataSize;
14800
+ flushesSinceSizeCheck++;
14509
14801
  } catch (error) {
14802
+ activeLogFile = null;
14803
+ activeLogSize = null;
14804
+ flushesSinceSizeCheck = 0;
14510
14805
  recordSwallowedWrite(error);
14511
14806
  }
14512
14807
  }
@@ -14523,9 +14818,9 @@ function log3(message, data) {
14523
14818
  return;
14524
14819
  try {
14525
14820
  const timestamp = new Date().toISOString();
14526
- const serialized = data === undefined ? "" : data instanceof Error ? ` ${data.message}${data.stack ? `
14527
- ${data.stack}` : ""}` : ` ${JSON.stringify(data)}`;
14528
- buffer.push(`[${timestamp}] ${message}${serialized}
14821
+ const serialized = data === undefined ? "" : data instanceof Error ? ` ${sanitizeDiagnosticText(`${data.message}${data.stack ? `
14822
+ ${data.stack}` : ""}`)}` : ` ${JSON.stringify(sanitizeConfigValue(data))}`;
14823
+ buffer.push(`[${timestamp}] ${sanitizeDiagnosticText(message)}${serialized}
14529
14824
  `);
14530
14825
  if (buffer.length >= BUFFER_SIZE_LIMIT) {
14531
14826
  flush();
@@ -14534,10 +14829,12 @@ ${data.stack}` : ""}` : ` ${JSON.stringify(data)}`;
14534
14829
  }
14535
14830
  } catch {}
14536
14831
  }
14537
- var isTestEnv = false, buffer, flushTimer = null, FLUSH_INTERVAL_MS = 500, BUFFER_SIZE_LIMIT = 50, swallowedWriteCount = 0, lastErrorMessage = null, lastErrorTime = null;
14832
+ var isTestEnv = false, buffer, flushTimer = null, FLUSH_INTERVAL_MS = 500, BUFFER_SIZE_LIMIT = 50, MAX_LOG_FILE_BYTES, SIZE_CHECK_INTERVAL_FLUSHES = 64, activeLogFile = null, activeLogSize = null, flushesSinceSizeCheck = 0, swallowedWriteCount = 0, lastErrorMessage = null, lastErrorTime = null;
14538
14833
  var init_logger = __esm(() => {
14539
14834
  init_data_path();
14835
+ init_redaction();
14540
14836
  buffer = [];
14837
+ MAX_LOG_FILE_BYTES = 32 * 1024 * 1024;
14541
14838
  if (!isTestEnv) {
14542
14839
  process.on("exit", flush);
14543
14840
  }
@@ -15054,7 +15351,7 @@ __export(exports_util, {
15054
15351
  createTransparentProxy: () => createTransparentProxy,
15055
15352
  defineLazy: () => defineLazy,
15056
15353
  esc: () => esc,
15057
- escapeRegex: () => escapeRegex,
15354
+ escapeRegex: () => escapeRegex2,
15058
15355
  explicitlyAborted: () => explicitlyAborted,
15059
15356
  extend: () => extend,
15060
15357
  finalizeIssue: () => finalizeIssue,
@@ -15261,7 +15558,7 @@ function numKeys(data) {
15261
15558
  }
15262
15559
  return keyCount;
15263
15560
  }
15264
- function escapeRegex(str) {
15561
+ function escapeRegex2(str) {
15265
15562
  return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
15266
15563
  }
15267
15564
  function clone(inst, def, params) {
@@ -16045,7 +16342,7 @@ var cuid, cuid2, ulid, xid, ksuid, nanoid, duration, extendedDuration, guid, uui
16045
16342
  return /^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/;
16046
16343
  return new RegExp(`^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-${version}[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$`);
16047
16344
  }, uuid4, uuid6, uuid7, email, html5Email, rfc5322Email, unicodeEmail, idnEmail, browserEmail, _emoji = `^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$`, ipv4, ipv6, mac = (delimiter3) => {
16048
- const escapedDelim = escapeRegex(delimiter3 ?? ":");
16345
+ const escapedDelim = escapeRegex2(delimiter3 ?? ":");
16049
16346
  return new RegExp(`^(?:[0-9A-F]{2}${escapedDelim}){5}[0-9A-F]{2}$|^(?:[0-9a-f]{2}${escapedDelim}){5}[0-9a-f]{2}$`);
16050
16347
  }, cidrv4, cidrv6, base64, base64url, hostname, domain, httpProtocol, e164, dateSource = `(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))`, date, string = (params) => {
16051
16348
  const regex = params ? `[\\s\\S]{${params?.minimum ?? 0},${params?.maximum ?? ""}}` : `[\\s\\S]*`;
@@ -16553,7 +16850,7 @@ var init_checks = __esm(() => {
16553
16850
  });
16554
16851
  $ZodCheckIncludes = /* @__PURE__ */ $constructor("$ZodCheckIncludes", (inst, def) => {
16555
16852
  $ZodCheck.init(inst, def);
16556
- const escapedRegex = escapeRegex(def.includes);
16853
+ const escapedRegex = escapeRegex2(def.includes);
16557
16854
  const pattern = new RegExp(typeof def.position === "number" ? `^.{${def.position}}${escapedRegex}` : escapedRegex);
16558
16855
  def.pattern = pattern;
16559
16856
  inst._zod.onattach.push((inst2) => {
@@ -16577,7 +16874,7 @@ var init_checks = __esm(() => {
16577
16874
  });
16578
16875
  $ZodCheckStartsWith = /* @__PURE__ */ $constructor("$ZodCheckStartsWith", (inst, def) => {
16579
16876
  $ZodCheck.init(inst, def);
16580
- const pattern = new RegExp(`^${escapeRegex(def.prefix)}.*`);
16877
+ const pattern = new RegExp(`^${escapeRegex2(def.prefix)}.*`);
16581
16878
  def.pattern ?? (def.pattern = pattern);
16582
16879
  inst._zod.onattach.push((inst2) => {
16583
16880
  const bag = inst2._zod.bag;
@@ -16600,7 +16897,7 @@ var init_checks = __esm(() => {
16600
16897
  });
16601
16898
  $ZodCheckEndsWith = /* @__PURE__ */ $constructor("$ZodCheckEndsWith", (inst, def) => {
16602
16899
  $ZodCheck.init(inst, def);
16603
- const pattern = new RegExp(`.*${escapeRegex(def.suffix)}$`);
16900
+ const pattern = new RegExp(`.*${escapeRegex2(def.suffix)}$`);
16604
16901
  def.pattern ?? (def.pattern = pattern);
16605
16902
  inst._zod.onattach.push((inst2) => {
16606
16903
  const bag = inst2._zod.bag;
@@ -18330,7 +18627,7 @@ var init_schemas = __esm(() => {
18330
18627
  const values = getEnumValues(def.entries);
18331
18628
  const valuesSet = new Set(values);
18332
18629
  inst._zod.values = valuesSet;
18333
- inst._zod.pattern = new RegExp(`^(${values.filter((k) => propertyKeyTypes.has(typeof k)).map((o2) => typeof o2 === "string" ? escapeRegex(o2) : o2.toString()).join("|")})$`);
18630
+ inst._zod.pattern = new RegExp(`^(${values.filter((k) => propertyKeyTypes.has(typeof k)).map((o2) => typeof o2 === "string" ? escapeRegex2(o2) : o2.toString()).join("|")})$`);
18334
18631
  inst._zod.parse = (payload, _ctx) => {
18335
18632
  const input = payload.value;
18336
18633
  if (valuesSet.has(input)) {
@@ -18352,7 +18649,7 @@ var init_schemas = __esm(() => {
18352
18649
  }
18353
18650
  const values = new Set(def.values);
18354
18651
  inst._zod.values = values;
18355
- inst._zod.pattern = new RegExp(`^(${def.values.map((o2) => typeof o2 === "string" ? escapeRegex(o2) : o2 ? escapeRegex(o2.toString()) : String(o2)).join("|")})$`);
18652
+ inst._zod.pattern = new RegExp(`^(${def.values.map((o2) => typeof o2 === "string" ? escapeRegex2(o2) : o2 ? escapeRegex2(o2.toString()) : String(o2)).join("|")})$`);
18356
18653
  inst._zod.parse = (payload, _ctx) => {
18357
18654
  const input = payload.value;
18358
18655
  if (values.has(input)) {
@@ -18656,7 +18953,7 @@ var init_schemas = __esm(() => {
18656
18953
  const end = source.endsWith("$") ? source.length - 1 : source.length;
18657
18954
  regexParts.push(source.slice(start, end));
18658
18955
  } else if (part === null || primitiveTypes.has(typeof part)) {
18659
- regexParts.push(escapeRegex(`${part}`));
18956
+ regexParts.push(escapeRegex2(`${part}`));
18660
18957
  } else {
18661
18958
  throw new Error(`Invalid template literal part: ${part}`);
18662
18959
  }
@@ -29663,7 +29960,7 @@ var init_agent_overrides = __esm(() => {
29663
29960
  });
29664
29961
 
29665
29962
  // ../plugin/src/config/schema/magic-context.ts
29666
- import { homedir as homedir7 } from "node:os";
29963
+ import { homedir as homedir8 } from "node:os";
29667
29964
  function defaultTaskConfig(task) {
29668
29965
  const base = { schedule: DEFAULT_TASK_SCHEDULES2[task] };
29669
29966
  if (task === "review-user-memories")
@@ -29675,9 +29972,9 @@ function defaultTaskConfig(task) {
29675
29972
  function expandConfigPath(value) {
29676
29973
  const trimmed = value.trim();
29677
29974
  if (trimmed === "~")
29678
- return homedir7();
29975
+ return homedir8();
29679
29976
  if (trimmed.startsWith("~/"))
29680
- return `${homedir7()}/${trimmed.slice(2)}`;
29977
+ return `${homedir8()}/${trimmed.slice(2)}`;
29681
29978
  return trimmed;
29682
29979
  }
29683
29980
  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, PiConfigSchema, PromptSurfacePresetSchema, PromptSurfaceModelKeySchema, PromptSurfaceToolKeySchema, PromptSurfaceConfigSchema, PER_HARNESS_MIGRATION_INVENTORY, OcEntryObjectSchema, OcEntrySchema, PiEntryObjectSchema, PiEntrySchema, OpenCodeHarnessBlockSchema, PiHarnessBlockSchema, OpenCodeTaskExecutionSchema, PiTaskExecutionSchema, DreamerOpenCodeHarnessBlockSchema, DreamerPiHarnessBlockSchema, ProfileOpenCodeModelBlockSchema, ProfilePiModelBlockSchema, ProfileHistorianSchema, ProfileDreamerSchema, ProfileSidekickSchema, ConfigProfileSchema, ConfigProfilesSchema, CronScheduleSchema, DreamTaskBaseConfigSchema, PromotionThresholdSchema, PrimerPromotionThresholdSchema, DreamTaskConfigSchema, ReviewUserMemoriesTaskConfigSchema, PromotePrimersTaskConfigSchema, DEFAULT_TASK_SCHEDULES2, DreamTasksSchema, AgentMetadataSchema, DreamerConfigSchema, SidekickConfigSchema, HistorianConfigSchema, EmbeddingFallbackProviderSchema, BaseEmbeddingConfigSchema, EmbeddingConfigSchema, MagicContextConfigSchema;
@@ -29916,6 +30213,7 @@ var init_magic_context = __esm(() => {
29916
30213
  query_input_type: exports_external.string().optional().describe("Optional input_type for query (search) embeddings on asymmetric models (e.g. NVIDIA NIM 'query'). When unset, query embeddings use embedding.input_type. Passage/stored content always uses embedding.input_type."),
29917
30214
  truncate: exports_external.string().optional().describe("Optional truncate mode sent in the embedding request body (e.g. NVIDIA NIM accepts 'NONE' | 'START' | 'END'). Omitted from the request when unset."),
29918
30215
  max_input_tokens: exports_external.number().int().positive().optional().describe("Optional maximum input tokens for chunk embeddings. Defaults conservatively to 512 when omitted."),
30216
+ local_runtime: exports_external.enum(["auto", "native", "wasm"]).default("auto").describe("Local provider only: ONNX runtime selection. 'auto' uses native under Node and uses WASM under Bun versions before 1.4.0, where Bun's NAPI teardown race can panic on quit; native is restored automatically on Bun 1.4.0+. Set 'native' only to prefer speed while accepting that pre-1.4.0 Bun crash risk, or 'wasm' to avoid loading the native addon."),
29919
30217
  local_dtype: exports_external.enum([
29920
30218
  "auto",
29921
30219
  "fp32",
@@ -29972,6 +30270,7 @@ var init_magic_context = __esm(() => {
29972
30270
  return {
29973
30271
  provider: "local",
29974
30272
  model: data.model?.trim() || DEFAULT_LOCAL_EMBEDDING_MODEL,
30273
+ local_runtime: data.local_runtime,
29975
30274
  ...data.max_input_tokens ? { max_input_tokens: data.max_input_tokens } : {},
29976
30275
  ...data.local_dtype ? { local_dtype: data.local_dtype } : {}
29977
30276
  };
@@ -30052,7 +30351,8 @@ var init_magic_context = __esm(() => {
30052
30351
  }).default({ enforce_private_permissions: true }).describe("Storage permission policy. The default keeps session content and memories owner-private. Disabling enforcement is for trusted shared-group storage managed externally; every group member able to read the storage can read all stored session content and memories."),
30053
30352
  embedding: EmbeddingConfigSchema.default({
30054
30353
  provider: "local",
30055
- model: DEFAULT_LOCAL_EMBEDDING_MODEL
30354
+ model: DEFAULT_LOCAL_EMBEDDING_MODEL,
30355
+ local_runtime: "auto"
30056
30356
  }).describe("Embedding provider configuration"),
30057
30357
  subc: exports_external.object({
30058
30358
  connection_file: exports_external.string().trim().min(1).transform(expandConfigPath).describe("Path to the owner-only subc connection file.")
@@ -30654,15 +30954,15 @@ var RUST_COMPACTION_OFF_WARNING = "compaction-off mode does not support rust tra
30654
30954
 
30655
30955
  // ../plugin/src/config/variable.ts
30656
30956
  import { existsSync as existsSync14, readFileSync as readFileSync9 } from "node:fs";
30657
- import { homedir as homedir8 } from "node:os";
30658
- import { dirname as dirname9, isAbsolute as isAbsolute3, resolve as resolve3 } from "node:path";
30957
+ import { homedir as homedir9 } from "node:os";
30958
+ import { dirname as dirname9, isAbsolute as isAbsolute4, resolve as resolve4 } from "node:path";
30659
30959
  function sensitiveFilePathReason(resolvedPath) {
30660
- const home = homedir8();
30960
+ const home = homedir9();
30661
30961
  const sensitiveDirs = [
30662
- { dir: resolve3(home, ".ssh"), label: "SSH keys" },
30663
- { dir: resolve3(home, ".aws"), label: "AWS credentials" },
30664
- { dir: resolve3(home, ".gnupg"), label: "GnuPG keyring" },
30665
- { dir: resolve3(home, ".config", "gh"), label: "GitHub CLI auth" }
30962
+ { dir: resolve4(home, ".ssh"), label: "SSH keys" },
30963
+ { dir: resolve4(home, ".aws"), label: "AWS credentials" },
30964
+ { dir: resolve4(home, ".gnupg"), label: "GnuPG keyring" },
30965
+ { dir: resolve4(home, ".config", "gh"), label: "GitHub CLI auth" }
30666
30966
  ];
30667
30967
  for (const { dir, label } of sensitiveDirs) {
30668
30968
  if (resolvedPath === dir || resolvedPath.startsWith(`${dir}/`)) {
@@ -30720,9 +31020,9 @@ function substituteConfigVariables(input) {
30720
31020
  }
30721
31021
  let filePath = rawPath.trim();
30722
31022
  if (filePath.startsWith("~/")) {
30723
- filePath = resolve3(homedir8(), filePath.slice(2));
30724
- } else if (!isAbsolute3(filePath)) {
30725
- filePath = resolve3(configDir, filePath);
31023
+ filePath = resolve4(homedir9(), filePath.slice(2));
31024
+ } else if (!isAbsolute4(filePath)) {
31025
+ filePath = resolve4(configDir, filePath);
30726
31026
  }
30727
31027
  const sensitiveReason = sensitiveFilePathReason(filePath);
30728
31028
  if (sensitiveReason) {
@@ -31127,17 +31427,17 @@ var init_config = __esm(() => {
31127
31427
  });
31128
31428
 
31129
31429
  // ../plugin/src/shared/opencode-config-dir.ts
31130
- import { homedir as homedir9 } from "node:os";
31131
- import { join as join11, resolve as resolve4 } from "node:path";
31430
+ import { homedir as homedir10 } from "node:os";
31431
+ import { join as join11, resolve as resolve5 } from "node:path";
31132
31432
  function getCliConfigDir() {
31133
31433
  const envConfigDir = process.env.OPENCODE_CONFIG_DIR?.trim();
31134
31434
  if (envConfigDir) {
31135
- return resolve4(envConfigDir);
31435
+ return resolve5(envConfigDir);
31136
31436
  }
31137
31437
  if (process.platform === "win32") {
31138
- return join11(homedir9(), ".config", "opencode");
31438
+ return join11(homedir10(), ".config", "opencode");
31139
31439
  }
31140
- return join11(process.env.XDG_CONFIG_HOME || join11(homedir9(), ".config"), "opencode");
31440
+ return join11(process.env.XDG_CONFIG_HOME || join11(homedir10(), ".config"), "opencode");
31141
31441
  }
31142
31442
  function getOpenCodeConfigDir2(_options) {
31143
31443
  return getCliConfigDir();
@@ -31155,7 +31455,7 @@ function getOpenCodeConfigPaths(options) {
31155
31455
  var init_opencode_config_dir = () => {};
31156
31456
 
31157
31457
  // ../plugin/src/shared/conflict-detector.ts
31158
- import { homedir as homedir10 } from "node:os";
31458
+ import { homedir as homedir11 } from "node:os";
31159
31459
  import { join as join12 } from "node:path";
31160
31460
  function detectConflicts(directory, options) {
31161
31461
  const compactionEnabled = options?.compactionEnabled ?? true;
@@ -31343,7 +31643,7 @@ function readOmoDisabledHooks(directory) {
31343
31643
  }
31344
31644
  }
31345
31645
  }
31346
- const homeDir2 = process.env.HOME || homedir10();
31646
+ const homeDir2 = process.env.HOME || homedir11();
31347
31647
  const omoHomeDir = join12(homeDir2, ".omo");
31348
31648
  for (const name of ["omo.jsonc", "omo.json"]) {
31349
31649
  const config2 = readJsoncFile(join12(omoHomeDir, name));
@@ -31374,7 +31674,7 @@ var init_conflict_detector = __esm(() => {
31374
31674
 
31375
31675
  // ../plugin/src/shared/conflict-fixer.ts
31376
31676
  import { existsSync as existsSync16, readFileSync as readFileSync10, writeFileSync as writeFileSync5 } from "node:fs";
31377
- import { homedir as homedir11 } from "node:os";
31677
+ import { homedir as homedir12 } from "node:os";
31378
31678
  import { join as join13 } from "node:path";
31379
31679
  function isRecord2(value) {
31380
31680
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -31434,7 +31734,7 @@ function collectOmoConfigPaths(directory) {
31434
31734
  paths.add(projectPath);
31435
31735
  }
31436
31736
  }
31437
- const homeDir2 = process.env.HOME || homedir11();
31737
+ const homeDir2 = process.env.HOME || homedir12();
31438
31738
  const omoHomeDir = join13(homeDir2, ".omo");
31439
31739
  for (const name of OMO_UNIFIED_NAMES) {
31440
31740
  const userPath = join13(omoHomeDir, name);
@@ -32256,6 +32556,9 @@ async function drainAuthority(args) {
32256
32556
  if (next === cursor3)
32257
32557
  break;
32258
32558
  }
32559
+ if (args.domain === "memories") {
32560
+ resolvePendingMemoryReferencesForDrain(args.db);
32561
+ }
32259
32562
  for (const step of [
32260
32563
  "seed",
32261
32564
  "memories",
@@ -32376,6 +32679,47 @@ function rowNullableString(row, key) {
32376
32679
  const value = row[key];
32377
32680
  return typeof value === "string" ? value : null;
32378
32681
  }
32682
+ function memorySnapshotTimestamp(row, key) {
32683
+ const value = row[key];
32684
+ return typeof value === "number" && Number.isFinite(value) ? value : 0;
32685
+ }
32686
+ function parsedMemorySnapshot(snapshotJson, fallback) {
32687
+ try {
32688
+ const parsed = JSON.parse(snapshotJson);
32689
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : fallback;
32690
+ } catch {
32691
+ return fallback;
32692
+ }
32693
+ }
32694
+ function guardMemorySnapshotByRecency(args) {
32695
+ const effectiveRow = { ...args.row };
32696
+ if (!args.existing) {
32697
+ return { effectiveRow, hostUpdatedNewer: false, hostVerificationNewer: false };
32698
+ }
32699
+ const existing = args.existing;
32700
+ const preserve = (columns) => {
32701
+ for (const column of columns) {
32702
+ if (Object.hasOwn(existing, column)) {
32703
+ effectiveRow[column] = existing[column];
32704
+ }
32705
+ }
32706
+ };
32707
+ preserve(IMMUTABLE_MEMORY_SNAPSHOT_COLUMNS);
32708
+ const hostUpdatedNewer = memorySnapshotTimestamp(existing, "updated_at") > memorySnapshotTimestamp(args.snapshot, "updated_at");
32709
+ const hostClassificationNewer = hostUpdatedNewer || memorySnapshotTimestamp(existing, "classified_at") > memorySnapshotTimestamp(args.snapshot, "classified_at");
32710
+ const snapshotCarriesUpdatedAt = hasSnapshotField(args.snapshot, "updated_at");
32711
+ const hostVerificationNewer = hostUpdatedNewer && snapshotCarriesUpdatedAt;
32712
+ const hostMuralNewer = hostUpdatedNewer && snapshotCarriesUpdatedAt;
32713
+ if (hostUpdatedNewer)
32714
+ preserve(UPDATED_MEMORY_SNAPSHOT_COLUMNS);
32715
+ if (hostClassificationNewer)
32716
+ preserve(CLASSIFICATION_MEMORY_SNAPSHOT_COLUMNS);
32717
+ if (hostVerificationNewer)
32718
+ preserve(VERIFICATION_MEMORY_SNAPSHOT_COLUMNS);
32719
+ if (hostMuralNewer)
32720
+ preserve(MURAL_MEMORY_SNAPSHOT_COLUMNS);
32721
+ return { effectiveRow, hostUpdatedNewer, hostVerificationNewer };
32722
+ }
32379
32723
  function hasSnapshotField(row, key) {
32380
32724
  return Object.prototype.hasOwnProperty.call(row, key);
32381
32725
  }
@@ -32520,11 +32864,11 @@ function prepareMirrorPageStatements(db) {
32520
32864
  verification_status = ?, verified_at = ?, classified_at = ?, superseded_by_memory_id = ?,
32521
32865
  merged_from = ?, metadata_json = ?, mural_cue = ?, mural_cue_hash = ?, mural_cue_at = ?,
32522
32866
  mural_cue_rejection_count = ? WHERE id = ?`),
32523
- updateSuperseded: db.prepare("UPDATE memories SET superseded_by_memory_id = ? WHERE id = ?"),
32867
+ updateSuperseded: db.prepare("UPDATE memories SET superseded_by_memory_id = ?, updated_at = ? WHERE id = ?"),
32524
32868
  deletePendingReference: db.prepare("DELETE FROM mirror_pending_references WHERE domain = 'memories' AND module_project = ? AND module_row_id = ?"),
32525
32869
  upsertPendingReference: db.prepare("INSERT INTO mirror_pending_references(domain, module_project, module_row_id, target_module_row_id) VALUES ('memories', ?, ?, ?) ON CONFLICT(domain, module_project, module_row_id) DO UPDATE SET target_module_row_id = excluded.target_module_row_id"),
32526
32870
  deleteMemoryVerifications: db.prepare("DELETE FROM memory_verifications WHERE memory_id = ?"),
32527
- insertMemoryVerification: db.prepare("INSERT INTO memory_verifications(memory_id, file_path, verified_at, mapped_at) VALUES (?, ?, ?, ?)"),
32871
+ insertMemoryVerification: db.prepare("INSERT INTO memory_verifications(memory_id, file_path, verified_at, mapped_at, mapping_origin) VALUES (?, ?, ?, ?, ?)"),
32528
32872
  noteById: db.prepare("SELECT * FROM notes WHERE id = ?"),
32529
32873
  noteIdByStoreId: db.prepare("SELECT id FROM notes WHERE id = ? AND type = 'smart' AND project_path = ?"),
32530
32874
  insertNote: db.prepare("INSERT INTO notes (type, status, content, project_path, session_id, created_at, updated_at) VALUES ('smart', 'active', '', ?, ?, 0, 0)"),
@@ -32552,7 +32896,8 @@ function prepareMirrorPageStatements(db) {
32552
32896
  AND target.module_row_id = pending.target_module_row_id
32553
32897
  WHERE pending.domain = 'memories'
32554
32898
  AND source.context_row_id = memories.id
32555
- )
32899
+ ),
32900
+ updated_at = ?
32556
32901
  WHERE id IN (
32557
32902
  SELECT source.context_row_id
32558
32903
  FROM mirror_pending_references pending
@@ -32582,7 +32927,7 @@ function prepareMirrorPageStatements(db) {
32582
32927
  repairPending: db.prepare("SELECT dirty FROM mirror_memory_repair_state WHERE id = 1"),
32583
32928
  markRepairPending: db.prepare("UPDATE mirror_memory_repair_state SET dirty = 1, updated_at = ? WHERE id = 1"),
32584
32929
  clearRepairPending: db.prepare("UPDATE mirror_memory_repair_state SET dirty = 0, updated_at = ? WHERE id = 1"),
32585
- repairCandidates: db.prepare(`SELECT memory.id, live.full_row_snapshot
32930
+ repairCandidates: db.prepare(`SELECT memory.id, memory.updated_at, memory.classified_at, live.full_row_snapshot
32586
32931
  FROM memories memory
32587
32932
  JOIN mirror_identity identity
32588
32933
  ON identity.domain = 'memories'
@@ -32596,9 +32941,14 @@ function prepareMirrorPageStatements(db) {
32596
32941
  WHERE (memory.source_type IS NULL OR memory.importance IS NULL)
32597
32942
  AND live.full_row_snapshot IS NOT NULL`),
32598
32943
  repairMemory: db.prepare(`UPDATE memories
32599
- SET source_type = COALESCE(?, source_type),
32600
- importance = COALESCE(?, importance)
32601
- WHERE id = ?`),
32944
+ SET source_type = COALESCE(source_type, ?),
32945
+ importance = COALESCE(importance, ?),
32946
+ updated_at = ?
32947
+ WHERE id = ?
32948
+ AND COALESCE(updated_at, 0) <= ?
32949
+ AND COALESCE(classified_at, 0) <= ?
32950
+ AND ((source_type IS NULL AND ? IS NOT NULL)
32951
+ OR (importance IS NULL AND ? IS NOT NULL))`),
32602
32952
  updateCursor: db.prepare("INSERT INTO mirror_cursors(domain, cursor, updated_at) VALUES (?, ?, ?) ON CONFLICT(domain) DO UPDATE SET cursor = excluded.cursor, updated_at = excluded.updated_at"),
32603
32953
  contextStoreUuid: getContextStoreUuid(db)
32604
32954
  };
@@ -32606,11 +32956,16 @@ function prepareMirrorPageStatements(db) {
32606
32956
  function mirrorIdentity(db, domain2, moduleProject, moduleRowId, statements) {
32607
32957
  return (statements?.identityByModule ?? db.prepare("SELECT context_row_id FROM mirror_identity WHERE domain = ? AND module_project = ? AND module_row_id = ?")).get(domain2, moduleProject, moduleRowId) ?? null;
32608
32958
  }
32609
- function rememberIdentity(db, domain2, moduleProject, moduleRowId, contextRowId, statements) {
32959
+ function rememberIdentity(db, domain2, moduleProject, moduleRowId, contextRowId, statements, replaceContextIdentity = domain2 === "notes") {
32610
32960
  const existing = mirrorIdentity(db, domain2, moduleProject, moduleRowId, statements);
32611
- if (existing)
32961
+ if (existing?.context_row_id === contextRowId)
32612
32962
  return;
32613
- if (domain2 === "notes") {
32963
+ if (existing) {
32964
+ if (!replaceContextIdentity)
32965
+ return;
32966
+ (statements?.deleteIdentity ?? db.prepare("DELETE FROM mirror_identity WHERE domain = ? AND module_project = ? AND module_row_id = ?")).run(domain2, moduleProject, moduleRowId);
32967
+ }
32968
+ if (replaceContextIdentity) {
32614
32969
  (statements?.deleteIdentityByContext ?? db.prepare("DELETE FROM mirror_identity WHERE domain = ? AND context_row_id = ?")).run(domain2, contextRowId);
32615
32970
  }
32616
32971
  (statements?.insertIdentity ?? db.prepare("INSERT OR IGNORE INTO mirror_identity(domain, module_project, module_row_id, context_row_id) VALUES (?, ?, ?, ?)")).run(domain2, moduleProject, moduleRowId, contextRowId);
@@ -32625,7 +32980,7 @@ function contextMemoryId(db, domain2, moduleProject, row, moduleRowId, statement
32625
32980
  if (sourceUuid && sourceUuid === localStoreUuid && sourceId >= 0) {
32626
32981
  const existing = (statements?.memoryIdByStoreId ?? db.prepare("SELECT id FROM memories WHERE id = ? AND project_path = ?")).get(sourceId, moduleProject);
32627
32982
  if (existing?.id !== undefined) {
32628
- rememberIdentity(db, domain2, moduleProject, moduleRowId, existing.id, statements);
32983
+ rememberIdentity(db, domain2, moduleProject, moduleRowId, existing.id, statements, true);
32629
32984
  return existing.id;
32630
32985
  }
32631
32986
  }
@@ -32682,37 +33037,46 @@ function applyMemoryRow(db, feed, statements) {
32682
33037
  log3(`[magic-context] skipping memory mirror update for module ${moduleProject}/${feed.module_row_id}: context row ${contextId} belongs to ${existing.project_path}`);
32683
33038
  return;
32684
33039
  }
33040
+ const retainedRecencySnapshot = parsedMemorySnapshot(snapshotJson, row);
33041
+ const recencySnapshot = hasSnapshotField(row, "updated_at") ? row : hasSnapshotField(row, "classified_at") ? { ...retainedRecencySnapshot, classified_at: row.classified_at } : retainedRecencySnapshot;
33042
+ const recencyGuard = guardMemorySnapshotByRecency({
33043
+ row,
33044
+ snapshot: recencySnapshot,
33045
+ existing
33046
+ });
33047
+ const projectedRow = recencyGuard.effectiveRow;
32685
33048
  const has = (key) => hasSnapshotField(row, key);
32686
- const nullableNumber = (key, previous) => has(key) ? typeof row[key] === "number" && Number.isFinite(row[key]) ? row[key] : null : previous ?? null;
32687
- const nullableString = (key, previous) => has(key) ? rowNullableString(row, key) : previous ?? null;
32688
- const hasSuperseded = has("superseded_by_memory_id");
33049
+ const nullableNumber = (key, previous) => has(key) ? typeof projectedRow[key] === "number" && Number.isFinite(projectedRow[key]) ? projectedRow[key] : null : previous ?? null;
33050
+ const nullableString = (key, previous) => has(key) ? rowNullableString(projectedRow, key) : previous ?? null;
33051
+ const hasSuperseded = has("superseded_by_memory_id") && !recencyGuard.hostUpdatedNewer;
32689
33052
  const previousHash = existing?.normalized_hash;
32690
- statements.updateMemory.run(has("project_path") ? rowString(row, "project_path") : existing?.project_path ?? moduleProject, has("category") ? rowString(row, "category", "CONSTRAINTS") : existing?.category ?? "CONSTRAINTS", has("content") ? rowString(row, "content") : existing?.content ?? "", has("normalized_hash") ? rowString(row, "normalized_hash") : existing?.normalized_hash ?? "", has("importance") ? typeof row.importance === "number" && Number.isFinite(row.importance) ? row.importance : null : existing?.importance ?? null, has("scope") ? rowString(row, "scope", "project") : existing?.scope ?? "project", has("shareable") ? rowNumber(row, "shareable") : existing?.shareable ?? 0, nullableString("source_session_id", existing?.source_session_id), nullableString("source_type", existing?.source_type), has("seen_count") ? rowNumber(row, "seen_count", 1) : existing?.seen_count ?? 1, has("retrieval_count") ? rowNumber(row, "retrieval_count") : existing?.retrieval_count ?? 0, has("first_seen_at") ? rowNumber(row, "first_seen_at") : existing?.first_seen_at ?? 0, has("created_at") ? rowNumber(row, "created_at") : existing?.created_at ?? 0, has("updated_at") ? rowNumber(row, "updated_at") : existing?.updated_at ?? 0, has("last_seen_at") ? rowNumber(row, "last_seen_at") : existing?.last_seen_at ?? 0, nullableNumber("last_retrieved_at", existing?.last_retrieved_at), has("status") ? rowString(row, "status", "active") : existing?.status ?? "active", nullableNumber("expires_at", existing?.expires_at), has("verification_status") ? rowString(row, "verification_status", "unverified") : existing?.verification_status ?? "unverified", nullableNumber("verified_at", existing?.verified_at), nullableNumber("classified_at", existing?.classified_at), hasSuperseded ? null : existing?.superseded_by_memory_id ?? null, nullableString("merged_from", existing?.merged_from), nullableString("metadata_json", existing?.metadata_json), nullableString("mural_cue", existing?.mural_cue), nullableString("mural_cue_hash", existing?.mural_cue_hash), nullableNumber("mural_cue_at", existing?.mural_cue_at), has("mural_cue_rejection_count") ? rowNumber(row, "mural_cue_rejection_count") : existing?.mural_cue_rejection_count ?? 0, contextId);
32691
- if (hasSuperseded && typeof row.superseded_by_memory_id === "number") {
32692
- const translated = mirrorIdentity(db, "memories", moduleProject, row.superseded_by_memory_id, statements);
33053
+ statements.updateMemory.run(has("project_path") ? rowString(projectedRow, "project_path") : existing?.project_path ?? moduleProject, has("category") ? rowString(projectedRow, "category", "CONSTRAINTS") : existing?.category ?? "CONSTRAINTS", has("content") ? rowString(projectedRow, "content") : existing?.content ?? "", has("normalized_hash") ? rowString(projectedRow, "normalized_hash") : existing?.normalized_hash ?? "", has("importance") ? typeof projectedRow.importance === "number" && Number.isFinite(projectedRow.importance) ? projectedRow.importance : null : existing?.importance ?? null, has("scope") ? rowString(projectedRow, "scope", "project") : existing?.scope ?? "project", has("shareable") ? rowNumber(projectedRow, "shareable") : existing?.shareable ?? 0, nullableString("source_session_id", existing?.source_session_id), nullableString("source_type", existing?.source_type), has("seen_count") ? rowNumber(projectedRow, "seen_count", 1) : existing?.seen_count ?? 1, has("retrieval_count") ? rowNumber(projectedRow, "retrieval_count") : existing?.retrieval_count ?? 0, has("first_seen_at") ? rowNumber(projectedRow, "first_seen_at") : existing?.first_seen_at ?? 0, has("created_at") ? rowNumber(projectedRow, "created_at") : existing?.created_at ?? 0, has("updated_at") ? rowNumber(projectedRow, "updated_at") : existing?.updated_at ?? 0, has("last_seen_at") ? rowNumber(projectedRow, "last_seen_at") : existing?.last_seen_at ?? 0, nullableNumber("last_retrieved_at", existing?.last_retrieved_at), has("status") ? rowString(projectedRow, "status", "active") : existing?.status ?? "active", nullableNumber("expires_at", existing?.expires_at), has("verification_status") ? rowString(projectedRow, "verification_status", "unverified") : existing?.verification_status ?? "unverified", nullableNumber("verified_at", existing?.verified_at), nullableNumber("classified_at", existing?.classified_at), hasSuperseded ? null : existing?.superseded_by_memory_id ?? null, nullableString("merged_from", existing?.merged_from), nullableString("metadata_json", existing?.metadata_json), nullableString("mural_cue", existing?.mural_cue), nullableString("mural_cue_hash", existing?.mural_cue_hash), nullableNumber("mural_cue_at", existing?.mural_cue_at), has("mural_cue_rejection_count") ? rowNumber(projectedRow, "mural_cue_rejection_count") : existing?.mural_cue_rejection_count ?? 0, contextId);
33054
+ if (hasSuperseded && typeof projectedRow.superseded_by_memory_id === "number") {
33055
+ const translated = mirrorIdentity(db, "memories", moduleProject, projectedRow.superseded_by_memory_id, statements);
32693
33056
  if (translated) {
32694
- statements.updateSuperseded.run(translated.context_row_id, contextId);
33057
+ statements.updateSuperseded.run(translated.context_row_id, Date.now(), contextId);
32695
33058
  statements.deletePendingReference.run(moduleProject, feed.module_row_id);
32696
33059
  } else {
32697
- statements.upsertPendingReference.run(moduleProject, feed.module_row_id, row.superseded_by_memory_id);
33060
+ statements.upsertPendingReference.run(moduleProject, feed.module_row_id, projectedRow.superseded_by_memory_id);
32698
33061
  }
32699
33062
  } else if (hasSuperseded) {
32700
33063
  statements.deletePendingReference.run(moduleProject, feed.module_row_id);
32701
33064
  }
32702
- const appliedHash = has("normalized_hash") ? rowString(row, "normalized_hash") : previousHash;
33065
+ const appliedHash = has("normalized_hash") ? rowString(projectedRow, "normalized_hash") : previousHash;
32703
33066
  if (previousHash !== appliedHash && appliedHash !== undefined) {
32704
33067
  statements.deleteMemoryEmbeddings.run(contextId);
32705
33068
  }
32706
- if (has("mapping")) {
33069
+ if (has("mapping") && !recencyGuard.hostVerificationNewer) {
32707
33070
  statements.deleteMemoryVerifications.run(contextId);
32708
- if (Array.isArray(row.mapping)) {
33071
+ if (Array.isArray(projectedRow.mapping)) {
32709
33072
  const files = [
32710
- ...new Set(row.mapping.filter((file2) => typeof file2 === "string").sort())
33073
+ ...new Set(projectedRow.mapping.filter((file2) => typeof file2 === "string").sort())
32711
33074
  ];
32712
- const verifiedAt = rowNumber(row, "verified_at");
32713
- const mappedAt = rowNumber(row, "updated_at", Date.now());
33075
+ const verifiedAt = rowNumber(projectedRow, "verified_at");
33076
+ const mappedAt = rowNumber(projectedRow, "updated_at", Date.now());
33077
+ const mappingOrigin = projectedRow.mapping_origin === "host_rejected_fallback" ? "host_rejected_fallback" : "mapper";
32714
33078
  for (const file2 of files.length > 0 ? files : [""]) {
32715
- statements.insertMemoryVerification.run(contextId, file2, verifiedAt, mappedAt);
33079
+ statements.insertMemoryVerification.run(contextId, file2, verifiedAt, mappedAt, mappingOrigin);
32716
33080
  }
32717
33081
  }
32718
33082
  }
@@ -32738,7 +33102,11 @@ function repairNullClobberedMemoryRows(statements) {
32738
33102
  const importance = hasSnapshotField(snapshot, "importance") && typeof snapshot.importance === "number" && Number.isFinite(snapshot.importance) ? snapshot.importance : null;
32739
33103
  if (sourceType === null && importance === null)
32740
33104
  continue;
32741
- statements.repairMemory.run(sourceType, importance, candidate.id);
33105
+ const snapshotVintage = Math.max(memorySnapshotTimestamp(snapshot, "updated_at"), memorySnapshotTimestamp(snapshot, "classified_at"));
33106
+ const hostVintage = Math.max(candidate.updated_at ?? 0, candidate.classified_at ?? 0);
33107
+ if (hostVintage > snapshotVintage)
33108
+ continue;
33109
+ statements.repairMemory.run(sourceType, importance, Date.now(), candidate.id, snapshotVintage, snapshotVintage, sourceType, importance);
32742
33110
  }
32743
33111
  statements.clearRepairPending.run(Date.now());
32744
33112
  }
@@ -32763,9 +33131,17 @@ function contextNoteId(db, feed, moduleProject, statements) {
32763
33131
  return contextId;
32764
33132
  }
32765
33133
  function translateMemoryReferences(statements) {
32766
- statements.translateMemoryReferences.run();
33134
+ statements.translateMemoryReferences.run(Date.now());
32767
33135
  statements.clearTranslatedReferences.run();
32768
33136
  }
33137
+ function resolvePendingMemoryReferencesForDrain(db) {
33138
+ withPrivilegedWriter(db, () => {
33139
+ db.transaction(() => {
33140
+ const statements = prepareMirrorPageStatements(db);
33141
+ translateMemoryReferences(statements);
33142
+ }).immediate();
33143
+ });
33144
+ }
32769
33145
  function applyNoteRow(db, feed, statements) {
32770
33146
  const row = feed.full_row_snapshot;
32771
33147
  const moduleProject = rowString(row, "project_path");
@@ -32833,6 +33209,24 @@ function applyMirrorPage(args) {
32833
33209
  if (page.domain === "memories" && resnapshotStatus !== "complete" && page.rows.some((feed) => feed.op === "tombstone")) {
32834
33210
  throw new Error("memory mirror resnapshot must complete before tombstones");
32835
33211
  }
33212
+ if (page.domain === "memories") {
33213
+ for (const feed of page.rows) {
33214
+ if (feed.domain !== "memories" || feed.op === "tombstone" || feed.feed_seq <= durableCursor) {
33215
+ continue;
33216
+ }
33217
+ const row = feed.full_row_snapshot;
33218
+ const moduleProject = rowString(row, "project_path");
33219
+ const sourceUuid = rowNullableString(row, "context_store_uuid");
33220
+ const sourceId = rowNumber(row, "context_row_id", -1);
33221
+ if (!moduleProject || !sourceUuid || sourceUuid !== statements.contextStoreUuid || sourceId < 0) {
33222
+ continue;
33223
+ }
33224
+ const existing = statements.memoryIdByStoreId.get(sourceId, moduleProject);
33225
+ if (existing?.id === undefined)
33226
+ continue;
33227
+ rememberIdentity(db, "memories", moduleProject, feed.module_row_id, existing.id, statements, true);
33228
+ }
33229
+ }
32836
33230
  const touchedProjects = new Set;
32837
33231
  for (const feed of page.rows) {
32838
33232
  if (feed.domain !== page.domain || feed.feed_seq <= nextCursor)
@@ -32944,11 +33338,12 @@ async function ensureLiveMemoryResnapshot(args) {
32944
33338
  }).immediate();
32945
33339
  });
32946
33340
  }
32947
- var AUTHORITY_DOMAINS, moduleNoteEvaluationBridges, MAX_DRAIN_RECAPTURE_ATTEMPTS = 5, MAX_AUTHORITY_SEED_FRAME_BYTES, MEMORY_SNAPSHOT_COLUMNS, mirrorFlights;
33341
+ var AUTHORITY_DOMAINS, observedAuthorityRoutingByProject, moduleNoteEvaluationBridges, MAX_DRAIN_RECAPTURE_ATTEMPTS = 5, MAX_AUTHORITY_SEED_FRAME_BYTES, MEMORY_SNAPSHOT_COLUMNS, IMMUTABLE_MEMORY_SNAPSHOT_COLUMNS, CLASSIFICATION_MEMORY_SNAPSHOT_COLUMNS, VERIFICATION_MEMORY_SNAPSHOT_COLUMNS, MURAL_MEMORY_SNAPSHOT_COLUMNS, UPDATED_MEMORY_SNAPSHOT_COLUMNS, mirrorFlights;
32948
33342
  var init_context_authority = __esm(async () => {
32949
33343
  init_logger();
32950
33344
  await init_sqlite();
32951
33345
  AUTHORITY_DOMAINS = ["memories", "notes"];
33346
+ observedAuthorityRoutingByProject = new Map;
32952
33347
  moduleNoteEvaluationBridges = new Map;
32953
33348
  MAX_AUTHORITY_SEED_FRAME_BYTES = 900 * 1024;
32954
33349
  MEMORY_SNAPSHOT_COLUMNS = [
@@ -32984,13 +33379,49 @@ var init_context_authority = __esm(async () => {
32984
33379
  "mural_cue_at",
32985
33380
  "mural_cue_rejection_count"
32986
33381
  ];
33382
+ IMMUTABLE_MEMORY_SNAPSHOT_COLUMNS = ["project_path", "first_seen_at", "created_at"];
33383
+ CLASSIFICATION_MEMORY_SNAPSHOT_COLUMNS = [
33384
+ "importance",
33385
+ "scope",
33386
+ "shareable",
33387
+ "source_type",
33388
+ "classified_at"
33389
+ ];
33390
+ VERIFICATION_MEMORY_SNAPSHOT_COLUMNS = [
33391
+ "verification_status",
33392
+ "verified_at",
33393
+ "mapping",
33394
+ "mapping_origin"
33395
+ ];
33396
+ MURAL_MEMORY_SNAPSHOT_COLUMNS = [
33397
+ "mural_cue",
33398
+ "mural_cue_hash",
33399
+ "mural_cue_at",
33400
+ "mural_cue_rejection_count"
33401
+ ];
33402
+ UPDATED_MEMORY_SNAPSHOT_COLUMNS = [
33403
+ "category",
33404
+ "content",
33405
+ "normalized_hash",
33406
+ "source_session_id",
33407
+ "seen_count",
33408
+ "retrieval_count",
33409
+ "updated_at",
33410
+ "last_seen_at",
33411
+ "last_retrieved_at",
33412
+ "status",
33413
+ "expires_at",
33414
+ "superseded_by_memory_id",
33415
+ "merged_from",
33416
+ "metadata_json"
33417
+ ];
32987
33418
  mirrorFlights = new WeakMap;
32988
33419
  });
32989
33420
 
32990
33421
  // ../plugin/src/features/magic-context/memory/project-identity.ts
32991
33422
  import { execFileSync as execFileSync3 } from "node:child_process";
32992
33423
  import { createHash as createHash2 } from "node:crypto";
32993
- import { existsSync as existsSync18, realpathSync as realpathSync2, statSync as statSync7 } from "node:fs";
33424
+ import { existsSync as existsSync18, realpathSync as realpathSync2, statSync as statSync8 } from "node:fs";
32994
33425
  import path3 from "node:path";
32995
33426
  function asError(error51) {
32996
33427
  return error51 instanceof Error ? error51 : undefined;
@@ -33035,7 +33466,7 @@ function directoryFallback(directory) {
33035
33466
  }
33036
33467
  function assertDirectoryUsable(canonicalDirectory, rawDirectory) {
33037
33468
  try {
33038
- const stat = statSync7(canonicalDirectory);
33469
+ const stat = statSync8(canonicalDirectory);
33039
33470
  if (!stat.isDirectory()) {
33040
33471
  throw new ProjectIdentityError("unknown", rawDirectory, `Project path is not a directory: ${canonicalDirectory}`);
33041
33472
  }
@@ -33645,7 +34076,7 @@ class SubcSocket {
33645
34076
  return this.sock.localPort ?? null;
33646
34077
  }
33647
34078
  static connect(host, port, deadlineMs) {
33648
- return new Promise((resolve5, reject) => {
34079
+ return new Promise((resolve6, reject) => {
33649
34080
  const sock = net.connect({ host, port });
33650
34081
  sock.setNoDelay(true);
33651
34082
  const timer = setTimeout(() => {
@@ -33654,7 +34085,7 @@ class SubcSocket {
33654
34085
  }, Math.max(0, deadlineMs - Date.now()));
33655
34086
  sock.once("connect", () => {
33656
34087
  clearTimeout(timer);
33657
- resolve5(new SubcSocket(sock));
34088
+ resolve6(new SubcSocket(sock));
33658
34089
  });
33659
34090
  sock.once("error", (err) => {
33660
34091
  clearTimeout(timer);
@@ -33686,7 +34117,7 @@ class SubcSocket {
33686
34117
  }
33687
34118
  if (n2 === 0)
33688
34119
  return Promise.resolve(new Uint8Array(0));
33689
- return new Promise((resolve5, reject) => {
34120
+ return new Promise((resolve6, reject) => {
33690
34121
  let timer = null;
33691
34122
  if (Number.isFinite(deadlineMs)) {
33692
34123
  const remaining = deadlineMs - Date.now();
@@ -33699,7 +34130,7 @@ class SubcSocket {
33699
34130
  reject(new SocketTimeoutError(`timed out waiting for ${n2} bytes`));
33700
34131
  }, remaining);
33701
34132
  }
33702
- this.waiter = { need: n2, resolve: resolve5, reject, timer };
34133
+ this.waiter = { need: n2, resolve: resolve6, reject, timer };
33703
34134
  this.tryServe();
33704
34135
  });
33705
34136
  }
@@ -33723,7 +34154,7 @@ class SubcSocket {
33723
34154
  let queued = false;
33724
34155
  let settled = false;
33725
34156
  let timer = null;
33726
- const completed = new Promise((resolve5, reject) => {
34157
+ const completed = new Promise((resolve6, reject) => {
33727
34158
  const settle = (run) => {
33728
34159
  if (settled)
33729
34160
  return;
@@ -33747,7 +34178,7 @@ class SubcSocket {
33747
34178
  if (err) {
33748
34179
  reject(new SocketWriteQueuedError("subc socket reported a write error after bytes were handed to the socket", err instanceof Error ? err : new Error(String(err))));
33749
34180
  } else {
33750
- resolve5();
34181
+ resolve6();
33751
34182
  }
33752
34183
  });
33753
34184
  });
@@ -33948,14 +34379,14 @@ class SubcClient {
33948
34379
  const admission = opts.admissionClass ?? AdmissionClass.Normal;
33949
34380
  const corr = this.allocateCorr();
33950
34381
  const key = pendingKey(handle, corr);
33951
- const closed = new Promise((resolve5, reject) => {
34382
+ const closed = new Promise((resolve6, reject) => {
33952
34383
  if (this.closedErr) {
33953
34384
  reject(this.closedErr);
33954
34385
  return;
33955
34386
  }
33956
34387
  this.pending.set(key, {
33957
34388
  handle,
33958
- resolve: () => resolve5(),
34389
+ resolve: () => resolve6(),
33959
34390
  reject,
33960
34391
  onProgress: onEvent,
33961
34392
  timer: null,
@@ -34040,11 +34471,11 @@ class SubcClient {
34040
34471
  const waiters = [];
34041
34472
  for (const pending of this.pending.values()) {
34042
34473
  if (pending.handle === handle && !pending.subscription) {
34043
- waiters.push(new Promise((resolve5) => {
34474
+ waiters.push(new Promise((resolve6) => {
34044
34475
  const previous = pending.onSettle;
34045
34476
  pending.onSettle = () => {
34046
34477
  previous?.();
34047
- resolve5();
34478
+ resolve6();
34048
34479
  };
34049
34480
  }));
34050
34481
  }
@@ -34100,11 +34531,11 @@ class SubcClient {
34100
34531
  const channel = handle?.channel ?? 0;
34101
34532
  const epoch = handle?.epoch ?? 0;
34102
34533
  const frame = buildFrame(FrameType.Request, buildFlags(false, priority, false, admission), channel, epoch, corr, body);
34103
- return new Promise((resolve5, reject) => {
34534
+ return new Promise((resolve6, reject) => {
34104
34535
  const ms = timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
34105
34536
  const pending = {
34106
34537
  handle,
34107
- resolve: resolve5,
34538
+ resolve: resolve6,
34108
34539
  reject,
34109
34540
  onProgress,
34110
34541
  timer: null,
@@ -34178,11 +34609,11 @@ class SubcClient {
34178
34609
  }
34179
34610
  return this.outcomeUnknownCallError("connection dropped before the managed call returned a response", error51);
34180
34611
  };
34181
- return new Promise((resolve5, reject) => {
34612
+ return new Promise((resolve6, reject) => {
34182
34613
  const ms = timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
34183
34614
  const pending = {
34184
34615
  handle,
34185
- resolve: resolve5,
34616
+ resolve: resolve6,
34186
34617
  reject,
34187
34618
  onProgress,
34188
34619
  timer: null,
@@ -34562,7 +34993,7 @@ function normalizeConnectOptions(opts) {
34562
34993
  identity: opts.identity,
34563
34994
  targetKind: opts.targetKind ?? DEFAULT_MANAGED_TARGET_KIND,
34564
34995
  reconnectBackoff: opts.reconnectBackoff ?? DEFAULT_RECONNECT_BACKOFF,
34565
- sleep: opts.sleep ?? ((ms) => new Promise((resolve5) => setTimeout(resolve5, ms))),
34996
+ sleep: opts.sleep ?? ((ms) => new Promise((resolve6) => setTimeout(resolve6, ms))),
34566
34997
  timeoutArbitrationGraceMs: opts.timeoutArbitrationGraceMs ?? TIMEOUT_ARBITRATION_GRACE_MS
34567
34998
  };
34568
34999
  }
@@ -34715,6 +35146,12 @@ function isConnectionFailure(error51) {
34715
35146
  ].includes(code) || /\bclient closed\b|\bconnection closed\b|\bclosed the connection\b/i.test(message);
34716
35147
  });
34717
35148
  }
35149
+ function routeOpenWithoutAmbientConsumerIdentity(client, target, identity, options = {}) {
35150
+ return client.routeOpen(target, identity, {
35151
+ ...options,
35152
+ consumerIdentity: null
35153
+ });
35154
+ }
34718
35155
 
34719
35156
  class SubcModuleTransport {
34720
35157
  connectionFile;
@@ -34861,7 +35298,7 @@ class SubcModuleTransport {
34861
35298
  if (this.queuedLaneWaiters >= SERIAL_LANE_MAX_WAITERS || lane.waiters.length >= SERIAL_LANE_MAX_WAITERS_PER_SESSION) {
34862
35299
  return Promise.reject(this.queueFullError());
34863
35300
  }
34864
- return new Promise((resolve5, reject) => {
35301
+ return new Promise((resolve6, reject) => {
34865
35302
  const waiter = {};
34866
35303
  const removeAndReject = (error51) => {
34867
35304
  if (waiter.settled)
@@ -34879,7 +35316,7 @@ class SubcModuleTransport {
34879
35316
  };
34880
35317
  waiter.signal = signal;
34881
35318
  waiter.deadlineMs = deadlineMs;
34882
- waiter.resolve = resolve5;
35319
+ waiter.resolve = resolve6;
34883
35320
  waiter.reject = reject;
34884
35321
  waiter.settled = false;
34885
35322
  waiter.onAbort = () => removeAndReject(signal?.reason ?? new Error("module transport call aborted"));
@@ -35088,7 +35525,7 @@ class SubcModuleTransport {
35088
35525
  harness: getHarness(),
35089
35526
  session: `${this.routeSessionPrefix}${sessionId}`
35090
35527
  };
35091
- const route = await this.beforeDeadline(client.routeOpen(target, identity), deadlineMs, "opening the module route");
35528
+ const route = await this.beforeDeadline(routeOpenWithoutAmbientConsumerIdentity(client, target, identity), deadlineMs, "opening the module route");
35092
35529
  if (this.client !== client || generation !== this.connectionGeneration) {
35093
35530
  await client.closeRoute(route).catch(() => {
35094
35531
  return;
@@ -35146,7 +35583,7 @@ class SubcModuleTransport {
35146
35583
  return error51;
35147
35584
  }
35148
35585
  sleepAbortable(durationMs, signal) {
35149
- return new Promise((resolve5, reject) => {
35586
+ return new Promise((resolve6, reject) => {
35150
35587
  if (signal?.aborted) {
35151
35588
  reject(signal.reason ?? new Error("module transport call aborted"));
35152
35589
  return;
@@ -35158,7 +35595,7 @@ class SubcModuleTransport {
35158
35595
  };
35159
35596
  const timer = setTimeout(() => {
35160
35597
  signal?.removeEventListener("abort", onAbort);
35161
- resolve5();
35598
+ resolve6();
35162
35599
  }, Math.max(0, durationMs));
35163
35600
  signal?.addEventListener("abort", onAbort, { once: true });
35164
35601
  });
@@ -35539,192 +35976,6 @@ var init_rpc_utils = __esm(() => {
35539
35976
  rpcProcessListExecFileSync = execFileSync4;
35540
35977
  rpcIdentityPlatform = process.platform;
35541
35978
  });
35542
- // ../plugin/src/shared/redaction.ts
35543
- import { homedir as homedir12, userInfo } from "node:os";
35544
- function escapeRegex2(value) {
35545
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
35546
- }
35547
- function redactionTypeForKey(key) {
35548
- const normalized = key.trim().toLowerCase().replace(/[^a-z0-9_.-]+/g, "_");
35549
- const suffix = normalized.split(".").filter(Boolean).at(-1) ?? normalized;
35550
- return suffix || "secret";
35551
- }
35552
- function isNonSecretScalarValue(value) {
35553
- const v = value.trim();
35554
- if (v === "true" || v === "false" || v === "null" || v === "undefined")
35555
- return true;
35556
- return /^[+-]?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?$/.test(v);
35557
- }
35558
- function isSecretKey(key) {
35559
- const segments = key.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase().split(/[._-]+/).filter(Boolean);
35560
- if (segments.length === 0)
35561
- return false;
35562
- if (segments.length === 1) {
35563
- const first = segments[0];
35564
- return Boolean(first && SECRET_SEGMENT_PATTERN.test(first));
35565
- }
35566
- for (let i2 = 0;i2 < segments.length; i2++) {
35567
- const seg = segments[i2];
35568
- if (!seg || !SECRET_SEGMENT_PATTERN.test(seg))
35569
- continue;
35570
- let trailingOk = true;
35571
- for (let j = i2 + 1;j < segments.length; j++) {
35572
- const tail = segments[j];
35573
- if (!tail)
35574
- continue;
35575
- if (TRAILING_DESCRIPTORS.has(tail))
35576
- continue;
35577
- if (SECRET_SEGMENT_PATTERN.test(tail))
35578
- continue;
35579
- trailingOk = false;
35580
- break;
35581
- }
35582
- if (!trailingOk)
35583
- continue;
35584
- for (let k = i2 - 1;k >= 0; k--) {
35585
- const lead = segments[k];
35586
- if (lead && SECRET_QUALIFIERS.has(lead))
35587
- return true;
35588
- }
35589
- }
35590
- return false;
35591
- }
35592
- function sanitizePathString(value) {
35593
- const home = homedir12();
35594
- const username = userInfo().username;
35595
- let sanitized = value;
35596
- if (home) {
35597
- sanitized = sanitized.replace(new RegExp(escapeRegex2(home), "g"), "~");
35598
- }
35599
- sanitized = sanitized.replace(/\/Users\/[^/]+\//g, "/Users/<USER>/");
35600
- sanitized = sanitized.replace(/\/home\/[^/]+\//g, "/home/<USER>/");
35601
- sanitized = sanitized.replace(/C:\\Users\\[^\\]+\\/g, "C:\\Users\\<USER>\\");
35602
- if (username) {
35603
- sanitized = sanitized.replace(new RegExp(escapeRegex2(username), "g"), "<USER>");
35604
- }
35605
- return sanitized;
35606
- }
35607
- function redactSecretText(value) {
35608
- let redacted = value;
35609
- for (const { pattern, replacement } of SECRET_TEXT_PATTERNS) {
35610
- if (typeof replacement === "string") {
35611
- redacted = redacted.replace(pattern, replacement);
35612
- } else {
35613
- redacted = redacted.replace(pattern, replacement);
35614
- }
35615
- }
35616
- return redacted;
35617
- }
35618
- function sanitizeDiagnosticText(value) {
35619
- return redactSecretText(sanitizePathString(value));
35620
- }
35621
- function sanitizeConfigValue(value, keyPath = []) {
35622
- if (value === null || typeof value === "number" || typeof value === "boolean")
35623
- return value;
35624
- const key = keyPath.at(-1) ?? "";
35625
- if (key && isSecretKey(key)) {
35626
- return `<REDACTED:${redactionTypeForKey(key)}>`;
35627
- }
35628
- if (typeof value === "string")
35629
- return sanitizeDiagnosticText(value);
35630
- if (Array.isArray(value)) {
35631
- return value.map((entry, index) => sanitizeConfigValue(entry, [...keyPath, String(index)]));
35632
- }
35633
- if (value && typeof value === "object") {
35634
- return Object.fromEntries(Object.entries(value).map(([entryKey, entry]) => [
35635
- entryKey,
35636
- sanitizeConfigValue(entry, [...keyPath, entryKey])
35637
- ]));
35638
- }
35639
- return value;
35640
- }
35641
- var SECRET_WORDS, SECRET_SEGMENT_PATTERN, TRAILING_DESCRIPTORS, SECRET_QUALIFIERS, SECRET_TEXT_PATTERNS;
35642
- var init_redaction = __esm(() => {
35643
- SECRET_WORDS = [
35644
- "key",
35645
- "token",
35646
- "secret",
35647
- "password",
35648
- "auth",
35649
- "authorization",
35650
- "bearer",
35651
- "credential"
35652
- ];
35653
- SECRET_SEGMENT_PATTERN = new RegExp(`^(?:${SECRET_WORDS.map((w) => `${w}s?`).join("|")})$`, "i");
35654
- TRAILING_DESCRIPTORS = new Set(["id", "ids", "value", "values", "header", "headers"]);
35655
- SECRET_QUALIFIERS = new Set([
35656
- "api",
35657
- "access",
35658
- "private",
35659
- "client",
35660
- "auth",
35661
- "authorization",
35662
- "secret",
35663
- "bearer",
35664
- "session",
35665
- "refresh",
35666
- "service",
35667
- "x",
35668
- "openai",
35669
- "anthropic",
35670
- "google",
35671
- "github",
35672
- "huggingface",
35673
- "aws",
35674
- "azure"
35675
- ]);
35676
- SECRET_TEXT_PATTERNS = [
35677
- {
35678
- pattern: /\bsk-ant-(?:api03-)?[A-Za-z0-9_-]{32,}/g,
35679
- replacement: "<ANTHROPIC_API_KEY_REDACTED>"
35680
- },
35681
- {
35682
- pattern: /\bsk-(?:proj-)?[A-Za-z0-9_-]{32,}/g,
35683
- replacement: "<OPENAI_API_KEY_REDACTED>"
35684
- },
35685
- {
35686
- pattern: /\bgithub_pat_[A-Za-z0-9_]{20,}/g,
35687
- replacement: "<GITHUB_PAT_REDACTED>"
35688
- },
35689
- {
35690
- pattern: /\b(?:gh[opsu]|ghr)_[A-Za-z0-9]{30,}/g,
35691
- replacement: "<GITHUB_TOKEN_REDACTED>"
35692
- },
35693
- {
35694
- pattern: /\bhf_[A-Za-z0-9]{30,}/g,
35695
- replacement: "<HUGGINGFACE_TOKEN_REDACTED>"
35696
- },
35697
- {
35698
- pattern: /\b(?:AKIA|ASIA)[0-9A-Z]{16}\b/g,
35699
- replacement: "<AWS_ACCESS_KEY_ID_REDACTED>"
35700
- },
35701
- {
35702
- pattern: /\bxox[abprsuvc]-[A-Za-z0-9-]{10,}/g,
35703
- replacement: "<SLACK_TOKEN_REDACTED>"
35704
- },
35705
- {
35706
- pattern: /\bAIza[A-Za-z0-9_-]{35}\b/g,
35707
- replacement: "<GOOGLE_API_KEY_REDACTED>"
35708
- },
35709
- {
35710
- pattern: /\b(Authorization\s*:\s*Bearer\s+)([A-Za-z0-9._~+/=-]{8,})/gi,
35711
- replacement: (_full, prefix) => `${prefix}<REDACTED:bearer>`
35712
- },
35713
- {
35714
- pattern: /\beyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g,
35715
- replacement: "<JWT_REDACTED>"
35716
- },
35717
- {
35718
- pattern: /(["'])([^"']*(?:key|token|secret|password|auth|bearer|credential)[^"']*)\1(\s*:\s*)(["'])([^"']*)\4/gi,
35719
- replacement: (full, quote, key, separator, valueQuote, value) => isNonSecretScalarValue(value) ? full : `${quote}${key}${quote}${separator}${valueQuote}<REDACTED:${redactionTypeForKey(key)}>${valueQuote}`
35720
- },
35721
- {
35722
- pattern: /\b([A-Za-z0-9_.-]*(?:key|token|secret|password|auth|bearer|credential)[A-Za-z0-9_.-]*)\s*=\s*([^\s'"`]+)/gi,
35723
- replacement: (full, key, value) => isNonSecretScalarValue(value) ? full : `${key}=<REDACTED:${redactionTypeForKey(key)}>`
35724
- }
35725
- ];
35726
- });
35727
-
35728
35979
  // ../plugin/src/features/magic-context/fail-closed-block.ts
35729
35980
  function attachFailClosedBlockingProcessEvidence(process3, evidence) {
35730
35981
  Object.defineProperties(process3, {
@@ -36043,6 +36294,20 @@ var init_compartment_parser = __esm(() => {
36043
36294
  EVENT_FIELD_REGEX = /<([a-z_]+)\s*>(.*?)<\/\1>/gs;
36044
36295
  });
36045
36296
 
36297
+ // ../plugin/src/shared/write-transaction-timing.ts
36298
+ function logSlowWriteTransaction(site, startedAt, thresholdMs = SLOW_WRITE_TRANSACTION_THRESHOLD_MS) {
36299
+ try {
36300
+ const durationMs = performance.now() - startedAt;
36301
+ if (durationMs < thresholdMs)
36302
+ return;
36303
+ log3(`[magic-context] slow write transaction: site=${site} held=${durationMs.toFixed(1)}ms`);
36304
+ } catch {}
36305
+ }
36306
+ var SLOW_WRITE_TRANSACTION_THRESHOLD_MS = 1000;
36307
+ var init_write_transaction_timing = __esm(() => {
36308
+ init_logger();
36309
+ });
36310
+
36046
36311
  // ../plugin/src/features/magic-context/storage-schema-helpers.ts
36047
36312
  function ensureColumn(db, table, column, definition) {
36048
36313
  if (!/^[a-z][a-z0-9_]*$/.test(table) || !/^[a-z][a-z0-9_]*$/.test(column) || !/^[A-Z0-9_"'(),[\]\s]+$/i.test(definition)) {
@@ -36374,6 +36639,7 @@ function runMigrations(db) {
36374
36639
  let migration;
36375
36640
  let currentVersion = 0;
36376
36641
  try {
36642
+ const transactionStartedAt = performance.now();
36377
36643
  const applied = db.transaction(() => {
36378
36644
  currentVersion = getCurrentVersion(db);
36379
36645
  migration = MIGRATIONS.find((candidate) => candidate.version > currentVersion && !isMigrationApplied(db, candidate.version));
@@ -36388,6 +36654,7 @@ function runMigrations(db) {
36388
36654
  db.prepare("INSERT INTO schema_migrations (version, description, applied_at) VALUES (?, ?, ?)").run(migration.version, migration.description, Date.now());
36389
36655
  return true;
36390
36656
  }).immediate();
36657
+ logSlowWriteTransaction("migration-runner", transactionStartedAt);
36391
36658
  if (!applied || !migration)
36392
36659
  break;
36393
36660
  if (migration.version <= 61)
@@ -36412,7 +36679,9 @@ function runMigrations(db) {
36412
36679
  }
36413
36680
  if (touchedLegacyAuthorityBatch) {
36414
36681
  try {
36682
+ const transactionStartedAt = performance.now();
36415
36683
  db.transaction(() => installLatestAuthorityTriggers(db)).immediate();
36684
+ logSlowWriteTransaction("migration-runner", transactionStartedAt);
36416
36685
  } catch (error51) {
36417
36686
  throw new Error(`Migration authority-trigger postcondition failed: ${error51 instanceof Error ? error51.message : String(error51)}. Database may need manual repair.`);
36418
36687
  }
@@ -36425,6 +36694,7 @@ var FORK_MIGRATION_VERSION_FLOOR = 1e4, MigrationLockBusyError, MIGRATIONS, LATE
36425
36694
  var init_migrations = __esm(() => {
36426
36695
  init_compartment_parser();
36427
36696
  init_logger();
36697
+ init_write_transaction_timing();
36428
36698
  init_workspaces();
36429
36699
  MigrationLockBusyError = class MigrationLockBusyError extends Error {
36430
36700
  constructor(message) {
@@ -38451,6 +38721,15 @@ var init_migrations = __esm(() => {
38451
38721
  );
38452
38722
  `);
38453
38723
  }
38724
+ },
38725
+ {
38726
+ version: 82,
38727
+ description: "record the origin of memory file-independent mappings",
38728
+ up(db) {
38729
+ if (!tableExists(db, "memory_verifications"))
38730
+ return;
38731
+ ensureColumn(db, "memory_verifications", "mapping_origin", "TEXT NOT NULL DEFAULT 'mapper'");
38732
+ }
38454
38733
  }
38455
38734
  ];
38456
38735
  LATEST_MIGRATION_VERSION = MIGRATIONS.reduce((max, m3) => Math.max(max, m3.version), 0);
@@ -38484,17 +38763,17 @@ var init_tool_owner_backfill = __esm(() => {
38484
38763
 
38485
38764
  // ../plugin/src/features/magic-context/storage-db.ts
38486
38765
  import {
38487
- chmodSync as chmodSync2,
38766
+ chmodSync as chmodSync3,
38488
38767
  copyFileSync,
38489
38768
  cpSync,
38490
38769
  existsSync as existsSync19,
38491
38770
  mkdirSync as mkdirSync7,
38492
38771
  readdirSync as readdirSync2,
38493
38772
  readFileSync as readFileSync13,
38494
- statSync as statSync8,
38773
+ statSync as statSync9,
38495
38774
  unlinkSync as unlinkSync3
38496
38775
  } from "node:fs";
38497
- import { basename as basename4, dirname as dirname11, join as join15, resolve as resolve5 } from "node:path";
38776
+ import { basename as basename4, dirname as dirname11, join as join15, resolve as resolve6 } from "node:path";
38498
38777
  function getPersistedSchemaVersion(db) {
38499
38778
  const hasMigrationsTable = db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'schema_migrations'").get();
38500
38779
  if (!hasMigrationsTable) {
@@ -39025,8 +39304,10 @@ function initializeDatabase(db) {
39025
39304
  -- verified_at=0 means "mapped (files known) but not yet content-verified".
39026
39305
  -- map-memories sets mapped_at + verified_at=0; verify sets verified_at=now.
39027
39306
  verified_at INTEGER NOT NULL,
39028
- mapped_at INTEGER NOT NULL DEFAULT 0,
39029
- PRIMARY KEY (memory_id, file_path)
39307
+ mapped_at INTEGER NOT NULL DEFAULT 0,
39308
+ -- Distinguishes mapper-authored independence from a host rejection fallback.
39309
+ mapping_origin TEXT NOT NULL DEFAULT 'mapper',
39310
+ PRIMARY KEY (memory_id, file_path)
39030
39311
  );
39031
39312
  CREATE INDEX IF NOT EXISTS idx_memory_verifications_memory ON memory_verifications(memory_id);
39032
39313
 
@@ -39810,7 +40091,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
39810
40091
  `);
39811
40092
  ensureColumn(db, "workspaces", "share_categories", `TEXT NOT NULL DEFAULT '["CONSTRAINTS"]'`);
39812
40093
  }
39813
- var databases, pendingAsyncOpens, persistenceByDatabase, persistenceErrorByDatabase, pathByDatabase, LATEST_SUPPORTED_VERSION = 81, PERMISSIONS_ENFORCEABLE, RPC_DISCOVERY_PARSE_GRACE_MS, defaultRpcDiscoveryFs, rpcDiscoveryFs, sqlitePragmaConfig, CHANNEL2_CLAIM_TTL_MS;
40094
+ var databases, pendingAsyncOpens, persistenceByDatabase, persistenceErrorByDatabase, pathByDatabase, LATEST_SUPPORTED_VERSION = 82, PERMISSIONS_ENFORCEABLE, RPC_DISCOVERY_PARSE_GRACE_MS, defaultRpcDiscoveryFs, rpcDiscoveryFs, sqlitePragmaConfig, CHANNEL2_CLAIM_TTL_MS;
39814
40095
  var init_storage_db = __esm(async () => {
39815
40096
  init_data_path();
39816
40097
  init_logger();
@@ -39833,7 +40114,7 @@ var init_storage_db = __esm(async () => {
39833
40114
  defaultRpcDiscoveryFs = {
39834
40115
  readdirSync: (path4, options) => options?.withFileTypes ? readdirSync2(path4, { withFileTypes: true }) : readdirSync2(path4),
39835
40116
  readFileSync: (path4, encoding) => String(readFileSync13(path4, encoding)),
39836
- statSync: (path4) => ({ mtimeMs: statSync8(path4).mtimeMs }),
40117
+ statSync: (path4) => ({ mtimeMs: statSync9(path4).mtimeMs }),
39837
40118
  unlinkSync: (path4) => unlinkSync3(path4)
39838
40119
  };
39839
40120
  rpcDiscoveryFs = defaultRpcDiscoveryFs;
@@ -40188,13 +40469,14 @@ function mergeMemoryRow(db, row, fromIdentity, toIdentity, mergedAt) {
40188
40469
  LIMIT 1`).get(toIdentity, row.category, row.normalized_hash, sourceId);
40189
40470
  if (collision && typeof collision.id === "number") {
40190
40471
  const targetId = collision.id;
40191
- const mergedSeen = Math.max(Number(collision.seen_count ?? 1), Number(row.seen_count ?? 1));
40472
+ const targetSeen = Number(collision.seen_count ?? 1);
40473
+ const mergedSeen = Math.max(targetSeen, Number(row.seen_count ?? 1));
40192
40474
  const sourceClassifiedAt = Number(row.classified_at ?? 0);
40193
40475
  const targetClassifiedAt = Number(collision.classified_at ?? 0);
40194
40476
  if (sourceClassifiedAt > targetClassifiedAt) {
40195
40477
  db.prepare(`UPDATE memories
40196
- SET importance = ?, scope = ?, shareable = ?, classified_at = ?
40197
- WHERE id = ?`).run(row.importance, row.scope, row.shareable, row.classified_at, targetId);
40478
+ SET importance = ?, scope = ?, shareable = ?, classified_at = ?, updated_at = ?
40479
+ WHERE id = ?`).run(row.importance, row.scope, row.shareable, row.classified_at, mergedAt, targetId);
40198
40480
  }
40199
40481
  const sourceHasCue = typeof row.mural_cue === "string" && row.mural_cue.length > 0;
40200
40482
  const targetHasCue = typeof collision.mural_cue === "string" && collision.mural_cue.length > 0;
@@ -40202,19 +40484,27 @@ function mergeMemoryRow(db, row, fromIdentity, toIdentity, mergedAt) {
40202
40484
  const targetCueAt = Number(collision.mural_cue_at ?? 0);
40203
40485
  if (sourceHasCue && (!targetHasCue || sourceCueAt > targetCueAt)) {
40204
40486
  db.prepare(`UPDATE memories
40205
- SET mural_cue = ?, mural_cue_hash = ?, mural_cue_at = ?,
40206
- mural_cue_rejection_count = ?
40207
- WHERE id = ?`).run(row.mural_cue, row.mural_cue_hash, row.mural_cue_at, row.mural_cue_rejection_count, targetId);
40208
- }
40209
- db.prepare(`INSERT INTO memory_verifications (memory_id, file_path, verified_at, mapped_at)
40210
- SELECT ?, file_path, verified_at, mapped_at
40211
- FROM memory_verifications
40212
- WHERE memory_id = ?
40213
- ON CONFLICT(memory_id, file_path) DO UPDATE SET
40214
- verified_at = MAX(memory_verifications.verified_at, excluded.verified_at),
40215
- mapped_at = MAX(memory_verifications.mapped_at, excluded.mapped_at)`).run(targetId, sourceId);
40487
+ SET mural_cue = ?, mural_cue_hash = ?, mural_cue_at = ?,
40488
+ mural_cue_rejection_count = ?, updated_at = ?
40489
+ WHERE id = ?`).run(row.mural_cue, row.mural_cue_hash, row.mural_cue_at, row.mural_cue_rejection_count, mergedAt, targetId);
40490
+ }
40491
+ db.prepare(`INSERT INTO memory_verifications
40492
+ (memory_id, file_path, verified_at, mapped_at, mapping_origin)
40493
+ SELECT ?, file_path, verified_at, mapped_at, mapping_origin
40494
+ FROM memory_verifications
40495
+ WHERE memory_id = ?
40496
+ ON CONFLICT(memory_id, file_path) DO UPDATE SET
40497
+ verified_at = MAX(memory_verifications.verified_at, excluded.verified_at),
40498
+ mapped_at = MAX(memory_verifications.mapped_at, excluded.mapped_at),
40499
+ mapping_origin = CASE
40500
+ WHEN excluded.mapped_at >= memory_verifications.mapped_at
40501
+ THEN excluded.mapping_origin
40502
+ ELSE memory_verifications.mapping_origin
40503
+ END`).run(targetId, sourceId);
40216
40504
  db.prepare("DELETE FROM memory_verifications WHERE memory_id = ?").run(sourceId);
40217
- db.prepare("UPDATE memories SET seen_count = ?, status = COALESCE(status, 'active') WHERE id = ?").run(mergedSeen, targetId);
40505
+ if (mergedSeen !== targetSeen || collision.status === null || collision.status === undefined) {
40506
+ db.prepare("UPDATE memories SET seen_count = ?, status = COALESCE(status, 'active'), updated_at = ? WHERE id = ?").run(mergedSeen, mergedAt, targetId);
40507
+ }
40218
40508
  db.prepare(`UPDATE memories
40219
40509
  SET status = 'archived',
40220
40510
  superseded_by_memory_id = ?,
@@ -40230,7 +40520,7 @@ function mergeMemoryRow(db, row, fromIdentity, toIdentity, mergedAt) {
40230
40520
  logRow(db, fromIdentity, toIdentity, "memories", String(sourceId), "superseded", String(targetId), mergedAt);
40231
40521
  return true;
40232
40522
  }
40233
- const result = db.prepare("UPDATE memories SET project_path = ? WHERE id = ? AND project_path = ?").run(toIdentity, sourceId, fromIdentity);
40523
+ const result = db.prepare("UPDATE memories SET project_path = ?, updated_at = ? WHERE id = ? AND project_path = ?").run(toIdentity, mergedAt, sourceId, fromIdentity);
40234
40524
  if ((result.changes ?? 0) === 0)
40235
40525
  return false;
40236
40526
  logRow(db, fromIdentity, toIdentity, "memories", String(sourceId), "rekeyed", null, mergedAt);
@@ -40464,15 +40754,15 @@ __export(exports_doctor_repair_db, {
40464
40754
  });
40465
40755
  import { spawnSync as spawnSync3 } from "node:child_process";
40466
40756
  import {
40467
- chmodSync as chmodSync3,
40468
- closeSync as closeSync3,
40757
+ chmodSync as chmodSync4,
40758
+ closeSync as closeSync4,
40469
40759
  constants as constants2,
40470
40760
  copyFileSync as copyFileSync2,
40471
40761
  existsSync as existsSync21,
40472
- openSync as openSync3,
40762
+ openSync as openSync4,
40473
40763
  renameSync as renameSync4,
40474
40764
  rmSync as rmSync2,
40475
- statSync as statSync9
40765
+ statSync as statSync10
40476
40766
  } from "node:fs";
40477
40767
  import { dirname as dirname12, join as join17 } from "node:path";
40478
40768
  function defaultInspectHolders(storageDir) {
@@ -40589,13 +40879,13 @@ function isRecoverCapabilityMissing(errorDetail) {
40589
40879
  function runRecoverShell(sqliteExecutable, sourcePath, recoveredPath, dumpPath) {
40590
40880
  let dumpWriteFd = null;
40591
40881
  try {
40592
- dumpWriteFd = openSync3(dumpPath, "wx", 384);
40882
+ dumpWriteFd = openSync4(dumpPath, "wx", 384);
40593
40883
  const recovered = spawnSync3(sqliteExecutable, [sourcePath, ".recover"], {
40594
40884
  stdio: ["ignore", dumpWriteFd, "pipe"],
40595
40885
  encoding: "utf8",
40596
40886
  windowsHide: true
40597
40887
  });
40598
- closeSync3(dumpWriteFd);
40888
+ closeSync4(dumpWriteFd);
40599
40889
  dumpWriteFd = null;
40600
40890
  if (recovered.error || recovered.status !== 0) {
40601
40891
  const errorDetail = sqliteError(recovered);
@@ -40607,7 +40897,7 @@ function runRecoverShell(sqliteExecutable, sourcePath, recoveredPath, dumpPath)
40607
40897
  unavailable: attempted && isRecoverCapabilityMissing(errorDetail)
40608
40898
  };
40609
40899
  }
40610
- const dumpReadFd = openSync3(dumpPath, "r");
40900
+ const dumpReadFd = openSync4(dumpPath, "r");
40611
40901
  try {
40612
40902
  const replayed = spawnSync3(sqliteExecutable, [recoveredPath], {
40613
40903
  stdio: [dumpReadFd, "ignore", "pipe"],
@@ -40623,7 +40913,7 @@ function runRecoverShell(sqliteExecutable, sourcePath, recoveredPath, dumpPath)
40623
40913
  };
40624
40914
  }
40625
40915
  } finally {
40626
- closeSync3(dumpReadFd);
40916
+ closeSync4(dumpReadFd);
40627
40917
  }
40628
40918
  return { ok: true };
40629
40919
  } catch (error51) {
@@ -40635,7 +40925,7 @@ function runRecoverShell(sqliteExecutable, sourcePath, recoveredPath, dumpPath)
40635
40925
  };
40636
40926
  } finally {
40637
40927
  if (dumpWriteFd !== null)
40638
- closeSync3(dumpWriteFd);
40928
+ closeSync4(dumpWriteFd);
40639
40929
  rmSync2(dumpPath, { force: true });
40640
40930
  }
40641
40931
  }
@@ -40856,8 +41146,8 @@ async function runRepairDb(options = {}) {
40856
41146
  return reportSafetyRefusal(prompts, dbPath, finalInspection, backup.basePath);
40857
41147
  }
40858
41148
  try {
40859
- const originalMode = statSync9(dbPath).mode & 511;
40860
- chmodSync3(recoveredPath, originalMode);
41149
+ const originalMode = statSync10(dbPath).mode & 511;
41150
+ chmodSync4(recoveredPath, originalMode);
40861
41151
  const originalAsidePath = uniqueBase(`${dbPath}.corrupt-original-${stamp}`);
40862
41152
  const moved = activateReplacement(dbPath, recoveredPath, originalAsidePath);
40863
41153
  reportSchemaTransition(prompts, salvageResult);
@@ -40904,8 +41194,8 @@ async function runRepairDb(options = {}) {
40904
41194
  return REPAIR_DB_EXIT.failed;
40905
41195
  }
40906
41196
  try {
40907
- const originalMode = statSync9(dbPath).mode & 511;
40908
- chmodSync3(freshPath, originalMode);
41197
+ const originalMode = statSync10(dbPath).mode & 511;
41198
+ chmodSync4(freshPath, originalMode);
40909
41199
  const originalAsidePath = uniqueBase(`${dbPath}.corrupt-original-${stamp}`);
40910
41200
  const moved = activateReplacement(dbPath, freshPath, originalAsidePath);
40911
41201
  reportSchemaTransition(prompts, fresh);
@@ -41036,6 +41326,18 @@ function migrationKeyFor(sourceSessionId, targetHarness) {
41036
41326
  return createHash3("sha256").update(`${sourceSessionId}
41037
41327
  ${targetHarness}`).digest("hex");
41038
41328
  }
41329
+ function moduleManagedProjectForSession(db, sessionId) {
41330
+ const tables = db.prepare("SELECT name FROM sqlite_master WHERE type = 'table' AND name IN ('authority_managed', 'session_projects')").all();
41331
+ const names = new Set(tables.flatMap((row2) => typeof row2.name === "string" ? [row2.name] : []));
41332
+ if (!names.has("authority_managed") || !names.has("session_projects"))
41333
+ return null;
41334
+ const row = db.prepare(`SELECT am.project_path
41335
+ FROM authority_managed am
41336
+ JOIN session_projects sp ON sp.project_path = am.project_path
41337
+ WHERE sp.session_id = ? AND sp.harness = 'opencode'
41338
+ LIMIT 1`).get(sessionId);
41339
+ return typeof row?.project_path === "string" ? row.project_path : null;
41340
+ }
41039
41341
  function hasMigrationJournal(db) {
41040
41342
  return Boolean(stmt(db, "SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'migration_pending'").get());
41041
41343
  }
@@ -41596,6 +41898,10 @@ function migrateOpenCodeSessionToPi(opts) {
41596
41898
  const cwd = session.directory ?? session.path ?? process.cwd();
41597
41899
  const outputDir = join19(piSessionsRoot, projectPathToPiDirSlug(cwd));
41598
41900
  const targetHarness = opts.targetHarness ?? "pi";
41901
+ const moduleManagedProject = cortexkitDb === null ? null : moduleManagedProjectForSession(cortexkitDb, session.id);
41902
+ if (moduleManagedProject) {
41903
+ throw new Error(`Migration refused: source session ${session.id} belongs to module-managed project ${moduleManagedProject}; context.db may contain only host mirrors, not the Rust engine truth. Drain authority to TypeScript with \`magic-context doctor drain-authority ${cwd}\`, then retry.`);
41904
+ }
41599
41905
  const journalActive = cortexkitDb !== null && !opts.dryRun;
41600
41906
  let recovery;
41601
41907
  let migrationKey;
@@ -43009,7 +43315,7 @@ var init_redaction2 = __esm(() => {
43009
43315
  import { execFileSync as execFileSync5, spawnSync as spawnSync5 } from "node:child_process";
43010
43316
  import { existsSync as existsSync25, mkdirSync as mkdirSync9, readFileSync as readFileSync15 } from "node:fs";
43011
43317
  import { createRequire as createRequire2 } from "node:module";
43012
- import { dirname as dirname14, join as join21, resolve as resolve6 } from "node:path";
43318
+ import { dirname as dirname14, join as join21, resolve as resolve7 } from "node:path";
43013
43319
  function parseSemver(value) {
43014
43320
  const match = value?.match(/(\d+)\.(\d+)\.(\d+)/);
43015
43321
  return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : null;
@@ -43135,8 +43441,8 @@ async function runHealthChecks(options) {
43135
43441
  if (!reportedAgentDir.ok) {
43136
43442
  add(results, "warn", "Could not verify OMP active agent directory");
43137
43443
  } else {
43138
- const reportedPath = resolve6(reportedAgentDir.stdout);
43139
- const expectedPath = resolve6(getOmpAgentDir());
43444
+ const reportedPath = resolve7(reportedAgentDir.stdout);
43445
+ const expectedPath = resolve7(getOmpAgentDir());
43140
43446
  if (reportedPath === expectedPath) {
43141
43447
  add(results, "pass", `OMP agent directory resolved to ${getOmpAgentDir()}`);
43142
43448
  } else {
@@ -43161,7 +43467,9 @@ async function runHealthChecks(options) {
43161
43467
  else
43162
43468
  for (const warning of loaded.warnings.slice(0, 5))
43163
43469
  add(results, "warn", warning);
43164
- const dbPath = join21(getMagicContextStorageDir(), "context.db");
43470
+ const storage = getMagicContextStorageResolution();
43471
+ const dbPath = join21(storage.path, "context.db");
43472
+ add(results, "info", `Shared storage: ${storage.path} (source: ${storage.source})`);
43165
43473
  if (!existsSync25(dbPath))
43166
43474
  add(results, "info", `Shared context DB will be created at ${dbPath}`);
43167
43475
  else {
@@ -43485,12 +43793,12 @@ var DEFAULT_TIMEOUT_MS = 1e4, MAX_PREVIEW_CHARS = 240;
43485
43793
 
43486
43794
  // ../plugin/src/shared/tui-config.ts
43487
43795
  import {
43488
- chmodSync as chmodSync4,
43796
+ chmodSync as chmodSync5,
43489
43797
  existsSync as existsSync26,
43490
43798
  mkdirSync as mkdirSync10,
43491
43799
  readFileSync as readFileSync16,
43492
43800
  renameSync as renameSync6,
43493
- statSync as statSync10,
43801
+ statSync as statSync11,
43494
43802
  writeFileSync as writeFileSync7
43495
43803
  } from "node:fs";
43496
43804
  import { dirname as dirname15, join as join22 } from "node:path";
@@ -43526,8 +43834,8 @@ function writeTuiConfigAtomic(configPath, config2) {
43526
43834
  const tmpPath = `${configPath}.tmp`;
43527
43835
  writeFileSync7(tmpPath, body);
43528
43836
  try {
43529
- if (statSync10(configPath, { throwIfNoEntry: false })?.isFile()) {
43530
- chmodSync4(tmpPath, statSync10(configPath).mode & 511);
43837
+ if (statSync11(configPath, { throwIfNoEntry: false })?.isFile()) {
43838
+ chmodSync5(tmpPath, statSync11(configPath).mode & 511);
43531
43839
  }
43532
43840
  } catch {}
43533
43841
  renameSync6(tmpPath, configPath);
@@ -43599,7 +43907,7 @@ var init_tui_config = __esm(() => {
43599
43907
  });
43600
43908
 
43601
43909
  // src/lib/diagnostics-opencode.ts
43602
- import { existsSync as existsSync27, readdirSync as readdirSync3, readFileSync as readFileSync17, statSync as statSync11 } from "node:fs";
43910
+ import { existsSync as existsSync27, readdirSync as readdirSync3, readFileSync as readFileSync17, statSync as statSync12 } from "node:fs";
43603
43911
  import { createRequire as createRequire3 } from "node:module";
43604
43912
  import { homedir as homedir15 } from "node:os";
43605
43913
  import { join as join23 } from "node:path";
@@ -43632,13 +43940,12 @@ function getPluginCacheInfo() {
43632
43940
  }
43633
43941
  return { path: path6, cached: cached2, latest: getSelfVersion() };
43634
43942
  }
43635
- function getStorageDir() {
43636
- const dataHome = process.env.XDG_DATA_HOME || join23(homedir15(), ".local", "share");
43637
- return join23(dataHome, "cortexkit", "magic-context");
43943
+ function getStorageResolution() {
43944
+ return getMagicContextStorageResolution();
43638
43945
  }
43639
43946
  function fileSize(path6) {
43640
43947
  try {
43641
- return existsSync27(path6) ? statSync11(path6).size : 0;
43948
+ return existsSync27(path6) ? statSync12(path6).size : 0;
43642
43949
  } catch {
43643
43950
  return 0;
43644
43951
  }
@@ -43715,7 +44022,7 @@ function listDumpsInDir(dir, limit) {
43715
44022
  return { count: 0, recent: [] };
43716
44023
  try {
43717
44024
  const entries = readdirSync3(dir).filter((name) => name.endsWith(".xml")).map((name) => {
43718
- const stat = statSync11(join23(dir, name));
44025
+ const stat = statSync12(join23(dir, name));
43719
44026
  return {
43720
44027
  name,
43721
44028
  mtime: stat.mtimeMs,
@@ -43965,10 +44272,11 @@ async function collectDiagnostics() {
43965
44272
  const opencodeConfig = readConfig3(configPaths.opencodeConfig);
43966
44273
  const tuiConfig = readConfig3(configPaths.tuiConfig);
43967
44274
  const magicContextConfig = readConfig3(configPaths.magicContextConfig);
43968
- const storageDirPath = getStorageDir();
44275
+ const storageResolution = getStorageResolution();
44276
+ const storageDirPath = storageResolution.path;
43969
44277
  const contextDbPath = join23(storageDirPath, "context.db");
43970
44278
  const logPath = getMagicContextLogPath2("opencode");
43971
- const logFileSize = existsSync27(logPath) ? statSync11(logPath).size : 0;
44279
+ const logFileSize = existsSync27(logPath) ? statSync12(logPath).size : 0;
43972
44280
  let compactionEnabled = false;
43973
44281
  try {
43974
44282
  compactionEnabled = isCompactionEnabled(loadPluginConfig(process.cwd()));
@@ -44003,6 +44311,7 @@ async function collectDiagnostics() {
44003
44311
  pluginCache: getPluginCacheInfo(),
44004
44312
  storageDir: {
44005
44313
  path: storageDirPath,
44314
+ source: storageResolution.source,
44006
44315
  exists: existsSync27(storageDirPath),
44007
44316
  contextDbSizeBytes: fileSize(contextDbPath)
44008
44317
  },
@@ -44049,6 +44358,7 @@ function renderDiagnosticsMarkdown(report) {
44049
44358
  };
44050
44359
  const storage = {
44051
44360
  path: sanitizeString(report.storageDir.path),
44361
+ source: report.storageDir.source ?? "unknown",
44052
44362
  exists: report.storageDir.exists,
44053
44363
  context_db_size: formatBytes(report.storageDir.contextDbSizeBytes)
44054
44364
  };
@@ -44166,6 +44476,66 @@ var init_diagnostics_opencode = __esm(() => {
44166
44476
  import_comment_json10 = __toESM(require_src3(), 1);
44167
44477
  });
44168
44478
 
44479
+ // ../plugin/src/features/magic-context/memory/embedding-synapse.ts
44480
+ var SYNAPSE_CERTIFICATION_REFUSAL_REASONS, factoryClients;
44481
+ var init_embedding_synapse = __esm(() => {
44482
+ init_dist5();
44483
+ init_logger();
44484
+ SYNAPSE_CERTIFICATION_REFUSAL_REASONS = new Set([
44485
+ "not_certified",
44486
+ "probe_required",
44487
+ "migration_required"
44488
+ ]);
44489
+ factoryClients = new WeakMap;
44490
+ });
44491
+
44492
+ // ../plugin/src/features/magic-context/memory/normalize-hash.ts
44493
+ var init_normalize_hash = () => {};
44494
+
44495
+ // ../plugin/src/features/magic-context/memory/embedding-identity.ts
44496
+ var init_embedding_identity = __esm(() => {
44497
+ init_magic_context();
44498
+ init_embedding_synapse();
44499
+ init_normalize_hash();
44500
+ });
44501
+
44502
+ // ../plugin/src/features/magic-context/memory/embedding-local.ts
44503
+ function currentLocalEmbeddingHost() {
44504
+ const bun = globalThis.Bun;
44505
+ const bunVersion = typeof process !== "undefined" && typeof process.versions?.bun === "string" ? process.versions.bun : undefined;
44506
+ return {
44507
+ isElectron: typeof process !== "undefined" && Boolean(process.versions?.electron),
44508
+ isBun: Boolean(bun) || Boolean(bunVersion),
44509
+ bunVersion
44510
+ };
44511
+ }
44512
+ function bunHasNapiTeardownFix(version2) {
44513
+ const match = version2?.match(/^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/);
44514
+ if (!match || match[4])
44515
+ return false;
44516
+ const parsed = [Number(match[1]), Number(match[2]), Number(match[3])];
44517
+ return parsed.some((part) => !Number.isSafeInteger(part)) ? false : parsed[0] > BUN_NAPI_TEARDOWN_FIX_VERSION[0] || parsed[0] === BUN_NAPI_TEARDOWN_FIX_VERSION[0] && (parsed[1] > BUN_NAPI_TEARDOWN_FIX_VERSION[1] || parsed[1] === BUN_NAPI_TEARDOWN_FIX_VERSION[1] && parsed[2] >= BUN_NAPI_TEARDOWN_FIX_VERSION[2]);
44518
+ }
44519
+ function resolveLocalEmbeddingRuntime(preference = "auto", host = currentLocalEmbeddingHost()) {
44520
+ if (preference === "native" || preference === "wasm")
44521
+ return preference;
44522
+ if (host.isElectron)
44523
+ return "electron";
44524
+ if (host.isBun && !bunHasNapiTeardownFix(host.bunVersion))
44525
+ return "wasm";
44526
+ return "native";
44527
+ }
44528
+ var BUN_NAPI_TEARDOWN_FIX_VERSION, STALE_LOCK_MS, MAX_LOCK_WAIT_MS;
44529
+ var init_embedding_local = __esm(() => {
44530
+ init_magic_context();
44531
+ init_data_path();
44532
+ init_logger();
44533
+ init_embedding_identity();
44534
+ BUN_NAPI_TEARDOWN_FIX_VERSION = [1, 4, 0];
44535
+ STALE_LOCK_MS = 3 * 60000;
44536
+ MAX_LOCK_WAIT_MS = 5 * 60000;
44537
+ });
44538
+
44169
44539
  // src/lib/embedding-runtime.ts
44170
44540
  import { spawnSync as spawnSync6 } from "node:child_process";
44171
44541
  import { existsSync as existsSync28 } from "node:fs";
@@ -44274,9 +44644,12 @@ function describeNativeFailure(status) {
44274
44644
  return status.state === "package-missing" ? "package is not installed" : status.state === "binary-missing" ? "expected platform binding file is absent" : `binding failed to load: ${status.reason}`;
44275
44645
  }
44276
44646
  function isLocalEmbeddingRuntimeBroken(status) {
44277
- return status.state === "both-broken" || isNativeLocalEmbeddingRuntimeFailure(status);
44647
+ return status.state === "both-broken" || status.state === "wasm-broken" || isNativeLocalEmbeddingRuntimeFailure(status);
44278
44648
  }
44279
44649
  function formatLocalEmbeddingRuntimeDoctorWarning(status) {
44650
+ if (status.state === "wasm-broken") {
44651
+ return "Embedding provider: local — configured/selected onnxruntime-web (WASM) is unavailable — " + `${status.wasmReason}. Reinstall the plugin package or select embedding.local_runtime: native ` + "only on a host where its native runtime is safe.";
44652
+ }
44280
44653
  if (status.state !== "both-broken") {
44281
44654
  return "Embedding provider: local — onnxruntime-node native binding missing — " + `${describeNativeFailure(status)}; its postinstall likely failed. Embeddings will not work. ` + "Reinstall with network access to the npm registry and GitHub releases, " + "or switch `embedding.provider` to an HTTP endpoint (`openai-compatible`).";
44282
44655
  }
@@ -44316,11 +44689,19 @@ function withWasmFallback(native, probeWasm) {
44316
44689
  }
44317
44690
  return { state: "both-broken", nativeFailure: native, wasmReason: wasm.reason };
44318
44691
  }
44692
+ function formatLocalEmbeddingRuntimeWasmSelected(status) {
44693
+ return "Embedding provider: local — onnxruntime-web (WASM) selected by embedding.local_runtime/host at " + `${status.wasmPath}. The native addon was not probed or loaded. WASM inference is slower than native.`;
44694
+ }
44319
44695
  function probeWasmRuntimeAt(installRoot) {
44320
44696
  const requireFn = createRequire4(join24(installRoot, "package.json"));
44321
44697
  return probeWasmRuntimeFromRequire(requireFn);
44322
44698
  }
44323
- function checkLocalEmbeddingRuntimeAt(installRoot, platform = process.platform, arch = process.arch) {
44699
+ function checkLocalEmbeddingRuntimeAt(installRoot, platform = process.platform, arch = process.arch, runtimePreference = "auto", host) {
44700
+ const selectedRuntime = resolveLocalEmbeddingRuntime(runtimePreference, host);
44701
+ if (selectedRuntime !== "native") {
44702
+ const wasm = probeWasmRuntimeAt(installRoot);
44703
+ return wasm.state === "ok" ? { state: "wasm-selected", wasmPath: wasm.wasmPath } : { state: "wasm-broken", wasmReason: wasm.reason };
44704
+ }
44324
44705
  const packageDir = join24(installRoot, "node_modules", "onnxruntime-node");
44325
44706
  let native;
44326
44707
  if (!existsSync28(join24(packageDir, "package.json"))) {
@@ -44339,7 +44720,7 @@ function checkLocalEmbeddingRuntimeAt(installRoot, platform = process.platform,
44339
44720
  }
44340
44721
  return withWasmFallback(native, () => probeWasmRuntimeAt(installRoot));
44341
44722
  }
44342
- function checkLocalEmbeddingRuntime(installRoots, platform = process.platform, arch = process.arch) {
44723
+ function checkLocalEmbeddingRuntime(installRoots, platform = process.platform, arch = process.arch, runtimePreference = "auto", host) {
44343
44724
  const existing = installRoots.filter((root) => existsSync28(root));
44344
44725
  if (existing.length === 0) {
44345
44726
  return {
@@ -44350,7 +44731,7 @@ function checkLocalEmbeddingRuntime(installRoots, platform = process.platform, a
44350
44731
  let firstFallback = null;
44351
44732
  let firstFailure = null;
44352
44733
  for (const root of existing) {
44353
- const status = checkLocalEmbeddingRuntimeAt(root, platform, arch);
44734
+ const status = checkLocalEmbeddingRuntimeAt(root, platform, arch, runtimePreference, host);
44354
44735
  if (status.state === "ok")
44355
44736
  return status;
44356
44737
  if (status.state === "wasm-fallback") {
@@ -44385,10 +44766,15 @@ function probeWasmRuntimeByResolution(pluginDir) {
44385
44766
  };
44386
44767
  }
44387
44768
  }
44388
- function checkLocalEmbeddingRuntimeByResolution(pluginDir, platform = process.platform, arch = process.arch) {
44769
+ function checkLocalEmbeddingRuntimeByResolution(pluginDir, platform = process.platform, arch = process.arch, runtimePreference = "auto", host) {
44389
44770
  if (!existsSync28(join24(pluginDir, "package.json"))) {
44390
44771
  return { state: "unknown", reason: "plugin package dir not found" };
44391
44772
  }
44773
+ const selectedRuntime = resolveLocalEmbeddingRuntime(runtimePreference, host);
44774
+ if (selectedRuntime !== "native") {
44775
+ const wasm = probeWasmRuntimeByResolution(pluginDir);
44776
+ return wasm.state === "ok" ? { state: "wasm-selected", wasmPath: wasm.wasmPath } : { state: "wasm-broken", wasmReason: wasm.reason };
44777
+ }
44392
44778
  let onnxDir = null;
44393
44779
  let resolveError;
44394
44780
  try {
@@ -44429,6 +44815,7 @@ function checkLocalEmbeddingRuntimeByResolution(pluginDir, platform = process.pl
44429
44815
  }
44430
44816
  var ONNX_LOAD_PROBE_TIMEOUT_MS = 1e4, ONNX_LOAD_PROBE_OUTPUT_LIMIT = 800, ONNX_LOAD_PROBE_PACKAGE_DIR_ENV = "MAGIC_CONTEXT_ONNX_RUNTIME_NODE_PACKAGE_DIR", ONNX_RUNTIME_NODE_LOAD_PROBE_SCRIPT, runOnnxRuntimeNodeLoadProbeChildForRuntime;
44431
44817
  var init_embedding_runtime = __esm(() => {
44818
+ init_embedding_local();
44432
44819
  ONNX_RUNTIME_NODE_LOAD_PROBE_SCRIPT = [
44433
44820
  'const { createRequire } = require("node:module");',
44434
44821
  'const { join } = require("node:path");',
@@ -44968,10 +45355,10 @@ import {
44968
45355
  constants as fsConstants,
44969
45356
  readFileSync as readFileSync19,
44970
45357
  renameSync as renameSync7,
44971
- statSync as statSync12,
45358
+ statSync as statSync13,
44972
45359
  writeFileSync as writeFileSync9
44973
45360
  } from "node:fs";
44974
- import { dirname as dirname17, isAbsolute as isAbsolute4, join as join27, resolve as resolve7 } from "node:path";
45361
+ import { dirname as dirname17, isAbsolute as isAbsolute5, join as join27, resolve as resolve8 } from "node:path";
44975
45362
  function warn(message) {
44976
45363
  log3(`WARN: ${message}`);
44977
45364
  }
@@ -45401,7 +45788,7 @@ var init_doctor_opencode_cache = __esm(() => {
45401
45788
 
45402
45789
  // src/commands/doctor-opencode.ts
45403
45790
  import { spawnSync as spawnSync7 } from "node:child_process";
45404
- import { existsSync as existsSync32, readFileSync as readFileSync22, statSync as statSync13 } from "node:fs";
45791
+ import { existsSync as existsSync32, readFileSync as readFileSync22, statSync as statSync14 } from "node:fs";
45405
45792
  import { createRequire as createRequire5 } from "node:module";
45406
45793
  import { homedir as homedir17 } from "node:os";
45407
45794
  import { join as join29 } from "node:path";
@@ -45623,8 +46010,12 @@ async function runIssueFlow2() {
45623
46010
  return 1;
45624
46011
  }
45625
46012
  }
45626
- function checkLocalEmbeddingRuntimeForDoctor() {
45627
- const runtime = checkLocalEmbeddingRuntime(getOpenCodePluginCacheRoots());
46013
+ function checkLocalEmbeddingRuntimeForDoctor(runtimePreference = "auto") {
46014
+ const runtime = checkLocalEmbeddingRuntime(getOpenCodePluginCacheRoots(), process.platform, process.arch, runtimePreference);
46015
+ if (runtime.state === "wasm-selected") {
46016
+ log2.info(formatLocalEmbeddingRuntimeWasmSelected(runtime));
46017
+ return { issues: 0 };
46018
+ }
45628
46019
  if (runtime.state === "wasm-fallback") {
45629
46020
  log2.warn(formatLocalEmbeddingRuntimeWasmFallback(runtime));
45630
46021
  return { issues: 0 };
@@ -45637,7 +46028,7 @@ function checkLocalEmbeddingRuntimeForDoctor() {
45637
46028
  log2.warn(`Local embedding runtime unverified: ${runtime.reason}`);
45638
46029
  return { issues: 0, unverified: true };
45639
46030
  }
45640
- log2.success("Embedding provider: local (native runtime OK; Xenova/all-MiniLM-L6-v2 bundled)");
46031
+ log2.success("Embedding provider: local (native runtime selected and OK; Xenova/all-MiniLM-L6-v2 bundled)");
45641
46032
  return { issues: 0 };
45642
46033
  }
45643
46034
  async function checkEmbeddingConfig(magicContextConfigPath) {
@@ -45672,7 +46063,8 @@ async function checkEmbeddingConfig(magicContextConfigPath) {
45672
46063
  return { issues: 0 };
45673
46064
  }
45674
46065
  if (provider === undefined || provider === "local") {
45675
- return checkLocalEmbeddingRuntimeForDoctor();
46066
+ const runtimePreference = embedding?.local_runtime === "native" || embedding?.local_runtime === "wasm" ? embedding.local_runtime : "auto";
46067
+ return checkLocalEmbeddingRuntimeForDoctor(runtimePreference);
45676
46068
  }
45677
46069
  if (provider !== "openai-compatible") {
45678
46070
  log2.warn(`Unknown embedding provider: ${String(provider)} (expected local | openai-compatible | off)`);
@@ -46164,7 +46556,9 @@ async function runDoctor2(options = {}) {
46164
46556
  warnCount++;
46165
46557
  else
46166
46558
  passCount++;
46167
- const dbPath = join29(getMagicContextStorageDir(), "context.db");
46559
+ const storage = getMagicContextStorageResolution();
46560
+ const dbPath = join29(storage.path, "context.db");
46561
+ log2.info(`Shared storage: ${storage.path} (source: ${storage.source})`);
46168
46562
  if (!existsSync32(dbPath)) {
46169
46563
  log2.info(`Shared context DB not yet created at ${dbPath} (will be created on first run)`);
46170
46564
  } else {
@@ -46288,7 +46682,7 @@ ${formatDatabaseRepairGuidance(dbPath)}`);
46288
46682
  }
46289
46683
  const logPath = getMagicContextLogPath2("opencode");
46290
46684
  if (existsSync32(logPath)) {
46291
- const logStat = statSync13(logPath);
46685
+ const logStat = statSync14(logPath);
46292
46686
  const sizeKb = (logStat.size / 1024).toFixed(0);
46293
46687
  log2.info(`Log file: ${logPath} (${sizeKb} KB)`);
46294
46688
  } else {
@@ -46370,10 +46764,8 @@ var init_doctor_opencode = __esm(async () => {
46370
46764
  });
46371
46765
 
46372
46766
  // src/lib/diagnostics-pi.ts
46373
- import { createHash as createHash5 } from "node:crypto";
46374
- import { existsSync as existsSync33, readdirSync as readdirSync5, readFileSync as readFileSync23, statSync as statSync14 } from "node:fs";
46767
+ import { existsSync as existsSync33, readdirSync as readdirSync5, readFileSync as readFileSync23, statSync as statSync15 } from "node:fs";
46375
46768
  import { createRequire as createRequire6 } from "node:module";
46376
- import { homedir as homedir18, userInfo as userInfo2 } from "node:os";
46377
46769
  import { join as join30 } from "node:path";
46378
46770
  function getSelfVersion3() {
46379
46771
  const req = createRequire6(import.meta.url);
@@ -46389,56 +46781,16 @@ function getSelfVersion3() {
46389
46781
  }
46390
46782
  function fileSize2(path6) {
46391
46783
  try {
46392
- return existsSync33(path6) ? statSync14(path6).size : 0;
46784
+ return existsSync33(path6) ? statSync15(path6).size : 0;
46393
46785
  } catch {
46394
46786
  return 0;
46395
46787
  }
46396
46788
  }
46397
- function escapeRegex3(value) {
46398
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
46399
- }
46400
- function currentUserHash() {
46401
- const username = userInfo2().username || "unknown";
46402
- return createHash5("sha256").update(username).digest("hex").slice(0, 12);
46403
- }
46404
- function redactSecretString(value) {
46405
- return redactSecretText(value).replace(/Bearer\s+[A-Za-z0-9._~+\-/=]+/g, "Bearer <REDACTED>").replace(/sk-[A-Za-z0-9_-]{12,}/g, "sk-<REDACTED>").replace(/api[_-]?key=([^\s&]+)/gi, "api_key=<REDACTED>").replace(/token=([^\s&]+)/gi, "token=<REDACTED>");
46406
- }
46407
46789
  function sanitizeString2(value) {
46408
- const home = process.env.HOME || homedir18();
46409
- const username = userInfo2().username;
46410
- const userHash = `<USER:${currentUserHash()}>`;
46411
- let sanitized = redactSecretString(value);
46412
- if (home) {
46413
- sanitized = sanitized.replace(new RegExp(escapeRegex3(home), "g"), "<HOME>");
46414
- }
46415
- sanitized = sanitized.replace(/\/Users\/[^/]+\//g, `/Users/${userHash}/`);
46416
- sanitized = sanitized.replace(/\/home\/[^/]+\//g, `/home/${userHash}/`);
46417
- sanitized = sanitized.replace(/C:\\Users\\[^\\]+\\/g, `C:\\Users\\${userHash}\\`);
46418
- if (username) {
46419
- sanitized = sanitized.replace(new RegExp(escapeRegex3(username), "g"), userHash);
46420
- }
46421
- return sanitized;
46422
- }
46423
- function shouldRedactKey(key) {
46424
- return /api[_-]?key|token|secret|password|authorization|cookie/i.test(key);
46790
+ return sanitizeDiagnosticText(value);
46425
46791
  }
46426
- function sanitizeValue2(value, key = "") {
46427
- if (value === null || typeof value === "number" || typeof value === "boolean")
46428
- return value;
46429
- if (shouldRedactKey(key))
46430
- return "<REDACTED>";
46431
- if (typeof value === "string")
46432
- return sanitizeString2(value);
46433
- if (Array.isArray(value))
46434
- return value.map((entry) => sanitizeValue2(entry));
46435
- if (value && typeof value === "object") {
46436
- return Object.fromEntries(Object.entries(value).map(([entryKey, entry]) => [
46437
- entryKey,
46438
- sanitizeValue2(entry, entryKey)
46439
- ]));
46440
- }
46441
- return value;
46792
+ function sanitizeValue2(value) {
46793
+ return sanitizeConfigValue(value);
46442
46794
  }
46443
46795
  function readJsonc(path6) {
46444
46796
  if (!existsSync33(path6))
@@ -46497,7 +46849,7 @@ function collectPiRecentSessions() {
46497
46849
  }
46498
46850
  for (const file2 of files) {
46499
46851
  try {
46500
- const mtime = statSync14(join30(slugDir, file2)).mtimeMs;
46852
+ const mtime = statSync15(join30(slugDir, file2)).mtimeMs;
46501
46853
  const sessionId = file2.replace(/\.jsonl$/, "");
46502
46854
  candidates.push({ sessionId, directory, mtime });
46503
46855
  } catch {}
@@ -46552,7 +46904,7 @@ function listDumpsInDir2(dir, limit) {
46552
46904
  return { count: 0, recent: [] };
46553
46905
  try {
46554
46906
  const entries = readdirSync5(dir).filter((name) => name.endsWith(".xml")).map((name) => {
46555
- const stat = statSync14(join30(dir, name));
46907
+ const stat = statSync15(join30(dir, name));
46556
46908
  return {
46557
46909
  name,
46558
46910
  mtime: stat.mtimeMs,
@@ -46623,10 +46975,11 @@ async function collectDiagnostics2(cwd = process.cwd()) {
46623
46975
  const userConfigPath = getPiUserConfigPath();
46624
46976
  const projectConfigPath = getProjectConfigPath(cwd);
46625
46977
  const loaded = loadPiConfig({ cwd });
46626
- const storageDirPath = getMagicContextStorageDir();
46978
+ const storageResolution = getMagicContextStorageResolution();
46979
+ const storageDirPath = storageResolution.path;
46627
46980
  const dbPath = join30(storageDirPath, "context.db");
46628
46981
  const logPath = getMagicContextLogPath2("pi");
46629
- const logFileSize = existsSync33(logPath) ? statSync14(logPath).size : 0;
46982
+ const logFileSize = existsSync33(logPath) ? statSync15(logPath).size : 0;
46630
46983
  const otherPiExtensions = packages.filter((entry) => !isPiMagicContextPackageEntry(entry)).map(describePiPackageEntry);
46631
46984
  const recentSessions = collectPiRecentSessions();
46632
46985
  const historianDumps = collectPiHistorianDumps(recentSessions);
@@ -46657,6 +47010,7 @@ async function collectDiagnostics2(cwd = process.cwd()) {
46657
47010
  loadWarnings: loaded.warnings.map(sanitizeString2),
46658
47011
  storageDir: {
46659
47012
  path: storageDirPath,
47013
+ source: storageResolution.source,
46660
47014
  exists: existsSync33(storageDirPath),
46661
47015
  contextDbSizeBytes: fileSize2(dbPath)
46662
47016
  },
@@ -46687,6 +47041,7 @@ function renderDiagnosticsMarkdown2(report) {
46687
47041
  const settings2 = sanitizeValue2(report.settings);
46688
47042
  const storage = {
46689
47043
  path: sanitizeString2(report.storageDir.path),
47044
+ source: report.storageDir.source ?? "unknown",
46690
47045
  exists: report.storageDir.exists,
46691
47046
  context_db_size: formatBytes2(report.storageDir.contextDbSizeBytes)
46692
47047
  };
@@ -46844,10 +47199,10 @@ var init_logs_pi = __esm(() => {
46844
47199
 
46845
47200
  // src/commands/doctor-pi.ts
46846
47201
  import { execFileSync as execFileSync6, spawnSync as spawnSync8 } from "node:child_process";
46847
- import { existsSync as existsSync34, mkdirSync as mkdirSync11, readdirSync as readdirSync6, readFileSync as readFileSync25, rmSync as rmSync4, statSync as statSync15 } from "node:fs";
47202
+ import { existsSync as existsSync34, mkdirSync as mkdirSync11, readdirSync as readdirSync6, readFileSync as readFileSync25, rmSync as rmSync4, statSync as statSync16 } from "node:fs";
46848
47203
  import { createRequire as createRequire7 } from "node:module";
46849
- import { homedir as homedir19 } from "node:os";
46850
- import { dirname as dirname18, isAbsolute as isAbsolute5, join as join32 } from "node:path";
47204
+ import { homedir as homedir18 } from "node:os";
47205
+ import { dirname as dirname18, isAbsolute as isAbsolute6, join as join32 } from "node:path";
46851
47206
  function depsFrom(options) {
46852
47207
  return {
46853
47208
  ...DEFAULT_DEPS5,
@@ -46969,7 +47324,7 @@ function piPluginDirCandidates(packages, cwd) {
46969
47324
  const spec = typeof entry === "string" ? entry.trim() : "";
46970
47325
  if (!spec || spec.startsWith("npm:"))
46971
47326
  continue;
46972
- const resolved = isAbsolute5(spec) ? spec : join32(agentDir, spec);
47327
+ const resolved = isAbsolute6(spec) ? spec : join32(agentDir, spec);
46973
47328
  dirs.push(resolved);
46974
47329
  }
46975
47330
  dirs.push(join32(agentDir, "npm", "node_modules", PACKAGE_NAME2));
@@ -47066,7 +47421,7 @@ function pinnedVersionFromPackageSpecifier(specifier) {
47066
47421
  }
47067
47422
  function cacheRoots(cwd) {
47068
47423
  const home = process.env.HOME?.trim();
47069
- const cacheHome = process.env.XDG_CACHE_HOME || join32(home || homedir19(), ".cache");
47424
+ const cacheHome = process.env.XDG_CACHE_HOME || join32(home || homedir18(), ".cache");
47070
47425
  const piCacheRoot = getPiCacheRoot();
47071
47426
  return [
47072
47427
  join32(piCacheRoot, "extensions"),
@@ -47085,7 +47440,7 @@ function findPiMagicContextCacheDirs(cwd, expectedVersion, force = false) {
47085
47440
  return;
47086
47441
  let stat;
47087
47442
  try {
47088
- stat = statSync15(path6);
47443
+ stat = statSync16(path6);
47089
47444
  } catch {
47090
47445
  return;
47091
47446
  }
@@ -47221,8 +47576,10 @@ async function runHealthChecks2(options) {
47221
47576
  } else if (historianModel.startsWith("github-copilot/") && historianThinkingLevel) {
47222
47577
  add2(results, "pass", `historian.model "${historianModel}" has thinking_level "${historianThinkingLevel}" configured`);
47223
47578
  }
47224
- const storageDir = getMagicContextStorageDir();
47579
+ const storage = getMagicContextStorageResolution();
47580
+ const storageDir = storage.path;
47225
47581
  const dbPath = join32(storageDir, "context.db");
47582
+ add2(results, "info", `Shared storage: ${storageDir} (source: ${storage.source})`);
47226
47583
  const existedBeforeOpen = existsSync34(dbPath);
47227
47584
  if (existedBeforeOpen)
47228
47585
  add2(results, "pass", `Shared context DB exists at ${dbPath}`);
@@ -47319,9 +47676,14 @@ ${formatDatabaseRepairGuidance(dbPath)}`);
47319
47676
  let runtimeReported = false;
47320
47677
  let runtimeUnverifiedReason = "no installed plugin tree found to inspect";
47321
47678
  for (const pluginDir of piPluginDirCandidates(packages, options.cwd)) {
47322
- const runtime = checkLocalEmbeddingRuntimeByResolution(pluginDir);
47679
+ const runtime = checkLocalEmbeddingRuntimeByResolution(pluginDir, process.platform, process.arch, loadedConfig.config.embedding.provider === "local" ? loadedConfig.config.embedding.local_runtime : "auto", { isBun: false, isElectron: false });
47680
+ if (runtime.state === "wasm-selected") {
47681
+ add2(results, "info", formatLocalEmbeddingRuntimeWasmSelected(runtime));
47682
+ runtimeReported = true;
47683
+ break;
47684
+ }
47323
47685
  if (runtime.state === "ok") {
47324
- add2(results, "pass", `Embedding provider: ${loadedConfig.config.embedding.provider} (native runtime OK)`);
47686
+ add2(results, "pass", `Embedding provider: ${loadedConfig.config.embedding.provider} (native runtime selected and OK)`);
47325
47687
  runtimeReported = true;
47326
47688
  break;
47327
47689
  }
@@ -47339,7 +47701,7 @@ ${formatDatabaseRepairGuidance(dbPath)}`);
47339
47701
  runtimeUnverifiedReason = runtime.reason;
47340
47702
  }
47341
47703
  if (!runtimeReported) {
47342
- add2(results, "warn", `Embedding provider ${loadedConfig.config.embedding.provider}: native runtime unverified (${runtimeUnverifiedReason})`);
47704
+ add2(results, "warn", `Embedding provider ${loadedConfig.config.embedding.provider}: selected runtime unverified (${runtimeUnverifiedReason})`);
47343
47705
  }
47344
47706
  }
47345
47707
  const piEntries = packages.filter(isPiMagicContextPackageEntry).map(describePiPackageEntry);
@@ -47366,7 +47728,7 @@ ${formatDatabaseRepairGuidance(dbPath)}`);
47366
47728
  }
47367
47729
  const logPath = getMagicContextLogPath2("pi");
47368
47730
  if (existsSync34(logPath)) {
47369
- const stat = statSync15(logPath);
47731
+ const stat = statSync16(logPath);
47370
47732
  const sizeKb = (stat.size / 1024).toFixed(0);
47371
47733
  const lines = readFileSync25(logPath, "utf-8").split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
47372
47734
  add2(results, "info", `Log file: ${logPath} (${sizeKb} KB)`);