@cortexkit/opencode-magic-context 0.30.5 → 0.30.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -15446,6 +15446,340 @@ var init_magic_context = __esm(() => {
15446
15446
  });
15447
15447
  });
15448
15448
 
15449
+ // src/shared/error-message.ts
15450
+ function getErrorMessage(error51) {
15451
+ return error51 instanceof Error ? error51.message : String(error51);
15452
+ }
15453
+ function readString(value) {
15454
+ if (typeof value === "string" && value.length > 0)
15455
+ return value;
15456
+ if (typeof value === "number")
15457
+ return String(value);
15458
+ return;
15459
+ }
15460
+ function clip(value, max) {
15461
+ if (value.length <= max)
15462
+ return value;
15463
+ return `${value.slice(0, max)}…`;
15464
+ }
15465
+ function describeError(error51) {
15466
+ const stringForm = clip(safeString(error51), 400);
15467
+ if (!(error51 instanceof Error) && !(error51 && typeof error51 === "object")) {
15468
+ return {
15469
+ name: typeof error51,
15470
+ message: "",
15471
+ stringForm,
15472
+ brief: stringForm || "<empty>"
15473
+ };
15474
+ }
15475
+ const obj = error51;
15476
+ const nameFromField = readString(obj.name);
15477
+ const nameFromCtor = error51?.constructor?.name;
15478
+ const name = nameFromField ?? nameFromCtor ?? "Error";
15479
+ const message = readString(obj.message) ?? "";
15480
+ const status = readString(obj.status) ?? readString(obj.statusCode);
15481
+ const code = readString(obj.code);
15482
+ let causeName;
15483
+ const cause = obj.cause;
15484
+ if (cause && typeof cause === "object") {
15485
+ const causeRecord = cause;
15486
+ causeName = readString(causeRecord.name) ?? cause.constructor?.name;
15487
+ }
15488
+ const stack = readString(obj.stack);
15489
+ const stackHead = stack ? stack.split(`
15490
+ `).slice(0, 4).map((l) => l.trim()).filter((l) => l.length > 0).join(" | ") : undefined;
15491
+ const briefParts = [];
15492
+ if (name)
15493
+ briefParts.push(name);
15494
+ if (message)
15495
+ briefParts.push(`message="${clip(message, 200)}"`);
15496
+ if (status)
15497
+ briefParts.push(`status=${status}`);
15498
+ if (code)
15499
+ briefParts.push(`code=${code}`);
15500
+ if (causeName)
15501
+ briefParts.push(`cause=${causeName}`);
15502
+ if (!message && stringForm && stringForm !== name) {
15503
+ briefParts.push(`str="${clip(stringForm, 200)}"`);
15504
+ }
15505
+ const brief = briefParts.join(" ") || stringForm || name;
15506
+ return {
15507
+ name,
15508
+ message,
15509
+ ...status ? { status } : {},
15510
+ ...code ? { code } : {},
15511
+ ...causeName ? { causeName } : {},
15512
+ ...stackHead ? { stackHead } : {},
15513
+ stringForm,
15514
+ brief
15515
+ };
15516
+ }
15517
+ function safeString(value) {
15518
+ try {
15519
+ return String(value);
15520
+ } catch {
15521
+ return "<unstringifiable>";
15522
+ }
15523
+ }
15524
+
15525
+ // src/shared/sqlite.ts
15526
+ function buildNodeSqliteDatabaseClass(DatabaseSync) {
15527
+ const SAVEPOINT = "mc_tx_sp";
15528
+
15529
+ class NodeSqliteDatabase extends DatabaseSync {
15530
+ constructor(filename, options) {
15531
+ const translated = { ...options };
15532
+ if (options && "readonly" in options) {
15533
+ translated.readOnly = options.readonly;
15534
+ delete translated.readonly;
15535
+ }
15536
+ super(typeof filename === "string" ? filename : ":memory:", translated);
15537
+ }
15538
+ prepare(sql) {
15539
+ const stmt = super.prepare(sql);
15540
+ for (const method of ["run", "get", "all"]) {
15541
+ const original = stmt[method].bind(stmt);
15542
+ stmt[method] = (...args) => args.length === 1 && Array.isArray(args[0]) ? original(...args[0]) : original(...args);
15543
+ }
15544
+ return stmt;
15545
+ }
15546
+ transaction(fn) {
15547
+ const self2 = this;
15548
+ const wrapped = function(...args) {
15549
+ const nested = self2.isTransaction === true;
15550
+ self2.exec(nested ? `SAVEPOINT ${SAVEPOINT}` : "BEGIN");
15551
+ try {
15552
+ const result = fn.apply(this, args);
15553
+ self2.exec(nested ? `RELEASE ${SAVEPOINT}` : "COMMIT");
15554
+ return result;
15555
+ } catch (error51) {
15556
+ if (nested) {
15557
+ self2.exec(`ROLLBACK TO ${SAVEPOINT}`);
15558
+ self2.exec(`RELEASE ${SAVEPOINT}`);
15559
+ } else {
15560
+ self2.exec("ROLLBACK");
15561
+ }
15562
+ throw error51;
15563
+ }
15564
+ };
15565
+ return wrapped;
15566
+ }
15567
+ }
15568
+ return NodeSqliteDatabase;
15569
+ }
15570
+ var isBun, bunSpec, nodeSpec, sqliteModule, DatabaseImpl, Database;
15571
+ var init_sqlite = __esm(async () => {
15572
+ isBun = typeof process !== "undefined" && typeof process.versions?.bun === "string";
15573
+ bunSpec = "bun:" + "sqlite";
15574
+ nodeSpec = "node:" + "sqlite";
15575
+ sqliteModule = isBun ? await import(bunSpec) : await import(nodeSpec);
15576
+ DatabaseImpl = isBun ? sqliteModule.Database : buildNodeSqliteDatabaseClass(sqliteModule.DatabaseSync);
15577
+ Database = DatabaseImpl;
15578
+ });
15579
+
15580
+ // src/shared/sqlite-helpers.ts
15581
+ function closeQuietly(db) {
15582
+ if (!db)
15583
+ return;
15584
+ try {
15585
+ db.close();
15586
+ } catch {}
15587
+ }
15588
+
15589
+ // src/features/magic-context/compaction-marker.ts
15590
+ import { existsSync as existsSync6 } from "node:fs";
15591
+ import { join as join3 } from "node:path";
15592
+ function randomBase62(length) {
15593
+ const chars = [];
15594
+ for (let i = 0;i < length; i++) {
15595
+ chars.push(BASE62_CHARS[Math.floor(Math.random() * BASE62_CHARS.length)]);
15596
+ }
15597
+ return chars.join("");
15598
+ }
15599
+ function generateId(prefix, timestampMs, counter = 0n) {
15600
+ const encoded = BigInt(timestampMs) * 0x1000n + counter;
15601
+ const hex3 = encoded.toString(16).padStart(14, "0");
15602
+ return `${prefix}_${hex3}${randomBase62(14)}`;
15603
+ }
15604
+ function generateMessageId(timestampMs, counter = 0n) {
15605
+ return generateId("msg", timestampMs, counter);
15606
+ }
15607
+ function generatePartId(timestampMs, counter = 0n) {
15608
+ return generateId("prt", timestampMs, counter);
15609
+ }
15610
+ function getOpenCodeDbPath() {
15611
+ return join3(getDataDir(), "opencode", "opencode.db");
15612
+ }
15613
+ function isOpenCodeSchemaCompatible(db, dbPath) {
15614
+ if (cachedSchemaCompatible?.path === dbPath) {
15615
+ return cachedSchemaCompatible.compatible;
15616
+ }
15617
+ try {
15618
+ const messageCols = new Set(db.prepare("PRAGMA table_info(message)").all().map((r) => r.name ?? "").filter((n) => n.length > 0));
15619
+ const partCols = new Set(db.prepare("PRAGMA table_info(part)").all().map((r) => r.name ?? "").filter((n) => n.length > 0));
15620
+ const missingMessage = REQUIRED_MESSAGE_COLUMNS.filter((c) => !messageCols.has(c));
15621
+ const missingPart = REQUIRED_PART_COLUMNS.filter((c) => !partCols.has(c));
15622
+ if (missingMessage.length > 0 || missingPart.length > 0) {
15623
+ log(`[magic-context] compaction-marker: OpenCode DB schema missing required columns ` + `(message: [${missingMessage.join(", ")}], part: [${missingPart.join(", ")}]). ` + `Marker injection disabled for this process. ` + `This usually means OpenCode was updated and magic-context is out of date.`);
15624
+ cachedSchemaCompatible = { path: dbPath, compatible: false };
15625
+ return false;
15626
+ }
15627
+ cachedSchemaCompatible = { path: dbPath, compatible: true };
15628
+ return true;
15629
+ } catch (error51) {
15630
+ log(`[magic-context] compaction-marker: schema probe failed: ${error51 instanceof Error ? error51.message : String(error51)}. ` + `Marker injection disabled until next process restart.`);
15631
+ cachedSchemaCompatible = { path: dbPath, compatible: false };
15632
+ return false;
15633
+ }
15634
+ }
15635
+ function getWritableOpenCodeDb() {
15636
+ const dbPath = getOpenCodeDbPath();
15637
+ if (cachedWriteDb?.path === dbPath) {
15638
+ return cachedWriteDb.db;
15639
+ }
15640
+ if (cachedWriteDb) {
15641
+ try {
15642
+ closeQuietly(cachedWriteDb.db);
15643
+ } catch {}
15644
+ }
15645
+ if (!existsSync6(dbPath)) {
15646
+ throw new Error(`OpenCode database not found at ${dbPath} (is OpenCode installed?)`);
15647
+ }
15648
+ const db = new Database(dbPath);
15649
+ db.exec("PRAGMA busy_timeout=5000");
15650
+ db.exec("PRAGMA journal_mode=WAL");
15651
+ cachedWriteDb = { path: dbPath, db };
15652
+ return db;
15653
+ }
15654
+ function getNonSummaryMessageSortKey(sessionId, messageId) {
15655
+ const db = getWritableOpenCodeDb();
15656
+ const row = db.prepare(`SELECT time_created, id
15657
+ FROM message
15658
+ WHERE session_id = ?
15659
+ AND id = ?
15660
+ AND NOT (COALESCE(json_extract(data, '$.summary'), 0) = 1
15661
+ AND COALESCE(json_extract(data, '$.finish'), '') = 'stop')
15662
+ LIMIT 1`).get(sessionId, messageId);
15663
+ if (typeof row?.time_created !== "number" || typeof row.id !== "string") {
15664
+ return null;
15665
+ }
15666
+ return { id: row.id, timeCreated: row.time_created };
15667
+ }
15668
+ function findBoundaryUserMessage(sessionId, endMessageId) {
15669
+ const db = getWritableOpenCodeDb();
15670
+ const target = getNonSummaryMessageSortKey(sessionId, endMessageId);
15671
+ if (!target)
15672
+ return null;
15673
+ const boundary = db.prepare(`SELECT id, time_created, data
15674
+ FROM message
15675
+ WHERE session_id = ?
15676
+ AND NOT (COALESCE(json_extract(data, '$.summary'), 0) = 1
15677
+ AND COALESCE(json_extract(data, '$.finish'), '') = 'stop')
15678
+ AND COALESCE(json_extract(data, '$.role'), '') = 'user'
15679
+ AND (time_created < ? OR (time_created = ? AND id <= ?))
15680
+ ORDER BY time_created DESC, id DESC
15681
+ LIMIT 1`).get(sessionId, target.timeCreated, target.timeCreated, target.id);
15682
+ if (typeof boundary?.id !== "string" || typeof boundary.time_created !== "number") {
15683
+ return null;
15684
+ }
15685
+ return { id: boundary.id, timeCreated: boundary.time_created };
15686
+ }
15687
+ function compareOpenCodeMessagesByCanonicalOrder(sessionId, leftMessageId, rightMessageId) {
15688
+ const left = getNonSummaryMessageSortKey(sessionId, leftMessageId);
15689
+ const right = getNonSummaryMessageSortKey(sessionId, rightMessageId);
15690
+ if (!left || !right)
15691
+ return null;
15692
+ if (left.timeCreated < right.timeCreated)
15693
+ return -1;
15694
+ if (left.timeCreated > right.timeCreated)
15695
+ return 1;
15696
+ if (left.id < right.id)
15697
+ return -1;
15698
+ if (left.id > right.id)
15699
+ return 1;
15700
+ return 0;
15701
+ }
15702
+ function getOpenCodeMessageById(sessionId, messageId) {
15703
+ const db = getWritableOpenCodeDb();
15704
+ const row = db.prepare(`SELECT id FROM message WHERE session_id = ? AND id = ? LIMIT 1`).get(sessionId, messageId);
15705
+ return row ?? null;
15706
+ }
15707
+ function injectCompactionMarker(args) {
15708
+ const db = getWritableOpenCodeDb();
15709
+ if (!isOpenCodeSchemaCompatible(db, getOpenCodeDbPath())) {
15710
+ return null;
15711
+ }
15712
+ const boundary = args.resolvedBoundary ?? findBoundaryUserMessage(args.sessionId, args.endMessageId);
15713
+ if (!boundary) {
15714
+ log(`[magic-context] compaction-marker: no user message found at or before endMessageId ${args.endMessageId} (ordinal ${args.endOrdinal})`);
15715
+ return null;
15716
+ }
15717
+ const boundaryTime = boundary.timeCreated;
15718
+ const summaryMsgId = generateMessageId(boundaryTime + 1, 1n);
15719
+ const compactionPartId = generatePartId(boundaryTime, 1n);
15720
+ const summaryPartId = generatePartId(boundaryTime + 1, 2n);
15721
+ const summaryMsgData = JSON.stringify({
15722
+ role: "assistant",
15723
+ parentID: boundary.id,
15724
+ summary: true,
15725
+ finish: "stop",
15726
+ mode: "compaction",
15727
+ agent: "compaction",
15728
+ path: { cwd: args.directory, root: args.directory },
15729
+ cost: 0,
15730
+ tokens: { input: 0, output: 0, reasoning: 0, cache: { read: 0, write: 0 } },
15731
+ modelID: "magic-context",
15732
+ providerID: "magic-context",
15733
+ time: { created: boundaryTime + 1 }
15734
+ });
15735
+ try {
15736
+ db.transaction(() => {
15737
+ db.prepare("INSERT INTO part (id, message_id, session_id, time_created, time_updated, data) VALUES (?, ?, ?, ?, ?, ?)").run(compactionPartId, boundary.id, args.sessionId, boundaryTime, boundaryTime, '{"type":"compaction","auto":true}');
15738
+ db.prepare("INSERT INTO message (id, session_id, time_created, time_updated, data) VALUES (?, ?, ?, ?, ?)").run(summaryMsgId, args.sessionId, boundaryTime + 1, boundaryTime + 1, summaryMsgData);
15739
+ db.prepare("INSERT INTO part (id, message_id, session_id, time_created, time_updated, data) VALUES (?, ?, ?, ?, ?, ?)").run(summaryPartId, summaryMsgId, args.sessionId, boundaryTime + 1, boundaryTime + 1, JSON.stringify({ type: "text", text: args.summaryText }));
15740
+ })();
15741
+ log(`[magic-context] compaction-marker: injected boundary at user msg ${boundary.id} (ordinal ~${args.endOrdinal}), summary msg ${summaryMsgId}`);
15742
+ return {
15743
+ boundaryMessageId: boundary.id,
15744
+ summaryMessageId: summaryMsgId,
15745
+ compactionPartId,
15746
+ summaryPartId
15747
+ };
15748
+ } catch (error51) {
15749
+ log(`[magic-context] compaction-marker: injection failed: ${error51 instanceof Error ? error51.message : String(error51)}`);
15750
+ return null;
15751
+ }
15752
+ }
15753
+ function removeCompactionMarker(state) {
15754
+ try {
15755
+ const db = getWritableOpenCodeDb();
15756
+ db.transaction(() => {
15757
+ db.prepare("DELETE FROM part WHERE id = ?").run(state.summaryPartId);
15758
+ db.prepare("DELETE FROM message WHERE id = ?").run(state.summaryMessageId);
15759
+ db.prepare("DELETE FROM part WHERE id = ?").run(state.compactionPartId);
15760
+ })();
15761
+ return true;
15762
+ } catch (error51) {
15763
+ log(`[magic-context] compaction-marker: removal failed: ${error51 instanceof Error ? error51.message : String(error51)}`);
15764
+ return false;
15765
+ }
15766
+ }
15767
+ var BASE62_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", cachedWriteDb = null, REQUIRED_MESSAGE_COLUMNS, REQUIRED_PART_COLUMNS, cachedSchemaCompatible = null;
15768
+ var init_compaction_marker = __esm(async () => {
15769
+ init_data_path();
15770
+ init_logger();
15771
+ await init_sqlite();
15772
+ REQUIRED_MESSAGE_COLUMNS = ["id", "session_id", "time_created", "time_updated", "data"];
15773
+ REQUIRED_PART_COLUMNS = [
15774
+ "id",
15775
+ "message_id",
15776
+ "session_id",
15777
+ "time_created",
15778
+ "time_updated",
15779
+ "data"
15780
+ ];
15781
+ });
15782
+
15449
15783
  // src/features/magic-context/memory/project-identity.ts
