memorix 1.9.1 → 1.9.3

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 (46) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +17 -4
  3. package/README.zh-CN.md +8 -4
  4. package/dist/cli/index.js +448 -243
  5. package/dist/index.js +302 -165
  6. package/dist/maintenance-runner.js +194 -98
  7. package/dist/media-audio-runner.js +196 -100
  8. package/dist/media-video-runner.js +194 -98
  9. package/dist/memcode-runtime/CHANGELOG.md +22 -0
  10. package/dist/sdk.js +301 -164
  11. package/dist/vector-backfill-runner.js +194 -98
  12. package/docs/AGENT_OPERATOR_PLAYBOOK.md +15 -0
  13. package/docs/ARCHITECTURE.md +23 -0
  14. package/docs/DEVELOPMENT.md +1 -1
  15. package/docs/INTEGRATIONS.md +4 -0
  16. package/docs/PERFORMANCE.md +50 -0
  17. package/docs/README.md +1 -1
  18. package/docs/SETUP.md +5 -0
  19. package/package.json +1 -2
  20. package/plugins/antigravity/memorix/plugin.json +1 -1
  21. package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
  22. package/plugins/codebuddy/memorix/.codebuddy-plugin/plugin.json +1 -1
  23. package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
  24. package/plugins/copilot/memorix/plugin.json +1 -1
  25. package/plugins/gemini/memorix/gemini-extension.json +1 -1
  26. package/plugins/hermes/memorix/plugin.yaml +1 -1
  27. package/plugins/omp/memorix/package.json +1 -1
  28. package/plugins/openclaw/memorix/.codex-plugin/plugin.json +1 -1
  29. package/plugins/pi/memorix/package.json +1 -1
  30. package/server.json +2 -2
  31. package/src/cli/commands/doctor.ts +78 -17
  32. package/src/cli/commands/memory.ts +2 -1
  33. package/src/cli/default-mode.ts +15 -0
  34. package/src/cli/index.ts +10 -1
  35. package/src/codegraph/lite-provider.ts +10 -1
  36. package/src/dashboard/maintenance.ts +11 -2
  37. package/src/memory/consolidation.ts +15 -6
  38. package/src/store/mini-skill-store.ts +31 -22
  39. package/src/store/obs-store.ts +46 -30
  40. package/src/store/session-store.ts +35 -21
  41. package/src/store/sqlite-db.ts +16 -7
  42. package/src/store/sqlite-reliability.ts +87 -0
  43. package/src/store/sqlite-store.ts +4 -1
  44. package/assets/star-history-dark.svg +0 -30
  45. package/assets/star-history-light.svg +0 -30
  46. package/assets/star-history.json +0 -712
package/dist/cli/index.js CHANGED
@@ -3232,7 +3232,7 @@ ${import_picocolors.default.gray(m3)} ${s4}
3232
3232
 
3233
3233
  // src/cli/version.ts
3234
3234
  function getCliVersion() {
3235
- return true ? "1.9.1" : pkg.version;
3235
+ return true ? "1.9.3" : pkg.version;
3236
3236
  }
