@cortexkit/pi-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
@@ -149634,6 +149634,263 @@ function parseReportedLimit(message) {
149634
149634
  }
149635
149635
  return;
149636
149636
  }
149637
+
149638
+ // ../plugin/src/features/magic-context/session-project-backfill.ts
149639
+ init_logger();
149640
+ import { existsSync as existsSync4 } from "node:fs";
149641
+
149642
+ // ../plugin/src/features/magic-context/session-project-storage.ts
149643
+ var upsertSessionProjectStatements = new WeakMap;
149644
+ var repairSessionChunkProjectStatements = new WeakMap;
149645
+ var repairProjectChunkProjectStatements = new WeakMap;
149646
+ function getUpsertSessionProjectStatement(db) {
149647
+ let stmt = upsertSessionProjectStatements.get(db);
149648
+ if (!stmt) {
149649
+ stmt = db.prepare(`INSERT INTO session_projects (session_id, harness, project_path, updated_at)
149650
+ VALUES (?, ?, ?, ?)
149651
+ ON CONFLICT(session_id, harness) DO UPDATE SET
149652
+ project_path = excluded.project_path,
149653
+ updated_at = excluded.updated_at
149654
+ WHERE session_projects.project_path <> excluded.project_path`);
149655
+ upsertSessionProjectStatements.set(db, stmt);
149656
+ }
149657
+ return stmt;
149658
+ }
149659
+ function getRepairSessionChunkProjectStatement(db) {
149660
+ let stmt = repairSessionChunkProjectStatements.get(db);
149661
+ if (!stmt) {
149662
+ stmt = db.prepare(`UPDATE compartment_chunk_embeddings
149663
+ SET project_path = ?
149664
+ WHERE session_id = ?
149665
+ AND harness = ?
149666
+ AND project_path <> ?`);
149667
+ repairSessionChunkProjectStatements.set(db, stmt);
149668
+ }
149669
+ return stmt;
149670
+ }
149671
+ function getRepairProjectChunkProjectStatement(db) {
149672
+ let stmt = repairProjectChunkProjectStatements.get(db);
149673
+ if (!stmt) {
149674
+ stmt = db.prepare(`UPDATE compartment_chunk_embeddings
149675
+ SET project_path = (
149676
+ SELECT sp.project_path
149677
+ FROM session_projects sp
149678
+ WHERE sp.session_id = compartment_chunk_embeddings.session_id
149679
+ AND sp.harness = compartment_chunk_embeddings.harness
149680
+ LIMIT 1
149681
+ )
149682
+ WHERE EXISTS (
149683
+ SELECT 1
149684
+ FROM session_projects sp
149685
+ WHERE sp.session_id = compartment_chunk_embeddings.session_id
149686
+ AND sp.harness = compartment_chunk_embeddings.harness
149687
+ AND sp.project_path <> compartment_chunk_embeddings.project_path
149688
+ AND (
149689
+ sp.project_path = ?
149690
+ OR compartment_chunk_embeddings.project_path = ?
149691
+ )
149692
+ )`);
149693
+ repairProjectChunkProjectStatements.set(db, stmt);
149694
+ }
149695
+ return stmt;
149696
+ }
149697
+ function recordSessionProjectIdentity(db, sessionId, projectPath) {
149698
+ if (!sessionId || !projectPath)
149699
+ return;
149700
+ const harness = getHarness();
149701
+ const now = Date.now();
149702
+ db.transaction(() => {
149703
+ getUpsertSessionProjectStatement(db).run(sessionId, harness, projectPath, now);
149704
+ getRepairSessionChunkProjectStatement(db).run(projectPath, sessionId, harness, projectPath);
149705
+ })();
149706
+ }
149707
+ function repairMisScopedCompartmentChunkEmbeddingsForProject(db, projectPath) {
149708
+ if (!projectPath)
149709
+ return 0;
149710
+ return getRepairProjectChunkProjectStatement(db).run(projectPath, projectPath).changes;
149711
+ }
149712
+
149713
+ // ../plugin/src/features/magic-context/session-project-backfill.ts
149714
+ var LEASE_TTL_MS = 10 * 60 * 1000;
149715
+ var SESSION_QUERY_CHUNK_SIZE = 250;
149716
+ var YIELD_EVERY_NEW_DIRECTORIES = 10;
149717
+ function ensureBackfillStateTable(db) {
149718
+ db.exec(`
149719
+ CREATE TABLE IF NOT EXISTS session_project_backfill_state (
149720
+ harness TEXT PRIMARY KEY,
149721
+ status TEXT NOT NULL CHECK (status IN ('running', 'completed')),
149722
+ started_at INTEGER,
149723
+ lease_expires_at INTEGER,
149724
+ completed_at INTEGER
149725
+ );
149726
+ `);
149727
+ }
149728
+ function withImmediateTransaction(db, fn) {
149729
+ db.exec("BEGIN IMMEDIATE");
149730
+ try {
149731
+ const result = fn();
149732
+ db.exec("COMMIT");
149733
+ return result;
149734
+ } catch (error) {
149735
+ try {
149736
+ db.exec("ROLLBACK");
149737
+ } catch {}
149738
+ throw error;
149739
+ }
149740
+ }
149741
+ function defaultYieldFn() {
149742
+ return new Promise((resolve) => setTimeout(resolve, 0));
149743
+ }
149744
+ function acquireBackfillLease(db, harness, now) {
149745
+ ensureBackfillStateTable(db);
149746
+ return withImmediateTransaction(db, () => {
149747
+ const current = db.prepare(`SELECT harness, status, started_at, lease_expires_at, completed_at
149748
+ FROM session_project_backfill_state
149749
+ WHERE harness = ?`).get(harness);
149750
+ if (current?.status === "completed") {
149751
+ return "already_completed";
149752
+ }
149753
+ if (current?.status === "running" && current.lease_expires_at !== null && current.lease_expires_at > now) {
149754
+ return "blocked_by_lease";
149755
+ }
149756
+ db.prepare(`INSERT INTO session_project_backfill_state(
149757
+ harness,
149758
+ status,
149759
+ started_at,
149760
+ lease_expires_at,
149761
+ completed_at
149762
+ )
149763
+ VALUES (?, 'running', ?, ?, NULL)
149764
+ ON CONFLICT(harness) DO UPDATE SET
149765
+ status = 'running',
149766
+ started_at = excluded.started_at,
149767
+ lease_expires_at = excluded.lease_expires_at,
149768
+ completed_at = NULL`).run(harness, now, now + LEASE_TTL_MS);
149769
+ return "completed";
149770
+ });
149771
+ }
149772
+ function renewBackfillLease(db, harness, now) {
149773
+ ensureBackfillStateTable(db);
149774
+ db.prepare(`UPDATE session_project_backfill_state
149775
+ SET lease_expires_at = ?
149776
+ WHERE harness = ? AND status = 'running'`).run(now + LEASE_TTL_MS, harness);
149777
+ }
149778
+ function markBackfillCompleted(db, harness, now) {
149779
+ ensureBackfillStateTable(db);
149780
+ db.prepare(`INSERT INTO session_project_backfill_state(
149781
+ harness,
149782
+ status,
149783
+ started_at,
149784
+ lease_expires_at,
149785
+ completed_at
149786
+ )
149787
+ VALUES (?, 'completed', ?, NULL, ?)
149788
+ ON CONFLICT(harness) DO UPDATE SET
149789
+ status = 'completed',
149790
+ lease_expires_at = NULL,
149791
+ completed_at = excluded.completed_at`).run(harness, now, now);
149792
+ }
149793
+ function dedupeSessions(sessions) {
149794
+ const sessionsById = new Map;
149795
+ for (const session of sessions) {
149796
+ if (!session.sessionId)
149797
+ continue;
149798
+ const existing = sessionsById.get(session.sessionId);
149799
+ if (!existing) {
149800
+ sessionsById.set(session.sessionId, {
149801
+ sessionId: session.sessionId,
149802
+ directory: session.directory
149803
+ });
149804
+ continue;
149805
+ }
149806
+ if (!existing.directory && session.directory) {
149807
+ sessionsById.set(session.sessionId, {
149808
+ sessionId: session.sessionId,
149809
+ directory: session.directory
149810
+ });
149811
+ }
149812
+ }
149813
+ return [...sessionsById.values()];
149814
+ }
149815
+ function getMappedSessionIds(db, harness, sessions) {
149816
+ const mapped = new Set;
149817
+ for (let index = 0;index < sessions.length; index += SESSION_QUERY_CHUNK_SIZE) {
149818
+ const chunk = sessions.slice(index, index + SESSION_QUERY_CHUNK_SIZE);
149819
+ if (chunk.length === 0)
149820
+ continue;
149821
+ const placeholders = chunk.map(() => "?").join(", ");
149822
+ const rows = db.prepare(`SELECT session_id
149823
+ FROM session_projects
149824
+ WHERE harness = ?
149825
+ AND session_id IN (${placeholders})`).all(harness, ...chunk.map((session) => session.sessionId));
149826
+ for (const row of rows) {
149827
+ mapped.add(row.session_id);
149828
+ }
149829
+ }
149830
+ return mapped;
149831
+ }
149832
+ async function runSessionProjectBackfill(db, sessions, options = {}) {
149833
+ const startedAt = performance.now();
149834
+ const harness = getHarness();
149835
+ const now = options.now ?? Date.now;
149836
+ const resolveIdentity = options.resolveIdentity ?? resolveProjectIdentity;
149837
+ const yieldFn = options.yieldFn ?? defaultYieldFn;
149838
+ const dedupedSessions = dedupeSessions(sessions);
149839
+ const result = {
149840
+ status: "completed",
149841
+ totalSessions: dedupedSessions.length,
149842
+ alreadyMappedSessions: 0,
149843
+ unmappedSessions: 0,
149844
+ backfilledSessions: 0,
149845
+ skippedDeadDirectories: 0,
149846
+ skippedEmptyDirectories: 0,
149847
+ durationMs: 0
149848
+ };
149849
+ const leaseStatus = acquireBackfillLease(db, harness, now());
149850
+ if (leaseStatus !== "completed") {
149851
+ result.status = leaseStatus;
149852
+ result.durationMs = performance.now() - startedAt;
149853
+ return result;
149854
+ }
149855
+ const mappedSessionIds = getMappedSessionIds(db, harness, dedupedSessions);
149856
+ result.alreadyMappedSessions = mappedSessionIds.size;
149857
+ const existenceCache = new Map;
149858
+ const identityCache2 = new Map;
149859
+ let newDirectoryResolutions = 0;
149860
+ for (const session of dedupedSessions) {
149861
+ if (mappedSessionIds.has(session.sessionId)) {
149862
+ continue;
149863
+ }
149864
+ result.unmappedSessions += 1;
149865
+ if (!session.directory) {
149866
+ result.skippedEmptyDirectories += 1;
149867
+ continue;
149868
+ }
149869
+ const stillExists = existenceCache.get(session.directory) ?? existsSync4(session.directory);
149870
+ existenceCache.set(session.directory, stillExists);
149871
+ if (!stillExists) {
149872
+ result.skippedDeadDirectories += 1;
149873
+ continue;
149874
+ }
149875
+ let identity = identityCache2.get(session.directory);
149876
+ if (!identity) {
149877
+ identity = resolveIdentity(session.directory);
149878
+ identityCache2.set(session.directory, identity);
149879
+ newDirectoryResolutions += 1;
149880
+ if (newDirectoryResolutions % YIELD_EVERY_NEW_DIRECTORIES === 0) {
149881
+ renewBackfillLease(db, harness, now());
149882
+ await yieldFn();
149883
+ renewBackfillLease(db, harness, now());
149884
+ }
149885
+ }
149886
+ recordSessionProjectIdentity(db, session.sessionId, identity);
149887
+ result.backfilledSessions += 1;
149888
+ }
149889
+ markBackfillCompleted(db, harness, now());
149890
+ result.durationMs = performance.now() - startedAt;
149891
+ log(`[session-projects] backfilled ${result.backfilledSessions} of ${result.unmappedSessions} unmapped sessions (skipped ${result.skippedDeadDirectories} dead dirs) in ${Math.round(result.durationMs)}ms`);
149892
+ return result;
149893
+ }
149637
149894
  // ../plugin/src/features/magic-context/compartment-lease.ts