15450
15784
  import { execFileSync } from "node:child_process";
15451
15785
  import { createHash } from "node:crypto";
@@ -15625,6 +15959,80 @@ var init_project_identity = __esm(() => {
15625
15959
  };
15626
15960
  });
15627
15961
 
15962
+ // src/features/magic-context/session-project-storage.ts
15963
+ function getUpsertSessionProjectStatement(db) {
15964
+ let stmt = upsertSessionProjectStatements.get(db);
15965
+ if (!stmt) {
15966
+ stmt = db.prepare(`INSERT INTO session_projects (session_id, harness, project_path, updated_at)
15967
+ VALUES (?, ?, ?, ?)
15968
+ ON CONFLICT(session_id, harness) DO UPDATE SET
15969
+ project_path = excluded.project_path,
15970
+ updated_at = excluded.updated_at
15971
+ WHERE session_projects.project_path <> excluded.project_path`);
15972
+ upsertSessionProjectStatements.set(db, stmt);
15973
+ }
15974
+ return stmt;
15975
+ }
15976
+ function getRepairSessionChunkProjectStatement(db) {
15977
+ let stmt = repairSessionChunkProjectStatements.get(db);
15978
+ if (!stmt) {
15979
+ stmt = db.prepare(`UPDATE compartment_chunk_embeddings
15980
+ SET project_path = ?
15981
+ WHERE session_id = ?
15982
+ AND harness = ?
15983
+ AND project_path <> ?`);
15984
+ repairSessionChunkProjectStatements.set(db, stmt);
15985
+ }
15986
+ return stmt;
15987
+ }
15988
+ function getRepairProjectChunkProjectStatement(db) {
15989
+ let stmt = repairProjectChunkProjectStatements.get(db);
15990
+ if (!stmt) {
15991
+ stmt = db.prepare(`UPDATE compartment_chunk_embeddings
15992
+ SET project_path = (
15993
+ SELECT sp.project_path
15994
+ FROM session_projects sp
15995
+ WHERE sp.session_id = compartment_chunk_embeddings.session_id
15996
+ AND sp.harness = compartment_chunk_embeddings.harness
15997
+ LIMIT 1
15998
+ )
15999
+ WHERE EXISTS (
16000
+ SELECT 1
16001
+ FROM session_projects sp
16002
+ WHERE sp.session_id = compartment_chunk_embeddings.session_id
16003
+ AND sp.harness = compartment_chunk_embeddings.harness
16004
+ AND sp.project_path <> compartment_chunk_embeddings.project_path
16005
+ AND (
16006
+ sp.project_path = ?
16007
+ OR compartment_chunk_embeddings.project_path = ?
16008
+ )
16009
+ )`);
16010
+ repairProjectChunkProjectStatements.set(db, stmt);
16011
+ }
16012
+ return stmt;
16013
+ }
16014
+ function recordSessionProjectIdentity(db, sessionId, projectPath) {
16015
+ if (!sessionId || !projectPath)
16016
+ return;
16017
+ const harness = getHarness();
16018
+ const now = Date.now();
16019
+ db.transaction(() => {
16020
+ getUpsertSessionProjectStatement(db).run(sessionId, harness, projectPath, now);
16021
+ getRepairSessionChunkProjectStatement(db).run(projectPath, sessionId, harness, projectPath);
16022
+ })();
16023
+ }
16024
+ function repairMisScopedCompartmentChunkEmbeddingsForProject(db, projectPath) {
16025
+ if (!projectPath)
16026
+ return 0;
16027
+ return getRepairProjectChunkProjectStatement(db).run(projectPath, projectPath).changes;
16028
+ }
16029
+ var upsertSessionProjectStatements, repairSessionChunkProjectStatements, repairProjectChunkProjectStatements;
16030
+ var init_session_project_storage = __esm(() => {
16031
+ upsertSessionProjectStatements = new WeakMap;
16032
+ repairSessionChunkProjectStatements = new WeakMap;
16033
+ repairProjectChunkProjectStatements = new WeakMap;
16034
+ });
16035
+
15628
16036
  // src/features/magic-context/overflow-detection.ts