3237
3237
  var init_version = __esm({
3238
3238
  "src/cli/version.ts"() {
@@ -9515,70 +9515,79 @@ function getDatabase(dataDir) {
9515
9515
  loadBetterSqlite3();
9516
9516
  fs.mkdirSync(dataDir, { recursive: true });
9517
9517
  const dbPath = path3.join(dataDir, "memorix.db");
9518
- const db2 = createDatabase(dbPath);
9519
- db2.pragma("journal_mode = WAL");
9520
- db2.pragma("busy_timeout = 5000");
9521
- db2.pragma("foreign_keys = ON");
9522
- db2.exec(CREATE_OBSERVATIONS_TABLE);
9523
- db2.exec(CREATE_MINI_SKILLS_TABLE);
9524
- db2.exec(CREATE_SESSIONS_TABLE);
9525
- db2.exec(CREATE_META_TABLE);
9526
- db2.exec(CREATE_TEAM_AGENTS_TABLE);
9527
- db2.exec(CREATE_TEAM_TASKS_TABLE);
9528
- db2.exec(CREATE_TEAM_TASK_DEPS_TABLE);
9529
- db2.exec(CREATE_TEAM_MESSAGES_TABLE);
9530
- db2.exec(CREATE_TEAM_LOCKS_TABLE);
9531
- db2.exec(CREATE_TEAM_ROLES_TABLE);
9532
- db2.exec(CREATE_GRAPH_ENTITIES_TABLE);
9533
- db2.exec(CREATE_GRAPH_RELATIONS_TABLE);
9534
- db2.exec(CREATE_CHAT_TRANSCRIPT_TABLE);
9535
- db2.exec(CREATE_CODE_FILES_TABLE);
9536
- db2.exec(CREATE_CODE_SYMBOLS_TABLE);
9537
- db2.exec(CREATE_CODE_EDGES_TABLE);
9538
- db2.exec(CREATE_OBSERVATION_CODE_REFS_TABLE);
9539
- db2.exec(CREATE_MAINTENANCE_JOBS_TABLE);
9540
- db2.exec(CREATE_MAINTENANCE_TARGETS_TABLE);
9541
- db2.exec(CREATE_COMPACTION_CHECKPOINTS_TABLE);
9518
+ let db2;
9542
9519
  try {
9543
- db2.exec(`ALTER TABLE mini_skills ADD COLUMN sourceSnapshot TEXT NOT NULL DEFAULT ''`);
9544
- } catch {
9545
- }
9546
- try {
9547
- db2.exec(`ALTER TABLE mini_skills ADD COLUMN updatedAt TEXT`);
9548
- } catch {
9549
- }
9550
- try {
9551
- db2.exec(`ALTER TABLE observations ADD COLUMN createdByAgentId TEXT`);
9552
- } catch {
9553
- }
9554
- try {
9555
- db2.exec(`ALTER TABLE observations ADD COLUMN writeGeneration INTEGER DEFAULT 0`);
9556
- } catch {
9557
- }
9558
- try {
9559
- db2.exec(`ALTER TABLE team_tasks ADD COLUMN required_role TEXT`);
9560
- } catch {
9561
- }
9562
- try {
9563
- db2.exec(`ALTER TABLE team_tasks ADD COLUMN preferred_role TEXT`);
9564
- } catch {
9565
- }
9566
- try {
9567
- db2.exec(`ALTER TABLE team_messages ADD COLUMN to_role TEXT`);
9568
- } catch {
9569
- }
9570
- try {
9571
- db2.exec(`ALTER TABLE team_messages ADD COLUMN handoff_status TEXT`);
9572
- } catch {
9520
+ db2 = createDatabase(dbPath);
9521
+ db2.pragma("busy_timeout = 5000");
9522
+ db2.pragma("journal_mode = WAL");
9523
+ db2.pragma("foreign_keys = ON");
9524
+ db2.exec(CREATE_OBSERVATIONS_TABLE);
9525
+ db2.exec(CREATE_MINI_SKILLS_TABLE);
9526
+ db2.exec(CREATE_SESSIONS_TABLE);
9527
+ db2.exec(CREATE_META_TABLE);
9528
+ db2.exec(CREATE_TEAM_AGENTS_TABLE);
9529
+ db2.exec(CREATE_TEAM_TASKS_TABLE);
9530
+ db2.exec(CREATE_TEAM_TASK_DEPS_TABLE);
9531
+ db2.exec(CREATE_TEAM_MESSAGES_TABLE);
9532
+ db2.exec(CREATE_TEAM_LOCKS_TABLE);
9533
+ db2.exec(CREATE_TEAM_ROLES_TABLE);
9534
+ db2.exec(CREATE_GRAPH_ENTITIES_TABLE);
9535
+ db2.exec(CREATE_GRAPH_RELATIONS_TABLE);
9536
+ db2.exec(CREATE_CHAT_TRANSCRIPT_TABLE);
9537
+ db2.exec(CREATE_CODE_FILES_TABLE);
9538
+ db2.exec(CREATE_CODE_SYMBOLS_TABLE);
9539
+ db2.exec(CREATE_CODE_EDGES_TABLE);
9540
+ db2.exec(CREATE_OBSERVATION_CODE_REFS_TABLE);
9541
+ db2.exec(CREATE_MAINTENANCE_JOBS_TABLE);
9542
+ db2.exec(CREATE_MAINTENANCE_TARGETS_TABLE);
9543
+ db2.exec(CREATE_COMPACTION_CHECKPOINTS_TABLE);
9544
+ try {
9545
+ db2.exec(`ALTER TABLE mini_skills ADD COLUMN sourceSnapshot TEXT NOT NULL DEFAULT ''`);
9546
+ } catch {
9547
+ }
9548
+ try {
9549
+ db2.exec(`ALTER TABLE mini_skills ADD COLUMN updatedAt TEXT`);
9550
+ } catch {
9551
+ }
9552
+ try {
9553
+ db2.exec(`ALTER TABLE observations ADD COLUMN createdByAgentId TEXT`);
9554
+ } catch {
9555
+ }
9556
+ try {
9557
+ db2.exec(`ALTER TABLE observations ADD COLUMN writeGeneration INTEGER DEFAULT 0`);
9558
+ } catch {
9559
+ }
9560
+ try {
9561
+ db2.exec(`ALTER TABLE team_tasks ADD COLUMN required_role TEXT`);
9562
+ } catch {
9563
+ }
9564
+ try {
9565
+ db2.exec(`ALTER TABLE team_tasks ADD COLUMN preferred_role TEXT`);
9566
+ } catch {
9567
+ }
9568
+ try {
9569
+ db2.exec(`ALTER TABLE team_messages ADD COLUMN to_role TEXT`);
9570
+ } catch {
9571
+ }
9572
+ try {
9573
+ db2.exec(`ALTER TABLE team_messages ADD COLUMN handoff_status TEXT`);
9574
+ } catch {
9575
+ }
9576
+ applySchemaMigrations(db2);
9577
+ db2.exec(CREATE_INDEXES);
9578
+ initializeObservationLexicalIndex(db2);
9579
+ db2.prepare(`INSERT OR IGNORE INTO meta (key, value) VALUES ('storage_generation', '0')`).run();
9580
+ db2.prepare(`INSERT OR IGNORE INTO meta (key, value) VALUES ('next_id', '1')`).run();
9581
+ db2.prepare(`INSERT OR IGNORE INTO meta (key, value) VALUES ('mini_skills_generation', '0')`).run();
9582
+ _dbCache.set(normalized, db2);
9583
+ return db2;
9584
+ } catch (error40) {
9585
+ try {
9586
+ db2?.close();
9587
+ } catch {
9588
+ }
9589
+ throw error40;
9573
9590
  }
9574
- applySchemaMigrations(db2);
9575
- db2.exec(CREATE_INDEXES);
9576
- initializeObservationLexicalIndex(db2);
9577
- db2.prepare(`INSERT OR IGNORE INTO meta (key, value) VALUES ('storage_generation', '0')`).run();
9578
- db2.prepare(`INSERT OR IGNORE INTO meta (key, value) VALUES ('next_id', '1')`).run();
9579
- db2.prepare(`INSERT OR IGNORE INTO meta (key, value) VALUES ('mini_skills_generation', '0')`).run();
9580
- _dbCache.set(normalized, db2);
9581
- return db2;
9582
9591
  }
9583
9592
  function closeAllDatabases() {
9584
9593
  for (const [key, db2] of _dbCache) {
@@ -10568,6 +10577,74 @@ CREATE UNIQUE INDEX IF NOT EXISTS idx_maintenance_jobs_active_dedupe
10568
10577
  }
10569
10578
  });
10570
10579
 
10580
+ // src/store/sqlite-reliability.ts
10581
+ function isTransientSqliteError(error40) {
10582
+ const code = error40?.code;
10583
+ if (typeof code === "string") {
10584
+ return /^SQLITE_BUSY(?:_|$)/i.test(code);
10585
+ }
10586
+ return error40 instanceof Error && /\bdatabase is locked\b|\bdatabase is busy\b/i.test(error40.message);
10587
+ }
10588
+ function isSqliteUnavailableError(error40) {
10589
+ return error40 instanceof SqliteUnavailableError || error40 instanceof Error && /SQLite is not available|better-sqlite3.*failed|node:sqlite.*failed|bun:sqlite.*failed/i.test(error40.message);
10590
+ }
10591
+ function degradedReadError(storeName) {
10592
+ return new Error(`[memorix] Cannot read ${storeName}: SQLite backend unavailable (memory is not loaded)`);
10593
+ }
10594
+ function degradedWriteError(storeName) {
10595
+ return new Error(`[memorix] Cannot write ${storeName}: SQLite backend unavailable (degraded mode; read-only)`);
10596
+ }
10597
+ function formatSqliteFailure(error40) {
10598
+ return error40 instanceof Error && error40.message ? error40.message : String(error40);
10599
+ }
10600
+ function delay(ms2) {
10601
+ return new Promise((resolve9) => setTimeout(resolve9, ms2));
10602
+ }
10603
+ async function retrySqliteBusy(operation, label) {
10604
+ for (let attempt = 0; ; attempt++) {
10605
+ try {
10606
+ return await operation();
10607
+ } catch (error40) {
10608
+ if (!isTransientSqliteError(error40) || attempt >= SQLITE_BUSY_RETRY_DELAYS_MS.length) throw error40;
10609
+ const waitMs = SQLITE_BUSY_RETRY_DELAYS_MS[attempt];
10610
+ console.error(
10611
+ `[memorix] ${label} SQLite busy (attempt ${attempt + 1}/${SQLITE_BUSY_RETRY_DELAYS_MS.length + 1}), retrying in ${waitMs}ms`
10612
+ );
10613
+ await delay(waitMs);
10614
+ }
10615
+ }
10616
+ }
10617
+ async function initializeSqliteStore(factory, dataDir, label) {
10618
+ try {
10619
+ loadBetterSqlite3();
10620
+ } catch (error40) {
10621
+ throw new SqliteUnavailableError(error40);
10622
+ }
10623
+ return retrySqliteBusy(async () => {
10624
+ const store2 = factory();
10625
+ await store2.init(dataDir);
10626
+ return store2;
10627
+ }, label);
10628
+ }
10629
+ var SQLITE_BUSY_RETRY_DELAYS_MS, SqliteUnavailableError;
10630
+ var init_sqlite_reliability = __esm({
10631
+ "src/store/sqlite-reliability.ts"() {
10632
+ "use strict";
10633
+ init_esm_shims();
10634
+ init_sqlite_db();
10635
+ SQLITE_BUSY_RETRY_DELAYS_MS = [50, 150, 400, 1e3, 2500];
10636
+ SqliteUnavailableError = class extends Error {
10637
+ code = "MEMORIX_SQLITE_UNAVAILABLE";
10638
+ constructor(cause) {
10639
+ super(
10640
+ cause instanceof Error && cause.message ? cause.message : "[memorix] SQLite is unavailable (install a supported SQLite runtime)"
10641
+ );
10642
+ this.name = "SqliteUnavailableError";
10643
+ }
10644
+ };
10645
+ }
10646
+ });
10647
+
10571
10648
  // src/store/file-lock.ts
10572
10649
  import { promises as fs2 } from "fs";
10573
10650
  import { randomUUID } from "crypto";
@@ -11065,16 +11142,18 @@ async function initMiniSkillStore(dataDir) {
11065
11142
  if (_store && _storeDataDir === dataDir) return _store;
11066
11143
  _store = null;
11067
11144
  _storeDataDir = null;
11145
+ let degradedReason = "SQLite runtime unavailable";
11068
11146
  try {
11069
- const store3 = new MiniSkillSqliteStore();
11070
- await store3.init(dataDir);
11147
+ const store3 = await initializeSqliteStore(() => new MiniSkillSqliteStore(), dataDir, "Mini-skill store");
11071
11148
  _store = store3;
11072
11149
  _storeDataDir = dataDir;
11073
11150
  return store3;
11074
11151
  } catch (err) {
11075
- console.error(`[memorix] MiniSkillSqliteStore unavailable, running in degraded read-only mode: ${err instanceof Error ? err.message : err}`);
11152
+ if (!isSqliteUnavailableError(err)) throw err;
11153
+ degradedReason = err instanceof Error ? err.message : String(err);
11154
+ console.error(`[memorix] MiniSkillSqliteStore unavailable, running in degraded read-only mode: ${degradedReason}`);
11076
11155
  }
11077
- const store2 = new MiniSkillGracefulDegrade();
11156
+ const store2 = new MiniSkillGracefulDegrade(degradedReason);
11078
11157
  await store2.init(dataDir);
11079
11158
  _store = store2;
11080
11159
  _storeDataDir = dataDir;
@@ -11086,6 +11165,7 @@ var init_mini_skill_store = __esm({
11086
11165
  "use strict";
11087
11166
  init_esm_shims();
11088
11167
  init_sqlite_db();
11168
+ init_sqlite_reliability();
11089
11169
  MiniSkillSqliteStore = class {
11090
11170
  db = null;
11091
11171
  dataDir = "";
@@ -11194,7 +11274,7 @@ var init_mini_skill_store = __esm({
11194
11274
  * SQLite serializes write transactions, so concurrent calls are safely sequenced.
11195
11275
  */
11196
11276
  async atomicInsertWithId(skillWithoutId) {
11197
- const result = this.db.transaction(() => {
11277
+ return retrySqliteBusy(async () => this.db.transaction(() => {
11198
11278
  const row = this.stmtGetMeta.get("mini_skills_next_id");
11199
11279
  const nextId2 = row ? parseInt(row.value, 10) : 1;
11200
11280
  const skill2 = { ...skillWithoutId, id: nextId2 };
@@ -11203,8 +11283,7 @@ var init_mini_skill_store = __esm({
11203
11283
  this.stmtBumpGeneration.run();
11204
11284
  this.knownGeneration = this.readGeneration();
11205
11285
  return skill2;
11206
- })();
11207
- return result;
11286
+ })(), "Mini-skill promotion");
11208
11287
  }
11209
11288
  // ── Freshness ────────────────────────────────────────────────────
11210
11289
  async ensureFresh() {
@@ -11223,10 +11302,17 @@ var init_mini_skill_store = __esm({
11223
11302
  }
11224
11303
  };
11225
11304
  MiniSkillGracefulDegrade = class {
11305
+ constructor(reason = "SQLite runtime unavailable") {
11306
+ this.reason = reason;
11307
+ }
11308
+ reason;
11226
11309
  warned = false;
11310
+ unavailableRead() {
11311
+ return degradedReadError("mini-skills");
11312
+ }
11227
11313
  warn() {
11228
11314
  if (!this.warned) {
11229
- console.error("[memorix] MiniSkillStore: SQLite unavailable \u2014 mini-skills are disabled (read-only empty). Install better-sqlite3 for full functionality.");
11315
+ console.error("[memorix] MiniSkillStore: SQLite unavailable \u2014 mini-skills cannot be read or written. Install a supported SQLite runtime.");
11230
11316
  this.warned = true;
11231
11317
  }
11232
11318
  }
@@ -11234,28 +11320,33 @@ var init_mini_skill_store = __esm({
11234
11320
  this.warn();
11235
11321
  }
11236
11322
  async loadAll() {
11237
- return [];
11323
+ throw this.unavailableRead();
11238
11324
  }
11239
11325
  async loadByProject(_projectId) {
11240
- return [];
11326
+ throw this.unavailableRead();
11241
11327
  }
11242
11328
  async loadIdCounter() {
11243
- return 1;
11329
+ throw this.unavailableRead();
11244
11330
  }
11245
11331
  async insert(_skill) {
11246
11332
  this.warn();
11333
+ throw degradedWriteError("mini-skills");
11247
11334
  }
11248
11335
  async update(_skill) {
11249
11336
  this.warn();
11337
+ throw degradedWriteError("mini-skills");
11250
11338
  }
11251
11339
  async remove(_id) {
11252
11340
  this.warn();
11341
+ throw degradedWriteError("mini-skills");
11253
11342
  }
11254
11343
  async saveIdCounter(_nextId) {
11344
+ this.warn();
11345
+ throw degradedWriteError("mini-skills");
11255
11346
  }
11256
11347
  async atomicInsertWithId(skillWithoutId) {
11257
11348
  this.warn();
11258
- return { ...skillWithoutId, id: 0 };
11349
+ throw degradedWriteError("mini-skills");
11259
11350
  }
11260
11351
  async ensureFresh() {
11261
11352
  return false;
@@ -11266,6 +11357,9 @@ var init_mini_skill_store = __esm({
11266
11357
  getBackendName() {
11267
11358
  return "degraded";
11268
11359
  }
11360
+ getBackendReason() {
11361
+ return this.reason;
11362
+ }
11269
11363
  };
11270
11364
  _store = null;
11271
11365
  _storeDataDir = null;
@@ -23207,10 +23301,10 @@ async function fetchWithRetry(url2, apiKey, body, options = {}, attempt = 0, nat
23207
23301
  );
23208
23302
  }
23209
23303
  if (options.retry !== false && (response.status === 429 || response.status >= 500) && attempt < MAX_RETRIES2) {
23210
- const delay2 = BASE_DELAY_MS * Math.pow(2, attempt);
23304
+ const delay3 = BASE_DELAY_MS * Math.pow(2, attempt);
23211
23305
  const retryAfter = response.headers.get("retry-after");
23212
23306
  const parsedRetryAfter = retryAfter ? parseInt(retryAfter, 10) * 1e3 : NaN;
23213
- const waitMs = Number.isFinite(parsedRetryAfter) ? parsedRetryAfter : delay2;
23307
+ const waitMs = Number.isFinite(parsedRetryAfter) ? parsedRetryAfter : delay3;
23214
23308
  console.error(`[memorix] Embedding API ${response.status}, retry ${attempt + 1}/${MAX_RETRIES2} in ${waitMs}ms`);
23215
23309
  await waitForRetry(waitMs, options.signal);
23216
23310
  return fetchWithRetry(url2, apiKey, body, options, attempt + 1, nativeGemini);
@@ -25242,6 +25336,7 @@ var init_sqlite_store = __esm({
25242
25336
  "use strict";
25243
25337
  init_esm_shims();
25244
25338
  init_sqlite_db();
25339
+ init_sqlite_reliability();
25245
25340
  init_sqlite_fts();
25246
25341
  SqliteBackend = class {
25247
25342
  db = null;
@@ -25519,7 +25614,9 @@ var init_sqlite_store = __esm({
25519
25614
  // ── Compound atomic operation ────────────────────────────────────
25520
25615
  async atomic(fn2) {
25521
25616
  const run = this._atomicQueue.catch(() => void 0).then(async () => {
25522
- this.db.prepare("BEGIN IMMEDIATE").run();
25617
+ await retrySqliteBusy(async () => {
25618
+ this.db.prepare("BEGIN IMMEDIATE").run();
25619
+ }, "Observation atomic write");
25523
25620
  try {
25524
25621
  const tx = {
25525
25622
  loadAll: async () => this.rawLoadAll(),
@@ -25618,15 +25715,15 @@ function resetObservationStore() {
25618
25715
  async function createObservationStore(dataDir) {
25619
25716
  try {
25620
25717
  const { SqliteBackend: SqliteBackend2 } = await Promise.resolve().then(() => (init_sqlite_store(), sqlite_store_exports));
25621
- const store3 = new SqliteBackend2();
25622
- await store3.init(dataDir);
25623
- return store3;
25718
+ return await initializeSqliteStore(() => new SqliteBackend2(), dataDir, "Observation store");
25624
25719
  } catch (err) {
25625
- console.error(`[memorix] SQLite backend unavailable \u2014 degraded mode (read-only): ${err instanceof Error ? err.message : err}`);
25720
+ if (!isSqliteUnavailableError(err)) throw err;
25721
+ const reason = formatSqliteFailure(err);
25722
+ console.error(`[memorix] SQLite module unavailable \u2014 degraded mode (reads/writes disabled): ${reason}`);
25723
+ const degraded = new DegradedBackend(reason);
25724
+ await degraded.init(dataDir);
25725
+ return degraded;
25626
25726
  }
25627
- const store2 = new DegradedBackend();
25628
- await store2.init(dataDir);
25629
- return store2;
25630
25727
  }
25631
25728
  async function initObservationStore(dataDir) {
25632
25729
  if (_store2 && _storeDataDir2 === dataDir) {
@@ -25650,36 +25747,44 @@ var init_obs_store = __esm({
25650
25747
  "src/store/obs-store.ts"() {
25651
25748
  "use strict";
25652
25749
  init_esm_shims();
25750
+ init_sqlite_reliability();
25653
25751
  _store2 = null;
25654
25752
  _storeDataDir2 = null;
25655
25753
  DegradedBackend = class {
25754
+ constructor(reason = "SQLite runtime unavailable") {
25755
+ this.reason = reason;
25756
+ }
25757
+ reason;
25656
25758
  dataDir = "";
25759
+ unavailableRead() {
25760
+ return degradedReadError("observations");
25761
+ }
25657
25762
  async init(dataDir) {
25658
25763
  this.dataDir = dataDir;
25659
25764
  }
25660
25765
  async loadAll() {
25661
- return [];
25766
+ throw this.unavailableRead();
25662
25767
  }
25663
25768
  async loadByProject(_projectId, _options) {
25664
- return [];
25769
+ throw this.unavailableRead();
25665
25770
  }
25666
25771
  async countByProject(_projectId, _options) {
25667
- return 0;
25772
+ throw this.unavailableRead();
25668
25773
  }
25669
25774
  async getById(_id) {
25670
- return void 0;
25775
+ throw this.unavailableRead();
25671
25776
  }
25672
25777
  async loadIdCounter() {
25673
- return 1;
25778
+ throw this.unavailableRead();
25674
25779
  }
25675
25780
  async countAll() {
25676
- return 0;
25781
+ throw this.unavailableRead();
25677
25782
  }
25678
25783
  async listProjectIds() {
25679
- return [];
25784
+ throw this.unavailableRead();
25680
25785
  }
25681
25786
  async searchLexical(_options) {
25682
- return [];
25787
+ throw this.unavailableRead();
25683
25788
  }
25684
25789
  hasLexicalIndex() {
25685
25790
  return false;
@@ -25688,25 +25793,25 @@ var init_obs_store = __esm({
25688
25793
  return false;
25689
25794
  }
25690
25795
  async insert(_obs) {
25691
- throw new Error("[memorix] Cannot write observations: SQLite backend unavailable (degraded mode)");
25796
+ throw degradedWriteError("observations");
25692
25797
  }
25693
25798
  async update(_obs) {
25694
- throw new Error("[memorix] Cannot write observations: SQLite backend unavailable (degraded mode)");
25799
+ throw degradedWriteError("observations");
25695
25800
  }
25696
25801
  async remove(_id) {
25697
- throw new Error("[memorix] Cannot write observations: SQLite backend unavailable (degraded mode)");
25802
+ throw degradedWriteError("observations");
25698
25803
  }
25699
25804
  async bulkReplace(_obs) {
25700
- throw new Error("[memorix] Cannot write observations: SQLite backend unavailable (degraded mode)");
25805
+ throw degradedWriteError("observations");
25701
25806
  }
25702
25807
  async bulkRemoveByIds(_ids) {
25703
- throw new Error("[memorix] Cannot write observations: SQLite backend unavailable (degraded mode)");
25808
+ throw degradedWriteError("observations");
25704
25809
  }
25705
25810
  async saveIdCounter(_nextId) {
25706
- throw new Error("[memorix] Cannot write observations: SQLite backend unavailable (degraded mode)");
25811
+ throw degradedWriteError("observations");
25707
25812
  }
25708
25813
  async atomic(_fn) {
25709
- throw new Error("[memorix] Cannot write observations: SQLite backend unavailable (degraded mode)");
25814
+ throw degradedWriteError("observations");
25710
25815
  }
25711
25816
  async ensureFresh() {
25712
25817
  return false;
@@ -25719,6 +25824,9 @@ var init_obs_store = __esm({
25719
25824
  getBackendName() {
25720
25825
  return "degraded";
25721
25826
  }
25827
+ getBackendReason() {
25828
+ return this.reason;
25829
+ }
25722
25830
  };
25723
25831
  }
25724
25832
  });
@@ -27498,7 +27606,8 @@ function clampCursor(afterId) {
27498
27606
  }
27499
27607
  async function loadConsolidationPage(projectId, options) {
27500
27608
  const limit2 = clampBatchSize(options.limit);
27501
- const page = await getObservationStore().loadByProject(projectId, {
27609
+ const store2 = options.store ?? getObservationStore();
27610
+ const page = await store2.loadByProject(projectId, {
27502
27611
  status: "active",
27503
27612
  afterId: clampCursor(options.afterId),
27504
27613
  limit: limit2 + 1
@@ -27558,7 +27667,7 @@ async function findConsolidationCandidates(_projectDir, projectId, opts) {
27558
27667
  return findClusters(page.observations, threshold);
27559
27668
  }
27560
27669
  async function executeConsolidation(_projectDir, projectId, opts) {
27561
- const store2 = getObservationStore();
27670
+ const store2 = opts?.store ?? getObservationStore();
27562
27671
  const page = await loadConsolidationPage(projectId, opts ?? {});
27563
27672
  const clusters = findClusters(page.observations, opts?.threshold ?? DEFAULT_SIMILARITY_THRESHOLD);
27564
27673
  if (clusters.length === 0) {
@@ -73578,10 +73687,10 @@ var require_retry3 = __commonJS({
73578
73687
  if (!await shouldRetryFn(err)) {
73579
73688
  return { shouldRetry: false, config: err.config };
73580
73689
  }
73581
- const delay2 = getNextRetryDelay(config2);
73690
+ const delay3 = getNextRetryDelay(config2);
73582
73691
  err.config.retryConfig.currentRetryAttempt += 1;
73583
- const backoff = config2.retryBackoff ? config2.retryBackoff(err, delay2) : new Promise((resolve9) => {
73584
- setTimeout(resolve9, delay2);
73692
+ const backoff = config2.retryBackoff ? config2.retryBackoff(err, delay3) : new Promise((resolve9) => {
73693
+ setTimeout(resolve9, delay3);
73585
73694
  });
73586
73695
  if (config2.onRetryAttempt) {
73587
73696
  await config2.onRetryAttempt(err);
@@ -127106,7 +127215,7 @@ async function retryBackoff(fn2, strategy) {
127106
127215
  retryInterval = initialInterval * Math.pow(x5, exponent) + Math.random() * 1e3;
127107
127216
  }
127108
127217
  const d4 = Math.min(retryInterval, maxInterval);
127109
- await delay(d4);
127218
+ await delay2(d4);
127110
127219
  x5++;
127111
127220
  }
127112
127221
  }
@@ -127127,8 +127236,8 @@ function retryIntervalFromResponse(res) {
127127
127236
  }
127128
127237
  return 0;
127129
127238
  }
127130
- async function delay(delay2) {
127131
- return new Promise((resolve9) => setTimeout(resolve9, delay2));
127239
+ async function delay2(delay3) {
127240
+ return new Promise((resolve9) => setTimeout(resolve9, delay3));
127132
127241
  }
127133
127242
  var defaultBackoff, PermanentError, TemporaryError, codeRangeRE2;
127134
127243
  var init_retries = __esm({
@@ -181365,7 +181474,7 @@ __export(lite_provider_exports, {
181365
181474
  refreshProjectLite: () => refreshProjectLite
181366
181475
  });
181367
181476
  import { createHash as createHash10 } from "crypto";
181368
- import { readdirSync as readdirSync2, readFileSync as readFileSync9, statSync as statSync4 } from "fs";
181477
+ import { existsSync as existsSync14, readdirSync as readdirSync2, readFileSync as readFileSync9, statSync as statSync4 } from "fs";
181369
181478
  import { join as join5, relative as relative2 } from "path";
181370
181479
  function hashText2(text3) {
181371
181480
  return createHash10("sha256").update(text3).digest("hex");
@@ -181382,6 +181491,9 @@ function resolveMaxFileBytes(value) {
181382
181491
  if (!Number.isFinite(value)) return DEFAULT_CODEGRAPH_MAX_FILE_BYTES;
181383
181492
  return Math.max(1, Math.floor(value));
181384
181493
  }
181494
+ function isPythonVirtualenvDir(dir) {
181495
+ return existsSync14(join5(dir, "pyvenv.cfg"));
181496
+ }
181385
181497
  function walk(root, exclude, maxFiles) {
181386
181498
  const out = [];
181387
181499
  const visit = (dir) => {
@@ -181399,6 +181511,7 @@ function walk(root, exclude, maxFiles) {
181399
181511
  if (entry.isDirectory()) {
181400
181512
  if (entry.name === ".git" || entry.name === ".worktrees" || entry.name === ".tmp" || entry.name === "node_modules") continue;
181401
181513
  if (rel === ".claude/worktrees" || rel.startsWith(".claude/worktrees/")) continue;
181514
+ if (isPythonVirtualenvDir(abs)) continue;
181402
181515
  visit(abs);
181403
181516
  if (out.length >= maxFiles) return;
181404
181517
  continue;
@@ -185295,7 +185408,7 @@ __export(vector_backfill_runner_exports, {
185295
185408
  import { spawn as spawn4 } from "child_process";
185296
185409
  import {
185297
185410
  closeSync,
185298
- existsSync as existsSync14,
185411
+ existsSync as existsSync15,
185299
185412
  mkdirSync as mkdirSync2,
185300
185413
  openSync,
185301
185414
  readFileSync as readFileSync10,
@@ -185423,7 +185536,7 @@ function releaseVectorBackfillLock(lockPath = process.env.MEMORIX_VECTOR_BACKFIL
185423
185536
  }
185424
185537
  function launchDetachedVectorBackfill(request, options = {}) {
185425
185538
  const runnerPath = options.runnerPath ?? resolveVectorBackfillRunnerPath();
185426
- const exists3 = options.exists ?? existsSync14;
185539
+ const exists3 = options.exists ?? existsSync15;
185427
185540
  if (!exists3(runnerPath)) return false;
185428
185541
  const lock = acquireVectorBackfillLock(request.dataDir, request.projectId, options.lockPath);
185429
185542
  if (!lock) return false;
@@ -191547,16 +191660,18 @@ async function initSessionStore(dataDir) {
191547
191660
  if (_store3 && _storeDataDir3 === dataDir) return _store3;
191548
191661
  _store3 = null;
191549
191662
  _storeDataDir3 = null;
191663
+ let degradedReason = "SQLite runtime unavailable";
191550
191664
  try {
191551
- const store3 = new SessionSqliteStore();
191552
- await store3.init(dataDir);
191665
+ const store3 = await initializeSqliteStore(() => new SessionSqliteStore(), dataDir, "Session store");
191553
191666
  _store3 = store3;
191554
191667
  _storeDataDir3 = dataDir;
191555
191668
  return store3;
191556
191669
  } catch (err) {
191557
- console.error(`[memorix] SessionSqliteStore unavailable, running in degraded read-only mode: ${err instanceof Error ? err.message : err}`);
191670
+ if (!isSqliteUnavailableError(err)) throw err;
191671
+ degradedReason = formatSqliteFailure(err);
191672
+ console.error(`[memorix] SessionSqliteStore unavailable, running in degraded read-only mode: ${degradedReason}`);
191558
191673
  }
191559
- const store2 = new SessionGracefulDegrade();
191674
+ const store2 = new SessionGracefulDegrade(degradedReason);
191560
191675
  await store2.init(dataDir);
191561
191676
  _store3 = store2;
191562
191677
  _storeDataDir3 = dataDir;
@@ -191568,6 +191683,7 @@ var init_session_store = __esm({
191568
191683
  "use strict";
191569
191684
  init_esm_shims();
191570
191685
  init_sqlite_db();
191686
+ init_sqlite_reliability();
191571
191687
  SessionSqliteStore = class {
191572
191688
  db = null;
191573
191689
  dataDir = "";
@@ -191656,7 +191772,7 @@ var init_session_store = __esm({
191656
191772
  }
191657
191773
  const stmtComplete = this._stmtCompleteActive;
191658
191774
  const stmtIns = this.stmtInsert;
191659
- const result = this.db.transaction(() => {
191775
+ return retrySqliteBusy(async () => this.db.transaction(() => {
191660
191776
  let completedCount = 0;
191661
191777
  for (const pid of projectIds) {
191662
191778
  const info2 = stmtComplete.run({ pid, now: now3 });
@@ -191664,18 +191780,24 @@ var init_session_store = __esm({
191664
191780
  }
191665
191781
  stmtIns.run(sessionToRow(newSession));
191666
191782
  return completedCount;
191667
- })();
191668
- return result;
191783
+ })(), "Session rollover");
191669
191784
  }
191670
191785
  getBackendName() {
191671
191786
  return "sqlite";
191672
191787
  }
191673
191788
  };
191674
191789
  SessionGracefulDegrade = class {
191790
+ constructor(reason = "SQLite runtime unavailable") {
191791
+ this.reason = reason;
191792
+ }
191793
+ reason;
191675
191794
  warned = false;
191795
+ unavailableRead() {
191796
+ return degradedReadError("sessions");
191797
+ }
191676
191798
  warn() {
191677
191799
  if (!this.warned) {
191678
- console.error("[memorix] SessionStore: SQLite unavailable \u2014 sessions are disabled (read-only empty). Install better-sqlite3 for full functionality.");
191800
+ console.error("[memorix] SessionStore: SQLite unavailable \u2014 sessions cannot be read or written. Install a supported SQLite runtime.");
191679
191801
  this.warned = true;
191680
191802
  }
191681
191803
  }
@@ -191683,33 +191805,39 @@ var init_session_store = __esm({
191683
191805
  this.warn();
191684
191806
  }
191685
191807
  async loadAll() {
191686
- return [];
191808
+ throw this.unavailableRead();
191687
191809
  }
191688
191810
  async getById(_id) {
191689
- return void 0;
191811
+ throw this.unavailableRead();
191690
191812
  }
191691
191813
  async loadByProject(_projectId) {
191692
- return [];
191814
+ throw this.unavailableRead();
191693
191815
  }
191694
191816
  async loadActive(_projectId) {
191695
- return [];
191817
+ throw this.unavailableRead();
191696
191818
  }
191697
191819
  async insert(_session) {
191698
191820
  this.warn();
191821
+ throw degradedWriteError("sessions");
191699
191822
  }
191700
191823
  async update(_session) {
191701
191824
  this.warn();
191825
+ throw degradedWriteError("sessions");
191702
191826
  }
191703
191827
  async bulkUpdate(_sessions) {
191704
191828
  this.warn();
191829
+ throw degradedWriteError("sessions");
191705
191830
  }
191706
191831
  async atomicRolloverInsert(_newSession, _projectIds, _now) {
191707
191832
  this.warn();
191708
- return 0;
191833
+ throw degradedWriteError("sessions");
191709
191834
  }
191710
191835
  getBackendName() {
191711
191836
  return "degraded";
191712
191837
  }
191838
+ getBackendReason() {
191839
+ return this.reason;
191840
+ }
191713
191841
  };
191714
191842
  _store3 = null;
191715
191843
  _storeDataDir3 = null;
@@ -192262,7 +192390,8 @@ var init_memory3 = __esm({
192262
192390
  case "deduplicate": {
192263
192391
  const query = asStringArg(args.query);
192264
192392
  const dryRun = !!args.dryRun || !!args["dry-run"];
192265
- const { isLLMEnabled: isLLMEnabled2 } = await Promise.resolve().then(() => (init_provider2(), provider_exports2));
192393
+ const { initLLM: initLLM2, isLLMEnabled: isLLMEnabled2 } = await Promise.resolve().then(() => (init_provider2(), provider_exports2));
192394
+ initLLM2({ scope: "memory", projectRoot: project.rootPath });
192266
192395
  if (!isLLMEnabled2()) {
192267
192396
  emitResult(
192268
192397
  { project, available: false, usedLLM: false },
@@ -192615,7 +192744,7 @@ __export(init_exports, {
192615
192744
  buildInitTomlConfig: () => buildInitTomlConfig,
192616
192745
  default: () => init_default5
192617
192746
  });
192618
- import { existsSync as existsSync15, mkdirSync as mkdirSync3, writeFileSync as writeFileSync3 } from "fs";
192747
+ import { existsSync as existsSync16, mkdirSync as mkdirSync3, writeFileSync as writeFileSync3 } from "fs";
192619
192748
  import { homedir as homedir8 } from "os";
192620
192749
  import path29 from "path";
192621
192750
  function buildInitTomlConfig(options) {
@@ -192764,7 +192893,7 @@ var init_init = __esm({
192764
192893
  const targetPath = path29.join(targetDir, isGlobal ? getInitConfigFilename() : getInitProjectConfigFilename());
192765
192894
  const envPath = path29.join(targetDir, ".env");
192766
192895
  v3.info(getInitScopeDescription(scope));
192767
- if (existsSync15(targetPath)) {
192896
+ if (existsSync16(targetPath)) {
192768
192897
  const overwrite = await me({
192769
192898
  message: `${targetPath} already exists. Overwrite it?`,
192770
192899
  initialValue: false
@@ -192872,10 +193001,10 @@ var init_init = __esm({
192872
193001
  v3.success(`Created ${targetPath}`);
192873
193002
  if (shouldOfferDotenv(scope)) {
192874
193003
  const envExamplePath = getEnvTemplateTarget(targetDir, {
192875
- hasDotenvExample: existsSync15(path29.join(targetDir, ".env.example"))
193004
+ hasDotenvExample: existsSync16(path29.join(targetDir, ".env.example"))
192876
193005
  });
192877
193006
  const envContent = envLines.join("\n");
192878
- if (existsSync15(envExamplePath)) {
193007
+ if (existsSync16(envExamplePath)) {
192879
193008
  const overwriteEnvTemplate = await me({
192880
193009
  message: `${envExamplePath} already exists. Overwrite it?`,
192881
193010
  initialValue: false
@@ -192887,7 +193016,7 @@ var init_init = __esm({
192887
193016
  }
192888
193017
  writeFileSync3(envExamplePath, envContent, "utf-8");
192889
193018
  v3.success(`Created ${envExamplePath}`);
192890
- const createEnv = !existsSync15(envPath) ? await me({
193019
+ const createEnv = !existsSync16(envPath) ? await me({
192891
193020
  message: `Create .env from ${path29.basename(envExamplePath)} now? (you can fill in keys later)`,
192892
193021
  initialValue: true
192893
193022
  }) : false;
@@ -196057,7 +196186,7 @@ __export(setup_exports, {
196057
196186
  tryInstallCodexPlugin: () => tryInstallCodexPlugin
196058
196187
  });
196059
196188
  import { spawnSync } from "child_process";
196060
- import { existsSync as existsSync16 } from "fs";
196189
+ import { existsSync as existsSync17 } from "fs";
196061
196190
  import { copyFile as copyFile2, mkdir as mkdir6, readFile as readFile6, readdir as readdir3, rm as rm2, writeFile as writeFile7 } from "fs/promises";
196062
196191
  import { homedir as homedir27 } from "os";
196063
196192
  import path32 from "path";
@@ -196102,7 +196231,7 @@ function buildSetupPlan(options) {
196102
196231
  function findPackageRoot(start = path32.dirname(fileURLToPath7(import.meta.url))) {
196103
196232
  let dir = start;
196104
196233
  for (let i4 = 0; i4 < 8; i4++) {
196105
- if (existsSync16(path32.join(dir, "package.json")) && existsSync16(path32.join(dir, "plugins"))) {
196234
+ if (existsSync17(path32.join(dir, "package.json")) && existsSync17(path32.join(dir, "plugins"))) {
196106
196235
  return dir;
196107
196236
  }
196108
196237
  const parent = path32.dirname(dir);
@@ -196388,8 +196517,8 @@ function isOwnedLegacyCodexHooks(content) {
196388
196517
  async function removeOwnedLegacyCodexPluginFolder(homeDir) {
196389
196518
  const canonicalPath2 = path32.join(homeDir, "plugins", "memorix");
196390
196519
  const legacyPath = path32.join(homeDir, ".codex", "plugins", "memorix");
196391
- if (!existsSync16(legacyPath)) return "missing";
196392
- if (!existsSync16(canonicalPath2)) return "preserved";
196520
+ if (!existsSync17(legacyPath)) return "missing";
196521
+ if (!existsSync17(canonicalPath2)) return "preserved";
196393
196522
  try {
196394
196523
  const manifest = JSON.parse(await readFile6(path32.join(legacyPath, ".codex-plugin", "plugin.json"), "utf-8"));
196395
196524
  const repository = String(manifest.repository ?? "");
@@ -196605,7 +196734,7 @@ async function installCodeBuddyPluginPackage(options = {}) {
196605
196734
  const home = options.homeDir ?? homedir27();
196606
196735
  const packageRoot = findPackageRoot();
196607
196736
  const source = path32.join(packageRoot, "plugins", "codebuddy", "memorix");
196608
- if (!existsSync16(source)) throw new Error(`CodeBuddy plugin template not found: ${source}`);
196737
+ if (!existsSync17(source)) throw new Error(`CodeBuddy plugin template not found: ${source}`);
196609
196738
  const marketplaceRoot = path32.join(home, ".codebuddy", "memorix-local");
196610
196739
  const marketplacePath = path32.join(marketplaceRoot, ".codebuddy-plugin", "marketplace.json");
196611
196740
  const pluginPath = path32.join(marketplaceRoot, "plugins", "memorix");
@@ -196626,7 +196755,7 @@ async function installPluginPackage(options) {
196626
196755
  const packageRoot = findPackageRoot();
196627
196756
  const source = path32.join(packageRoot, "plugins", options.agent, "memorix");
196628
196757
  const includeHooks = options.includeHooks ?? true;
196629
- if (!existsSync16(source)) {
196758
+ if (!existsSync17(source)) {
196630
196759
  throw new Error(`Plugin package template not found: ${source}`);
196631
196760
  }
196632
196761
  if (options.agent === "codex") {
@@ -196674,7 +196803,7 @@ async function installGeminiExtensionPackage(options = {}) {
196674
196803
  const home = options.homeDir ?? homedir27();
196675
196804
  const packageRoot = findPackageRoot();
196676
196805
  const source = path32.join(packageRoot, "plugins", "gemini", "memorix");
196677
- if (!existsSync16(source)) {
196806
+ if (!existsSync17(source)) {
196678
196807
  throw new Error(`Gemini extension template not found: ${source}`);
196679
196808
  }
196680
196809
  const extensionPath = path32.join(home, ".gemini", "extensions", "memorix");
@@ -196688,7 +196817,7 @@ async function installGeminiExtensionPackage(options = {}) {
196688
196817
  async function installAntigravityPluginPackage(options = {}) {
196689
196818
  const packageRoot = findPackageRoot();
196690
196819
  const source = path32.join(packageRoot, "plugins", "antigravity", "memorix");
196691
- if (!existsSync16(source)) {
196820
+ if (!existsSync17(source)) {
196692
196821
  throw new Error(`Antigravity plugin template not found: ${source}`);
196693
196822
  }
196694
196823
  const pluginPath = options.global === false ? path32.join(options.projectRoot ?? process.cwd(), ".agents", "plugins", "memorix") : path32.join(options.homeDir ?? homedir27(), ".gemini", "config", "plugins", "memorix");
@@ -196706,7 +196835,7 @@ async function installAntigravityPluginPackage(options = {}) {
196706
196835
  async function installPiPackage(options = {}) {
196707
196836
  const packageRoot = findPackageRoot();
196708
196837
  const source = path32.join(packageRoot, "plugins", "pi", "memorix");
196709
- if (!existsSync16(source)) {
196838
+ if (!existsSync17(source)) {
196710
196839
  throw new Error(`Pi package template not found: ${source}`);
196711
196840
  }
196712
196841
  const defaultRoot = options.global ? path32.join(options.homeDir ?? homedir27(), ".pi", "agent", "packages") : path32.join(process.cwd(), ".pi", "packages");
@@ -196724,7 +196853,7 @@ async function installOpenClawBundlePackage(options = {}) {
196724
196853
  const home = options.homeDir ?? homedir27();
196725
196854
  const packageRoot = findPackageRoot();
196726
196855
  const source = path32.join(packageRoot, "plugins", "openclaw", "memorix");
196727
- if (!existsSync16(source)) {
196856
+ if (!existsSync17(source)) {
196728
196857
  throw new Error(`OpenClaw bundle template not found: ${source}`);
196729
196858
  }
196730
196859
  const bundlePath = path32.join(home, ".openclaw", "extensions", "memorix");
@@ -196740,7 +196869,7 @@ async function installOpenClawBundlePackage(options = {}) {
196740
196869
  async function installHermesPluginPackage(options = {}) {
196741
196870
  const packageRoot = findPackageRoot();
196742
196871
  const source = path32.join(packageRoot, "plugins", "hermes", "memorix");
196743
- if (!existsSync16(source)) {
196872
+ if (!existsSync17(source)) {
196744
196873
  throw new Error(`Hermes plugin template not found: ${source}`);
196745
196874
  }
196746
196875
  const hermesHome = resolveHermesHome(options.homeDir);
@@ -196767,7 +196896,7 @@ async function installHermesPluginPackage(options = {}) {
196767
196896
  async function installOmpPackage(options = {}) {
196768
196897
  const packageRoot = findPackageRoot();
196769
196898
  const source = path32.join(packageRoot, "plugins", "omp", "memorix");
196770
- if (!existsSync16(source)) {
196899
+ if (!existsSync17(source)) {
196771
196900
  throw new Error(`Oh-my-Pi package template not found: ${source}`);
196772
196901
  }
196773
196902
  const defaultRoot = options.global ? path32.join(options.homeDir ?? homedir27(), ".omp", "agent", "packages") : path32.join(process.cwd(), ".omp", "packages");
@@ -196994,7 +197123,7 @@ ${hook.stdout || ""}`.toLowerCase();
196994
197123
  function resolveHermesCommand(hermesHome) {
196995
197124
  if (process.platform === "win32") {
196996
197125
  const localHermes = path32.join(hermesHome, "hermes-agent", "venv", "Scripts", "hermes.exe");
196997
- if (existsSync16(localHermes)) return localHermes;
197126
+ if (existsSync17(localHermes)) return localHermes;
196998
197127
  }
196999
197128
  return "hermes";
197000
197129
  }
@@ -198610,11 +198739,11 @@ __export(current_facts_exports, {
198610
198739
  formatGitFact: () => formatGitFact
198611
198740
  });
198612
198741
  import { execFileSync } from "child_process";
198613
- import { existsSync as existsSync17, readFileSync as readFileSync11 } from "fs";
198742
+ import { existsSync as existsSync18, readFileSync as readFileSync11 } from "fs";
198614
198743
  import path33 from "path";
198615
198744
  function readTextIfExists(filePath) {
198616
198745
  try {
198617
- if (!existsSync17(filePath)) return null;
198746
+ if (!existsSync18(filePath)) return null;
198618
198747
  return readFileSync11(filePath, "utf8");
198619
198748
  } catch {
198620
198749
  return null;
@@ -198905,7 +199034,7 @@ __export(external_provider_exports, {
198905
199034
  runExternalCodeGraphLifecycle: () => runExternalCodeGraphLifecycle
198906
199035
  });
198907
199036
  import { spawn as spawn5 } from "child_process";
198908
- import { existsSync as existsSync18, readFileSync as readFileSync12 } from "fs";
199037
+ import { existsSync as existsSync19, readFileSync as readFileSync12 } from "fs";
198909
199038
  import { delimiter, dirname as dirname5, extname, isAbsolute as isAbsolute4, join as join24, relative as relative4, resolve as resolve6, sep as sep2 } from "path";
198910
199039
  function boundedTimeout(value) {
198911
199040
  if (!Number.isFinite(value)) return DEFAULT_EXTERNAL_CODEGRAPH_TIMEOUT_MS;
@@ -198942,13 +199071,13 @@ function resolveCommandCandidates(command) {
198942
199071
  }
198943
199072
  function resolveLaunch(command) {
198944
199073
  for (const candidate2 of resolveCommandCandidates(command)) {
198945
- if (!existsSync18(candidate2)) continue;
199074
+ if (!existsSync19(candidate2)) continue;
198946
199075
  const extension3 = extname(candidate2).toLowerCase();
198947
199076
  if (extension3 === ".cmd") {
198948
199077
  const bundleRoot = resolve6(dirname5(candidate2), "..");
198949
199078
  const node = join24(bundleRoot, "node.exe");
198950
199079
  const entry = join24(bundleRoot, "lib", "dist", "bin", "codegraph.js");
198951
- if (existsSync18(node) && existsSync18(entry)) {
199080
+ if (existsSync19(node) && existsSync19(entry)) {
198952
199081
  return { executable: node, prefixArgs: ["--liftoff-only", entry] };
198953
199082
  }
198954
199083
  try {
@@ -198957,7 +199086,7 @@ function resolveLaunch(command) {
198957
199086
  if (match2?.[1]) {
198958
199087
  const base = dirname5(candidate2).endsWith(sep2) ? dirname5(candidate2) : dirname5(candidate2) + sep2;
198959
199088
  const entry2 = resolve6(match2[1].replace(/%(?:~)?dp0%?/gi, base));
198960
- if (existsSync18(entry2)) return { executable: process.execPath, prefixArgs: [entry2] };
199089
+ if (existsSync19(entry2)) return { executable: process.execPath, prefixArgs: [entry2] };
198961
199090
  }
198962
199091
  } catch {
198963
199092
  }
@@ -199105,7 +199234,7 @@ async function inspectExternalCodeGraph(input) {
199105
199234
  const health2 = { state: "disabled", reason: "External CodeGraph is disabled by configuration." };
199106
199235
  return { health: health2, quality: providerQuality({ mode, health: health2 }) };
199107
199236
  }
199108
- if (!existsSync18(join24(input.projectRoot, ".codegraph"))) {
199237
+ if (!existsSync19(join24(input.projectRoot, ".codegraph"))) {
199109
199238
  const health2 = { state: "not-detected", reason: "No local .codegraph index is present for this project." };
199110
199239
  return { health: health2, quality: providerQuality({ mode, health: health2 }) };
199111
199240
  }
@@ -199141,7 +199270,7 @@ async function runExternalCodeGraphLifecycle(input) {
199141
199270
  };
199142
199271
  }
199143
199272
  const indexPath = join24(input.projectRoot, ".codegraph");
199144
- if (input.action === "sync" && !existsSync18(indexPath)) {
199273
+ if (input.action === "sync" && !existsSync19(indexPath)) {
199145
199274
  const health = { state: "not-detected", reason: "No local .codegraph index is present for this project." };
199146
199275
  return {
199147
199276
  action: input.action,
@@ -199151,7 +199280,7 @@ async function runExternalCodeGraphLifecycle(input) {
199151
199280
  quality: providerQuality({ mode, health })
199152
199281
  };
199153
199282
  }
199154
- if (input.action === "init" && existsSync18(indexPath)) {
199283
+ if (input.action === "init" && existsSync19(indexPath)) {
199155
199284
  const inspected2 = await inspectExternalCodeGraph(input);
199156
199285
  return {
199157
199286
  action: input.action,
@@ -201120,7 +201249,7 @@ __export(auto_context_exports, {
201120
201249
  formatAutoProjectContextSummary: () => formatAutoProjectContextSummary,
201121
201250
  formatLegacyAutoProjectContextPrompt: () => formatLegacyAutoProjectContextPrompt
201122
201251
  });
201123
- import { existsSync as existsSync19, statSync as statSync6 } from "fs";
201252
+ import { existsSync as existsSync20, statSync as statSync6 } from "fs";
201124
201253
  import path35 from "path";
201125
201254
  function activeProjectObservations(observations2, projectId) {
201126
201255
  return observations2.filter((obs) => obs.projectId === projectId && (obs.status ?? "active") === "active");
@@ -201466,7 +201595,7 @@ function existingLensCandidates(rootPath, lens) {
201466
201595
  for (const candidate2 of lensPathCandidates(lens)) {
201467
201596
  const absolute = path35.join(rootPath, candidate2);
201468
201597
  try {
201469
- if (!existsSync19(absolute)) continue;
201598
+ if (!existsSync20(absolute)) continue;
201470
201599
  const stat6 = statSync6(absolute);
201471
201600
  if (stat6.isFile()) out.push(candidate2);
201472
201601
  if (stat6.isDirectory()) out.push(candidate2.replace(/\\/g, "/"));
@@ -205105,7 +205234,7 @@ var engine_exports2 = {};
205105
205234
  __export(engine_exports2, {
205106
205235
  SkillsEngine: () => SkillsEngine
205107
205236
  });
205108
- import { existsSync as existsSync20, readFileSync as readFileSync13, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5, readdirSync as readdirSync3 } from "fs";
205237
+ import { existsSync as existsSync21, readFileSync as readFileSync13, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5, readdirSync as readdirSync3 } from "fs";
205109
205238
  import { join as join25 } from "path";
205110
205239
  import { homedir as homedir31 } from "os";
205111
205240
  var SKILLS_DIRS, SKILL_WORTHY_TYPES, MIN_OBS_FOR_SKILL, MIN_SCORE_FOR_SKILL, LOW_SIGNAL_TITLE_PATTERNS, LOW_SIGNAL_ENTITY_PATTERNS, COMMAND_TRACE_PATTERNS2, SkillsEngine;
@@ -205186,7 +205315,7 @@ var init_engine4 = __esm({
205186
205315
  paths.push(join25(home, dir));
205187
205316
  }
205188
205317
  for (const skillsRoot of paths) {
205189
- if (!existsSync20(skillsRoot)) continue;
205318
+ if (!existsSync21(skillsRoot)) continue;
205190
205319
  try {
205191
205320
  const entries = readdirSync3(skillsRoot, { withFileTypes: true });
205192
205321
  for (const entry of entries) {
@@ -205194,7 +205323,7 @@ var init_engine4 = __esm({
205194
205323
  const name = entry.name;
205195
205324
  if (seen.has(name)) continue;
205196
205325
  const skillMd = join25(skillsRoot, name, "SKILL.md");
205197
- if (!existsSync20(skillMd)) continue;
205326
+ if (!existsSync21(skillMd)) continue;
205198
205327
  try {
205199
205328
  const content = readFileSync13(skillMd, "utf-8");
205200
205329
  const description = this.parseDescription(content);
@@ -206416,7 +206545,7 @@ var init_task_graph = __esm({
206416
206545
 
206417
206546
  // src/orchestrate/context-collector.ts
206418
206547
  import { execFileSync as execFileSync2 } from "child_process";
206419
- import { readFileSync as readFileSync14, existsSync as existsSync21 } from "fs";
206548
+ import { readFileSync as readFileSync14, existsSync as existsSync22 } from "fs";
206420
206549
  import { join as join26 } from "path";
206421
206550
  function normalizeEntryLimit(value, fallback) {
206422
206551
  if (!Number.isSafeInteger(value) || value < 1) return fallback;
@@ -206493,7 +206622,7 @@ function collectFileTree(projectDir2, maxEntries) {
206493
206622
  function collectDependencies(projectDir2) {
206494
206623
  try {
206495
206624
  const pkgPath = join26(projectDir2, "package.json");
206496
- if (!existsSync21(pkgPath)) return "";
206625
+ if (!existsSync22(pkgPath)) return "";
206497
206626
  const pkg = JSON.parse(readFileSync14(pkgPath, "utf-8"));
206498
206627
  const parts = [];
206499
206628
  if (pkg.dependencies && Object.keys(pkg.dependencies).length > 0) {
@@ -207543,7 +207672,7 @@ __export(receipt_service_exports, {
207543
207672
  formatHandoffReceipt: () => formatHandoffReceipt
207544
207673
  });
207545
207674
  import { createHash as createHash18 } from "crypto";
207546
- import { existsSync as existsSync22, readFileSync as readFileSync15 } from "fs";
207675
+ import { existsSync as existsSync23, readFileSync as readFileSync15 } from "fs";
207547
207676
  import path37 from "path";
207548
207677
  function sha256(value) {
207549
207678
  return `sha256:${createHash18("sha256").update(value).digest("hex")}`;
@@ -207574,7 +207703,7 @@ function safeJsonArray(value) {
207574
207703
  }
207575
207704
  async function loadReceiptObservations(dataDir, projectId) {
207576
207705
  const dbPath = path37.join(dataDir, "memorix.db");
207577
- if (existsSync22(dbPath)) {
207706
+ if (existsSync23(dbPath)) {
207578
207707
  try {
207579
207708
  const DB = loadBetterSqlite3();
207580
207709
  const db2 = new DB(dbPath, { readonly: true, fileMustExist: true });
@@ -207591,7 +207720,7 @@ async function loadReceiptObservations(dataDir, projectId) {
207591
207720
  }
207592
207721
  }
207593
207722
  const jsonPath = path37.join(dataDir, "observations.json");
207594
- if (!existsSync22(jsonPath)) return [];
207723
+ if (!existsSync23(jsonPath)) return [];
207595
207724
  try {
207596
207725
  const parsed = JSON.parse(readFileSync15(jsonPath, "utf-8"));
207597
207726
  if (!Array.isArray(parsed)) return [];
@@ -207829,7 +207958,7 @@ var init_tool_profile = __esm({
207829
207958
  function getMcpServerInfo() {
207830
207959
  return {
207831
207960
  name: "memorix",
207832
- version: true ? "1.9.1" : "1.0.1"
207961
+ version: true ? "1.9.3" : "1.0.1"
207833
207962
  };
207834
207963
  }
207835
207964
  function createMcpDiscoverResult(capabilities, serverInfo) {
@@ -221527,7 +221656,7 @@ var init_sanitizer = __esm({
221527
221656
  });
221528
221657
 
221529
221658
  // src/workspace/applier.ts
221530
- import { existsSync as existsSync23, mkdirSync as mkdirSync6, copyFileSync, writeFileSync as writeFileSync6, unlinkSync as unlinkSync2, renameSync } from "fs";
221659
+ import { existsSync as existsSync24, mkdirSync as mkdirSync6, copyFileSync, writeFileSync as writeFileSync6, unlinkSync as unlinkSync2, renameSync } from "fs";
221531
221660
  import { dirname as dirname6 } from "path";
221532
221661
  var WorkspaceSyncApplier;
221533
221662
  var init_applier = __esm({
@@ -221558,7 +221687,7 @@ var init_applier = __esm({
221558
221687
  for (const file2 of files) {
221559
221688
  try {
221560
221689
  const dir = dirname6(file2.filePath);
221561
- if (!existsSync23(dir)) {
221690
+ if (!existsSync24(dir)) {
221562
221691
  mkdirSync6(dir, { recursive: true });
221563
221692
  }
221564
221693
  } catch (err) {
@@ -221567,7 +221696,7 @@ var init_applier = __esm({
221567
221696
  }
221568
221697
  }
221569
221698
  for (const file2 of files) {
221570
- if (existsSync23(file2.filePath)) {
221699
+ if (existsSync24(file2.filePath)) {
221571
221700
  try {
221572
221701
  const backupPath = file2.filePath + `.backup-${Date.now()}`;
221573
221702
  copyFileSync(file2.filePath, backupPath);
@@ -221618,7 +221747,7 @@ var init_applier = __esm({
221618
221747
  cleanBackups(backups) {
221619
221748
  for (const backup of backups) {
221620
221749
  try {
221621
- if (existsSync23(backup.backupPath)) {
221750
+ if (existsSync24(backup.backupPath)) {
221622
221751
  unlinkSync2(backup.backupPath);
221623
221752
  }
221624
221753
  } catch {
@@ -221634,7 +221763,7 @@ var engine_exports3 = {};
221634
221763
  __export(engine_exports3, {
221635
221764
  WorkspaceSyncEngine: () => WorkspaceSyncEngine
221636
221765
  });
221637
- import { readFileSync as readFileSync16, readdirSync as readdirSync4, existsSync as existsSync24, cpSync, mkdirSync as mkdirSync7 } from "fs";
221766
+ import { readFileSync as readFileSync16, readdirSync as readdirSync4, existsSync as existsSync25, cpSync, mkdirSync as mkdirSync7 } from "fs";
221638
221767
  import { join as join28 } from "path";
221639
221768
  import { homedir as homedir32 } from "os";
221640
221769
  var WorkspaceSyncEngine;
@@ -221714,7 +221843,7 @@ var init_engine5 = __esm({
221714
221843
  }
221715
221844
  const merged = /* @__PURE__ */ new Map();
221716
221845
  for (const path50 of pathsToCheck) {
221717
- if (existsSync24(path50)) {
221846
+ if (existsSync25(path50)) {
221718
221847
  try {
221719
221848
  const content = readFileSync16(path50, "utf-8");
221720
221849
  const servers = adapter.parse(content);
@@ -221768,7 +221897,7 @@ var init_engine5 = __esm({
221768
221897
  const adapter = this.adapters.get(target);
221769
221898
  const configPath = adapter.getConfigPath(this.projectRoot);
221770
221899
  let configContent;
221771
- if (target === "antigravity" && existsSync24(configPath)) {
221900
+ if (target === "antigravity" && existsSync25(configPath)) {
221772
221901
  try {
221773
221902
  const existing = JSON.parse(readFileSync16(configPath, "utf-8"));
221774
221903
  const generated = JSON.parse(adapter.generate(result.mcpServers.scanned));
@@ -221844,13 +221973,13 @@ var init_engine5 = __esm({
221844
221973
  join28(home, dir)
221845
221974
  ];
221846
221975
  for (const skillsRoot of paths) {
221847
- if (!existsSync24(skillsRoot)) continue;
221976
+ if (!existsSync25(skillsRoot)) continue;
221848
221977
  try {
221849
221978
  const entries = readdirSync4(skillsRoot, { withFileTypes: true });
221850
221979
  for (const entry of entries) {
221851
221980
  if (!entry.isDirectory()) continue;
221852
221981
  const skillMd = join28(skillsRoot, entry.name, "SKILL.md");
221853
- if (!existsSync24(skillMd)) continue;
221982
+ if (!existsSync25(skillMd)) continue;
221854
221983
  let description = "";
221855
221984
  try {
221856
221985
  const content = readFileSync16(skillMd, "utf-8");
@@ -221899,7 +222028,7 @@ var init_engine5 = __esm({
221899
222028
  for (const skill2 of skills) {
221900
222029
  if (skill2.sourceAgent === target) continue;
221901
222030
  const dest = join28(targetDir, skill2.name);
221902
- if (existsSync24(dest)) {
222031
+ if (existsSync25(dest)) {
221903
222032
  skipped.push(`${skill2.name} (already exists in ${target})`);
221904
222033
  continue;
221905
222034
  }
@@ -221915,7 +222044,7 @@ var init_engine5 = __esm({
221915
222044
  scanWorkflows() {
221916
222045
  const workflows = [];
221917
222046
  const wfDir = join28(this.projectRoot, ".windsurf", "workflows");
221918
- if (!existsSync24(wfDir)) return workflows;
222047
+ if (!existsSync25(wfDir)) return workflows;
221919
222048
  try {
221920
222049
  const files = readdirSync4(wfDir).filter((f7) => f7.endsWith(".md"));
221921
222050
  for (const file2 of files) {
@@ -222194,7 +222323,7 @@ __export(behavior_exports, {
222194
222323
  getBehaviorConfig: () => getBehaviorConfig,
222195
222324
  resetBehaviorConfigCache: () => resetBehaviorConfigCache
222196
222325
  });
222197
- import { existsSync as existsSync25, readFileSync as readFileSync17 } from "fs";
222326
+ import { existsSync as existsSync26, readFileSync as readFileSync17 } from "fs";
222198
222327
  import { homedir as homedir33 } from "os";
222199
222328
  function isSessionInject(value) {
222200
222329
  return value === "full" || value === "minimal" || value === "silent";
@@ -222205,7 +222334,7 @@ function isFormationMode(value) {
222205
222334
  function legacyBehavior(homeDir) {
222206
222335
  const configPath = getLegacyConfigJsonPath(homeDir);
222207
222336
  try {
222208
- if (!existsSync25(configPath)) return {};
222337
+ if (!existsSync26(configPath)) return {};
222209
222338
  const parsed = JSON.parse(readFileSync17(configPath, "utf-8"));
222210
222339
  return parsed.behavior && typeof parsed.behavior === "object" && !Array.isArray(parsed.behavior) ? parsed.behavior : {};
222211
222340
  } catch {
@@ -222519,7 +222648,8 @@ async function executeDeduplicate(context, payload, token) {
222519
222648
  async function previewConsolidate(context) {
222520
222649
  const clusters = await findConsolidationCandidates(
222521
222650
  context.projectRoot ?? context.dataDir,
222522
- context.projectId
222651
+ context.projectId,
222652
+ { store: context.store }
222523
222653
  );
222524
222654
  const payload = { clusterIds: normalizeClusters(clusters.map((cluster) => cluster.ids)) };
222525
222655
  return {
@@ -222542,11 +222672,19 @@ async function executeConsolidate(context, payload, token) {
222542
222672
  const clusterIds = record2.clusterIds.map((ids, index) => payloadIds(ids, `clusterIds[${index}]`));
222543
222673
  const normalized = { clusterIds: normalizeClusters(clusterIds) };
222544
222674
  verify("consolidate", context.projectId, normalized, token);
222545
- const current = await findConsolidationCandidates(context.projectRoot ?? context.dataDir, context.projectId);
222675
+ const current = await findConsolidationCandidates(
222676
+ context.projectRoot ?? context.dataDir,
222677
+ context.projectId,
222678
+ { store: context.store }
222679
+ );
222546
222680
  if (JSON.stringify(normalized.clusterIds) !== JSON.stringify(normalizeClusters(current.map((cluster) => cluster.ids)))) {
222547
222681
  throw new DashboardMaintenanceError("Memory changed after the preview. Refresh before consolidating.", 409);
222548
222682
  }
222549
- const result = await executeConsolidation(context.projectRoot ?? context.dataDir, context.projectId);
222683
+ const result = await executeConsolidation(
222684
+ context.projectRoot ?? context.dataDir,
222685
+ context.projectId,
222686
+ { store: context.store }
222687
+ );
222550
222688
  return { action: "consolidate", projectId: context.projectId, ...result };
222551
222689
  }
222552
222690
  async function retentionCandidates(context) {
@@ -223703,7 +223841,7 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
223703
223841
  }
223704
223842
  case "/config": {
223705
223843
  const os10 = await import("os");
223706
- const { existsSync: existsSync35 } = await import("fs");
223844
+ const { existsSync: existsSync36 } = await import("fs");
223707
223845
  const { join: join35 } = await import("path");
223708
223846
  const configProjectRoot = effectiveProjectRoot;
223709
223847
  const resolved = getResolvedConfig({ projectRoot: configProjectRoot });
@@ -223731,7 +223869,7 @@ async function handleApi(req, res, dataDir, projectId, projectName, baseDir, pro
223731
223869
  if (fpath === null) {
223732
223870
  files[key] = { exists: false, path: "unavailable", unavailable: true };
223733
223871
  } else {
223734
- files[key] = { exists: existsSync35(fpath), path: fpath };
223872
+ files[key] = { exists: existsSync36(fpath), path: fpath };
223735
223873
  }
223736
223874
  }
223737
223875
  } catch {
@@ -264200,11 +264338,11 @@ __export(hooks_path_exports, {
264200
264338
  resolveGitDir: () => resolveGitDir,
264201
264339
  resolveHooksDir: () => resolveHooksDir
264202
264340
  });
264203
- import { existsSync as existsSync26, readFileSync as readFileSync18, statSync as statSync7, mkdirSync as mkdirSync8 } from "fs";
264341
+ import { existsSync as existsSync27, readFileSync as readFileSync18, statSync as statSync7, mkdirSync as mkdirSync8 } from "fs";
264204
264342
  import path42 from "path";
264205
264343
  function resolveGitDir(projectRoot) {
264206
264344
  const dotGit = path42.join(projectRoot, ".git");
264207
- if (!existsSync26(dotGit)) return null;
264345
+ if (!existsSync27(dotGit)) return null;
264208
264346
  const stat6 = statSync7(dotGit);
264209
264347
  if (stat6.isDirectory()) {
264210
264348
  return dotGit;
@@ -264216,7 +264354,7 @@ function resolveGitDir(projectRoot) {
264216
264354
  if (match2) {
264217
264355
  const gitdir = match2[1].trim();
264218
264356
  const resolved = path42.isAbsolute(gitdir) ? gitdir : path42.resolve(projectRoot, gitdir);
264219
- if (existsSync26(resolved)) {
264357
+ if (existsSync27(resolved)) {
264220
264358
  return resolved;
264221
264359
  }
264222
264360
  }
@@ -268809,10 +268947,10 @@ Preview: ${analysis.description.slice(0, 300)}${analysis.description.length > 30
268809
268947
  const { ensureHooksDir: ensureHooksDir2 } = await Promise.resolve().then(() => (init_hooks_path(), hooks_path_exports));
268810
268948
  const resolved = ensureHooksDir2(project.rootPath);
268811
268949
  if (resolved) {
268812
- const { existsSync: existsSync35, readFileSync: readFileSync25, writeFileSync: writeFileSync13, chmodSync: chmodSync2 } = await import("fs");
268950
+ const { existsSync: existsSync36, readFileSync: readFileSync25, writeFileSync: writeFileSync13, chmodSync: chmodSync2 } = await import("fs");
268813
268951
  const { hookPath } = resolved;
268814
268952
  const HOOK_MARKER3 = "# [memorix-git-hook]";
268815
- const needsInstall = !existsSync35(hookPath) || !readFileSync25(hookPath, "utf-8").includes(HOOK_MARKER3);
268953
+ const needsInstall = !existsSync36(hookPath) || !readFileSync25(hookPath, "utf-8").includes(HOOK_MARKER3);
268816
268954
  if (needsInstall) {
268817
268955
  const hookScript = `#!/bin/sh
268818
268956
  ${HOOK_MARKER3}
@@ -268821,7 +268959,7 @@ if command -v memorix >/dev/null 2>&1; then
268821
268959
  memorix ingest commit --auto >/dev/null 2>&1 &
268822
268960
  fi
268823
268961
  `;
268824
- if (existsSync35(hookPath)) {
268962
+ if (existsSync36(hookPath)) {
268825
268963
  const existing = readFileSync25(hookPath, "utf-8");
268826
268964
  writeFileSync13(hookPath, existing.trimEnd() + `
268827
268965
 
@@ -272883,7 +273021,7 @@ var init_serve_http = __esm({
272883
273021
  if (apiPath === "/config") {
272884
273022
  const { projectId: configProjectId } = await resolveRequestProject(url2);
272885
273023
  const os10 = await import("os");
272886
- const { existsSync: existsSync35 } = await import("fs");
273024
+ const { existsSync: existsSync36 } = await import("fs");
272887
273025
  const { join: join35 } = await import("path");
272888
273026
  const { loadYamlConfig: loadYamlConfig2 } = await Promise.resolve().then(() => (init_yaml_loader(), yaml_loader_exports));
272889
273027
  const { loadFileConfig: loadFileConfig2, loadDotenv: loadDotenv2, getLoadedEnvFiles: getLoadedEnvFiles2 } = await Promise.resolve().then(() => (init_config(), config_exports));
@@ -272905,7 +273043,7 @@ var init_serve_http = __esm({
272905
273043
  "legacy config.json": join35(home, ".memorix", "config.json")
272906
273044
  };
272907
273045
  for (const [key, fpath] of Object.entries(paths)) {
272908
- files[key] = { exists: existsSync35(fpath), path: fpath };
273046
+ files[key] = { exists: existsSync36(fpath), path: fpath };
272909
273047
  }
272910
273048
  } else {
272911
273049
  files["project memorix.yml"] = { exists: false, path: "unavailable", unavailable: true };
@@ -272916,7 +273054,7 @@ var init_serve_http = __esm({
272916
273054
  "legacy config.json": join35(home, ".memorix", "config.json")
272917
273055
  };
272918
273056
  for (const [key, fpath] of Object.entries(userPaths)) {
272919
- files[key] = { exists: existsSync35(fpath), path: fpath };
273057
+ files[key] = { exists: existsSync36(fpath), path: fpath };
272920
273058
  }
272921
273059
  }
272922
273060
  const values = [];
@@ -273452,7 +273590,7 @@ var init_status = __esm({
273452
273590
  const { getProjectDataDir: getProjectDataDir2 } = await Promise.resolve().then(() => (init_persistence(), persistence_exports));
273453
273591
  const { getEmbeddingProvider: getEmbeddingProvider2 } = await Promise.resolve().then(() => (init_provider(), provider_exports));
273454
273592
  const { getResolvedConfig: getResolvedConfig2, getResolvedAgentLane: getResolvedAgentLane2 } = await Promise.resolve().then(() => (init_resolved_config(), resolved_config_exports));
273455
- const { existsSync: existsSync35, readFileSync: readFileSync25 } = await import("fs");
273593
+ const { existsSync: existsSync36, readFileSync: readFileSync25 } = await import("fs");
273456
273594
  const project = detectProject2();
273457
273595
  if (!project) {
273458
273596
  const message = "Memorix requires a git repo to establish project identity. Run `git init` in this workspace first.";
@@ -273535,7 +273673,7 @@ var init_status = __esm({
273535
273673
  try {
273536
273674
  const { resolveHooksDir: resolveHooksDir2 } = await Promise.resolve().then(() => (init_hooks_path(), hooks_path_exports));
273537
273675
  const resolved2 = resolveHooksDir2(project.rootPath);
273538
- if (resolved2 && existsSync35(resolved2.hookPath)) {
273676
+ if (resolved2 && existsSync36(resolved2.hookPath)) {
273539
273677
  const hookContent = readFileSync25(resolved2.hookPath, "utf-8");
273540
273678
  if (hookContent.includes("# [memorix-git-hook]")) {
273541
273679
  diagLines.push(` Git hook: installed [OK]`);
@@ -279510,7 +279648,7 @@ var git_hook_install_exports = {};
279510
279648
  __export(git_hook_install_exports, {
279511
279649
  default: () => git_hook_install_default
279512
279650
  });
279513
- import { existsSync as existsSync27, readFileSync as readFileSync19, writeFileSync as writeFileSync7, chmodSync } from "fs";
279651
+ import { existsSync as existsSync28, readFileSync as readFileSync19, writeFileSync as writeFileSync7, chmodSync } from "fs";
279514
279652
  function generateHookScript() {
279515
279653
  return `${HOOK_MARKER}
279516
279654
  # Memorix: Auto-ingest git commits as memories
@@ -279557,7 +279695,7 @@ var init_git_hook_install = __esm({
279557
279695
  return;
279558
279696
  }
279559
279697
  const { hookPath } = resolved;
279560
- if (existsSync27(hookPath)) {
279698
+ if (existsSync28(hookPath)) {
279561
279699
  const existing = readFileSync19(hookPath, "utf-8");
279562
279700
  if (existing.includes(HOOK_MARKER)) {
279563
279701
  v3.warn("Memorix git hook is already installed.");
@@ -279607,7 +279745,7 @@ var git_hook_uninstall_exports = {};
279607
279745
  __export(git_hook_uninstall_exports, {
279608
279746
  default: () => git_hook_uninstall_default
279609
279747
  });
279610
- import { existsSync as existsSync28, readFileSync as readFileSync20, writeFileSync as writeFileSync8, unlinkSync as unlinkSync3 } from "fs";
279748
+ import { existsSync as existsSync29, readFileSync as readFileSync20, writeFileSync as writeFileSync8, unlinkSync as unlinkSync3 } from "fs";
279611
279749
  var HOOK_MARKER2, git_hook_uninstall_default;
279612
279750
  var init_git_hook_uninstall = __esm({
279613
279751
  "src/cli/commands/git-hook-uninstall.ts"() {
@@ -279639,7 +279777,7 @@ var init_git_hook_uninstall = __esm({
279639
279777
  return;
279640
279778
  }
279641
279779
  const { hookPath } = resolved;
279642
- if (!existsSync28(hookPath)) {
279780
+ if (!existsSync29(hookPath)) {
279643
279781
  v3.warn("No post-commit hook found.");
279644
279782
  fe2("Nothing to uninstall.");
279645
279783
  return;
@@ -280486,7 +280624,7 @@ __export(agent_integrations_exports, {
280486
280624
  repairAgentIntegrations: () => repairAgentIntegrations
280487
280625
  });
280488
280626
  import { spawnSync as spawnSync2 } from "child_process";
280489
- import { existsSync as existsSync30, realpathSync as realpathSync2 } from "fs";
280627
+ import { existsSync as existsSync31, realpathSync as realpathSync2 } from "fs";
280490
280628
  import { mkdir as mkdir9, readFile as readFile10, writeFile as writeFile10 } from "fs/promises";
280491
280629
  import { basename as basename5, dirname as dirname8, resolve as resolve7 } from "path";
280492
280630
  import { homedir as homedir35 } from "os";
@@ -280608,7 +280746,7 @@ async function inspectCodexPluginBundle() {
280608
280746
  const manifestPath = `${pluginPath}/.codex-plugin/plugin.json`;
280609
280747
  const hooksPath = `${pluginPath}/hooks/hooks.json`;
280610
280748
  const mcpPath = codexPluginMcpPath();
280611
- if (!existsSync30(pluginPath)) {
280749
+ if (!existsSync31(pluginPath)) {
280612
280750
  return {
280613
280751
  scope: "global",
280614
280752
  kind: "bundle",
@@ -280618,7 +280756,7 @@ async function inspectCodexPluginBundle() {
280618
280756
  issues: ["codex-plugin-bundle-missing"]
280619
280757
  };
280620
280758
  }
280621
- if (!existsSync30(manifestPath)) {
280759
+ if (!existsSync31(manifestPath)) {
280622
280760
  return {
280623
280761
  scope: "global",
280624
280762
  kind: "bundle",
@@ -280655,7 +280793,7 @@ async function inspectCodexPluginBundle() {
280655
280793
  const issues = [];
280656
280794
  if (version2 !== getCliVersion()) issues.push("codex-plugin-version-mismatch");
280657
280795
  if (manifest.hooks !== "./hooks/hooks.json") issues.push("codex-hook-manifest-missing");
280658
- if (!existsSync30(mcpPath)) {
280796
+ if (!existsSync31(mcpPath)) {
280659
280797
  issues.push("codex-plugin-mcp-manifest-missing");
280660
280798
  } else {
280661
280799
  try {
@@ -280669,7 +280807,7 @@ async function inspectCodexPluginBundle() {
280669
280807
  }
280670
280808
  }
280671
280809
  let declared = [];
280672
- if (!existsSync30(hooksPath)) {
280810
+ if (!existsSync31(hooksPath)) {
280673
280811
  issues.push("codex-hook-manifest-missing");
280674
280812
  } else {
280675
280813
  try {
@@ -280696,7 +280834,7 @@ async function inspectCodexPluginBundle() {
280696
280834
  }
280697
280835
  async function inspectCodexMarketplace() {
280698
280836
  const marketplacePath = codexMarketplacePath();
280699
- if (!existsSync30(marketplacePath)) {
280837
+ if (!existsSync31(marketplacePath)) {
280700
280838
  return {
280701
280839
  scope: "global",
280702
280840
  kind: "marketplace",
@@ -280786,7 +280924,7 @@ function inspectCodexPluginRuntime() {
280786
280924
  }
280787
280925
  async function inspectCodexHookTrust() {
280788
280926
  const configPath = codexConfigPath();
280789
- if (!existsSync30(configPath)) {
280927
+ if (!existsSync31(configPath)) {
280790
280928
  return {
280791
280929
  scope: "global",
280792
280930
  kind: "hook-trust",
@@ -280887,7 +281025,7 @@ function defaultClaudeProjectKey(projectRoot) {
280887
281025
  }
280888
281026
  function canonicalProjectPath(projectRoot) {
280889
281027
  const resolved = resolve7(projectRoot);
280890
- const canonical = existsSync30(resolved) ? realpathSync2(resolved) : resolved;
281028
+ const canonical = existsSync31(resolved) ? realpathSync2(resolved) : resolved;
280891
281029
  return canonical.replace(/\\/g, "/");
280892
281030
  }
280893
281031
  function getClaudeLocalConfigPath() {
@@ -280919,7 +281057,7 @@ function findClaudeLocalProject(config2, projectRoot) {
280919
281057
  }
280920
281058
  async function inspectClaudeLocalMcp(projectRoot) {
280921
281059
  const configPath = getClaudeLocalConfigPath();
280922
- if (!existsSync30(configPath)) {
281060
+ if (!existsSync31(configPath)) {
280923
281061
  return {
280924
281062
  scope: "local",
280925
281063
  path: configPath,
@@ -281007,7 +281145,7 @@ async function inspectCodexPluginMcp() {
281007
281145
  const runtime = inspectCodexPluginRuntime();
281008
281146
  if (!runtime.runtime?.installed || !runtime.runtime.enabled) return null;
281009
281147
  const mcpPath = codexPluginMcpPath();
281010
- if (!existsSync30(mcpPath)) {
281148
+ if (!existsSync31(mcpPath)) {
281011
281149
  return {
281012
281150
  scope: "global",
281013
281151
  path: mcpPath,
@@ -281075,7 +281213,7 @@ async function inspectMcp(agent, projectRoot, scope) {
281075
281213
  if (targetScope === "global" && configPath === adapter.getConfigPath(projectRoot) && scope === "all") {
281076
281214
  continue;
281077
281215
  }
281078
- if (!existsSync30(configPath)) {
281216
+ if (!existsSync31(configPath)) {
281079
281217
  checks.push({
281080
281218
  scope: targetScope,
281081
281219
  path: configPath,
@@ -281152,7 +281290,7 @@ async function inspectGuidance(agent, projectRoot, scope) {
281152
281290
  for (const targetScope of requestedGuidanceScopes(scope)) {
281153
281291
  const root = targetScope === "project" ? projectRoot : homedir35();
281154
281292
  const rulesPath = getAgentRulesPath(agent, root, targetScope === "global");
281155
- if (!existsSync30(rulesPath)) {
281293
+ if (!existsSync31(rulesPath)) {
281156
281294
  checks.push({
281157
281295
  scope: targetScope,
281158
281296
  path: rulesPath,
@@ -281430,7 +281568,7 @@ var init_doctor = __esm({
281430
281568
  }
281431
281569
  return;
281432
281570
  }
281433
- const { existsSync: existsSync35, readFileSync: readFileSync25 } = await import("fs");
281571
+ const { existsSync: existsSync36, readFileSync: readFileSync25 } = await import("fs");
281434
281572
  const { join: join35, basename: basename7 } = await import("path");
281435
281573
  const { homedir: homedir37 } = await import("os");
281436
281574
  const { execSync: execSync5 } = await import("child_process");
@@ -281501,7 +281639,7 @@ var init_doctor = __esm({
281501
281639
  let bgPid = 0;
281502
281640
  let backgroundHealthy = false;
281503
281641
  try {
281504
- if (existsSync35(bgStatePath)) {
281642
+ if (existsSync36(bgStatePath)) {
281505
281643
  const bgState = JSON.parse(readFileSync25(bgStatePath, "utf-8"));
281506
281644
  bgPid = bgState.pid;
281507
281645
  bgPort = bgState.port;
@@ -281616,7 +281754,7 @@ var init_doctor = __esm({
281616
281754
  }
281617
281755
  try {
281618
281756
  const cachePath = join35(memorixDir, "embedding-cache.json");
281619
- if (existsSync35(cachePath)) {
281757
+ if (existsSync36(cachePath)) {
281620
281758
  const cache5 = JSON.parse(readFileSync25(cachePath, "utf-8"));
281621
281759
  const cacheCount = Object.keys(cache5).length;
281622
281760
  lines.push(info2(`Cached embeddings: ${cacheCount}`));
@@ -281631,27 +281769,44 @@ var init_doctor = __esm({
281631
281769
  }
281632
281770
  lines.push("");
281633
281771
  lines.push("\u250C\u2500 Data Status \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
281634
- if (dataDir && existsSync35(dataDir)) {
281772
+ if (dataDir && existsSync36(dataDir)) {
281635
281773
  let obsCount = 0;
281636
281774
  let activeCount = 0;
281637
281775
  let ranCount = 0;
281638
281776
  let backendName = "unknown";
281777
+ let backendReason;
281778
+ let observationFailure;
281639
281779
  try {
281640
281780
  const { initObservationStore: initObservationStore2, getObservationStore: getObservationStore2 } = await Promise.resolve().then(() => (init_obs_store(), obs_store_exports));
281641
281781
  await initObservationStore2(dataDir);
281642
281782
  const store2 = getObservationStore2();
281643
281783
  backendName = store2.getBackendName();
281784
+ backendReason = store2.getBackendReason?.();
281644
281785
  const { filterReadableObservations: filterReadableObservations2 } = await Promise.resolve().then(() => (init_visibility(), visibility_exports));
281645
281786
  projectObservations = projectId ? filterReadableObservations2(await store2.loadAll(), { projectId }) : [];
281646
281787
  obsCount = projectObservations.length;
281647
281788
  activeCount = projectObservations.filter((o4) => (o4.status ?? "active") === "active").length;
281648
281789
  ranCount = projectObservations.filter((o4) => /^Ran:\s/i.test(o4.title ?? "")).length;
281649
- } catch {
281650
- }
281651
- if (backendName === "degraded") {
281652
- lines.push(warn2("Observations: SQLite unavailable \u2014 degraded (read-only, no data)"));
281653
- issues.push("SQLite backend unavailable \u2014 observations cannot be read or written.");
281790
+ } catch (error40) {
281791
+ observationFailure = error40 instanceof Error ? error40.message : String(error40);
281792
+ }
281793
+ if (observationFailure) {
281794
+ lines.push(fail2(`Observations: storage unavailable \u2014 ${observationFailure}`));
281795
+ issues.push(`Observation store could not be opened: ${observationFailure}`);
281796
+ report.data = {
281797
+ backend: "unavailable",
281798
+ observations: null,
281799
+ active: null,
281800
+ commandLogs: null,
281801
+ error: observationFailure
281802
+ };
281803
+ } else if (backendName === "degraded") {
281804
+ lines.push(fail2(`Backend: degraded (read-only; writes disabled${backendReason ? `; ${backendReason}` : ""})`));
281805
+ lines.push(fail2("Observations: unavailable \u2014 count not reported"));
281806
+ issues.push("SQLite backend unavailable \u2014 observation storage is in degraded read-only mode; observations are not being persisted.");
281807
+ report.data = { backend: "degraded", ...backendReason ? { backendReason } : {}, observations: null, active: null, commandLogs: null };
281654
281808
  } else {
281809
+ lines.push(ok("Backend: sqlite (read-write)"));
281655
281810
  lines.push(ok(`Observations: ${obsCount} total, ${activeCount} active`));
281656
281811
  if (ranCount > 0) {
281657
281812
  const pct = Math.round(ranCount / obsCount * 100);
@@ -281661,29 +281816,63 @@ var init_doctor = __esm({
281661
281816
  }
281662
281817
  }
281663
281818
  }
281664
- report.data = { observations: obsCount, active: activeCount, commandLogs: ranCount };
281819
+ if (!report.data) {
281820
+ report.data = { backend: backendName, observations: obsCount, active: activeCount, commandLogs: ranCount };
281821
+ } else if (!report.data.backend) {
281822
+ report.data.backend = backendName;
281823
+ }
281824
+ let sessionBackend = "unknown";
281825
+ let sessionReason;
281665
281826
  try {
281666
281827
  const { initSessionStore: initSessionStore2, getSessionStore: getSessionStore2 } = await Promise.resolve().then(() => (init_session_store(), session_store_exports));
281667
281828
  await initSessionStore2(dataDir);
281668
281829
  const sessStore = getSessionStore2();
281669
- const sess = await sessStore.loadAll();
281670
- const sessCount = sess.length;
281671
- const activeSess = sess.filter((s4) => s4.status === "active").length;
281672
- lines.push(ok(`Sessions: ${sessCount} total, ${activeSess} active`));
281673
- report.data.sessions = sessCount;
281674
- } catch {
281830
+ sessionBackend = sessStore.getBackendName();
281831
+ sessionReason = sessStore.getBackendReason?.();
281832
+ if (sessionBackend === "degraded") {
281833
+ lines.push(fail2(`Sessions: unavailable \u2014 read-only degraded backend${sessionReason ? `; ${sessionReason}` : ""}`));
281834
+ issues.push("Session storage is in degraded read-only mode.");
281835
+ report.data.sessions = null;
281836
+ if (sessionReason) report.data.sessionBackendReason = sessionReason;
281837
+ } else {
281838
+ const sess = await sessStore.loadAll();
281839
+ const sessCount = sess.length;
281840
+ const activeSess = sess.filter((s4) => s4.status === "active").length;
281841
+ lines.push(ok(`Sessions: ${sessCount} total, ${activeSess} active`));
281842
+ report.data.sessions = sessCount;
281843
+ }
281844
+ } catch (error40) {
281845
+ const message = error40 instanceof Error ? error40.message : String(error40);
281846
+ lines.push(fail2(`Sessions: unavailable (${message})`));
281847
+ issues.push(`Session storage is unavailable: ${message}`);
281848
+ report.data.sessions = null;
281675
281849
  }
281850
+ let skillBackend = "unknown";
281851
+ let skillReason;
281676
281852
  try {
281677
281853
  const { initMiniSkillStore: initMiniSkillStore2, getMiniSkillStore: getMiniSkillStore2 } = await Promise.resolve().then(() => (init_mini_skill_store(), mini_skill_store_exports));
281678
281854
  await initMiniSkillStore2(dataDir);
281679
281855
  const skillStore = getMiniSkillStore2();
281680
- const skills = await skillStore.loadAll();
281681
- const skillCount = skills.length;
281682
- if (skillCount > 0) {
281683
- lines.push(ok(`Mini-skills: ${skillCount}`));
281684
- report.data.miniSkills = skillCount;
281856
+ skillBackend = skillStore.getBackendName();
281857
+ skillReason = skillStore.getBackendReason?.();
281858
+ if (skillBackend === "degraded") {
281859
+ lines.push(fail2(`Mini-skills: unavailable \u2014 read-only degraded backend${skillReason ? `; ${skillReason}` : ""}`));
281860
+ issues.push("Mini-skill storage is in degraded read-only mode.");
281861
+ report.data.miniSkills = null;
281862
+ if (skillReason) report.data.miniSkillBackendReason = skillReason;
281863
+ } else {
281864
+ const skills = await skillStore.loadAll();
281865
+ const skillCount = skills.length;
281866
+ if (skillCount > 0) {
281867
+ lines.push(ok(`Mini-skills: ${skillCount}`));
281868
+ report.data.miniSkills = skillCount;
281869
+ }
281685
281870
  }
281686
- } catch {
281871
+ } catch (error40) {
281872
+ const message = error40 instanceof Error ? error40.message : String(error40);
281873
+ lines.push(fail2(`Mini-skills: unavailable (${message})`));
281874
+ issues.push(`Mini-skill storage is unavailable: ${message}`);
281875
+ report.data.miniSkills = null;
281687
281876
  }
281688
281877
  } else {
281689
281878
  lines.push(warn2("No data directory found for current project"));
@@ -281819,7 +282008,7 @@ var init_doctor = __esm({
281819
282008
  let conflictsFound = false;
281820
282009
  if (dataDir) {
281821
282010
  const lockFile = join35(dataDir, ".memorix.lock");
281822
- if (existsSync35(lockFile)) {
282011
+ if (existsSync36(lockFile)) {
281823
282012
  try {
281824
282013
  const lockData = JSON.parse(readFileSync25(lockFile, "utf-8"));
281825
282014
  const lockAge = Date.now() - lockData.time;
@@ -281931,6 +282120,9 @@ var init_doctor = __esm({
281931
282120
  } else {
281932
282121
  console.log(lines.join("\n"));
281933
282122
  }
282123
+ if (issues.some((issue2) => /^(Observation store could not be opened|Observation storage |Session storage |Mini-skill storage |SQLite backend unavailable)/.test(issue2))) {
282124
+ process.exitCode = 1;
282125
+ }
281934
282126
  }
281935
282127
  });
281936
282128
  }
@@ -284026,7 +284218,7 @@ var init_pipeline_trace = __esm({
284026
284218
 
284027
284219
  // src/orchestrate/worktree.ts
284028
284220
  import { execFileSync as execFileSync5 } from "child_process";
284029
- import { existsSync as existsSync32, rmSync as rmSync2 } from "fs";
284221
+ import { existsSync as existsSync33, rmSync as rmSync2 } from "fs";
284030
284222
  import { join as join33, basename as basename6 } from "path";
284031
284223
  function runGit4(cwd, args, timeout = 5e3) {
284032
284224
  return String(execFileSync5("git", args, {
@@ -284072,7 +284264,7 @@ function createWorktree(projectDir2, taskId, pipelineId) {
284072
284264
  const suffix = attempt === 1 ? "" : `-${attempt}`;
284073
284265
  const worktreePath = `${worktreeBase}${suffix}`;
284074
284266
  const branch = `${branchBase}${suffix}`;
284075
- if (existsSync32(worktreePath)) continue;
284267
+ if (existsSync33(worktreePath)) continue;
284076
284268
  if (!isBranchAvailable(projectDir2, branch)) continue;
284077
284269
  runGit4(projectDir2, ["worktree", "add", "-b", branch, worktreePath], 3e4);
284078
284270
  return { worktreePath, branch };
@@ -284123,7 +284315,7 @@ function removeWorktree(projectDir2, worktreePath, branch) {
284123
284315
  try {
284124
284316
  runGit4(projectDir2, ["worktree", "remove", worktreePath, "--force"], 1e4);
284125
284317
  } catch {
284126
- if (existsSync32(worktreePath)) {
284318
+ if (existsSync33(worktreePath)) {
284127
284319
  try {
284128
284320
  rmSync2(worktreePath, { recursive: true, force: true });
284129
284321
  } catch {
@@ -284378,12 +284570,12 @@ function classifyError(ctx, taskId) {
284378
284570
  if (taskId) backoffState.set(taskId, attempt);
284379
284571
  const baseDelay = 2e3;
284380
284572
  const maxDelay = 3e4;
284381
- const delay2 = Math.min(baseDelay * Math.pow(2, attempt - 1), maxDelay);
284382
- const jitter = delay2 * 0.25 * (Math.random() * 2 - 1);
284573
+ const delay3 = Math.min(baseDelay * Math.pow(2, attempt - 1), maxDelay);
284574
+ const jitter = delay3 * 0.25 * (Math.random() * 2 - 1);
284383
284575
  return {
284384
284576
  category: "transient",
284385
284577
  strategy: "backoff_and_retry",
284386
- delayMs: Math.round(delay2 + jitter),
284578
+ delayMs: Math.round(delay3 + jitter),
284387
284579
  reason: `Transient error detected (attempt ${attempt})`,
284388
284580
  backoffAttempt: attempt
284389
284581
  };
@@ -290064,10 +290256,10 @@ function WorkbenchApp({ version: version2, onExitForInteractive }) {
290064
290256
  }
290065
290257
  try {
290066
290258
  const { resolveHooksDir: resolveHooksDir2 } = await Promise.resolve().then(() => (init_hooks_path(), hooks_path_exports));
290067
- const { existsSync: existsSync35, readFileSync: readFileSync25, writeFileSync: writeFileSync13, unlinkSync: unlinkSync5 } = await import("fs");
290259
+ const { existsSync: existsSync36, readFileSync: readFileSync25, writeFileSync: writeFileSync13, unlinkSync: unlinkSync5 } = await import("fs");
290068
290260
  const resolved = resolveHooksDir2(proj.rootPath);
290069
290261
  const hookMarker = "# [memorix-git-hook]";
290070
- if (!resolved || !existsSync35(resolved.hookPath)) {
290262
+ if (!resolved || !existsSync36(resolved.hookPath)) {
290071
290263
  setActionStatus("No post-commit hook found.");
290072
290264
  return;
290073
290265
  }
@@ -290222,7 +290414,7 @@ function WorkbenchApp({ version: version2, onExitForInteractive }) {
290222
290414
  break;
290223
290415
  }
290224
290416
  case "3": {
290225
- const { existsSync: existsSync35, readFileSync: readFileSync25, writeFileSync: writeFileSync13, chmodSync: chmodSync2 } = await import("fs");
290417
+ const { existsSync: existsSync36, readFileSync: readFileSync25, writeFileSync: writeFileSync13, chmodSync: chmodSync2 } = await import("fs");
290226
290418
  const { ensureHooksDir: ensureHooksDir2 } = await Promise.resolve().then(() => (init_hooks_path(), hooks_path_exports));
290227
290419
  const hookMarker = "# [memorix-git-hook]";
290228
290420
  const resolved = ensureHooksDir2(cwd);
@@ -290236,7 +290428,7 @@ if command -v memorix >/dev/null 2>&1; then
290236
290428
  memorix ingest commit --auto >/dev/null 2>&1 &
290237
290429
  fi
290238
290430
  `;
290239
- if (existsSync35(resolved.hookPath)) {
290431
+ if (existsSync36(resolved.hookPath)) {
290240
290432
  if (readFileSync25(resolved.hookPath, "utf-8").includes(hookMarker)) {
290241
290433
  setActionStatus("Post-commit hook already installed.");
290242
290434
  break;
@@ -290256,11 +290448,11 @@ ${hookScript}`, "utf-8");
290256
290448
  break;
290257
290449
  }
290258
290450
  case "4": {
290259
- const { existsSync: existsSync35, readFileSync: readFileSync25, writeFileSync: writeFileSync13, unlinkSync: unlinkSync5 } = await import("fs");
290451
+ const { existsSync: existsSync36, readFileSync: readFileSync25, writeFileSync: writeFileSync13, unlinkSync: unlinkSync5 } = await import("fs");
290260
290452
  const { resolveHooksDir: resolveHooksDir2 } = await Promise.resolve().then(() => (init_hooks_path(), hooks_path_exports));
290261
290453
  const hookMarker = "# [memorix-git-hook]";
290262
290454
  const resolved = resolveHooksDir2(cwd);
290263
- if (!resolved || !existsSync35(resolved.hookPath)) {
290455
+ if (!resolved || !existsSync36(resolved.hookPath)) {
290264
290456
  setActionStatus("No post-commit hook found.");
290265
290457
  break;
290266
290458
  }
@@ -291072,6 +291264,14 @@ function printCliGuideForHelp(argv2 = process.argv.slice(2)) {
291072
291264
  return true;
291073
291265
  }
291074
291266
 
291267
+ // src/cli/default-mode.ts
291268
+ init_esm_shims();
291269
+ function shouldDefaultToMcp(options = {}) {
291270
+ const stdinIsTTY = options.stdinIsTTY ?? process.stdin.isTTY;
291271
+ const stdoutIsTTY = options.stdoutIsTTY ?? process.stdout.isTTY;
291272
+ return stdinIsTTY !== true || stdoutIsTTY !== true;
291273
+ }
291274
+
291075
291275
  // src/cli/index.ts
291076
291276
  installCliPipeErrorGuard();
291077
291277
  var NO_GIT_MSG = "Memorix requires a git repo to establish project identity. Run `git init` in this workspace first.";
@@ -291382,6 +291582,11 @@ var main2 = defineCommand({
291382
291582
  ];
291383
291583
  if (firstArg && knownSubs.includes(firstArg)) return;
291384
291584
  if (!firstArg) {
291585
+ if (shouldDefaultToMcp()) {
291586
+ const serve = await Promise.resolve().then(() => (init_serve(), serve_exports));
291587
+ await serve.default.run?.({ args: {}, rawArgs: [], cmd: serve.default });
291588
+ return;
291589
+ }
291385
291590
  try {
291386
291591
  const { runCli } = await importBundledMemcode();
291387
291592
  await runCli(process.argv.slice(2));