149638
149895
  var COMPARTMENT_LEASE_TTL_MS = 5 * 60 * 1000;
149639
149896
  var COMPARTMENT_LEASE_RENEWAL_MS = 60 * 1000;
@@ -152047,7 +152304,7 @@ function readProjectDocsCanonical(projectDirectory) {
152047
152304
  return { renderedBlock, canonicalHash };
152048
152305
  }
152049
152306
  // ../plugin/src/features/magic-context/storage-db.ts
152050
- import { chmodSync, copyFileSync, cpSync, existsSync as existsSync5, mkdirSync as mkdirSync4, mkdtempSync } from "node:fs";
152307
+ import { chmodSync, copyFileSync, cpSync, existsSync as existsSync6, mkdirSync as mkdirSync4, mkdtempSync } from "node:fs";
152051
152308
  init_data_path();
152052
152309
  import { dirname as dirname3, join as join5 } from "node:path";
152053
152310
 
@@ -152186,14 +152443,14 @@ function loadToolDefinitionMeasurements(db) {
152186
152443
  // ../plugin/src/features/magic-context/tool-owner-backfill.ts
152187
152444
  init_data_path();
152188
152445
  init_logger();
152189
- import { existsSync as existsSync4 } from "node:fs";
152446
+ import { existsSync as existsSync5 } from "node:fs";
152190
152447
  import { join as join4 } from "node:path";
152191
152448
  var LEASE_DURATION_MS = 5 * 60 * 1000;
152192
152449
  var LEASE_RENEWAL_MS = 60 * 1000;
152193
152450
  function resolveOpencodeDbPath() {
152194
152451
  return join4(getDataDir(), "opencode", "opencode.db");
152195
152452
  }
152196
- function ensureBackfillStateTable(db) {
152453
+ function ensureBackfillStateTable2(db) {
152197
152454
  db.exec(`
152198
152455
  CREATE TABLE IF NOT EXISTS tool_owner_backfill_state (
152199
152456
  session_id TEXT PRIMARY KEY,
@@ -152209,7 +152466,7 @@ function ensureBackfillStateTable(db) {
152209
152466
  }
152210
152467
  function runToolOwnerBackfill(db) {
152211
152468
  const startedAt = performance.now();
152212
- ensureBackfillStateTable(db);
152469
+ ensureBackfillStateTable2(db);
152213
152470
  const result = {
152214
152471
  sessionsProcessed: 0,
152215
152472
  sessionsSkippedNoOcDb: 0,
@@ -152226,7 +152483,7 @@ function runToolOwnerBackfill(db) {
152226
152483
  return result;
152227
152484
  }
152228
152485
  const opencodeDbPath = resolveOpencodeDbPath();
152229
- if (!existsSync4(opencodeDbPath)) {
152486
+ if (!existsSync5(opencodeDbPath)) {
152230
152487
  log(`[backfill] OpenCode DB not found at ${opencodeDbPath} — marking all unbackfilled sessions as skipped. Lazy adoption (defense-in-depth) handles legacy rows at runtime.`);
152231
152488
  markAllUnbackfilledSessionsSkipped(db);
152232
152489
  result.sessionsSkippedNoOcDb = countSessionsByStatus(db, "skipped");
@@ -152249,7 +152506,7 @@ function runToolOwnerBackfill(db) {
152249
152506
  return result;
152250
152507
  }
152251
152508
  function isToolOwnerBackfillNeeded(db) {
152252
- ensureBackfillStateTable(db);
152509
+ ensureBackfillStateTable2(db);
152253
152510
  const row = db.prepare(`SELECT 1 AS hit
152254
152511
  FROM tags
152255
152512
  WHERE type = 'tool' AND tool_owner_message_id IS NULL
@@ -152465,7 +152722,7 @@ function restrictDatabaseFilePermissions(dbPath) {
152465
152722
  return;
152466
152723
  for (const suffix of ["", "-wal", "-shm"]) {
152467
152724
  const file = `${dbPath}${suffix}`;
152468
- if (!existsSync5(file))
152725
+ if (!existsSync6(file))
152469
152726
  continue;
152470
152727
  try {
152471
152728
  chmodSync(file, 384);
@@ -152491,11 +152748,11 @@ function getDatabasePath(db) {
152491
152748
  return pathByDatabase.get(db) ?? null;
152492
152749
  }
152493
152750
  function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
152494
- if (existsSync5(targetDbPath))
152751
+ if (existsSync6(targetDbPath))
152495
152752
  return;
152496
152753
  const legacyDir = getLegacyOpenCodeMagicContextStorageDir();
152497
152754
  const legacyDbPath = join5(legacyDir, "context.db");
152498
- if (!existsSync5(legacyDbPath))
152755
+ if (!existsSync6(legacyDbPath))
152499
152756
  return;
152500
152757
  log(`[magic-context] migrating legacy plugin storage: ${legacyDir} -> ${targetDbDir} (legacy left in place as backup)`);
152501
152758
  ensureSecureStorageDir(targetDbDir);
@@ -152512,7 +152769,7 @@ function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
152512
152769
  for (const suffix of ["", "-wal", "-shm"]) {
152513
152770
  const src = `${legacyDbPath}${suffix}`;
152514
152771
  const dst = join5(targetDbDir, `context.db${suffix}`);
152515
- if (existsSync5(src)) {
152772
+ if (existsSync6(src)) {
152516
152773
  try {
152517
152774
  copyFileSync(src, dst);
152518
152775
  } catch (error) {
@@ -152522,7 +152779,7 @@ function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
152522
152779
  }
152523
152780
  const legacyModelsDir = join5(legacyDir, "models");
152524
152781
  const targetModelsDir = join5(targetDbDir, "models");
152525
- if (existsSync5(legacyModelsDir) && !existsSync5(targetModelsDir)) {
152782
+ if (existsSync6(legacyModelsDir) && !existsSync6(targetModelsDir)) {
152526
152783
  try {
152527
152784
  cpSync(legacyModelsDir, targetModelsDir, { recursive: true });
152528
152785
  } catch (error) {
@@ -156667,7 +156924,7 @@ init_logger();
156667
156924
 
156668
156925
  // src/subagent-runner.ts
156669
156926
  import * as childProcess from "node:child_process";
156670
- import { existsSync as existsSync7, mkdtempSync as mkdtempSync2, rmSync as rmSync2, writeFileSync as writeFileSync5 } from "node:fs";
156927
+ import { existsSync as existsSync8, mkdtempSync as mkdtempSync2, rmSync as rmSync2, writeFileSync as writeFileSync5 } from "node:fs";
156671
156928
  import { createRequire as createRequire2 } from "node:module";
156672
156929
  import { tmpdir as tmpdir2 } from "node:os";
156673
156930
  import { basename as basename2, dirname as dirname4, join as join8, resolve as resolvePath } from "node:path";
@@ -156798,7 +157055,7 @@ function resolveBundledPiCli() {
156798
157055
  const require_ = createRequire2(import.meta.url);
156799
157056
  const pkgJson = require_.resolve("@earendil-works/pi-coding-agent/package.json");
156800
157057
  const cliPath = join8(dirname4(pkgJson), "dist/cli.js");
156801
- if (existsSync7(cliPath))
157058
+ if (existsSync8(cliPath))
156802
157059
  return cliPath;
156803
157060
  return null;
156804
157061
  } catch {
@@ -156809,7 +157066,7 @@ function resolvePiInvocation() {
156809
157066
  const execPath = process.execPath;
156810
157067
  const currentScript = process.argv[1];
156811
157068
  const isBunVirtualScript = currentScript?.startsWith("/$bunfs/root/") ?? false;
156812
- if (currentScript && !isBunVirtualScript && existsSync7(currentScript)) {
157069
+ if (currentScript && !isBunVirtualScript && existsSync8(currentScript)) {
156813
157070
  return { command: execPath, prefixArgs: [currentScript] };
156814
157071
  }
156815
157072
  const execName = basename2(execPath).toLowerCase();
@@ -156827,7 +157084,7 @@ function resolveSubagentEntryPath() {
156827
157084
  try {
156828
157085
  const here = dirname4(fileURLToPath(import.meta.url));
156829
157086
  const candidate = resolvePath(here, "subagent-entry.js");
156830
- if (existsSync7(candidate))
157087
+ if (existsSync8(candidate))
156831
157088
  return candidate;
156832
157089
  return;
156833
157090
  } catch {
@@ -157096,6 +157353,8 @@ class PiSubagentRunner {
157096
157353
  return;
157097
157354
  const parsed = parsePiEventLine(line);
157098
157355
  if (!parsed.ok) {
157356
+ if ("noise" in parsed)
157357
+ return;
157099
157358
  parseError = parsed.error;
157100
157359
  return;
157101
157360
  }
@@ -157396,6 +157655,9 @@ function countToolCalls(messages) {
157396
157655
  return count;
157397
157656
  }
157398
157657
  function parsePiEventLine(line) {
157658
+ if (!line.trimStart().startsWith("{")) {
157659
+ return { ok: false, noise: true };
157660
+ }
157399
157661
  try {
157400
157662
  return { ok: true, event: JSON.parse(line) };
157401
157663
  } catch (error) {
@@ -157491,12 +157753,13 @@ ${sidekickText}
157491
157753
  init_logger();
157492
157754
 
157493
157755
  // ../plugin/src/features/magic-context/dreamer/open-opencode-db.ts
157494
- import { existsSync as existsSync8 } from "node:fs";
157756
+ import { existsSync as existsSync10 } from "node:fs";
157495
157757
  init_logger();
157496
157758
 
157497
157759
  // ../plugin/src/features/magic-context/compaction-marker.ts
157498
157760
  init_data_path();
157499
157761
  init_logger();
157762
+ import { existsSync as existsSync9 } from "node:fs";
157500
157763
  import { join as join9 } from "node:path";
157501
157764
  var BASE62_CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
157502
157765
  function randomBase62(length) {
@@ -157563,6 +157826,9 @@ function getWritableOpenCodeDb() {
157563
157826
  closeQuietly(cachedWriteDb.db);
157564
157827
  } catch {}
157565
157828
  }
157829
+ if (!existsSync9(dbPath)) {
157830
+ throw new Error(`OpenCode database not found at ${dbPath} (is OpenCode installed?)`);
157831
+ }
157566
157832
  const db = new Database(dbPath);
157567
157833
  db.exec("PRAGMA busy_timeout=5000");
157568
157834
  db.exec("PRAGMA journal_mode=WAL");
@@ -157681,8 +157947,8 @@ function removeCompactionMarker(state) {
157681
157947
  // ../plugin/src/features/magic-context/dreamer/open-opencode-db.ts
157682
157948
  function openOpenCodeDb() {
157683
157949
  const dbPath = getOpenCodeDbPath2();
157684
- if (!existsSync8(dbPath)) {
157685
- log(`[key-files] OpenCode DB not found at ${dbPath} — skipping`);
157950
+ if (!existsSync10(dbPath)) {
157951
+ log(`[dreamer] OpenCode DB not found at ${dbPath} — skipping OpenCode history scan`);
157686
157952
  return null;
157687
157953
  }
157688
157954
  try {
@@ -157690,14 +157956,14 @@ function openOpenCodeDb() {
157690
157956
  db.exec("PRAGMA busy_timeout = 5000");
157691
157957
  return db;
157692
157958
  } catch (error) {
157693
- log(`[key-files] failed to open OpenCode DB at ${dbPath}: ${getErrorMessage(error)}`);
157959
+ log(`[dreamer] failed to open OpenCode DB at ${dbPath}: ${getErrorMessage(error)}`);
157694
157960
  return null;
157695
157961
  }
157696
157962
  }
157697
157963
 
157698
157964
  // ../plugin/src/features/magic-context/dreamer/task-executor.ts
157699
157965
  import { createHash as createHash10 } from "node:crypto";
157700
- import { existsSync as existsSync12 } from "node:fs";
157966
+ import { existsSync as existsSync14 } from "node:fs";
157701
157967
 
157702
157968
  // ../plugin/src/agents/dreamer.ts
157703
157969
  var DREAMER_AGENT = "dreamer";
@@ -174383,6 +174649,7 @@ function enforceProjectCap(db, projectPath, maxCommits) {
174383
174649
  // ../plugin/src/features/magic-context/git-commits/sweep-coordinator.ts
174384
174650
  var GIT_SWEEP_COOLDOWN_MS = 10 * 60 * 1000;
174385
174651
  var GIT_SWEEP_LEASE_TTL_MS = 5 * 60 * 1000;
174652
+ var GIT_SWEEP_NON_INDEXABLE_REPROBE_MS = 24 * 60 * 60 * 1000;
174386
174653
  var GIT_SWEEP_LEASE_RENEWAL_MS = 60 * 1000;
174387
174654
  function runImmediate(db, body) {
174388
174655
  db.exec("BEGIN IMMEDIATE");
@@ -174489,6 +174756,20 @@ function markGitSweepSuccessAndRelease(db, projectPath, holderId) {
174489
174756
  return result.changes === 1;
174490
174757
  });
174491
174758
  }
174759
+ function parkGitSweepNonIndexable(db, projectPath, holderId, reprobeMs = GIT_SWEEP_NON_INDEXABLE_REPROBE_MS) {
174760
+ return runImmediate(db, () => {
174761
+ const now = Date.now();
174762
+ const sweptAt = now + reprobeMs - GIT_SWEEP_COOLDOWN_MS;
174763
+ const result = db.prepare(`UPDATE git_sweep_coordinator
174764
+ SET lease_holder = NULL,
174765
+ lease_expires_at = NULL,
174766
+ last_swept_at = ?
174767
+ WHERE project_path = ?
174768
+ AND lease_holder = ?
174769
+ AND lease_expires_at > ?`).run(sweptAt, projectPath, holderId, now);
174770
+ return result.changes === 1;
174771
+ });
174772
+ }
174492
174773
  function releaseGitSweepLease(db, projectPath, holderId) {
174493
174774
  runImmediate(db, () => {
174494
174775
  db.prepare(`UPDATE git_sweep_coordinator
@@ -174552,77 +174833,6 @@ function invalidateMemory(projectPath, memoryId) {
174552
174833
  }
174553
174834
  }
174554
174835
 
174555
- // ../plugin/src/features/magic-context/session-project-storage.ts
174556
- var upsertSessionProjectStatements = new WeakMap;
174557
- var repairSessionChunkProjectStatements = new WeakMap;
174558
- var repairProjectChunkProjectStatements = new WeakMap;
174559
- function getUpsertSessionProjectStatement(db) {
174560
- let stmt = upsertSessionProjectStatements.get(db);
174561
- if (!stmt) {
174562
- stmt = db.prepare(`INSERT INTO session_projects (session_id, harness, project_path, updated_at)
174563
- VALUES (?, ?, ?, ?)
174564
- ON CONFLICT(session_id, harness) DO UPDATE SET
174565
- project_path = excluded.project_path,
174566
- updated_at = excluded.updated_at
174567
- WHERE session_projects.project_path <> excluded.project_path`);
174568
- upsertSessionProjectStatements.set(db, stmt);
174569
- }
174570
- return stmt;
174571
- }
174572
- function getRepairSessionChunkProjectStatement(db) {
174573
- let stmt = repairSessionChunkProjectStatements.get(db);
174574
- if (!stmt) {
174575
- stmt = db.prepare(`UPDATE compartment_chunk_embeddings
174576
- SET project_path = ?
174577
- WHERE session_id = ?
174578
- AND harness = ?
174579
- AND project_path <> ?`);
174580
- repairSessionChunkProjectStatements.set(db, stmt);
174581
- }
174582
- return stmt;
174583
- }
174584
- function getRepairProjectChunkProjectStatement(db) {
174585
- let stmt = repairProjectChunkProjectStatements.get(db);
174586
- if (!stmt) {
174587
- stmt = db.prepare(`UPDATE compartment_chunk_embeddings
174588
- SET project_path = (
174589
- SELECT sp.project_path
174590
- FROM session_projects sp
174591
- WHERE sp.session_id = compartment_chunk_embeddings.session_id
174592
- AND sp.harness = compartment_chunk_embeddings.harness
174593
- LIMIT 1
174594
- )
174595
- WHERE EXISTS (
174596
- SELECT 1
174597
- FROM session_projects sp
174598
- WHERE sp.session_id = compartment_chunk_embeddings.session_id
174599
- AND sp.harness = compartment_chunk_embeddings.harness
174600
- AND sp.project_path <> compartment_chunk_embeddings.project_path
174601
- AND (
174602
- sp.project_path = ?
174603
- OR compartment_chunk_embeddings.project_path = ?
174604
- )
174605
- )`);
174606
- repairProjectChunkProjectStatements.set(db, stmt);
174607
- }
174608
- return stmt;
174609
- }
174610
- function recordSessionProjectIdentity(db, sessionId, projectPath) {
174611
- if (!sessionId || !projectPath)
174612
- return;
174613
- const harness = getHarness();
174614
- const now = Date.now();
174615
- db.transaction(() => {
174616
- getUpsertSessionProjectStatement(db).run(sessionId, harness, projectPath, now);
174617
- getRepairSessionChunkProjectStatement(db).run(projectPath, sessionId, harness, projectPath);
174618
- })();
174619
- }
174620
- function repairMisScopedCompartmentChunkEmbeddingsForProject(db, projectPath) {
174621
- if (!projectPath)
174622
- return 0;
174623
- return getRepairProjectChunkProjectStatement(db).run(projectPath, projectPath).changes;
174624
- }
174625
-
174626
174836
  // ../plugin/src/features/magic-context/project-embedding-registry.ts
174627
174837
  var OFF_PROVIDER_IDENTITY = "embedding-provider:off";
174628
174838
  var SWEEP_MAX_WALL_CLOCK_MS = 10 * 60 * 1000;
@@ -176275,7 +176485,7 @@ function getMemoryVerifications(db, memoryIds) {
176275
176485
  }
176276
176486
  // ../plugin/src/features/magic-context/memory/verification-paths.ts
176277
176487
  import { execFile } from "node:child_process";
176278
- import { existsSync as existsSync9, realpathSync as realpathSync2, statSync as statSync4 } from "node:fs";
176488
+ import { existsSync as existsSync11, realpathSync as realpathSync2, statSync as statSync4 } from "node:fs";
176279
176489
  import path7 from "node:path";
176280
176490
  import { promisify } from "node:util";
176281
176491
  var execFileAsync = promisify(execFile);
@@ -176380,7 +176590,7 @@ function verificationFileExists(baseRoot, filePath) {
176380
176590
  return false;
176381
176591
  const root = path7.resolve(baseRoot);
176382
176592
  const candidate = path7.resolve(root, filePath);
176383
- return isWithin(root, candidate) && existsSync9(candidate);
176593
+ return isWithin(root, candidate) && existsSync11(candidate);
176384
176594
  }
176385
176595
  async function normalizeVerificationFiles(args) {
176386
176596
  const cwd = path7.resolve(args.cwd);
@@ -176413,7 +176623,7 @@ async function normalizeVerificationFiles(args) {
176413
176623
  warnings.push(`Skipped verification path "${value}" because it is the repo/project root.`);
176414
176624
  continue;
176415
176625
  }
176416
- if (existsSync9(candidate)) {
176626
+ if (existsSync11(candidate)) {
176417
176627
  try {
176418
176628
  if (statSync4(candidate).isDirectory()) {
176419
176629
  warnings.push(`Skipped verification path "${value}" because it is a directory.`);
@@ -176444,7 +176654,7 @@ async function normalizeVerificationFiles(args) {
176444
176654
  }
176445
176655
  normalized.push(tracked);
176446
176656
  } else {
176447
- if (!existsSync9(candidate)) {
176657
+ if (!existsSync11(candidate)) {
176448
176658
  warnings.push(`Skipped verification path "${value}" because it does not exist.`);
176449
176659
  continue;
176450
176660
  }
@@ -179087,7 +179297,7 @@ Output exactly JSON: {"met": false}`;
179087
179297
 
179088
179298
  // ../plugin/src/features/magic-context/dreamer/maintain-docs-protected-enforcement.ts
179089
179299
  init_logger();
179090
- import { existsSync as existsSync10, readFileSync as readFileSync6, writeFileSync as writeFileSync6 } from "node:fs";
179300
+ import { existsSync as existsSync12, readFileSync as readFileSync6, writeFileSync as writeFileSync6 } from "node:fs";
179091
179301
  import { join as join11 } from "node:path";
179092
179302
 
179093
179303
  // ../plugin/src/features/magic-context/dreamer/protected-regions.ts
@@ -179191,7 +179401,7 @@ function snapshotMaintainDocsFiles(docsDir) {
179191
179401
  for (const name2 of MAINTAIN_DOCS_SNAPSHOT_FILES) {
179192
179402
  const path9 = join11(docsDir, name2);
179193
179403
  try {
179194
- if (existsSync10(path9)) {
179404
+ if (existsSync12(path9)) {
179195
179405
  snapshot.set(name2, readFileSync6(path9, "utf8"));
179196
179406
  }
179197
179407
  } catch {}
@@ -179219,7 +179429,7 @@ function enforceMaintainDocsProtectedRegions(args) {
179219
179429
  init_logger();
179220
179430
 
179221
179431
  // ../plugin/src/features/magic-context/dreamer/map-memories-prompt.ts
179222
- import { existsSync as existsSync11, statSync as statSync5 } from "node:fs";
179432
+ import { existsSync as existsSync13, statSync as statSync5 } from "node:fs";
179223
179433
  import path9 from "node:path";
179224
179434
  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.
179225
179435
 
@@ -179257,7 +179467,7 @@ function extractMemoryCandidatePaths(content, repoDir) {
179257
179467
  if (!abs.startsWith(`${root}/`))
179258
179468
  continue;
179259
179469
  try {
179260
- if (existsSync11(abs) && statSync5(abs).isFile())
179470
+ if (existsSync13(abs) && statSync5(abs).isFile())
179261
179471
  found.add(rel);
179262
179472
  } catch {}
179263
179473
  if (found.size >= MAX_SEED_PATHS_PER_MEMORY)
@@ -181398,8 +181608,8 @@ async function runAgenticTask(config2, ctx, helpers) {
181398
181608
  const lastRunAt = getTaskScheduleState(db, projectIdentity, config2.task)?.lastRunAt ?? null;
181399
181609
  const maintainDocsSnapshot = task === "maintain-docs" ? snapshotMaintainDocsFiles(docsDir) : undefined;
181400
181610
  const existingDocs = task === "maintain-docs" ? {
181401
- architecture: existsSync12(`${docsDir}/ARCHITECTURE.md`),
181402
- structure: existsSync12(`${docsDir}/STRUCTURE.md`)
181611
+ architecture: existsSync14(`${docsDir}/ARCHITECTURE.md`),
181612
+ structure: existsSync14(`${docsDir}/STRUCTURE.md`)
181403
181613
  } : undefined;
181404
181614
  const userMemories = task === "curate" ? getActiveUserMemories(db).map((um) => ({ id: um.id, content: um.content })) : undefined;
181405
181615
  let curateMemories;
@@ -181657,11 +181867,21 @@ function recordTransientFailure(db, projectIdentity, due, finishedAt, error51) {
181657
181867
  });
181658
181868
  }
181659
181869
  }
181870
+ var LEASE_WAIT_POLL_MS = 2000;
181871
+ var MANUAL_RUN_LEASE_WAIT_MS = 60000;
181660
181872
  async function runDomainGroup(deps, group, cb) {
181661
181873
  const { db, projectIdentity, executor } = deps;
181662
181874
  const leaseKey = leaseKeyFor(group[0].config.task, projectIdentity);
181663
181875
  const holderId = crypto.randomUUID();
181664
- if (!acquireLease(db, holderId, leaseKey)) {
181876
+ let acquired = acquireLease(db, holderId, leaseKey);
181877
+ if (!acquired && cb?.leaseWaitMs) {
181878
+ const deadline = Date.now() + cb.leaseWaitMs;
181879
+ while (!acquired && Date.now() < deadline) {
181880
+ await new Promise((resolve) => setTimeout(resolve, LEASE_WAIT_POLL_MS));
181881
+ acquired = acquireLease(db, holderId, leaseKey);
181882
+ }
181883
+ }
181884
+ if (!acquired) {
181665
181885
  log(`[dreamer] domain lease busy (${leaseKey}) — deferring ${group.length} task(s)`);
181666
181886
  for (const due of group)
181667
181887
  cb?.onBusy?.(due.config.task);
@@ -181756,6 +181976,7 @@ async function runManualDream(deps) {
181756
181976
  }
181757
181977
  await Promise.all([...groups.values()].map((group) => runDomainGroup({ ...deps, executor: deps.executor }, group, {
181758
181978
  forceGate,
181979
+ leaseWaitMs: MANUAL_RUN_LEASE_WAIT_MS,
181759
181980
  onRan: (t) => result.ran.push(t),
181760
181981
  onFailed: (t) => result.failed.push(t),
181761
181982
  onBusy: (t) => result.deferredBusy.push(t)
@@ -181886,7 +182107,15 @@ var GIT_TIMEOUT_MS3 = 1e4;
181886
182107
  var DEFAULT_MAX_COMMITS = 5000;
181887
182108
  var RECORD_SEPARATOR = "\x1E";
181888
182109
  var FIELD_SEPARATOR = "\x1F";
181889
- async function readGitCommits(directory, options = {}) {
182110
+ function classifyGitLogFailure(message) {
182111
+ if (message.includes("not a git repository"))
182112
+ return "not_a_repo";
182113
+ if (message.includes("unknown revision or path not in the working tree") || message.includes("does not have any commits yet") || message.includes("bad revision")) {
182114
+ return "no_head";
182115
+ }
182116
+ return "transient";
182117
+ }
182118
+ async function readGitCommitsResult(directory, options = {}) {
181890
182119
  const revision = options.branch ?? "HEAD";
181891
182120
  if (revision.startsWith("-")) {
181892
182121
  throw new Error(`readGitCommits: refusing revision that looks like an option: "${revision}"`);
@@ -181914,13 +182143,18 @@ async function readGitCommits(directory, options = {}) {
181914
182143
  stdout = result.stdout;
181915
182144
  } catch (error51) {
181916
182145
  const message = error51 instanceof Error ? error51.message : String(error51);
181917
- log(`[git-commits] readGitCommits failed for ${projectLabel}: ${message.slice(0, 500)}`);
181918
- return [];
182146
+ const failure = classifyGitLogFailure(message);
182147
+ if (failure === "transient") {
182148
+ log(`[git-commits] readGitCommits failed for ${projectLabel}: ${message.slice(0, 500)}`);
182149
+ } else {
182150
+ log(`[git-commits] ${projectLabel} is not indexable (${failure})`);
182151
+ }
182152
+ return { commits: [], failure };
181919
182153
  }
181920
182154
  if (stdout.trim().length === 0) {
181921
182155
  log(`[git-commits] readGitCommits returned empty stdout for ${projectLabel} (sinceMs=${options.sinceMs ?? "none"} args=${args.slice(0, 4).join(" ")})`);
181922
182156
  }
181923
- return parseGitLogOutput(stdout);
182157
+ return { commits: parseGitLogOutput(stdout), failure: null };
181924
182158
  }
181925
182159
  function parseGitLogOutput(stdout) {
181926
182160
  const commits = [];
@@ -181976,7 +182210,8 @@ async function indexCommitsForProject(db, projectPath, directory, options) {
181976
182210
  inserted: 0,
181977
182211
  updated: 0,
181978
182212
  evicted: 0,
181979
- embedded: 0
182213
+ embedded: 0,
182214
+ nonIndexable: false
181980
182215
  };
181981
182216
  if (indexInProgress.has(projectPath)) {
181982
182217
  log(`[git-commits] index already in progress for ${projectPath}, skipping`);
@@ -181986,12 +182221,17 @@ async function indexCommitsForProject(db, projectPath, directory, options) {
181986
182221
  try {
181987
182222
  const latestIndexed = getLatestIndexedCommitTimeMs(db, projectPath);
181988
182223
  const sinceMs = latestIndexed !== null ? Math.max(latestIndexed - 60000, Date.now() - options.sinceDays * MS_PER_DAY) : Date.now() - options.sinceDays * MS_PER_DAY;
181989
- const commits = await readGitCommits(directory, {
182224
+ const read = await readGitCommitsResult(directory, {
181990
182225
  sinceMs,
181991
182226
  maxCommits: options.maxCommits,
181992
182227
  projectIdentity: projectPath
181993
182228
  });
182229
+ const commits = read.commits;
181994
182230
  result.scanned = commits.length;
182231
+ if (read.failure === "not_a_repo" || read.failure === "no_head") {
182232
+ result.nonIndexable = true;
182233
+ return result;
182234
+ }
181995
182235
  if (commits.length === 0) {
181996
182236
  result.evicted = enforceProjectCap(db, projectPath, options.maxCommits);
181997
182237
  log(`[git-commits] no new commits for ${projectPath} (sinceMs=${sinceMs} latestIndexed=${latestIndexed ?? "none"} evicted=${result.evicted})`);
@@ -182413,6 +182653,12 @@ async function sweepGitCommits(args) {
182413
182653
  sinceDays: gitCommitIndexing.since_days,
182414
182654
  maxCommits: gitCommitIndexing.max_commits
182415
182655
  });
182656
+ if (result.nonIndexable) {
182657
+ if (!parkGitSweepNonIndexable(db, projectIdentity, holderId)) {
182658
+ releaseGitSweepLease(db, projectIdentity, holderId);
182659
+ }
182660
+ return;
182661
+ }
182416
182662
  let drainedEmbeddings = 0;
182417
182663
  if (result.embedded > 0) {
182418
182664
  drainedEmbeddings = await embedUnembeddedCommits(db, projectIdentity);
@@ -182578,7 +182824,7 @@ function pruneNestedConfigLeaf(block, relativePath) {
182578
182824
  }
182579
182825
 
182580
182826
  // src/config/index.ts
182581
- import { existsSync as existsSync14, readFileSync as readFileSync8 } from "node:fs";
182827
+ import { existsSync as existsSync16, readFileSync as readFileSync8 } from "node:fs";
182582
182828
 
182583
182829
  // ../plugin/src/config/migrate-dreamer-v2.ts
182584
182830
  var OLD_VERIFY_TASK = "verify";
@@ -182960,7 +183206,7 @@ function dropInheritedEmbeddingKeyOnRedirect(projectRaw, mergedRaw, userRaw) {
182960
183206
  }
182961
183207
 
182962
183208
  // ../plugin/src/config/variable.ts
182963
- import { existsSync as existsSync13, readFileSync as readFileSync7 } from "node:fs";
183209
+ import { existsSync as existsSync15, readFileSync as readFileSync7 } from "node:fs";
182964
183210
  import { homedir as homedir4 } from "node:os";
182965
183211
  import { dirname as dirname6, isAbsolute as isAbsolute2, resolve } from "node:path";
182966
183212
 
@@ -183095,7 +183341,7 @@ function substituteConfigVariables(input) {
183095
183341
  if (sensitiveReason) {
183096
183342
  warnings.push(`${token} resolves to a sensitive path (${sensitiveReason}: ${filePath}); ` + "inlining its contents into config — make sure this is intentional.");
183097
183343
  }
183098
- if (!existsSync13(filePath)) {
183344
+ if (!existsSync15(filePath)) {
183099
183345
  warnings.push(`File not found for ${token} (resolved to ${filePath}); using empty string`);
183100
183346
  continue;
183101
183347
  }
@@ -183124,10 +183370,10 @@ function getUserConfigPaths() {
183124
183370
  return [`${basePath}.jsonc`, `${basePath}.json`];
183125
183371
  }
183126
183372
  function resolveFirstExisting(paths) {
183127
- return paths.find((path11) => existsSync14(path11));
183373
+ return paths.find((path11) => existsSync16(path11));
183128
183374
  }
183129
183375
  function resolvePiLegacyFallback(sources) {
183130
- return sources.find((source) => existsSync14(source.path)) ?? null;
183376
+ return sources.find((source) => existsSync16(source.path)) ?? null;
183131
183377
  }
183132
183378
  function loadConfigFile(path11, scope) {
183133
183379
  try {
@@ -183264,7 +183510,7 @@ function loadPiConfig(opts = {}) {
183264
183510
  if (loaded)
183265
183511
  loadedFiles.push(loaded);
183266
183512
  }
183267
- const legacyProjectUnmigrated = !projectPath && !projectLegacyFallback && legacySources.project.some((source) => existsSync14(source.path));
183513
+ const legacyProjectUnmigrated = !projectPath && !projectLegacyFallback && legacySources.project.some((source) => existsSync16(source.path));
183268
183514
  const userPath = resolveFirstExisting(getUserConfigPaths());
183269
183515
  const userLegacyFallback = userPath ? null : resolvePiLegacyFallback(harnessLegacy.user);
183270
183516
  const userReadPath = userPath ?? userLegacyFallback?.path;
@@ -183273,7 +183519,7 @@ function loadPiConfig(opts = {}) {
183273
183519
  if (loaded)
183274
183520
  loadedFiles.push(loaded);
183275
183521
  }
183276
- const legacyUserUnmigrated = !userPath && !userLegacyFallback && legacySources.user.some((source) => existsSync14(source.path));
183522
+ const legacyUserUnmigrated = !userPath && !userLegacyFallback && legacySources.user.some((source) => existsSync16(source.path));
183277
183523
  if (userLegacyFallback) {
183278
183524
  warnings.push(`[user config] reading legacy config from ${userLegacyFallback.path} until migration completes; run \`npx @cortexkit/magic-context doctor\` to consolidate into the shared CortexKit location.`);
183279
183525
  } else if (legacyUserUnmigrated) {
@@ -183374,7 +183620,7 @@ function loadPiConfigDetailed(opts = {}) {
183374
183620
  if (loaded)
183375
183621
  loadedFiles.push(loaded);
183376
183622
  }
183377
- const legacyProjectUnmigrated = !projectPath && !projectLegacyFallback && legacySources.project.some((source) => existsSync14(source.path));
183623
+ const legacyProjectUnmigrated = !projectPath && !projectLegacyFallback && legacySources.project.some((source) => existsSync16(source.path));
183378
183624
  const userPath = resolveFirstExisting(getUserConfigPaths());
183379
183625
  const userLegacyFallback = userPath ? null : resolvePiLegacyFallback(harnessLegacy.user);
183380
183626
  const userReadPath = userPath ?? userLegacyFallback?.path;
@@ -183383,7 +183629,7 @@ function loadPiConfigDetailed(opts = {}) {
183383
183629
  if (loaded)
183384
183630
  loadedFiles.push(loaded);
183385
183631
  }
183386
- const legacyUserUnmigrated = !userPath && !userLegacyFallback && legacySources.user.some((source) => existsSync14(source.path));
183632
+ const legacyUserUnmigrated = !userPath && !userLegacyFallback && legacySources.user.some((source) => existsSync16(source.path));
183387
183633
  if (userLegacyFallback) {
183388
183634
  warnings.push(`[user config] reading legacy config from ${userLegacyFallback.path} until migration completes; run \`npx @cortexkit/magic-context doctor\` to consolidate into the shared CortexKit location.`);
183389
183635
  } else if (legacyUserUnmigrated) {
@@ -184229,7 +184475,7 @@ Unknown task "${requested}".`,
184229
184475
  if (result.skippedNoWork.length > 0)
184230
184476
  lines.push(`Skipped (no work): ${result.skippedNoWork.join(", ")}`);
184231
184477
  if (result.deferredBusy.length > 0)
184232
- lines.push(`Busy (already running): ${result.deferredBusy.join(", ")}`);
184478
+ lines.push(`Busy: ${result.deferredBusy.join(", ")} — another dream task holds this domain's lease; retry in a minute`);
184233
184479
  if (lines.length === 0)
184234
184480
  lines.push("No enabled dream tasks to run.");
184235
184481
  sendCtxStatusMessage(pi, {
@@ -194574,6 +194820,9 @@ function getMessageId(message) {
194574
194820
  }
194575
194821
  return "";
194576
194822
  }
194823
+ function isReplayableAnchor(message) {
194824
+ return message.stopReason !== "aborted" && message.stopReason !== "error";
194825
+ }
194577
194826
  function hasToolCallWithId(message, callId) {
194578
194827
  if (!Array.isArray(message.content))
194579
194828
  return false;
@@ -194630,6 +194879,8 @@ function injectByAssistantId(messages, messageId, part) {
194630
194879
  const assistant = m;
194631
194880
  if (getMessageId(assistant) !== messageId)
194632
194881
  continue;
194882
+ if (!isReplayableAnchor(assistant))
194883
+ return false;
194633
194884
  if (hasToolCallWithId(assistant, part.callID)) {
194634
194885
  if (findToolResultAfter(messages, i, part.callID) >= 0)
194635
194886
  return true;
@@ -194655,6 +194906,8 @@ function injectIntoLatestAssistant(messages, part) {
194655
194906
  if (m.role !== "assistant")
194656
194907
  continue;
194657
194908
  const assistant = m;
194909
+ if (!isReplayableAnchor(assistant))
194910
+ continue;
194658
194911
  const id = getMessageId(assistant);
194659
194912
  if (id.length === 0)
194660
194913
  continue;
@@ -197732,6 +197985,9 @@ function existingMarkerAlreadyCoversTarget(sessionId, existing, targetOrdinal, t
197732
197985
  return true;
197733
197986
  }
197734
197987
  function updateCompactionMarkerAfterPublication(db, sessionId, lastCompartmentEnd, directory) {
197988
+ if (getHarness() !== "opencode") {
197989
+ return true;
197990
+ }
197735
197991
  const targetEndMessageId = getCompartmentEndMessageIdForOrdinal(db, sessionId, lastCompartmentEnd);
197736
197992
  if (!targetEndMessageId) {
197737
197993
  sessionLog(sessionId, `compaction-marker: no compartment endMessageId for ordinal ${lastCompartmentEnd}; preserving existing marker`);
@@ -200063,7 +200319,7 @@ function formatThresholdPercent(value) {
200063
200319
  // package.json
200064
200320
  var package_default = {
200065
200321
  name: "@cortexkit/pi-magic-context",
200066
- version: "0.30.5",
200322
+ version: "0.30.7",
200067
200323
  type: "module",
200068
200324
  description: "Pi coding agent extension for Magic Context — cross-session memory and context management",
200069
200325
  main: "dist/index.js",
@@ -206434,6 +206690,20 @@ async function src_default2(pi) {
206434
206690
  runDeferredV22Backfill(db).catch((err5) => {
206435
206691
  warn(`[v22-backfill] background runner failed: ${err5}`);
206436
206692
  });
206693
+ setTimeout(() => {
206694
+ (async () => {
206695
+ try {
206696
+ const api2 = await loadDefaultPiSessionApi();
206697
+ const sessions = await api2.listSessions();
206698
+ await runSessionProjectBackfill(database, sessions.map((session) => ({
206699
+ sessionId: typeof session?.id === "string" ? session.id : "",
206700
+ directory: typeof session?.cwd === "string" ? session.cwd : ""
206701
+ })));
206702
+ } catch (err5) {
206703
+ warn(`[session-projects] background runner failed: ${err5}`);
206704
+ }
206705
+ })();
206706
+ }, 0);
206437
206707
  const projectDir = process.cwd();
206438
206708
  const projectIdentity = resolveProjectIdentity(projectDir);
206439
206709
  const seenDreamerProjectIdentities = new Set([projectIdentity]);
@@ -206558,7 +206828,7 @@ async function src_default2(pi) {
206558
206828
  const bootContextOptions = buildContextOptions(config2, historianConfig, autoSearchConfig);
206559
206829
  contextOptionsByDir.set(projectDir, bootContextOptions);
206560
206830
  registerPiContextHandler(pi, bootContextOptions);
206561
- info(historianConfig ? `registered historian trigger (model=${historianConfig.model}, executeThreshold=${historianConfig.executeThresholdPercentage ?? 65}%)` : "registered historian trigger: DISABLED (set historian.model in magic-context.jsonc)");
206831
+ info(historianConfig ? `registered historian trigger (model=${historianConfig.model}, executeThreshold=${formatExecuteThresholdForLog(historianConfig.executeThresholdPercentage)})` : "registered historian trigger: DISABLED (set historian.model in magic-context.jsonc)");
206562
206832
  info(autoSearchConfig.enabled ? `registered auto-search hint (threshold=${autoSearchConfig.scoreThreshold}, minChars=${autoSearchConfig.minPromptChars})` : "registered auto-search hint: DISABLED (memory.auto_search.enabled=false)");
206563
206833
  const sidekickConfig = resolveSidekickFromConfig(config2);
206564
206834
  registerCtxAugCommand(pi, sidekickConfig);
@@ -207015,6 +207285,15 @@ ${block}` : event.systemPrompt;
207015
207285
  } catch {}
207016
207286
  });
207017
207287
  }
207288
+ function formatExecuteThresholdForLog(value) {
207289
+ if (value === undefined)
207290
+ return "65%";
207291
+ if (typeof value === "number")
207292
+ return `${value}%`;
207293
+ const overrides = Object.entries(value).filter(([key]) => key !== "default").map(([key, pct]) => `${key}=${pct}%`);
207294
+ const base = `${value.default}%`;
207295
+ return overrides.length > 0 ? `${base} (${overrides.join(", ")})` : base;
207296
+ }
207018
207297
  export {
207019
207298
  resolveSidekickFromConfig,
207020
207299
  resolveHistorianFromConfig,
@@ -161941,6 +161941,7 @@ function enforceProjectCap(db, projectPath, maxCommits) {
161941
161941
  // ../plugin/src/features/magic-context/git-commits/sweep-coordinator.ts
161942
161942
  var GIT_SWEEP_COOLDOWN_MS = 10 * 60 * 1000;
161943
161943
  var GIT_SWEEP_LEASE_TTL_MS = 5 * 60 * 1000;
161944
+ var GIT_SWEEP_NON_INDEXABLE_REPROBE_MS = 24 * 60 * 60 * 1000;
161944
161945
  var GIT_SWEEP_LEASE_RENEWAL_MS = 60 * 1000;
161945
161946
  function runImmediate(db, body) {
161946
161947
  db.exec("BEGIN IMMEDIATE");
@@ -162047,6 +162048,20 @@ function markGitSweepSuccessAndRelease(db, projectPath, holderId) {
162047
162048
  return result.changes === 1;
162048
162049
  });
162049
162050
  }
162051
+ function parkGitSweepNonIndexable(db, projectPath, holderId, reprobeMs = GIT_SWEEP_NON_INDEXABLE_REPROBE_MS) {
162052
+ return runImmediate(db, () => {
162053
+ const now = Date.now();
162054
+ const sweptAt = now + reprobeMs - GIT_SWEEP_COOLDOWN_MS;
162055
+ const result = db.prepare(`UPDATE git_sweep_coordinator
162056
+ SET lease_holder = NULL,
162057
+ lease_expires_at = NULL,
162058
+ last_swept_at = ?
162059
+ WHERE project_path = ?
162060
+ AND lease_holder = ?
162061
+ AND lease_expires_at > ?`).run(sweptAt, projectPath, holderId, now);
162062
+ return result.changes === 1;
162063
+ });
162064
+ }
162050
162065
  function releaseGitSweepLease(db, projectPath, holderId) {
162051
162066
  runImmediate(db, () => {
162052
162067
  db.prepare(`UPDATE git_sweep_coordinator
@@ -173417,7 +173432,15 @@ var GIT_TIMEOUT_MS3 = 1e4;
173417
173432
  var DEFAULT_MAX_COMMITS = 5000;
173418
173433
  var RECORD_SEPARATOR = "\x1E";
173419
173434
  var FIELD_SEPARATOR = "\x1F";
173420
- async function readGitCommits(directory, options = {}) {
173435
+ function classifyGitLogFailure(message) {
173436
+ if (message.includes("not a git repository"))
173437
+ return "not_a_repo";
173438
+ if (message.includes("unknown revision or path not in the working tree") || message.includes("does not have any commits yet") || message.includes("bad revision")) {
173439
+ return "no_head";
173440
+ }
173441
+ return "transient";
173442
+ }
173443
+ async function readGitCommitsResult(directory, options = {}) {
173421
173444
  const revision = options.branch ?? "HEAD";
173422
173445
  if (revision.startsWith("-")) {
173423
173446
  throw new Error(`readGitCommits: refusing revision that looks like an option: "${revision}"`);
@@ -173445,13 +173468,18 @@ async function readGitCommits(directory, options = {}) {
173445
173468
  stdout = result.stdout;
173446
173469
  } catch (error51) {
173447
173470
  const message = error51 instanceof Error ? error51.message : String(error51);
173448
- log(`[git-commits] readGitCommits failed for ${projectLabel}: ${message.slice(0, 500)}`);
173449
- return [];
173471
+ const failure = classifyGitLogFailure(message);
173472
+ if (failure === "transient") {
173473
+ log(`[git-commits] readGitCommits failed for ${projectLabel}: ${message.slice(0, 500)}`);
173474
+ } else {
173475
+ log(`[git-commits] ${projectLabel} is not indexable (${failure})`);
173476
+ }
173477
+ return { commits: [], failure };
173450
173478
  }
173451
173479
  if (stdout.trim().length === 0) {
173452
173480
  log(`[git-commits] readGitCommits returned empty stdout for ${projectLabel} (sinceMs=${options.sinceMs ?? "none"} args=${args.slice(0, 4).join(" ")})`);
173453
173481
  }
173454
- return parseGitLogOutput(stdout);
173482
+ return { commits: parseGitLogOutput(stdout), failure: null };
173455
173483
  }
173456
173484
  function parseGitLogOutput(stdout) {
173457
173485
  const commits = [];
@@ -173507,7 +173535,8 @@ async function indexCommitsForProject(db, projectPath, directory, options) {
173507
173535
  inserted: 0,
173508
173536
  updated: 0,
173509
173537
  evicted: 0,
173510
- embedded: 0
173538
+ embedded: 0,
173539
+ nonIndexable: false
173511
173540
  };
173512
173541
  if (indexInProgress.has(projectPath)) {
173513
173542
  log(`[git-commits] index already in progress for ${projectPath}, skipping`);
@@ -173517,12 +173546,17 @@ async function indexCommitsForProject(db, projectPath, directory, options) {
173517
173546
  try {
173518
173547
  const latestIndexed = getLatestIndexedCommitTimeMs(db, projectPath);
173519
173548
  const sinceMs = latestIndexed !== null ? Math.max(latestIndexed - 60000, Date.now() - options.sinceDays * MS_PER_DAY) : Date.now() - options.sinceDays * MS_PER_DAY;
173520
- const commits = await readGitCommits(directory, {
173549
+ const read = await readGitCommitsResult(directory, {
173521
173550
  sinceMs,
173522
173551
  maxCommits: options.maxCommits,
173523
173552
  projectIdentity: projectPath
173524
173553
  });
173554
+ const commits = read.commits;
173525
173555
  result.scanned = commits.length;
173556
+ if (read.failure === "not_a_repo" || read.failure === "no_head") {
173557
+ result.nonIndexable = true;
173558
+ return result;
173559
+ }
173526
173560
  if (commits.length === 0) {
173527
173561
  result.evicted = enforceProjectCap(db, projectPath, options.maxCommits);
173528
173562
  log(`[git-commits] no new commits for ${projectPath} (sinceMs=${sinceMs} latestIndexed=${latestIndexed ?? "none"} evicted=${result.evicted})`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cortexkit/pi-magic-context",
3
- "version": "0.30.5",
3
+ "version": "0.30.7",
4
4
  "type": "module",
5
5
  "description": "Pi coding agent extension for Magic Context — cross-session memory and context management",
6
6
  "main": "dist/index.js",