15629
16037
  function extractErrorMessage(error51) {
15630
16038
  if (!error51)
@@ -16735,78 +17143,14 @@ function removeSystemReminders(text) {
16735
17143
  }
16736
17144
  var SYSTEM_DIRECTIVE_PREFIX = "[SYSTEM DIRECTIVE: MAGIC-CONTEXT";
16737
17145
 
16738
- // src/shared/sqlite.ts
16739
- function buildNodeSqliteDatabaseClass(DatabaseSync) {
16740
- const SAVEPOINT = "mc_tx_sp";
16741
-
16742
- class NodeSqliteDatabase extends DatabaseSync {
16743
- constructor(filename, options) {
16744
- const translated = { ...options };
16745
- if (options && "readonly" in options) {
16746
- translated.readOnly = options.readonly;
16747
- delete translated.readonly;
16748
- }
16749
- super(typeof filename === "string" ? filename : ":memory:", translated);
16750
- }
16751
- prepare(sql) {
16752
- const stmt = super.prepare(sql);
16753
- for (const method of ["run", "get", "all"]) {
16754
- const original = stmt[method].bind(stmt);
16755
- stmt[method] = (...args) => args.length === 1 && Array.isArray(args[0]) ? original(...args[0]) : original(...args);
16756
- }
16757
- return stmt;
16758
- }
16759
- transaction(fn) {
16760
- const self2 = this;
16761
- const wrapped = function(...args) {
16762
- const nested = self2.isTransaction === true;
16763
- self2.exec(nested ? `SAVEPOINT ${SAVEPOINT}` : "BEGIN");
16764
- try {
16765
- const result = fn.apply(this, args);
16766
- self2.exec(nested ? `RELEASE ${SAVEPOINT}` : "COMMIT");
16767
- return result;
16768
- } catch (error51) {
16769
- if (nested) {
16770
- self2.exec(`ROLLBACK TO ${SAVEPOINT}`);
16771
- self2.exec(`RELEASE ${SAVEPOINT}`);
16772
- } else {
16773
- self2.exec("ROLLBACK");
16774
- }
16775
- throw error51;
16776
- }
16777
- };
16778
- return wrapped;
16779
- }
16780
- }
16781
- return NodeSqliteDatabase;
16782
- }
16783
- var isBun, bunSpec, nodeSpec, sqliteModule, DatabaseImpl, Database;
16784
- var init_sqlite = __esm(async () => {
16785
- isBun = typeof process !== "undefined" && typeof process.versions?.bun === "string";
16786
- bunSpec = "bun:" + "sqlite";
16787
- nodeSpec = "node:" + "sqlite";
16788
- sqliteModule = isBun ? await import(bunSpec) : await import(nodeSpec);
16789
- DatabaseImpl = isBun ? sqliteModule.Database : buildNodeSqliteDatabaseClass(sqliteModule.DatabaseSync);
16790
- Database = DatabaseImpl;
16791
- });
16792
-
16793
- // src/shared/sqlite-helpers.ts
16794
- function closeQuietly(db) {
16795
- if (!db)
16796
- return;
16797
- try {
16798
- db.close();
16799
- } catch {}
16800
- }
16801
-
16802
17146
  // src/hooks/magic-context/read-session-db.ts
16803
- import { existsSync as existsSync6 } from "node:fs";
16804
- import { join as join3 } from "node:path";
16805
- function getOpenCodeDbPath() {
16806
- return join3(getDataDir(), "opencode", "opencode.db");
17147
+ import { existsSync as existsSync9 } from "node:fs";
17148
+ import { join as join4 } from "node:path";
17149
+ function getOpenCodeDbPath2() {
17150
+ return join4(getDataDir(), "opencode", "opencode.db");
16807
17151
  }
16808
17152
  function openCodeDbExists() {
16809
- return existsSync6(getOpenCodeDbPath());
17153
+ return existsSync9(getOpenCodeDbPath2());
16810
17154
  }
16811
17155
  function closeCachedReadOnlyDb() {
16812
17156
  if (!cachedReadOnlyDb) {
@@ -16821,7 +17165,7 @@ function closeCachedReadOnlyDb() {
16821
17165
  }
16822
17166
  }
16823
17167
  function getReadOnlySessionDb() {
16824
- const dbPath = getOpenCodeDbPath();
17168
+ const dbPath = getOpenCodeDbPath2();
16825
17169
  if (cachedReadOnlyDb?.path === dbPath) {
16826
17170
  return cachedReadOnlyDb.db;
16827
17171
  }
@@ -152555,82 +152899,6 @@ var init_project_docs_hash = __esm(() => {
152555
152899
  docsCache = new Map;
152556
152900
  });
152557
152901
 
152558
- // src/shared/error-message.ts
152559
- function getErrorMessage(error51) {
152560
- return error51 instanceof Error ? error51.message : String(error51);
152561
- }
152562
- function readString(value) {
152563
- if (typeof value === "string" && value.length > 0)
152564
- return value;
152565
- if (typeof value === "number")
152566
- return String(value);
152567
- return;
152568
- }
152569
- function clip(value, max) {
152570
- if (value.length <= max)
152571
- return value;
152572
- return `${value.slice(0, max)}…`;
152573
- }
152574
- function describeError(error51) {
152575
- const stringForm = clip(safeString(error51), 400);
152576
- if (!(error51 instanceof Error) && !(error51 && typeof error51 === "object")) {
152577
- return {
152578
- name: typeof error51,
152579
- message: "",
152580
- stringForm,
152581
- brief: stringForm || "<empty>"
152582
- };
152583
- }
152584
- const obj = error51;
152585
- const nameFromField = readString(obj.name);
152586
- const nameFromCtor = error51?.constructor?.name;
152587
- const name2 = nameFromField ?? nameFromCtor ?? "Error";
152588
- const message = readString(obj.message) ?? "";
152589
- const status = readString(obj.status) ?? readString(obj.statusCode);
152590
- const code = readString(obj.code);
152591
- let causeName;
152592
- const cause = obj.cause;
152593
- if (cause && typeof cause === "object") {
152594
- const causeRecord = cause;
152595
- causeName = readString(causeRecord.name) ?? cause.constructor?.name;
152596
- }
152597
- const stack = readString(obj.stack);
152598
- const stackHead = stack ? stack.split(`
152599
- `).slice(0, 4).map((l) => l.trim()).filter((l) => l.length > 0).join(" | ") : undefined;
152600
- const briefParts = [];
152601
- if (name2)
152602
- briefParts.push(name2);
152603
- if (message)
152604
- briefParts.push(`message="${clip(message, 200)}"`);
152605
- if (status)
152606
- briefParts.push(`status=${status}`);
152607
- if (code)
152608
- briefParts.push(`code=${code}`);
152609
- if (causeName)
152610
- briefParts.push(`cause=${causeName}`);
152611
- if (!message && stringForm && stringForm !== name2) {
152612
- briefParts.push(`str="${clip(stringForm, 200)}"`);
152613
- }
152614
- const brief = briefParts.join(" ") || stringForm || name2;
152615
- return {
152616
- name: name2,
152617
- message,
152618
- ...status ? { status } : {},
152619
- ...code ? { code } : {},
152620
- ...causeName ? { causeName } : {},
152621
- ...stackHead ? { stackHead } : {},
152622
- stringForm,
152623
- brief
152624
- };
152625
- }
152626
- function safeString(value) {
152627
- try {
152628
- return String(value);
152629
- } catch {
152630
- return "<unstringifiable>";
152631
- }
152632
- }
152633
-
152634
152902
  // src/shared/stable-json.ts
152635
152903
  function stableStringify(value, seen = new WeakSet) {
152636
152904
  if (value === undefined)
@@ -152742,12 +153010,12 @@ var init_tool_definition_tokens = __esm(() => {
152742
153010
  });
152743
153011
 
152744
153012
  // src/features/magic-context/tool-owner-backfill.ts
152745
- import { existsSync as existsSync7 } from "node:fs";
152746
- import { join as join4 } from "node:path";
153013
+ import { existsSync as existsSync10 } from "node:fs";
153014
+ import { join as join5 } from "node:path";
152747
153015
  function resolveOpencodeDbPath() {
152748
- return join4(getDataDir(), "opencode", "opencode.db");
153016
+ return join5(getDataDir(), "opencode", "opencode.db");
152749
153017
  }
152750
- function ensureBackfillStateTable(db) {
153018
+ function ensureBackfillStateTable2(db) {
152751
153019
  db.exec(`
152752
153020
  CREATE TABLE IF NOT EXISTS tool_owner_backfill_state (
152753
153021
  session_id TEXT PRIMARY KEY,
@@ -152763,7 +153031,7 @@ function ensureBackfillStateTable(db) {
152763
153031
  }
152764
153032
  function runToolOwnerBackfill(db) {
152765
153033
  const startedAt = performance.now();
152766
- ensureBackfillStateTable(db);
153034
+ ensureBackfillStateTable2(db);
152767
153035
  const result = {
152768
153036
  sessionsProcessed: 0,
152769
153037
  sessionsSkippedNoOcDb: 0,
@@ -152780,7 +153048,7 @@ function runToolOwnerBackfill(db) {
152780
153048
  return result;
152781
153049
  }
152782
153050
  const opencodeDbPath = resolveOpencodeDbPath();
152783
- if (!existsSync7(opencodeDbPath)) {
153051
+ if (!existsSync10(opencodeDbPath)) {
152784
153052
  log(`[backfill] OpenCode DB not found at ${opencodeDbPath} — marking all unbackfilled sessions as skipped. Lazy adoption (defense-in-depth) handles legacy rows at runtime.`);
152785
153053
  markAllUnbackfilledSessionsSkipped(db);
152786
153054
  result.sessionsSkippedNoOcDb = countSessionsByStatus(db, "skipped");
@@ -152803,7 +153071,7 @@ function runToolOwnerBackfill(db) {
152803
153071
  return result;
152804
153072
  }
152805
153073
  function isToolOwnerBackfillNeeded(db) {
152806
- ensureBackfillStateTable(db);
153074
+ ensureBackfillStateTable2(db);
152807
153075
  const row = db.prepare(`SELECT 1 AS hit
152808
153076
  FROM tags
152809
153077
  WHERE type = 'tool' AND tool_owner_message_id IS NULL
@@ -153004,8 +153272,8 @@ var init_tool_owner_backfill = __esm(() => {
153004
153272
  });
153005
153273
 
153006
153274
  // src/features/magic-context/storage-db.ts
153007
- import { chmodSync, copyFileSync, cpSync, existsSync as existsSync8, mkdirSync as mkdirSync4, mkdtempSync } from "node:fs";
153008
- import { dirname as dirname4, join as join5 } from "node:path";
153275
+ import { chmodSync, copyFileSync, cpSync, existsSync as existsSync11, mkdirSync as mkdirSync4, mkdtempSync } from "node:fs";
153276
+ import { dirname as dirname4, join as join6 } from "node:path";
153009
153277
  function getSchemaFenceRejection() {
153010
153278
  return lastSchemaFenceRejection;
153011
153279
  }
@@ -153024,7 +153292,7 @@ function restrictDatabaseFilePermissions(dbPath) {
153024
153292
  return;
153025
153293
  for (const suffix of ["", "-wal", "-shm"]) {
153026
153294
  const file2 = `${dbPath}${suffix}`;
153027
- if (!existsSync8(file2))
153295
+ if (!existsSync11(file2))
153028
153296
  continue;
153029
153297
  try {
153030
153298
  chmodSync(file2, 384);
@@ -153039,22 +153307,22 @@ function resolveDatabasePath(dbPathOverride) {
153039
153307
  }
153040
153308
  const testDataDir = process.env.MAGIC_CONTEXT_TEST_DATA_DIR;
153041
153309
  if (testDataDir && !process.env.XDG_DATA_HOME) {
153042
- const dbDir2 = join5(testDataDir, "cortexkit", "magic-context");
153043
- return { dbDir: dbDir2, dbPath: join5(dbDir2, "context.db") };
153310
+ const dbDir2 = join6(testDataDir, "cortexkit", "magic-context");
153311
+ return { dbDir: dbDir2, dbPath: join6(dbDir2, "context.db") };
153044
153312
  }
153045
153313
  if (false) {}
153046
153314
  const dbDir = getMagicContextStorageDir();
153047
- return { dbDir, dbPath: join5(dbDir, "context.db") };
153315
+ return { dbDir, dbPath: join6(dbDir, "context.db") };
153048
153316
  }
153049
153317
  function getDatabasePath(db) {
153050
153318
  return pathByDatabase.get(db) ?? null;
153051
153319
  }
153052
153320
  function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
153053
- if (existsSync8(targetDbPath))
153321
+ if (existsSync11(targetDbPath))
153054
153322
  return;
153055
153323
  const legacyDir = getLegacyOpenCodeMagicContextStorageDir();
153056
- const legacyDbPath = join5(legacyDir, "context.db");
153057
- if (!existsSync8(legacyDbPath))
153324
+ const legacyDbPath = join6(legacyDir, "context.db");
153325
+ if (!existsSync11(legacyDbPath))
153058
153326
  return;
153059
153327
  log(`[magic-context] migrating legacy plugin storage: ${legacyDir} -> ${targetDbDir} (legacy left in place as backup)`);
153060
153328
  ensureSecureStorageDir(targetDbDir);
@@ -153070,8 +153338,8 @@ function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
153070
153338
  }
153071
153339
  for (const suffix of ["", "-wal", "-shm"]) {
153072
153340
  const src = `${legacyDbPath}${suffix}`;
153073
- const dst = join5(targetDbDir, `context.db${suffix}`);
153074
- if (existsSync8(src)) {
153341
+ const dst = join6(targetDbDir, `context.db${suffix}`);
153342
+ if (existsSync11(src)) {
153075
153343
  try {
153076
153344
  copyFileSync(src, dst);
153077
153345
  } catch (error51) {
@@ -153079,9 +153347,9 @@ function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
153079
153347
  }
153080
153348
  }
153081
153349
  }
153082
- const legacyModelsDir = join5(legacyDir, "models");
153083
- const targetModelsDir = join5(targetDbDir, "models");
153084
- if (existsSync8(legacyModelsDir) && !existsSync8(targetModelsDir)) {
153350
+ const legacyModelsDir = join6(legacyDir, "models");
153351
+ const targetModelsDir = join6(targetDbDir, "models");
153352
+ if (existsSync11(legacyModelsDir) && !existsSync11(targetModelsDir)) {
153085
153353
  try {
153086
153354
  cpSync(legacyModelsDir, targetModelsDir, { recursive: true });
153087
153355
  } catch (error51) {
@@ -164181,10 +164449,10 @@ var require_stringify = __commonJS((exports, module) => {
164181
164449
  replacer = null;
164182
164450
  indent = EMPTY;
164183
164451
  };
164184
- var join6 = (one, two, gap) => one ? two ? one + two.trim() + LF + gap : one.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(one)), gap) : two ? two.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(two)), gap) : EMPTY;
164452
+ var join7 = (one, two, gap) => one ? two ? one + two.trim() + LF + gap : one.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(one)), gap) : two ? two.trimRight() + repeat_line_breaks(Math.max(1, count_trailing_line_breaks(two)), gap) : EMPTY;
164185
164453
  var join_content = (inside, value, gap) => {
164186
164454
  const comment = process_comments(value, PREFIX_BEFORE, gap + indent, true);
164187
- return join6(comment, inside, gap);
164455
+ return join7(comment, inside, gap);
164188
164456
  };
164189
164457
  var stringify_string = (holder, key, value) => {
164190
164458
  const raw = get_raw_string_literal(holder, key);
@@ -164206,13 +164474,13 @@ var require_stringify = __commonJS((exports, module) => {
164206
164474
  if (i !== 0) {
164207
164475
  inside += COMMA;
164208
164476
  }
164209
- const before = join6(after_comma, process_comments(value, BEFORE(i), deeper_gap), deeper_gap);
164477
+ const before = join7(after_comma, process_comments(value, BEFORE(i), deeper_gap), deeper_gap);
164210
164478
  inside += before || LF + deeper_gap;
164211
164479
  inside += stringify(i, value, deeper_gap) || STR_NULL;
164212
164480
  inside += process_comments(value, AFTER_VALUE(i), deeper_gap);
164213
164481
  after_comma = process_comments(value, AFTER(i), deeper_gap);
164214
164482
  }
164215
- inside += join6(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
164483
+ inside += join7(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
164216
164484
  return BRACKET_OPEN + join_content(inside, value, gap) + BRACKET_CLOSE;
164217
164485
  };
164218
164486
  var object_stringify = (value, gap) => {
@@ -164233,13 +164501,13 @@ var require_stringify = __commonJS((exports, module) => {
164233
164501
  inside += COMMA;
164234
164502
  }
164235
164503
  first = false;
164236
- const before = join6(after_comma, process_comments(value, BEFORE(key), deeper_gap), deeper_gap);
164504
+ const before = join7(after_comma, process_comments(value, BEFORE(key), deeper_gap), deeper_gap);
164237
164505
  inside += before || LF + deeper_gap;
164238
164506
  inside += quote(key) + process_comments(value, AFTER_PROP(key), deeper_gap) + COLON + process_comments(value, AFTER_COLON(key), deeper_gap) + SPACE + sv + process_comments(value, AFTER_VALUE(key), deeper_gap);
164239
164507
  after_comma = process_comments(value, AFTER(key), deeper_gap);
164240
164508
  };
164241
164509
  keys.forEach(iteratee);
164242
- inside += join6(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
164510
+ inside += join7(after_comma, process_comments(value, PREFIX_AFTER, deeper_gap), deeper_gap);
164243
164511
  return CURLY_BRACKET_OPEN + join_content(inside, value, gap) + CURLY_BRACKET_CLOSE;
164244
164512
  };
164245
164513
  function stringify(key, holder, gap) {
@@ -165239,16 +165507,16 @@ var init_compartment_prompt = () => {};
165239
165507
 
165240
165508
  // src/shared/opencode-config-dir.ts
165241
165509
  import { homedir as homedir6 } from "node:os";
165242
- import { join as join10, resolve as resolve3 } from "node:path";
165510
+ import { join as join11, resolve as resolve3 } from "node:path";
165243
165511
  function getCliConfigDir() {
165244
165512
  const envConfigDir = process.env.OPENCODE_CONFIG_DIR?.trim();
165245
165513
  if (envConfigDir) {
165246
165514
  return resolve3(envConfigDir);
165247
165515
  }
165248
165516
  if (process.platform === "win32") {
165249
- return join10(homedir6(), ".config", "opencode");
165517
+ return join11(homedir6(), ".config", "opencode");
165250
165518
  }
165251
- return join10(process.env.XDG_CONFIG_HOME || join10(homedir6(), ".config"), "opencode");
165519
+ return join11(process.env.XDG_CONFIG_HOME || join11(homedir6(), ".config"), "opencode");
165252
165520
  }
165253
165521
  function getOpenCodeConfigDir(_options) {
165254
165522
  return getCliConfigDir();
@@ -165257,16 +165525,16 @@ function getOpenCodeConfigPaths(options) {
165257
165525
  const configDir = getOpenCodeConfigDir(options);
165258
165526
  return {
165259
165527
  configDir,
165260
- configJson: join10(configDir, "opencode.json"),
165261
- configJsonc: join10(configDir, "opencode.jsonc"),
165262
- packageJson: join10(configDir, "package.json"),
165263
- omoConfig: join10(configDir, "magic-context.jsonc")
165528
+ configJson: join11(configDir, "opencode.json"),
165529
+ configJsonc: join11(configDir, "opencode.jsonc"),
165530
+ packageJson: join11(configDir, "package.json"),
165531
+ omoConfig: join11(configDir, "magic-context.jsonc")
165264
165532
  };
165265
165533
  }
165266
165534
  var init_opencode_config_dir = () => {};
165267
165535
 
165268
165536
  // src/shared/conflict-detector.ts
165269
- import { join as join11 } from "node:path";
165537
+ import { join as join12 } from "node:path";
165270
165538
  function detectConflicts(directory) {
165271
165539
  const conflicts = {
165272
165540
  compactionAuto: false,
@@ -165323,8 +165591,8 @@ function checkCompaction(directory) {
165323
165591
  return { auto: true, prune: false };
165324
165592
  }
165325
165593
  function readProjectCompaction(directory) {
165326
- const dotOcJsonc = join11(directory, ".opencode", "opencode.jsonc");
165327
- const dotOcJson = join11(directory, ".opencode", "opencode.json");
165594
+ const dotOcJsonc = join12(directory, ".opencode", "opencode.jsonc");
165595
+ const dotOcJson = join12(directory, ".opencode", "opencode.json");
165328
165596
  const dotOcConfig = readJsoncFile(dotOcJsonc) ?? readJsoncFile(dotOcJson);
165329
165597
  if (dotOcConfig?.compaction) {
165330
165598
  const c = dotOcConfig.compaction;
@@ -165332,8 +165600,8 @@ function readProjectCompaction(directory) {
165332
165600
  return { auto: c.auto === true, prune: c.prune === true, resolved: true };
165333
165601
  }
165334
165602
  }
165335
- const rootJsonc = join11(directory, "opencode.jsonc");
165336
- const rootJson = join11(directory, "opencode.json");
165603
+ const rootJsonc = join12(directory, "opencode.jsonc");
165604
+ const rootJson = join12(directory, "opencode.json");
165337
165605
  const rootConfig = readJsoncFile(rootJsonc) ?? readJsoncFile(rootJson);
165338
165606
  if (rootConfig?.compaction) {
165339
165607
  const c = rootConfig.compaction;
@@ -165387,10 +165655,10 @@ function collectPluginEntries(directory) {
165387
165655
  }
165388
165656
  };
165389
165657
  for (const configPath of [
165390
- join11(directory, ".opencode", "opencode.jsonc"),
165391
- join11(directory, ".opencode", "opencode.json"),
165392
- join11(directory, "opencode.jsonc"),
165393
- join11(directory, "opencode.json")
165658
+ join12(directory, ".opencode", "opencode.jsonc"),
165659
+ join12(directory, ".opencode", "opencode.json"),
165660
+ join12(directory, "opencode.jsonc"),
165661
+ join12(directory, "opencode.json")
165394
165662
  ]) {
165395
165663
  const config2 = readJsoncFile(configPath);
165396
165664
  pushFrom(config2?.plugin);
@@ -165431,7 +165699,7 @@ function readOmoDisabledHooks(directory) {
165431
165699
  try {
165432
165700
  const paths = getOpenCodeConfigPaths({ binary: "opencode" });
165433
165701
  for (const name2 of configNames) {
165434
- const configPath = join11(paths.configDir, name2);
165702
+ const configPath = join12(paths.configDir, name2);
165435
165703
  const config2 = readJsoncFile(configPath);
165436
165704
  if (config2?.disabled_hooks) {
165437
165705
  for (const hook of config2.disabled_hooks) {
@@ -165441,7 +165709,7 @@ function readOmoDisabledHooks(directory) {
165441
165709
  }
165442
165710
  } catch {}
165443
165711
  for (const name2 of configNames) {
165444
- const config2 = readJsoncFile(join11(directory, name2));
165712
+ const config2 = readJsoncFile(join12(directory, name2));
165445
165713
  if (config2?.disabled_hooks) {
165446
165714
  for (const hook of config2.disabled_hooks) {
165447
165715
  disabled.add(hook);
@@ -165592,28 +165860,28 @@ __export(exports_conflict_warning_hook, {
165592
165860
  sendConflictWarning: () => sendConflictWarning,
165593
165861
  cleanupConflictWarnings: () => cleanupConflictWarnings
165594
165862
  });
165595
- import { existsSync as existsSync12, readFileSync as readFileSync10 } from "node:fs";
165863
+ import { existsSync as existsSync15, readFileSync as readFileSync10 } from "node:fs";
165596
165864
  import { homedir as homedir7, platform as platform2 } from "node:os";
165597
- import { join as join12 } from "node:path";
165865
+ import { join as join13 } from "node:path";
165598
165866
  function getDesktopStatePath() {
165599
165867
  const os2 = platform2();
165600
165868
  const home = homedir7();
165601
165869
  if (os2 === "darwin") {
165602
- return join12(home, "Library", "Application Support", "ai.opencode.desktop", "opencode.global.dat");
165870
+ return join13(home, "Library", "Application Support", "ai.opencode.desktop", "opencode.global.dat");
165603
165871
  }
165604
165872
  if (os2 === "linux") {
165605
- const xdgConfig = process.env.XDG_CONFIG_HOME || join12(home, ".config");
165606
- return join12(xdgConfig, "ai.opencode.desktop", "opencode.global.dat");
165873
+ const xdgConfig = process.env.XDG_CONFIG_HOME || join13(home, ".config");
165874
+ return join13(xdgConfig, "ai.opencode.desktop", "opencode.global.dat");
165607
165875
  }
165608
165876
  if (os2 === "win32") {
165609
- const appData = process.env.APPDATA || join12(home, "AppData", "Roaming");
165610
- return join12(appData, "ai.opencode.desktop", "opencode.global.dat");
165877
+ const appData = process.env.APPDATA || join13(home, "AppData", "Roaming");
165878
+ return join13(appData, "ai.opencode.desktop", "opencode.global.dat");
165611
165879
  }
165612
165880
  return null;
165613
165881
  }
165614
165882
  function readDesktopState(directory) {
165615
165883
  const statePath = getDesktopStatePath();
165616
- if (!statePath || !existsSync12(statePath)) {
165884
+ if (!statePath || !existsSync15(statePath)) {
165617
165885
  log(`[magic-context] conflict-warning: Desktop state file not found at ${statePath}`);
165618
165886
  return { sessionId: null, sidecarUrl: null };
165619
165887
  }
@@ -165915,196 +166183,6 @@ var init_conflict_warning_hook = __esm(() => {
165915
166183
  cachedDesktopStateByDir = new Map;
165916
166184
  });
165917
166185
 
165918
- // src/features/magic-context/compaction-marker.ts
165919
- import { join as join13 } from "node:path";
165920
- function randomBase62(length) {
165921
- const chars = [];
165922
- for (let i = 0;i < length; i++) {
165923
- chars.push(BASE62_CHARS[Math.floor(Math.random() * BASE62_CHARS.length)]);
165924
- }
165925
- return chars.join("");
165926
- }
165927
- function generateId(prefix, timestampMs, counter = 0n) {
165928
- const encoded = BigInt(timestampMs) * 0x1000n + counter;
165929
- const hex3 = encoded.toString(16).padStart(14, "0");
165930
- return `${prefix}_${hex3}${randomBase62(14)}`;
165931
- }
165932
- function generateMessageId(timestampMs, counter = 0n) {
165933
- return generateId("msg", timestampMs, counter);
165934
- }
165935
- function generatePartId(timestampMs, counter = 0n) {
165936
- return generateId("prt", timestampMs, counter);
165937
- }
165938
- function getOpenCodeDbPath2() {
165939
- return join13(getDataDir(), "opencode", "opencode.db");
165940
- }
165941
- function isOpenCodeSchemaCompatible(db, dbPath) {
165942
- if (cachedSchemaCompatible?.path === dbPath) {
165943
- return cachedSchemaCompatible.compatible;
165944
- }
165945
- try {
165946
- const messageCols = new Set(db.prepare("PRAGMA table_info(message)").all().map((r) => r.name ?? "").filter((n) => n.length > 0));
165947
- const partCols = new Set(db.prepare("PRAGMA table_info(part)").all().map((r) => r.name ?? "").filter((n) => n.length > 0));
165948
- const missingMessage = REQUIRED_MESSAGE_COLUMNS.filter((c) => !messageCols.has(c));
165949
- const missingPart = REQUIRED_PART_COLUMNS.filter((c) => !partCols.has(c));
165950
- if (missingMessage.length > 0 || missingPart.length > 0) {
165951
- log(`[magic-context] compaction-marker: OpenCode DB schema missing required columns ` + `(message: [${missingMessage.join(", ")}], part: [${missingPart.join(", ")}]). ` + `Marker injection disabled for this process. ` + `This usually means OpenCode was updated and magic-context is out of date.`);
165952
- cachedSchemaCompatible = { path: dbPath, compatible: false };
165953
- return false;
165954
- }
165955
- cachedSchemaCompatible = { path: dbPath, compatible: true };
165956
- return true;
165957
- } catch (error51) {
165958
- log(`[magic-context] compaction-marker: schema probe failed: ${error51 instanceof Error ? error51.message : String(error51)}. ` + `Marker injection disabled until next process restart.`);
165959
- cachedSchemaCompatible = { path: dbPath, compatible: false };
165960
- return false;
165961
- }
165962
- }
165963
- function getWritableOpenCodeDb() {
165964
- const dbPath = getOpenCodeDbPath2();
165965
- if (cachedWriteDb?.path === dbPath) {
165966
- return cachedWriteDb.db;
165967
- }
165968
- if (cachedWriteDb) {
165969
- try {
165970
- closeQuietly(cachedWriteDb.db);
165971
- } catch {}
165972
- }
165973
- const db = new Database(dbPath);
165974
- db.exec("PRAGMA busy_timeout=5000");
165975
- db.exec("PRAGMA journal_mode=WAL");
165976
- cachedWriteDb = { path: dbPath, db };
165977
- return db;
165978
- }
165979
- function getNonSummaryMessageSortKey(sessionId, messageId) {
165980
- const db = getWritableOpenCodeDb();
165981
- const row = db.prepare(`SELECT time_created, id
165982
- FROM message
165983
- WHERE session_id = ?
165984
- AND id = ?
165985
- AND NOT (COALESCE(json_extract(data, '$.summary'), 0) = 1
165986
- AND COALESCE(json_extract(data, '$.finish'), '') = 'stop')
165987
- LIMIT 1`).get(sessionId, messageId);
165988
- if (typeof row?.time_created !== "number" || typeof row.id !== "string") {
165989
- return null;
165990
- }
165991
- return { id: row.id, timeCreated: row.time_created };
165992
- }
165993
- function findBoundaryUserMessage(sessionId, endMessageId) {
165994
- const db = getWritableOpenCodeDb();
165995
- const target = getNonSummaryMessageSortKey(sessionId, endMessageId);
165996
- if (!target)
165997
- return null;
165998
- const boundary = db.prepare(`SELECT id, time_created, data
165999
- FROM message
166000
- WHERE session_id = ?
166001
- AND NOT (COALESCE(json_extract(data, '$.summary'), 0) = 1
166002
- AND COALESCE(json_extract(data, '$.finish'), '') = 'stop')
166003
- AND COALESCE(json_extract(data, '$.role'), '') = 'user'
166004
- AND (time_created < ? OR (time_created = ? AND id <= ?))
166005
- ORDER BY time_created DESC, id DESC
166006
- LIMIT 1`).get(sessionId, target.timeCreated, target.timeCreated, target.id);
166007
- if (typeof boundary?.id !== "string" || typeof boundary.time_created !== "number") {
166008
- return null;
166009
- }
166010
- return { id: boundary.id, timeCreated: boundary.time_created };
166011
- }
166012
- function compareOpenCodeMessagesByCanonicalOrder(sessionId, leftMessageId, rightMessageId) {
166013
- const left = getNonSummaryMessageSortKey(sessionId, leftMessageId);
166014
- const right = getNonSummaryMessageSortKey(sessionId, rightMessageId);
166015
- if (!left || !right)
166016
- return null;
166017
- if (left.timeCreated < right.timeCreated)
166018
- return -1;
166019
- if (left.timeCreated > right.timeCreated)
166020
- return 1;
166021
- if (left.id < right.id)
166022
- return -1;
166023
- if (left.id > right.id)
166024
- return 1;
166025
- return 0;
166026
- }
166027
- function getOpenCodeMessageById(sessionId, messageId) {
166028
- const db = getWritableOpenCodeDb();
166029
- const row = db.prepare(`SELECT id FROM message WHERE session_id = ? AND id = ? LIMIT 1`).get(sessionId, messageId);
166030
- return row ?? null;
166031
- }
166032
- function injectCompactionMarker(args) {
166033
- const db = getWritableOpenCodeDb();
166034
- if (!isOpenCodeSchemaCompatible(db, getOpenCodeDbPath2())) {
166035
- return null;
166036
- }
166037
- const boundary = args.resolvedBoundary ?? findBoundaryUserMessage(args.sessionId, args.endMessageId);
166038
- if (!boundary) {
166039
- log(`[magic-context] compaction-marker: no user message found at or before endMessageId ${args.endMessageId} (ordinal ${args.endOrdinal})`);
166040
- return null;
166041
- }
166042
- const boundaryTime = boundary.timeCreated;
166043
- const summaryMsgId = generateMessageId(boundaryTime + 1, 1n);
166044
- const compactionPartId = generatePartId(boundaryTime, 1n);
166045
- const summaryPartId = generatePartId(boundaryTime + 1, 2n);
166046
- const summaryMsgData = JSON.stringify({
166047
- role: "assistant",
166048
- parentID: boundary.id,
166049
- summary: true,
166050
- finish: "stop",
166051
- mode: "compaction",
166052
- agent: "compaction",
166053
- path: { cwd: args.directory, root: args.directory },
166054
- cost: 0,
166055
- tokens: { input: 0, output: 0, reasoning: 0, cache: { read: 0, write: 0 } },
166056
- modelID: "magic-context",
166057
- providerID: "magic-context",
166058
- time: { created: boundaryTime + 1 }
166059
- });
166060
- try {
166061
- db.transaction(() => {
166062
- db.prepare("INSERT INTO part (id, message_id, session_id, time_created, time_updated, data) VALUES (?, ?, ?, ?, ?, ?)").run(compactionPartId, boundary.id, args.sessionId, boundaryTime, boundaryTime, '{"type":"compaction","auto":true}');
166063
- db.prepare("INSERT INTO message (id, session_id, time_created, time_updated, data) VALUES (?, ?, ?, ?, ?)").run(summaryMsgId, args.sessionId, boundaryTime + 1, boundaryTime + 1, summaryMsgData);
166064
- db.prepare("INSERT INTO part (id, message_id, session_id, time_created, time_updated, data) VALUES (?, ?, ?, ?, ?, ?)").run(summaryPartId, summaryMsgId, args.sessionId, boundaryTime + 1, boundaryTime + 1, JSON.stringify({ type: "text", text: args.summaryText }));
166065
- })();
166066
- log(`[magic-context] compaction-marker: injected boundary at user msg ${boundary.id} (ordinal ~${args.endOrdinal}), summary msg ${summaryMsgId}`);
166067
- return {
166068
- boundaryMessageId: boundary.id,
166069
- summaryMessageId: summaryMsgId,
166070
- compactionPartId,
166071
- summaryPartId
166072
- };
166073
- } catch (error51) {
166074
- log(`[magic-context] compaction-marker: injection failed: ${error51 instanceof Error ? error51.message : String(error51)}`);
166075
- return null;
166076
- }
166077
- }
166078
- function removeCompactionMarker(state) {
166079
- try {
166080
- const db = getWritableOpenCodeDb();
166081
- db.transaction(() => {
166082
- db.prepare("DELETE FROM part WHERE id = ?").run(state.summaryPartId);
166083
- db.prepare("DELETE FROM message WHERE id = ?").run(state.summaryMessageId);
166084
- db.prepare("DELETE FROM part WHERE id = ?").run(state.compactionPartId);
166085
- })();
166086
- return true;
166087
- } catch (error51) {
166088
- log(`[magic-context] compaction-marker: removal failed: ${error51 instanceof Error ? error51.message : String(error51)}`);
166089
- return false;
166090
- }
166091
- }
166092
- var BASE62_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", cachedWriteDb = null, REQUIRED_MESSAGE_COLUMNS, REQUIRED_PART_COLUMNS, cachedSchemaCompatible = null;
166093
- var init_compaction_marker = __esm(async () => {
166094
- init_data_path();
166095
- init_logger();
166096
- await init_sqlite();
166097
- REQUIRED_MESSAGE_COLUMNS = ["id", "session_id", "time_created", "time_updated", "data"];
166098
- REQUIRED_PART_COLUMNS = [
166099
- "id",
166100
- "message_id",
166101
- "session_id",
166102
- "time_created",
166103
- "time_updated",
166104
- "data"
166105
- ];
166106
- });
166107
-
166108
166186
  // src/features/magic-context/dreamer/task-config.ts
166109
166187
  var exports_task_config = {};
166110
166188
  __export(exports_task_config, {
@@ -167985,6 +168063,20 @@ function markGitSweepSuccessAndRelease(db, projectPath, holderId) {
167985
168063
  return result.changes === 1;
167986
168064
  });
167987
168065
  }
168066
+ function parkGitSweepNonIndexable(db, projectPath, holderId, reprobeMs = GIT_SWEEP_NON_INDEXABLE_REPROBE_MS) {
168067
+ return runImmediate2(db, () => {
168068
+ const now = Date.now();
168069
+ const sweptAt = now + reprobeMs - GIT_SWEEP_COOLDOWN_MS;
168070
+ const result = db.prepare(`UPDATE git_sweep_coordinator
168071
+ SET lease_holder = NULL,
168072
+ lease_expires_at = NULL,
168073
+ last_swept_at = ?
168074
+ WHERE project_path = ?
168075
+ AND lease_holder = ?
168076
+ AND lease_expires_at > ?`).run(sweptAt, projectPath, holderId, now);
168077
+ return result.changes === 1;
168078
+ });
168079
+ }
167988
168080
  function releaseGitSweepLease(db, projectPath, holderId) {
167989
168081
  runImmediate2(db, () => {
167990
168082
  db.prepare(`UPDATE git_sweep_coordinator
@@ -167994,10 +168086,11 @@ function releaseGitSweepLease(db, projectPath, holderId) {
167994
168086
  AND lease_holder = ?`).run(projectPath, holderId);
167995
168087
  });
167996
168088
  }
167997
- var GIT_SWEEP_COOLDOWN_MS, GIT_SWEEP_LEASE_TTL_MS, GIT_SWEEP_LEASE_RENEWAL_MS;
168089
+ var GIT_SWEEP_COOLDOWN_MS, GIT_SWEEP_LEASE_TTL_MS, GIT_SWEEP_NON_INDEXABLE_REPROBE_MS, GIT_SWEEP_LEASE_RENEWAL_MS;
167998
168090
  var init_sweep_coordinator = __esm(() => {
167999
168091
  GIT_SWEEP_COOLDOWN_MS = 10 * 60 * 1000;
168000
168092
  GIT_SWEEP_LEASE_TTL_MS = 5 * 60 * 1000;
168093
+ GIT_SWEEP_NON_INDEXABLE_REPROBE_MS = 24 * 60 * 60 * 1000;
168001
168094
  GIT_SWEEP_LEASE_RENEWAL_MS = 60 * 1000;
168002
168095
  });
168003
168096
 
@@ -168057,80 +168150,6 @@ var init_embedding_cache = __esm(() => {
168057
168150
  embeddingCacheTtlMs = DEFAULT_EMBEDDING_CACHE_TTL_MS;
168058
168151
  });
168059
168152
 
168060
- // src/features/magic-context/session-project-storage.ts
168061
- function getUpsertSessionProjectStatement(db) {
168062
- let stmt = upsertSessionProjectStatements.get(db);
168063
- if (!stmt) {
168064
- stmt = db.prepare(`INSERT INTO session_projects (session_id, harness, project_path, updated_at)
168065
- VALUES (?, ?, ?, ?)
168066
- ON CONFLICT(session_id, harness) DO UPDATE SET
168067
- project_path = excluded.project_path,
168068
- updated_at = excluded.updated_at
168069
- WHERE session_projects.project_path <> excluded.project_path`);
168070
- upsertSessionProjectStatements.set(db, stmt);
168071
- }
168072
- return stmt;
168073
- }
168074
- function getRepairSessionChunkProjectStatement(db) {
168075
- let stmt = repairSessionChunkProjectStatements.get(db);
168076
- if (!stmt) {
168077
- stmt = db.prepare(`UPDATE compartment_chunk_embeddings
168078
- SET project_path = ?
168079
- WHERE session_id = ?
168080
- AND harness = ?
168081
- AND project_path <> ?`);
168082
- repairSessionChunkProjectStatements.set(db, stmt);
168083
- }
168084
- return stmt;
168085
- }
168086
- function getRepairProjectChunkProjectStatement(db) {
168087
- let stmt = repairProjectChunkProjectStatements.get(db);
168088
- if (!stmt) {
168089
- stmt = db.prepare(`UPDATE compartment_chunk_embeddings
168090
- SET project_path = (
168091
- SELECT sp.project_path
168092
- FROM session_projects sp
168093
- WHERE sp.session_id = compartment_chunk_embeddings.session_id
168094
- AND sp.harness = compartment_chunk_embeddings.harness
168095
- LIMIT 1
168096
- )
168097
- WHERE EXISTS (
168098
- SELECT 1
168099
- FROM session_projects sp
168100
- WHERE sp.session_id = compartment_chunk_embeddings.session_id
168101
- AND sp.harness = compartment_chunk_embeddings.harness
168102
- AND sp.project_path <> compartment_chunk_embeddings.project_path
168103
- AND (
168104
- sp.project_path = ?
168105
- OR compartment_chunk_embeddings.project_path = ?
168106
- )
168107
- )`);
168108
- repairProjectChunkProjectStatements.set(db, stmt);
168109
- }
168110
- return stmt;
168111
- }
168112
- function recordSessionProjectIdentity(db, sessionId, projectPath) {
168113
- if (!sessionId || !projectPath)
168114
- return;
168115
- const harness = getHarness();
168116
- const now = Date.now();
168117
- db.transaction(() => {
168118
- getUpsertSessionProjectStatement(db).run(sessionId, harness, projectPath, now);
168119
- getRepairSessionChunkProjectStatement(db).run(projectPath, sessionId, harness, projectPath);
168120
- })();
168121
- }
168122
- function repairMisScopedCompartmentChunkEmbeddingsForProject(db, projectPath) {
168123
- if (!projectPath)
168124
- return 0;
168125
- return getRepairProjectChunkProjectStatement(db).run(projectPath, projectPath).changes;
168126
- }
168127
- var upsertSessionProjectStatements, repairSessionChunkProjectStatements, repairProjectChunkProjectStatements;
168128
- var init_session_project_storage = __esm(() => {
168129
- upsertSessionProjectStatements = new WeakMap;
168130
- repairSessionChunkProjectStatements = new WeakMap;
168131
- repairProjectChunkProjectStatements = new WeakMap;
168132
- });
168133
-
168134
168153
  // src/features/magic-context/project-embedding-registry.ts
168135
168154
  import { createHash as createHash8, randomUUID } from "node:crypto";
168136
168155
  function markProjectLoadUntrusted(projectIdentity) {
@@ -169767,7 +169786,7 @@ function getMemoryVerifications(db, memoryIds) {
169767
169786
  var MEMORY_VERIFICATION_SENTINEL = "";
169768
169787
  // src/features/magic-context/memory/verification-paths.ts
169769
169788
  import { execFile } from "node:child_process";
169770
- import { existsSync as existsSync14, realpathSync as realpathSync2, statSync as statSync5 } from "node:fs";
169789
+ import { existsSync as existsSync16, realpathSync as realpathSync2, statSync as statSync5 } from "node:fs";
169771
169790
  import path6 from "node:path";
169772
169791
  import { promisify } from "node:util";
169773
169792
  async function runGit(cwd, args) {
@@ -169870,7 +169889,7 @@ function verificationFileExists(baseRoot, filePath) {
169870
169889
  return false;
169871
169890
  const root = path6.resolve(baseRoot);
169872
169891
  const candidate = path6.resolve(root, filePath);
169873
- return isWithin(root, candidate) && existsSync14(candidate);
169892
+ return isWithin(root, candidate) && existsSync16(candidate);
169874
169893
  }
169875
169894
  async function normalizeVerificationFiles(args) {
169876
169895
  const cwd = path6.resolve(args.cwd);
@@ -169903,7 +169922,7 @@ async function normalizeVerificationFiles(args) {
169903
169922
  warnings.push(`Skipped verification path "${value}" because it is the repo/project root.`);
169904
169923
  continue;
169905
169924
  }
169906
- if (existsSync14(candidate)) {
169925
+ if (existsSync16(candidate)) {
169907
169926
  try {
169908
169927
  if (statSync5(candidate).isDirectory()) {
169909
169928
  warnings.push(`Skipped verification path "${value}" because it is a directory.`);
@@ -169934,7 +169953,7 @@ async function normalizeVerificationFiles(args) {
169934
169953
  }
169935
169954
  normalized.push(tracked);
169936
169955
  } else {
169937
- if (!existsSync14(candidate)) {
169956
+ if (!existsSync16(candidate)) {
169938
169957
  warnings.push(`Skipped verification path "${value}" because it does not exist.`);
169939
169958
  continue;
169940
169959
  }
@@ -177278,6 +177297,9 @@ function applyDeferredCompactionMarker(db, sessionId, pending, directory) {
177278
177297
  }
177279
177298
  }
177280
177299
  function updateCompactionMarkerAfterPublication(db, sessionId, lastCompartmentEnd, directory) {
177300
+ if (getHarness() !== "opencode") {
177301
+ return true;
177302
+ }
177281
177303
  const targetEndMessageId = getCompartmentEndMessageIdForOrdinal(db, sessionId, lastCompartmentEnd);
177282
177304
  if (!targetEndMessageId) {
177283
177305
  sessionLog(sessionId, `compaction-marker: no compartment endMessageId for ordinal ${lastCompartmentEnd}; preserving existing marker`);
@@ -186334,6 +186356,29 @@ function getMagicContextBuiltinCommands() {
186334
186356
  };
186335
186357
  }
186336
186358
 
186359
+ // src/features/magic-context/dreamer/open-opencode-db.ts
186360
+ init_logger();
186361
+ await __promiseAll([
186362
+ init_sqlite(),
186363
+ init_compaction_marker()
186364
+ ]);
186365
+ import { existsSync as existsSync7 } from "node:fs";
186366
+ function openOpenCodeDb() {
186367
+ const dbPath = getOpenCodeDbPath();
186368
+ if (!existsSync7(dbPath)) {
186369
+ log(`[dreamer] OpenCode DB not found at ${dbPath} — skipping OpenCode history scan`);
186370
+ return null;
186371
+ }
186372
+ try {
186373
+ const db = new Database(dbPath, { readonly: true });
186374
+ db.exec("PRAGMA busy_timeout = 5000");
186375
+ return db;
186376
+ } catch (error51) {
186377
+ log(`[dreamer] failed to open OpenCode DB at ${dbPath}: ${getErrorMessage(error51)}`);
186378
+ return null;
186379
+ }
186380
+ }
186381
+
186337
186382
  // src/features/magic-context/dreamer/task-prompts.ts
186338
186383
  var DREAMER_SYSTEM_PROMPT = `You are a background maintenance agent for the magic-context system, running during a scheduled dream window. Your task and its full instructions arrive in the message below. Never read or quote secrets from .env, credentials, or key files, and never commit — the user handles git.`;
186339
186384
  var PROJECT_MEMORY_TAXONOMY = `## Memory taxonomy (5 categories)
@@ -186643,6 +186688,192 @@ function buildDreamTaskPrompt(task, args) {
186643
186688
  // src/index.ts
186644
186689
  init_project_identity();
186645
186690
 
186691
+ // src/features/magic-context/session-project-backfill.ts
186692
+ init_logger();
186693
+ init_project_identity();
186694
+ init_session_project_storage();
186695
+ import { existsSync as existsSync8 } from "node:fs";
186696
+ var LEASE_TTL_MS = 10 * 60 * 1000;
186697
+ var SESSION_QUERY_CHUNK_SIZE = 250;
186698
+ var YIELD_EVERY_NEW_DIRECTORIES = 10;
186699
+ function ensureBackfillStateTable(db) {
186700
+ db.exec(`
186701
+ CREATE TABLE IF NOT EXISTS session_project_backfill_state (
186702
+ harness TEXT PRIMARY KEY,
186703
+ status TEXT NOT NULL CHECK (status IN ('running', 'completed')),
186704
+ started_at INTEGER,
186705
+ lease_expires_at INTEGER,
186706
+ completed_at INTEGER
186707
+ );
186708
+ `);
186709
+ }
186710
+ function withImmediateTransaction(db, fn) {
186711
+ db.exec("BEGIN IMMEDIATE");
186712
+ try {
186713
+ const result = fn();
186714
+ db.exec("COMMIT");
186715
+ return result;
186716
+ } catch (error51) {
186717
+ try {
186718
+ db.exec("ROLLBACK");
186719
+ } catch {}
186720
+ throw error51;
186721
+ }
186722
+ }
186723
+ function defaultYieldFn() {
186724
+ return new Promise((resolve2) => setTimeout(resolve2, 0));
186725
+ }
186726
+ function acquireBackfillLease(db, harness, now) {
186727
+ ensureBackfillStateTable(db);
186728
+ return withImmediateTransaction(db, () => {
186729
+ const current = db.prepare(`SELECT harness, status, started_at, lease_expires_at, completed_at
186730
+ FROM session_project_backfill_state
186731
+ WHERE harness = ?`).get(harness);
186732
+ if (current?.status === "completed") {
186733
+ return "already_completed";
186734
+ }
186735
+ if (current?.status === "running" && current.lease_expires_at !== null && current.lease_expires_at > now) {
186736
+ return "blocked_by_lease";
186737
+ }
186738
+ db.prepare(`INSERT INTO session_project_backfill_state(
186739
+ harness,
186740
+ status,
186741
+ started_at,
186742
+ lease_expires_at,
186743
+ completed_at
186744
+ )
186745
+ VALUES (?, 'running', ?, ?, NULL)
186746
+ ON CONFLICT(harness) DO UPDATE SET
186747
+ status = 'running',
186748
+ started_at = excluded.started_at,
186749
+ lease_expires_at = excluded.lease_expires_at,
186750
+ completed_at = NULL`).run(harness, now, now + LEASE_TTL_MS);
186751
+ return "completed";
186752
+ });
186753
+ }
186754
+ function renewBackfillLease(db, harness, now) {
186755
+ ensureBackfillStateTable(db);
186756
+ db.prepare(`UPDATE session_project_backfill_state
186757
+ SET lease_expires_at = ?
186758
+ WHERE harness = ? AND status = 'running'`).run(now + LEASE_TTL_MS, harness);
186759
+ }
186760
+ function markBackfillCompleted(db, harness, now) {
186761
+ ensureBackfillStateTable(db);
186762
+ db.prepare(`INSERT INTO session_project_backfill_state(
186763
+ harness,
186764
+ status,
186765
+ started_at,
186766
+ lease_expires_at,
186767
+ completed_at
186768
+ )
186769
+ VALUES (?, 'completed', ?, NULL, ?)
186770
+ ON CONFLICT(harness) DO UPDATE SET
186771
+ status = 'completed',
186772
+ lease_expires_at = NULL,
186773
+ completed_at = excluded.completed_at`).run(harness, now, now);
186774
+ }
186775
+ function dedupeSessions(sessions) {
186776
+ const sessionsById = new Map;
186777
+ for (const session of sessions) {
186778
+ if (!session.sessionId)
186779
+ continue;
186780
+ const existing = sessionsById.get(session.sessionId);
186781
+ if (!existing) {
186782
+ sessionsById.set(session.sessionId, {
186783
+ sessionId: session.sessionId,
186784
+ directory: session.directory
186785
+ });
186786
+ continue;
186787
+ }
186788
+ if (!existing.directory && session.directory) {
186789
+ sessionsById.set(session.sessionId, {
186790
+ sessionId: session.sessionId,
186791
+ directory: session.directory
186792
+ });
186793
+ }
186794
+ }
186795
+ return [...sessionsById.values()];
186796
+ }
186797
+ function getMappedSessionIds(db, harness, sessions) {
186798
+ const mapped = new Set;
186799
+ for (let index = 0;index < sessions.length; index += SESSION_QUERY_CHUNK_SIZE) {
186800
+ const chunk = sessions.slice(index, index + SESSION_QUERY_CHUNK_SIZE);
186801
+ if (chunk.length === 0)
186802
+ continue;
186803
+ const placeholders = chunk.map(() => "?").join(", ");
186804
+ const rows = db.prepare(`SELECT session_id
186805
+ FROM session_projects
186806
+ WHERE harness = ?
186807
+ AND session_id IN (${placeholders})`).all(harness, ...chunk.map((session) => session.sessionId));
186808
+ for (const row of rows) {
186809
+ mapped.add(row.session_id);
186810
+ }
186811
+ }
186812
+ return mapped;
186813
+ }
186814
+ async function runSessionProjectBackfill(db, sessions, options = {}) {
186815
+ const startedAt = performance.now();
186816
+ const harness = getHarness();
186817
+ const now = options.now ?? Date.now;
186818
+ const resolveIdentity = options.resolveIdentity ?? resolveProjectIdentity;
186819
+ const yieldFn = options.yieldFn ?? defaultYieldFn;
186820
+ const dedupedSessions = dedupeSessions(sessions);
186821
+ const result = {
186822
+ status: "completed",
186823
+ totalSessions: dedupedSessions.length,
186824
+ alreadyMappedSessions: 0,
186825
+ unmappedSessions: 0,
186826
+ backfilledSessions: 0,
186827
+ skippedDeadDirectories: 0,
186828
+ skippedEmptyDirectories: 0,
186829
+ durationMs: 0
186830
+ };
186831
+ const leaseStatus = acquireBackfillLease(db, harness, now());
186832
+ if (leaseStatus !== "completed") {
186833
+ result.status = leaseStatus;
186834
+ result.durationMs = performance.now() - startedAt;
186835
+ return result;
186836
+ }
186837
+ const mappedSessionIds = getMappedSessionIds(db, harness, dedupedSessions);
186838
+ result.alreadyMappedSessions = mappedSessionIds.size;
186839
+ const existenceCache = new Map;
186840
+ const identityCache2 = new Map;
186841
+ let newDirectoryResolutions = 0;
186842
+ for (const session of dedupedSessions) {
186843
+ if (mappedSessionIds.has(session.sessionId)) {
186844
+ continue;
186845
+ }
186846
+ result.unmappedSessions += 1;
186847
+ if (!session.directory) {
186848
+ result.skippedEmptyDirectories += 1;
186849
+ continue;
186850
+ }
186851
+ const stillExists = existenceCache.get(session.directory) ?? existsSync8(session.directory);
186852
+ existenceCache.set(session.directory, stillExists);
186853
+ if (!stillExists) {
186854
+ result.skippedDeadDirectories += 1;
186855
+ continue;
186856
+ }
186857
+ let identity = identityCache2.get(session.directory);
186858
+ if (!identity) {
186859
+ identity = resolveIdentity(session.directory);
186860
+ identityCache2.set(session.directory, identity);
186861
+ newDirectoryResolutions += 1;
186862
+ if (newDirectoryResolutions % YIELD_EVERY_NEW_DIRECTORIES === 0) {
186863
+ renewBackfillLease(db, harness, now());
186864
+ await yieldFn();
186865
+ renewBackfillLease(db, harness, now());
186866
+ }
186867
+ }
186868
+ recordSessionProjectIdentity(db, session.sessionId, identity);
186869
+ result.backfilledSessions += 1;
186870
+ }
186871
+ markBackfillCompleted(db, harness, now());
186872
+ result.durationMs = performance.now() - startedAt;
186873
+ log(`[session-projects] backfilled ${result.backfilledSessions} of ${result.unmappedSessions} unmapped sessions (skipped ${result.skippedDeadDirectories} dead dirs) in ${Math.round(result.durationMs)}ms`);
186874
+ return result;
186875
+ }
186876
+
186646
186877
  // src/features/magic-context/sidekick/agent.ts
186647
186878
  init_language_directive();
186648
186879
 
@@ -187033,45 +187264,45 @@ async function runDeferredV22Backfill(db, options = {}) {
187033
187264
 
187034
187265
  // src/hooks/auto-update-checker/index.ts
187035
187266
  init_logger();
187036
- import { existsSync as existsSync11, mkdirSync as mkdirSync5, readFileSync as readFileSync9, renameSync as renameSync3, writeFileSync as writeFileSync5 } from "node:fs";
187037
- import { dirname as dirname7, join as join9 } from "node:path";
187267
+ import { existsSync as existsSync14, mkdirSync as mkdirSync5, readFileSync as readFileSync9, renameSync as renameSync3, writeFileSync as writeFileSync5 } from "node:fs";
187268
+ import { dirname as dirname7, join as join10 } from "node:path";
187038
187269
 
187039
187270
  // src/hooks/auto-update-checker/cache.ts
187040
187271
  init_logger();
187041
187272
  var import_comment_json2 = __toESM(require_src2(), 1);
187042
187273
  import { spawn } from "node:child_process";
187043
- import { existsSync as existsSync10, readFileSync as readFileSync8, rmSync as rmSync2, writeFileSync as writeFileSync4 } from "node:fs";
187044
- import { basename as basename2, dirname as dirname6, join as join8 } from "node:path";
187274
+ import { existsSync as existsSync13, readFileSync as readFileSync8, rmSync as rmSync2, writeFileSync as writeFileSync4 } from "node:fs";
187275
+ import { basename as basename2, dirname as dirname6, join as join9 } from "node:path";
187045
187276
 
187046
187277
  // src/hooks/auto-update-checker/checker.ts
187047
187278
  init_logger();
187048
187279
  var import_comment_json = __toESM(require_src2(), 1);
187049
- import { existsSync as existsSync9, readFileSync as readFileSync7, renameSync as renameSync2, statSync as statSync4, writeFileSync as writeFileSync3 } from "node:fs";
187280
+ import { existsSync as existsSync12, readFileSync as readFileSync7, renameSync as renameSync2, statSync as statSync4, writeFileSync as writeFileSync3 } from "node:fs";
187050
187281
  import { homedir as homedir5 } from "node:os";
187051
- import { dirname as dirname5, isAbsolute as isAbsolute3, join as join7, resolve as resolve2 } from "node:path";
187282
+ import { dirname as dirname5, isAbsolute as isAbsolute3, join as join8, resolve as resolve2 } from "node:path";
187052
187283
  import { fileURLToPath } from "node:url";
187053
187284
 
187054
187285
  // src/hooks/auto-update-checker/constants.ts
187055
187286
  import { homedir as homedir4, platform } from "node:os";
187056
- import { join as join6 } from "node:path";
187287
+ import { join as join7 } from "node:path";
187057
187288
  var PACKAGE_NAME = "@cortexkit/opencode-magic-context";
187058
187289
  var NPM_REGISTRY_URL = "https://registry.npmjs.org";
187059
187290
  var NPM_FETCH_TIMEOUT = 1e4;
187060
187291
  function getOpenCodeCacheRoot() {
187061
187292
  if (platform() === "win32") {
187062
- return join6(process.env.LOCALAPPDATA ?? homedir4(), "opencode");
187293
+ return join7(process.env.LOCALAPPDATA ?? homedir4(), "opencode");
187063
187294
  }
187064
- return join6(homedir4(), ".cache", "opencode");
187295
+ return join7(homedir4(), ".cache", "opencode");
187065
187296
  }
187066
187297
  function getOpenCodeConfigRoot() {
187067
187298
  if (platform() === "win32") {
187068
- return join6(process.env.APPDATA ?? join6(homedir4(), "AppData", "Roaming"), "opencode");
187299
+ return join7(process.env.APPDATA ?? join7(homedir4(), "AppData", "Roaming"), "opencode");
187069
187300
  }
187070
- return join6(process.env.XDG_CONFIG_HOME ?? join6(homedir4(), ".config"), "opencode");
187301
+ return join7(process.env.XDG_CONFIG_HOME ?? join7(homedir4(), ".config"), "opencode");
187071
187302
  }
187072
- var CACHE_DIR = join6(getOpenCodeCacheRoot(), "packages");
187073
- var USER_OPENCODE_CONFIG = join6(getOpenCodeConfigRoot(), "opencode.json");
187074
- var USER_OPENCODE_CONFIG_JSONC = join6(getOpenCodeConfigRoot(), "opencode.jsonc");
187303
+ var CACHE_DIR = join7(getOpenCodeCacheRoot(), "packages");
187304
+ var USER_OPENCODE_CONFIG = join7(getOpenCodeConfigRoot(), "opencode.json");
187305
+ var USER_OPENCODE_CONFIG_JSONC = join7(getOpenCodeConfigRoot(), "opencode.jsonc");
187075
187306
  // src/hooks/auto-update-checker/types.ts
187076
187307
  init_zod();
187077
187308
  var NpmPackageEnvelopeSchema = exports_external.object({
@@ -187132,8 +187363,8 @@ function extractChannel(version2) {
187132
187363
  }
187133
187364
  function getConfigPaths(directory) {
187134
187365
  return [
187135
- join7(directory, ".opencode", "opencode.json"),
187136
- join7(directory, ".opencode", "opencode.jsonc"),
187366
+ join8(directory, ".opencode", "opencode.json"),
187367
+ join8(directory, ".opencode", "opencode.jsonc"),
187137
187368
  USER_OPENCODE_CONFIG,
187138
187369
  USER_OPENCODE_CONFIG_JSONC
187139
187370
  ];
@@ -187155,8 +187386,8 @@ function findPackageJsonUp(startPath) {
187155
187386
  const stat = statSync4(startPath);
187156
187387
  let dir = stat.isDirectory() ? startPath : dirname5(startPath);
187157
187388
  for (let i = 0;i < 10; i++) {
187158
- const pkgPath = join7(dir, "package.json");
187159
- if (existsSync9(pkgPath)) {
187389
+ const pkgPath = join8(dir, "package.json");
187390
+ if (existsSync12(pkgPath)) {
187160
187391
  try {
187161
187392
  const pkg = PackageJsonSchema.safeParse(JSON.parse(readFileSync7(pkgPath, "utf-8")));
187162
187393
  if (pkg.success && pkg.data.name === PACKAGE_NAME)
@@ -187174,7 +187405,7 @@ function findPackageJsonUp(startPath) {
187174
187405
  function getLocalDevPath(directory) {
187175
187406
  for (const configPath of getConfigPaths(directory)) {
187176
187407
  try {
187177
- if (!existsSync9(configPath))
187408
+ if (!existsSync12(configPath))
187178
187409
  continue;
187179
187410
  const rawConfig = parseJsonConfig(readFileSync7(configPath, "utf-8"));
187180
187411
  const plugins = getPluginEntries(rawConfig);
@@ -187220,7 +187451,7 @@ function getCurrentRuntimePackageJsonPath(currentModuleUrl = import.meta.url) {
187220
187451
  function findPluginEntry(directory) {
187221
187452
  for (const configPath of getConfigPaths(directory)) {
187222
187453
  try {
187223
- if (!existsSync9(configPath))
187454
+ if (!existsSync12(configPath))
187224
187455
  continue;
187225
187456
  const rawConfig = parseJsonConfig(readFileSync7(configPath, "utf-8"));
187226
187457
  const plugins = getPluginEntries(rawConfig);
@@ -187245,7 +187476,7 @@ function findPluginEntry(directory) {
187245
187476
  }
187246
187477
  var cachedPackageVersion = null;
187247
187478
  function getSpecCachePackageJsonPath(spec) {
187248
- return join7(CACHE_DIR, spec, "node_modules", PACKAGE_NAME, "package.json");
187479
+ return join8(CACHE_DIR, spec, "node_modules", PACKAGE_NAME, "package.json");
187249
187480
  }
187250
187481
  function getCachedVersion(spec) {
187251
187482
  if (!spec && cachedPackageVersion)
@@ -187254,11 +187485,11 @@ function getCachedVersion(spec) {
187254
187485
  getCurrentRuntimePackageJsonPath(),
187255
187486
  spec ? getSpecCachePackageJsonPath(spec) : null,
187256
187487
  getSpecCachePackageJsonPath(`${PACKAGE_NAME}@latest`),
187257
- join7(homedir5(), ".cache", "opencode", "node_modules", PACKAGE_NAME, "package.json")
187488
+ join8(homedir5(), ".cache", "opencode", "node_modules", PACKAGE_NAME, "package.json")
187258
187489
  ].filter(isString);
187259
187490
  for (const packageJsonPath of candidates) {
187260
187491
  try {
187261
- if (!existsSync9(packageJsonPath))
187492
+ if (!existsSync12(packageJsonPath))
187262
187493
  continue;
187263
187494
  const pkg = PackageJsonSchema.safeParse(JSON.parse(readFileSync7(packageJsonPath, "utf-8")));
187264
187495
  if (pkg.success && pkg.data.version) {
@@ -187312,8 +187543,8 @@ function stripPackageNameFromPath(pathValue, packageName) {
187312
187543
  return current;
187313
187544
  }
187314
187545
  function removeFromPackageLock(installDir, packageName) {
187315
- const lockPath = join8(installDir, "package-lock.json");
187316
- if (!existsSync10(lockPath))
187546
+ const lockPath = join9(installDir, "package-lock.json");
187547
+ if (!existsSync13(lockPath))
187317
187548
  return false;
187318
187549
  try {
187319
187550
  const lock = import_comment_json2.parse(readFileSync8(lockPath, "utf-8"));
@@ -187339,7 +187570,7 @@ function removeFromPackageLock(installDir, packageName) {
187339
187570
  }
187340
187571
  }
187341
187572
  function ensureDependencyVersion(packageJsonPath, packageName, version2) {
187342
- if (!existsSync10(packageJsonPath))
187573
+ if (!existsSync13(packageJsonPath))
187343
187574
  return false;
187344
187575
  try {
187345
187576
  const raw = import_comment_json2.parse(readFileSync8(packageJsonPath, "utf-8"));
@@ -187361,8 +187592,8 @@ function ensureDependencyVersion(packageJsonPath, packageName, version2) {
187361
187592
  }
187362
187593
  }
187363
187594
  function removeInstalledPackage(installDir, packageName) {
187364
- const packageDir = join8(installDir, "node_modules", packageName);
187365
- if (!existsSync10(packageDir))
187595
+ const packageDir = join9(installDir, "node_modules", packageName);
187596
+ if (!existsSync13(packageDir))
187366
187597
  return false;
187367
187598
  try {
187368
187599
  rmSync2(packageDir, { recursive: true, force: true, maxRetries: 5, retryDelay: 100 });
@@ -187383,8 +187614,8 @@ function resolveInstallContext(runtimePackageJsonPath = getCurrentRuntimePackage
187383
187614
  const nodeModulesDir = stripPackageNameFromPath(packageDir, PACKAGE_NAME);
187384
187615
  if (nodeModulesDir && basename2(nodeModulesDir) === "node_modules") {
187385
187616
  const installDir = dirname6(nodeModulesDir);
187386
- const packageJsonPath = join8(installDir, "package.json");
187387
- if (!existsSync10(packageJsonPath)) {
187617
+ const packageJsonPath = join9(installDir, "package.json");
187618
+ if (!existsSync13(packageJsonPath)) {
187388
187619
  try {
187389
187620
  writeFileSync4(packageJsonPath, `${JSON.stringify({ private: true, dependencies: {} }, null, 2)}
187390
187621
  `);
@@ -187398,8 +187629,8 @@ function resolveInstallContext(runtimePackageJsonPath = getCurrentRuntimePackage
187398
187629
  }
187399
187630
  return null;
187400
187631
  }
187401
- const legacyPackageJsonPath = join8(dirname6(CACHE_DIR), "package.json");
187402
- if (existsSync10(legacyPackageJsonPath)) {
187632
+ const legacyPackageJsonPath = join9(dirname6(CACHE_DIR), "package.json");
187633
+ if (existsSync13(legacyPackageJsonPath)) {
187403
187634
  return { installDir: dirname6(CACHE_DIR), packageJsonPath: legacyPackageJsonPath };
187404
187635
  }
187405
187636
  return null;
@@ -187523,8 +187754,8 @@ function claimCheckSlot(storageDir, intervalMs) {
187523
187754
  if (!storageDir)
187524
187755
  return true;
187525
187756
  try {
187526
- const file2 = join9(storageDir, TIMESTAMP_FILENAME);
187527
- if (existsSync11(file2)) {
187757
+ const file2 = join10(storageDir, TIMESTAMP_FILENAME);
187758
+ if (existsSync14(file2)) {
187528
187759
  try {
187529
187760
  const raw = JSON.parse(readFileSync9(file2, "utf-8"));
187530
187761
  const last = typeof raw.lastCheckedMs === "number" ? raw.lastCheckedMs : 0;
@@ -187830,29 +188061,6 @@ function releaseLease(db, holderId, leaseKey = DREAMING_LEASE_KEY) {
187830
188061
  });
187831
188062
  }
187832
188063
 
187833
- // src/features/magic-context/dreamer/open-opencode-db.ts
187834
- init_logger();
187835
- await __promiseAll([
187836
- init_sqlite(),
187837
- init_compaction_marker()
187838
- ]);
187839
- import { existsSync as existsSync13 } from "node:fs";
187840
- function openOpenCodeDb() {
187841
- const dbPath = getOpenCodeDbPath2();
187842
- if (!existsSync13(dbPath)) {
187843
- log(`[key-files] OpenCode DB not found at ${dbPath} — skipping`);
187844
- return null;
187845
- }
187846
- try {
187847
- const db = new Database(dbPath, { readonly: true });
187848
- db.exec("PRAGMA busy_timeout = 5000");
187849
- return db;
187850
- } catch (error51) {
187851
- log(`[key-files] failed to open OpenCode DB at ${dbPath}: ${getErrorMessage(error51)}`);
187852
- return null;
187853
- }
187854
- }
187855
-
187856
188064
  // src/features/magic-context/dreamer/retrospective-orphan-sweep.ts
187857
188065
  init_logger();
187858
188066
  var RETROSPECTIVE_CHILD_TITLE = "magic-context-dream-retrospective";
@@ -188275,7 +188483,7 @@ init_task_config();
188275
188483
 
188276
188484
  // src/features/magic-context/dreamer/task-executor.ts
188277
188485
  import { createHash as createHash10 } from "node:crypto";
188278
- import { existsSync as existsSync17 } from "node:fs";
188486
+ import { existsSync as existsSync19 } from "node:fs";
188279
188487
 
188280
188488
  // src/agents/dreamer.ts
188281
188489
  var DREAMER_AGENT = "dreamer";
@@ -190362,7 +190570,7 @@ Output exactly JSON: {"met": false}`;
190362
190570
 
190363
190571
  // src/features/magic-context/dreamer/maintain-docs-protected-enforcement.ts
190364
190572
  init_logger();
190365
- import { existsSync as existsSync15, readFileSync as readFileSync11, writeFileSync as writeFileSync6 } from "node:fs";
190573
+ import { existsSync as existsSync17, readFileSync as readFileSync11, writeFileSync as writeFileSync6 } from "node:fs";
190366
190574
  import { join as join15 } from "node:path";
190367
190575
 
190368
190576
  // src/features/magic-context/dreamer/protected-regions.ts
@@ -190466,7 +190674,7 @@ function snapshotMaintainDocsFiles(docsDir) {
190466
190674
  for (const name2 of MAINTAIN_DOCS_SNAPSHOT_FILES) {
190467
190675
  const path8 = join15(docsDir, name2);
190468
190676
  try {
190469
- if (existsSync15(path8)) {
190677
+ if (existsSync17(path8)) {
190470
190678
  snapshot.set(name2, readFileSync11(path8, "utf8"));
190471
190679
  }
190472
190680
  } catch {}
@@ -190498,7 +190706,7 @@ init_memory();
190498
190706
  init_subagent_token_capture();
190499
190707
 
190500
190708
  // src/features/magic-context/dreamer/map-memories-prompt.ts
190501
- import { existsSync as existsSync16, statSync as statSync6 } from "node:fs";
190709
+ import { existsSync as existsSync18, statSync as statSync6 } from "node:fs";
190502
190710
  import path8 from "node:path";
190503
190711
  var MAP_MEMORIES_SYSTEM_PROMPT = `You are a memory mapper for the magic-context system. You map project memories to the repository files that back them.
190504
190712
 
@@ -190536,7 +190744,7 @@ function extractMemoryCandidatePaths(content, repoDir) {
190536
190744
  if (!abs.startsWith(`${root}/`))
190537
190745
  continue;
190538
190746
  try {
190539
- if (existsSync16(abs) && statSync6(abs).isFile())
190747
+ if (existsSync18(abs) && statSync6(abs).isFile())
190540
190748
  found.add(rel);
190541
190749
  } catch {}
190542
190750
  if (found.size >= MAX_SEED_PATHS_PER_MEMORY)
@@ -192365,8 +192573,8 @@ async function runAgenticTask(config2, ctx, helpers) {
192365
192573
  const lastRunAt = getTaskScheduleState(db, projectIdentity, config2.task)?.lastRunAt ?? null;
192366
192574
  const maintainDocsSnapshot = task === "maintain-docs" ? snapshotMaintainDocsFiles(docsDir) : undefined;
192367
192575
  const existingDocs = task === "maintain-docs" ? {
192368
- architecture: existsSync17(`${docsDir}/ARCHITECTURE.md`),
192369
- structure: existsSync17(`${docsDir}/STRUCTURE.md`)
192576
+ architecture: existsSync19(`${docsDir}/ARCHITECTURE.md`),
192577
+ structure: existsSync19(`${docsDir}/STRUCTURE.md`)
192370
192578
  } : undefined;
192371
192579
  const userMemories = task === "curate" ? getActiveUserMemories(db).map((um) => ({ id: um.id, content: um.content })) : undefined;
192372
192580
  let curateMemories;
@@ -192632,11 +192840,21 @@ function recordTransientFailure(db, projectIdentity, due, finishedAt, error51) {
192632
192840
  });
192633
192841
  }
192634
192842
  }
192843
+ var LEASE_WAIT_POLL_MS = 2000;
192844
+ var MANUAL_RUN_LEASE_WAIT_MS = 60000;
192635
192845
  async function runDomainGroup(deps, group, cb) {
192636
192846
  const { db, projectIdentity, executor } = deps;
192637
192847
  const leaseKey = leaseKeyFor(group[0].config.task, projectIdentity);
192638
192848
  const holderId = crypto.randomUUID();
192639
- if (!acquireLease(db, holderId, leaseKey)) {
192849
+ let acquired = acquireLease(db, holderId, leaseKey);
192850
+ if (!acquired && cb?.leaseWaitMs) {
192851
+ const deadline = Date.now() + cb.leaseWaitMs;
192852
+ while (!acquired && Date.now() < deadline) {
192853
+ await new Promise((resolve4) => setTimeout(resolve4, LEASE_WAIT_POLL_MS));
192854
+ acquired = acquireLease(db, holderId, leaseKey);
192855
+ }
192856
+ }
192857
+ if (!acquired) {
192640
192858
  log(`[dreamer] domain lease busy (${leaseKey}) — deferring ${group.length} task(s)`);
192641
192859
  for (const due of group)
192642
192860
  cb?.onBusy?.(due.config.task);
@@ -192731,6 +192949,7 @@ async function runManualDream(deps) {
192731
192949
  }
192732
192950
  await Promise.all([...groups.values()].map((group) => runDomainGroup({ ...deps, executor: deps.executor }, group, {
192733
192951
  forceGate,
192952
+ leaseWaitMs: MANUAL_RUN_LEASE_WAIT_MS,
192734
192953
  onRan: (t) => result.ran.push(t),
192735
192954
  onFailed: (t) => result.failed.push(t),
192736
192955
  onBusy: (t) => result.deferredBusy.push(t)
@@ -192779,7 +192998,15 @@ var GIT_TIMEOUT_MS3 = 1e4;
192779
192998
  var DEFAULT_MAX_COMMITS = 5000;
192780
192999
  var RECORD_SEPARATOR = "\x1E";
192781
193000
  var FIELD_SEPARATOR = "\x1F";
192782
- async function readGitCommits(directory, options = {}) {
193001
+ function classifyGitLogFailure(message) {
193002
+ if (message.includes("not a git repository"))
193003
+ return "not_a_repo";
193004
+ if (message.includes("unknown revision or path not in the working tree") || message.includes("does not have any commits yet") || message.includes("bad revision")) {
193005
+ return "no_head";
193006
+ }
193007
+ return "transient";
193008
+ }
193009
+ async function readGitCommitsResult(directory, options = {}) {
192783
193010
  const revision = options.branch ?? "HEAD";
192784
193011
  if (revision.startsWith("-")) {
192785
193012
  throw new Error(`readGitCommits: refusing revision that looks like an option: "${revision}"`);
@@ -192807,13 +193034,18 @@ async function readGitCommits(directory, options = {}) {
192807
193034
  stdout = result.stdout;
192808
193035
  } catch (error51) {
192809
193036
  const message = error51 instanceof Error ? error51.message : String(error51);
192810
- log(`[git-commits] readGitCommits failed for ${projectLabel}: ${message.slice(0, 500)}`);
192811
- return [];
193037
+ const failure = classifyGitLogFailure(message);
193038
+ if (failure === "transient") {
193039
+ log(`[git-commits] readGitCommits failed for ${projectLabel}: ${message.slice(0, 500)}`);
193040
+ } else {
193041
+ log(`[git-commits] ${projectLabel} is not indexable (${failure})`);
193042
+ }
193043
+ return { commits: [], failure };
192812
193044
  }
192813
193045
  if (stdout.trim().length === 0) {
192814
193046
  log(`[git-commits] readGitCommits returned empty stdout for ${projectLabel} (sinceMs=${options.sinceMs ?? "none"} args=${args.slice(0, 4).join(" ")})`);
192815
193047
  }
192816
- return parseGitLogOutput(stdout);
193048
+ return { commits: parseGitLogOutput(stdout), failure: null };
192817
193049
  }
192818
193050
  function parseGitLogOutput(stdout) {
192819
193051
  const commits = [];
@@ -192872,7 +193104,8 @@ async function indexCommitsForProject(db, projectPath, directory, options) {
192872
193104
  inserted: 0,
192873
193105
  updated: 0,
192874
193106
  evicted: 0,
192875
- embedded: 0
193107
+ embedded: 0,
193108
+ nonIndexable: false
192876
193109
  };
192877
193110
  if (indexInProgress.has(projectPath)) {
192878
193111
  log(`[git-commits] index already in progress for ${projectPath}, skipping`);
@@ -192882,12 +193115,17 @@ async function indexCommitsForProject(db, projectPath, directory, options) {
192882
193115
  try {
192883
193116
  const latestIndexed = getLatestIndexedCommitTimeMs(db, projectPath);
192884
193117
  const sinceMs = latestIndexed !== null ? Math.max(latestIndexed - 60000, Date.now() - options.sinceDays * MS_PER_DAY) : Date.now() - options.sinceDays * MS_PER_DAY;
192885
- const commits = await readGitCommits(directory, {
193118
+ const read = await readGitCommitsResult(directory, {
192886
193119
  sinceMs,
192887
193120
  maxCommits: options.maxCommits,
192888
193121
  projectIdentity: projectPath
192889
193122
  });
193123
+ const commits = read.commits;
192890
193124
  result.scanned = commits.length;
193125
+ if (read.failure === "not_a_repo" || read.failure === "no_head") {
193126
+ result.nonIndexable = true;
193127
+ return result;
193128
+ }
192891
193129
  if (commits.length === 0) {
192892
193130
  result.evicted = enforceProjectCap(db, projectPath, options.maxCommits);
192893
193131
  log(`[git-commits] no new commits for ${projectPath} (sinceMs=${sinceMs} latestIndexed=${latestIndexed ?? "none"} evicted=${result.evicted})`);
@@ -193320,6 +193558,12 @@ async function sweepGitCommits(args) {
193320
193558
  sinceDays: gitCommitIndexing.since_days,
193321
193559
  maxCommits: gitCommitIndexing.max_commits
193322
193560
  });
193561
+ if (result.nonIndexable) {
193562
+ if (!parkGitSweepNonIndexable(db, projectIdentity, holderId)) {
193563
+ releaseGitSweepLease(db, projectIdentity, holderId);
193564
+ }
193565
+ return;
193566
+ }
193323
193567
  let drainedEmbeddings = 0;
193324
193568
  if (result.embedded > 0) {
193325
193569
  drainedEmbeddings = await embedUnembeddedCommits(db, projectIdentity);
@@ -194631,7 +194875,7 @@ function summarizeManualDream(s) {
194631
194875
  if (s.skippedNoWork.length > 0)
194632
194876
  lines.push(`Skipped (no work): ${s.skippedNoWork.join(", ")}`);
194633
194877
  if (s.deferredBusy.length > 0)
194634
- lines.push(`Busy (already running): ${s.deferredBusy.join(", ")}`);
194878
+ lines.push(`Busy: ${s.deferredBusy.join(", ")} — another dream task holds this domain's lease; retry in a minute`);
194635
194879
  if (s.ran.length === 0 && s.failed.length === 0 && s.skippedNoWork.length === 0 && s.deferredBusy.length === 0) {
194636
194880
  lines.push("No enabled dream tasks to run.");
194637
194881
  }
@@ -204922,6 +205166,31 @@ var server = async (ctx) => {
204922
205166
  log(`[v22-backfill] failed to start background runner: ${err}`);
204923
205167
  }
204924
205168
  }
205169
+ if (pluginConfig.enabled && hooks.magicContext) {
205170
+ setTimeout(() => {
205171
+ try {
205172
+ const db = openDatabase();
205173
+ if (!db || !isDatabasePersisted(db))
205174
+ return;
205175
+ const ocDb = openOpenCodeDb();
205176
+ if (!ocDb)
205177
+ return;
205178
+ try {
205179
+ const sessions = ocDb.prepare("SELECT id, COALESCE(directory, '') AS directory FROM session ORDER BY id ASC").all();
205180
+ runSessionProjectBackfill(db, sessions.map((session) => ({
205181
+ sessionId: session.id,
205182
+ directory: session.directory
205183
+ }))).catch((err) => {
205184
+ log(`[session-projects] background runner failed: ${err}`);
205185
+ });
205186
+ } finally {
205187
+ closeQuietly(ocDb);
205188
+ }
205189
+ } catch (err) {
205190
+ log(`[session-projects] failed to start background runner: ${err}`);
205191
+ }
205192
+ }, 0);
205193
+ }
204925
205194
  const storageDir = getMagicContextStorageDir();
204926
205195
  let rpcServer = null;
204927
205196
  let stopDreamTimerRegistration;