@cortexkit/pi-magic-context 0.45.0 → 0.46.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -31,18 +31,21 @@ import {
31
31
  getEmbeddingProviderIdentity,
32
32
  dominantEmbeddingFailure,
33
33
  LocalEmbeddingProvider
34
- } from "./index-ttf0cqq8.js";
34
+ } from "./index-r01b1b78.js";
35
35
  import {
36
36
  piModelRefToCanonical,
37
37
  modelRefLookupOrder
38
- } from "./index-g0xfx1c2.js";
38
+ } from "./index-phh7e055.js";
39
39
  import {
40
40
  resolveDecisionCalibration,
41
41
  calibrationForModelKey,
42
+ protectedToolTagNumbers,
42
43
  isRecord,
43
44
  TODO_STATUSES,
44
45
  TODO_PRIORITIES,
45
46
  TITLE_DONE_STATUSES,
47
+ queuePendingOp,
48
+ getPendingOps,
46
49
  updateTagStatus,
47
50
  getInertWhitespaceAssistantTags,
48
51
  getTagNumberByMessageId,
@@ -54,31 +57,33 @@ import {
54
57
  hasRawMessageProvider2,
55
58
  setRawMessageProvider2,
56
59
  cleanUserText2,
57
- readRawSessionMessages2,
58
60
  visitRawSessionMessages2,
59
61
  readRawSessionMessageById2,
60
62
  readSessionChunk2
61
- } from "./index-vxjgsr9m.js";
63
+ } from "./index-xvw8zptx.js";
62
64
  import {
63
65
  removeSystemReminders,
64
66
  hasMeaningfulUserText2,
65
67
  extractTexts2,
66
68
  getTokenEstimatorFingerprint,
67
69
  estimateTokens
68
- } from "./index-j0mbc5vj.js";
70
+ } from "./index-266qrgss.js";
71
+ import {
72
+ stableStringify,
73
+ closeQuietly,
74
+ isKnownAutocommit,
75
+ getTableColumnNames,
76
+ resolveOpenCodeDbPath,
77
+ assertOpenCodeStoreGeneration
78
+ } from "./index-td885aah.js";
69
79
  import {
70
80
  Database,
81
+ prepareCachedStatement,
71
82
  withSqliteBackgroundWriter,
72
83
  withoutSqliteTransformPass,
73
84
  isTransientSqliteError,
74
85
  withPrivilegedWriter
75
- } from "./index-2pbbk3en.js";
76
- import {
77
- stableStringify,
78
- resolveOpenCodeDbPath,
79
- assertOpenCodeStoreGeneration,
80
- closeQuietly
81
- } from "./index-e16q5sd7.js";
86
+ } from "./index-wv28nczk.js";
82
87
  import {
83
88
  isUserHomeDirectory,
84
89
  directoryHasGitMetadata,
@@ -104,10 +109,14 @@ import {
104
109
  sourceNameForMemory,
105
110
  managedAuthorityNoteRow,
106
111
  getErrorMessage
107
- } from "./index-k0yd1ph9.js";
112
+ } from "./index-4vfrjwf6.js";
113
+ import {
114
+ ensureStorageDirectorySync,
115
+ writeStorageFileAtomicSync
116
+ } from "./index-vf38qhee.js";
108
117
  import {
109
118
  logSlowWriteTransaction
110
- } from "./index-7s5yk3za.js";
119
+ } from "./index-2p1e8706.js";
111
120
 
112
121
  // ../plugin/src/config/agent-disable.ts
113
122
  var COMPACTION_ENABLED_PATH = `compaction${"."}enabled`;
@@ -610,18 +619,7 @@ function formatCompactTokens(value) {
610
619
  }
611
620
 
612
621
  // ../plugin/src/config/migrate-config-location.ts
613
- import {
614
- closeSync,
615
- existsSync,
616
- mkdirSync,
617
- openSync,
618
- readFileSync as readFileSync2,
619
- renameSync,
620
- rmSync,
621
- statSync,
622
- unlinkSync,
623
- writeFileSync
624
- } from "node:fs";
622
+ import { existsSync, readFileSync as readFileSync2, rmSync, statSync, unlinkSync } from "node:fs";
625
623
  import { homedir } from "node:os";
626
624
  import { basename, dirname, isAbsolute, join as join2 } from "node:path";
627
625
 
@@ -2280,7 +2278,7 @@ var CONFIG_LOCK_STALE_MS = 4000;
2280
2278
  function acquireConfigMigrationLock(lockDir) {
2281
2279
  for (let attempt = 0;attempt < 2; attempt++) {
2282
2280
  try {
2283
- mkdirSync(lockDir, { recursive: false });
2281
+ ensureStorageDirectorySync(lockDir, true, false);
2284
2282
  return () => {
2285
2283
  try {
2286
2284
  rmSync(lockDir, { recursive: true, force: true });
@@ -2305,26 +2303,7 @@ function acquireConfigMigrationLock(lockDir) {
2305
2303
  return null;
2306
2304
  }
2307
2305
  function atomicWriteConfigFile(targetPath, content) {
2308
- mkdirSync(dirname(targetPath), { recursive: true });
2309
- const tmpPath = join2(dirname(targetPath), `.${basename(targetPath)}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`);
2310
- let fd = null;
2311
- try {
2312
- fd = openSync(tmpPath, "wx", 384);
2313
- writeFileSync(fd, content);
2314
- closeSync(fd);
2315
- fd = null;
2316
- renameSync(tmpPath, targetPath);
2317
- } catch (err) {
2318
- if (fd !== null) {
2319
- try {
2320
- closeSync(fd);
2321
- } catch {}
2322
- }
2323
- try {
2324
- unlinkSync(tmpPath);
2325
- } catch {}
2326
- throw err;
2327
- }
2306
+ writeStorageFileAtomicSync(targetPath, content, true);
2328
2307
  }
2329
2308
  function movedMarkerContent(targetPath, originalName, originalContent) {
2330
2309
  const header = [
@@ -2378,7 +2357,7 @@ function migrateConfigFile(opts) {
2378
2357
  if (existingSources.length === 0) {
2379
2358
  return { migrated: false, conflict: false, targetPath: opts.targetPath, warnings };
2380
2359
  }
2381
- mkdirSync(dirname(opts.targetPath), { recursive: true });
2360
+ ensureStorageDirectorySync(dirname(opts.targetPath), true);
2382
2361
  const release = acquireConfigMigrationLock(`${opts.targetPath}.lock`);
2383
2362
  if (!release) {
2384
2363
  warnings.push(`Config migration for ${opts.scope} skipped this run (another instance is migrating); will retry on next start.`);
@@ -3058,6 +3037,9 @@ function escalationBands(effectiveThresholdPercentage) {
3058
3037
 
3059
3038
  // ../plugin/src/features/magic-context/merged-reasoning-decisions.ts
3060
3039
  var MERGED_REASONING_PARTS_PREFIX = "__merged_reasoning_parts_v1__:";
3040
+ var decodedDecisions = new Map;
3041
+ var decodedDecisionBytes = 0;
3042
+ var MAX_DECODED_DECISION_BYTES = 32 * 1024 * 1024;
3061
3043
  function decodeMergedReasoningParts(value) {
3062
3044
  if (!value.startsWith(MERGED_REASONING_PARTS_PREFIX))
3063
3045
  return null;
@@ -3078,9 +3060,24 @@ function decodeMergedReasoningParts(value) {
3078
3060
  function readFrozenMergedReasoningParts(ids) {
3079
3061
  const decisions = new Map;
3080
3062
  for (const value of ids) {
3081
- const record = decodeMergedReasoningParts(value);
3063
+ let record = decodedDecisions.get(value);
3064
+ if (record === undefined) {
3065
+ record = decodeMergedReasoningParts(value);
3066
+ const bytes = 2 * value.length + 128;
3067
+ if (bytes <= MAX_DECODED_DECISION_BYTES) {
3068
+ while (decodedDecisions.size >= 1e5 || decodedDecisionBytes + bytes > MAX_DECODED_DECISION_BYTES) {
3069
+ const oldest = decodedDecisions.keys().next().value;
3070
+ if (oldest === undefined)
3071
+ break;
3072
+ decodedDecisionBytes -= 2 * oldest.length + 128;
3073
+ decodedDecisions.delete(oldest);
3074
+ }
3075
+ decodedDecisions.set(value, record);
3076
+ decodedDecisionBytes += bytes;
3077
+ }
3078
+ }
3082
3079
  if (record && !decisions.has(record[0]))
3083
- decisions.set(...record);
3080
+ decisions.set(record[0], [...record[1]]);
3084
3081
  }
3085
3082
  return decisions;
3086
3083
  }
@@ -3628,7 +3625,15 @@ function getDefaultSessionMeta(sessionId) {
3628
3625
  piStableIdScheme: null
3629
3626
  };
3630
3627
  }
3628
+ var sessionMetaExistsStatements = new WeakMap;
3631
3629
  function ensureSessionMetaRow(db, sessionId, initialIsSubagent = false) {
3630
+ let exists = sessionMetaExistsStatements.get(db);
3631
+ if (!exists) {
3632
+ exists = prepareCachedStatement(db, "SELECT 1 FROM session_meta WHERE session_id = ?");
3633
+ sessionMetaExistsStatements.set(db, exists);
3634
+ }
3635
+ if (exists.get(sessionId))
3636
+ return;
3632
3637
  const defaults = getDefaultSessionMeta(sessionId);
3633
3638
  db.prepare("INSERT OR IGNORE INTO session_meta (session_id, harness, last_response_time, cache_ttl, counter, last_nudge_tokens, last_nudge_band, last_transform_error, is_subagent, last_context_percentage, last_input_tokens, observed_safe_input_tokens, cache_alert_sent, times_execute_threshold_reached, compartment_in_progress, system_prompt_hash, cleared_reasoning_through_tag) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)").run(sessionId, getHarness(), defaults.lastResponseTime, defaults.cacheTtl, defaults.counter, defaults.lastNudgeTokens, defaults.lastNudgeBand ?? "", defaults.lastTransformError ?? "", initialIsSubagent ? 1 : 0, defaults.lastContextPercentage, defaults.lastInputTokens, defaults.observedSafeInputTokens, defaults.cacheAlertSent ? 1 : 0, defaults.timesExecuteThresholdReached, defaults.compartmentInProgress ? 1 : 0, defaults.systemPromptHash ?? "", defaults.clearedReasoningThroughTag);
3634
3639
  }
@@ -3765,6 +3770,10 @@ function clearCachedM0M1(db, sessionId) {
3765
3770
  // ../plugin/src/features/magic-context/storage-replay-document.ts
3766
3771
  var CAS_RETRY_LIMIT = 5;
3767
3772
  var MISSING_REPLAY_DOCUMENT_COLUMN = Symbol("missing replay document column");
3773
+ function isRustMarkerAdmissionFenced(db, sessionId) {
3774
+ const row = db.prepare("SELECT COALESCE(json_extract(NULLIF(trailing_blank_decisions, ''), '$.rustMarkerAdmissionFence'), 0) AS fenced FROM session_meta WHERE session_id=?").get(sessionId);
3775
+ return row?.fenced === 1;
3776
+ }
3768
3777
  function isPersistedTrailingBlankDecision(value) {
3769
3778
  if (value === "keep" || value === "strip")
3770
3779
  return true;
@@ -5431,34 +5440,61 @@ function decode(row) {
5431
5440
  }
5432
5441
  return { ...row, data };
5433
5442
  }
5434
-
5443
+ function connect(path, identity = "") {
5444
+ const db = new Database(path, { readonly: true, fileMustExist: true });
5445
+ try {
5446
+ assertOpenCodeStoreGeneration(db, "v2", path);
5447
+ } catch (error) {
5448
+ db.close();
5449
+ throw error;
5450
+ }
5451
+ const counters = debugCounters();
5452
+ counters.openReaders += 1;
5453
+ counters.readersOpened += 1;
5454
+ counters.maxOpenReaders = Math.max(counters.maxOpenReaders, counters.openReaders);
5455
+ return { db, statements: new Map, identity, leases: 0, retired: false };
5456
+ }
5457
+ function closeConnection(connection) {
5458
+ connection.statements.clear();
5459
+ try {
5460
+ connection.db.close();
5461
+ } finally {
5462
+ const counters = debugCounters();
5463
+ counters.openReaders = Math.max(0, counters.openReaders - 1);
5464
+ counters.readersClosed += 1;
5465
+ }
5466
+ }
5435
5467
  class V2StoreReader {
5468
+ pool;
5436
5469
  db;
5470
+ connection;
5437
5471
  closed = false;
5438
- constructor(path) {
5439
- this.db = new Database(path, { readonly: true, fileMustExist: true });
5440
- try {
5441
- assertOpenCodeStoreGeneration(this.db, "v2", path);
5442
- } catch (error) {
5443
- this.db.close();
5444
- throw error;
5472
+ constructor(path, pool) {
5473
+ this.pool = pool;
5474
+ this.connection = pool ? pool.acquire(path) : connect(path);
5475
+ this.db = this.connection.db;
5476
+ }
5477
+ prepare(sql) {
5478
+ if (this.closed)
5479
+ throw new Error("Store reader is closed");
5480
+ const statements = this.connection.statements;
5481
+ let statement = statements.get(sql);
5482
+ if (!statement) {
5483
+ statement = this.db.prepare(sql);
5484
+ if (statements.size >= 128)
5485
+ statements.clear();
5486
+ statements.set(sql, statement);
5445
5487
  }
5446
- const counters = debugCounters();
5447
- counters.openReaders += 1;
5448
- counters.readersOpened += 1;
5449
- counters.maxOpenReaders = Math.max(counters.maxOpenReaders, counters.openReaders);
5488
+ return statement;
5450
5489
  }
5451
5490
  close() {
5452
5491
  if (this.closed)
5453
5492
  return;
5454
5493
  this.closed = true;
5455
- try {
5456
- this.db.close();
5457
- } finally {
5458
- const counters = debugCounters();
5459
- counters.openReaders = Math.max(0, counters.openReaders - 1);
5460
- counters.readersClosed += 1;
5461
- }
5494
+ if (this.pool)
5495
+ this.pool.release(this.connection);
5496
+ else
5497
+ closeConnection(this.connection);
5462
5498
  }
5463
5499
  page(sessionID, options = {}) {
5464
5500
  return trackDecodeOperation("page", () => {
@@ -5480,7 +5516,7 @@ class V2StoreReader {
5480
5516
  predicates.push("type = ?");
5481
5517
  parameters.push(options.type);
5482
5518
  }
5483
- const rows = this.db.prepare(`SELECT id, session_id, type, seq, time_created, data FROM session_message
5519
+ const rows = this.prepare(`SELECT id, session_id, type, seq, time_created, data FROM session_message
5484
5520
  WHERE ${predicates.join(" AND ")}
5485
5521
  ORDER BY seq ASC LIMIT ?`).all(...parameters, limit).map(decode);
5486
5522
  return { rows, cursor: rows.at(-1)?.seq };
@@ -5498,46 +5534,56 @@ class V2StoreReader {
5498
5534
  if (pageSize <= 0)
5499
5535
  return [];
5500
5536
  if (after) {
5501
- const anchor = this.db.prepare("SELECT seq FROM session_message WHERE session_id = ? AND id = ?").get(sessionID, after.id);
5537
+ const anchor = this.prepare("SELECT seq FROM session_message WHERE session_id = ? AND id = ?").get(sessionID, after.id);
5502
5538
  if (anchor) {
5503
- return this.db.prepare(`SELECT id, session_id, type, seq, time_created, data
5539
+ return this.prepare(`SELECT id, session_id, type, seq, time_created, data
5504
5540
  FROM session_message WHERE session_id = ? AND seq > ?
5505
5541
  AND type IN (${RAW_MESSAGE_TYPE_PARAMETERS}) ORDER BY seq ASC LIMIT ?`).all(sessionID, anchor.seq, ...RAW_MESSAGE_TYPES, pageSize).map(decode);
5506
5542
  }
5507
5543
  }
5508
5544
  const maximumSeq = Number.MAX_SAFE_INTEGER;
5509
- const rows = this.db.prepare(V2_MESSAGE_PAGE_SQL).all(afterOrdinal, sessionID, ...RAW_MESSAGE_TYPES, Math.max(0, afterOrdinal - 1), sessionID, ...RAW_MESSAGE_TYPES, finalWatermark - 1, maximumSeq, sessionID, ...RAW_MESSAGE_TYPES, pageSize);
5545
+ const rows = this.prepare(V2_MESSAGE_PAGE_SQL).all(afterOrdinal, sessionID, ...RAW_MESSAGE_TYPES, Math.max(0, afterOrdinal - 1), sessionID, ...RAW_MESSAGE_TYPES, finalWatermark - 1, maximumSeq, sessionID, ...RAW_MESSAGE_TYPES, pageSize);
5510
5546
  return rows.map(decode);
5511
5547
  });
5512
5548
  }
5513
5549
  messageCount(sessionID) {
5514
5550
  return trackDecodeOperation("messageCount", () => {
5515
5551
  const rawTypes = RAW_MESSAGE_TYPES.map(() => "?").join(", ");
5516
- const row = this.db.prepare(`SELECT COUNT(*) AS count FROM session_message
5552
+ const row = this.prepare(`SELECT COUNT(*) AS count FROM session_message
5517
5553
  WHERE session_id = ? AND type IN (${rawTypes})`).get(sessionID, ...RAW_MESSAGE_TYPES);
5518
5554
  return typeof row?.count === "number" ? row.count : 0;
5519
5555
  });
5520
5556
  }
5521
5557
  sessionDirectoryPage(afterSessionID, limit) {
5522
- const rows = this.db.prepare(`SELECT id, COALESCE(directory, '') AS directory FROM session_v2
5558
+ const rows = this.prepare(`SELECT id, COALESCE(directory, '') AS directory FROM session_v2
5523
5559
  WHERE id > ? ORDER BY id ASC LIMIT ?`).all(afterSessionID ?? "", limit);
5524
5560
  return rows.map((row) => ({ sessionId: row.id, directory: row.directory }));
5525
5561
  }
5526
5562
  latestMessageTime(sessionID) {
5527
- const row = this.db.prepare("SELECT MAX(time_created) AS time FROM session_message WHERE session_id = ?").get(sessionID);
5563
+ const row = this.prepare("SELECT MAX(time_created) AS time FROM session_message WHERE session_id = ?").get(sessionID);
5528
5564
  return row?.time ?? undefined;
5529
5565
  }
5530
5566
  isSubagent(sessionID) {
5531
- const row = this.db.prepare("SELECT parent_id FROM session_v2 WHERE id = ?").get(sessionID);
5567
+ const row = this.prepare("SELECT parent_id FROM session_v2 WHERE id = ?").get(sessionID);
5532
5568
  if (!row)
5533
5569
  return null;
5534
5570
  return typeof row.parent_id === "string" && row.parent_id.length > 0;
5535
5571
  }
5572
+ latestRootSessionInDirectory(directory) {
5573
+ const columns = new Set(this.prepare("PRAGMA table_info(session_v2)").all().map((column) => column.name));
5574
+ const archived = columns.has("time_archived") ? " AND time_archived IS NULL" : "";
5575
+ const order = columns.has("time_updated") ? "time_updated DESC, id DESC" : "id DESC";
5576
+ const row = this.prepare(`SELECT id FROM session_v2
5577
+ WHERE directory = ? AND parent_id IS NULL${archived}
5578
+ AND COALESCE(json_extract(metadata, '$.magic_context'), '') <> 'hidden-run'
5579
+ ORDER BY ${order} LIMIT 1`).get(directory);
5580
+ return row?.id;
5581
+ }
5536
5582
  rootSessionActivity(sessionIDs) {
5537
5583
  const roots = new Map;
5538
5584
  for (let offset = 0;offset < sessionIDs.length; offset += 500) {
5539
5585
  const chunk = sessionIDs.slice(offset, offset + 500);
5540
- const rows = this.db.prepare(`SELECT id, (
5586
+ const rows = this.prepare(`SELECT id, (
5541
5587
  SELECT MAX(time_created) FROM session_message
5542
5588
  WHERE session_id = session_v2.id AND type = 'user'
5543
5589
  ) AS time FROM session_v2
@@ -5554,7 +5600,7 @@ class V2StoreReader {
5554
5600
  const result = new Map;
5555
5601
  for (let offset = 0;offset < sessionIDs.length; offset += 500) {
5556
5602
  const chunk = sessionIDs.slice(offset, offset + 500);
5557
- const rows = this.db.prepare(`SELECT session_id, MIN(time_created) AS time FROM session_message
5603
+ const rows = this.prepare(`SELECT session_id, MIN(time_created) AS time FROM session_message
5558
5604
  WHERE type = 'user' AND time_created > ? AND session_id IN (${chunk.map(() => "?").join(",")})
5559
5605
  GROUP BY session_id`).all(sinceMs, ...chunk);
5560
5606
  for (const row of rows)
@@ -5571,7 +5617,7 @@ class V2StoreReader {
5571
5617
  const direction = before ? "DESC" : "ASC";
5572
5618
  const head = Math.floor((maxChars - truncationMarker.length) / 2);
5573
5619
  const tail = maxChars - truncationMarker.length - head;
5574
- return this.db.prepare(`WITH users AS (
5620
+ return this.prepare(`WITH users AS (
5575
5621
  SELECT seq, time_created, data FROM session_message
5576
5622
  WHERE session_id = ? AND type = 'user' AND time_created ${before ? "<=" : ">"} ?
5577
5623
  ORDER BY time_created ${direction}, seq ${direction} LIMIT ?
@@ -5591,14 +5637,14 @@ class V2StoreReader {
5591
5637
  }
5592
5638
  storedMessageCount(sessionID) {
5593
5639
  return trackDecodeOperation("storedMessageCount", () => {
5594
- const row = this.db.prepare("SELECT COUNT(*) AS count FROM session_message WHERE session_id = ?").get(sessionID);
5640
+ const row = this.prepare("SELECT COUNT(*) AS count FROM session_message WHERE session_id = ?").get(sessionID);
5595
5641
  return typeof row?.count === "number" ? row.count : 0;
5596
5642
  });
5597
5643
  }
5598
5644
  messageById(sessionID, id) {
5599
5645
  return trackDecodeOperation("messageById", () => {
5600
5646
  const rawTypes = RAW_MESSAGE_TYPES.map(() => "?").join(", ");
5601
- const row = this.db.prepare(`SELECT id, session_id, type, seq, time_created, data FROM session_message
5647
+ const row = this.prepare(`SELECT id, session_id, type, seq, time_created, data FROM session_message
5602
5648
  WHERE session_id = ? AND id = ? AND type IN (${rawTypes}) LIMIT 1`).get(sessionID, id, ...RAW_MESSAGE_TYPES);
5603
5649
  return row ? decode(row) : null;
5604
5650
  });
@@ -5606,7 +5652,7 @@ class V2StoreReader {
5606
5652
  messageExistsById(sessionID, id) {
5607
5653
  return trackDecodeOperation("messageExistsById", () => {
5608
5654
  const rawTypes = RAW_MESSAGE_TYPES.map(() => "?").join(", ");
5609
- const row = this.db.prepare(`SELECT 1 FROM session_message
5655
+ const row = this.prepare(`SELECT 1 FROM session_message
5610
5656
  WHERE id = ? AND session_id = ? AND type IN (${rawTypes}) LIMIT 1`).get(id, sessionID, ...RAW_MESSAGE_TYPES);
5611
5657
  return row != null;
5612
5658
  });
@@ -5614,7 +5660,7 @@ class V2StoreReader {
5614
5660
  messageOrdinalById(sessionID, id) {
5615
5661
  return trackDecodeOperation("messageOrdinalById", () => {
5616
5662
  const rawTypes = RAW_MESSAGE_TYPES.map(() => "?").join(", ");
5617
- const row = this.db.prepare(`WITH target AS (
5663
+ const row = this.prepare(`WITH target AS (
5618
5664
  SELECT seq FROM session_message
5619
5665
  WHERE session_id = ? AND id = ? AND type IN (${rawTypes})
5620
5666
  LIMIT 1
@@ -5636,7 +5682,7 @@ class V2StoreReader {
5636
5682
  if (!Number.isSafeInteger(toOrdinal) || toOrdinal < fromOrdinal)
5637
5683
  throw new Error("Invalid raw-message range end");
5638
5684
  const rawTypes = RAW_MESSAGE_TYPES.map(() => "?").join(", ");
5639
- const rows = this.db.prepare(`SELECT id FROM session_message
5685
+ const rows = this.prepare(`SELECT id FROM session_message
5640
5686
  WHERE session_id = ? AND type IN (${rawTypes})
5641
5687
  ORDER BY seq ASC LIMIT ? OFFSET ?`).all(sessionID, ...RAW_MESSAGE_TYPES, toOrdinal - fromOrdinal + 1, fromOrdinal - 1);
5642
5688
  return new Map(rows.map((row, index) => [row.id, fromOrdinal + index]));
@@ -5646,10 +5692,10 @@ class V2StoreReader {
5646
5692
  return trackDecodeOperation("messageOrdinalPage", () => {
5647
5693
  if (!Number.isSafeInteger(limit) || limit < 1 || limit > 1e4)
5648
5694
  throw new Error("Invalid page limit");
5649
- const rows = after ? this.db.prepare(`SELECT id, type, seq, json_valid(data) AS valid
5695
+ const rows = after ? this.prepare(`SELECT id, type, seq, json_valid(data) AS valid
5650
5696
  FROM session_message
5651
5697
  WHERE session_id = ? AND (seq > ? OR (seq = ? AND id > ?))
5652
- ORDER BY seq ASC, id ASC LIMIT ?`).all(sessionID, after.timeCreated, after.timeCreated, after.id, limit) : this.db.prepare(`SELECT id, type, seq, json_valid(data) AS valid
5698
+ ORDER BY seq ASC, id ASC LIMIT ?`).all(sessionID, after.timeCreated, after.timeCreated, after.id, limit) : this.prepare(`SELECT id, type, seq, json_valid(data) AS valid
5653
5699
  FROM session_message
5654
5700
  WHERE session_id = ?
5655
5701
  ORDER BY seq ASC, id ASC LIMIT ?`).all(sessionID, limit);
@@ -5668,7 +5714,7 @@ class V2StoreReader {
5668
5714
  spanRowStamps(sessionID, after, through) {
5669
5715
  if (!Number.isSafeInteger(after) || !Number.isSafeInteger(through))
5670
5716
  throw new Error("Invalid seq span");
5671
- const rows = this.db.prepare(`SELECT seq, id, time_updated AS updated, length(CAST(data AS BLOB)) AS bytes
5717
+ const rows = this.prepare(`SELECT seq, id, time_updated AS updated, length(CAST(data AS BLOB)) AS bytes
5672
5718
  FROM session_message WHERE session_id = ? AND seq > ? AND seq <= ?
5673
5719
  ORDER BY seq ASC`).all(sessionID, after, through);
5674
5720
  const stamps = new Map;
@@ -5683,7 +5729,7 @@ class V2StoreReader {
5683
5729
  if (!Number.isSafeInteger(limit) || limit < 1 || limit > 1e4)
5684
5730
  throw new Error("Invalid page limit");
5685
5731
  const rawTypes = RAW_MESSAGE_TYPES.map(() => "?").join(", ");
5686
- return this.db.prepare(`SELECT id, session_id, type, seq, time_created, data FROM session_message
5732
+ return this.prepare(`SELECT id, session_id, type, seq, time_created, data FROM session_message
5687
5733
  WHERE session_id = ? AND type IN (${rawTypes}) AND seq <= ?
5688
5734
  ORDER BY seq DESC LIMIT ?`).all(sessionID, ...RAW_MESSAGE_TYPES, throughSeq, limit).map(decode);
5689
5735
  });
@@ -5691,14 +5737,18 @@ class V2StoreReader {
5691
5737
  sequenceForId(sessionID, id) {
5692
5738
  if (!id)
5693
5739
  return;
5694
- const row = this.db.prepare("SELECT seq FROM session_message WHERE session_id = ? AND id = ? LIMIT 1").get(sessionID, id);
5740
+ const row = this.prepare("SELECT seq FROM session_message WHERE session_id = ? AND id = ? LIMIT 1").get(sessionID, id);
5695
5741
  return typeof row?.seq === "number" ? row.seq : undefined;
5696
5742
  }
5743
+ syntheticMessageIDs(sessionID) {
5744
+ const rows = this.prepare("SELECT id FROM session_message WHERE session_id = ? AND type = 'synthetic'").all(sessionID);
5745
+ return new Set(rows.map((row) => row.id));
5746
+ }
5697
5747
  forkOrigin(sessionID) {
5698
- const columns = new Set(this.db.prepare("PRAGMA table_info(session_v2)").all().map((column) => column.name));
5748
+ const columns = new Set(this.prepare("PRAGMA table_info(session_v2)").all().map((column) => column.name));
5699
5749
  if (!columns.has("fork_session_id") || !columns.has("fork_boundary"))
5700
5750
  return null;
5701
- const row = this.db.prepare("SELECT fork_session_id, fork_boundary FROM session_v2 WHERE id = ?").get(sessionID);
5751
+ const row = this.prepare("SELECT fork_session_id, fork_boundary FROM session_v2 WHERE id = ?").get(sessionID);
5702
5752
  if (!row?.fork_session_id || !row.fork_boundary)
5703
5753
  return null;
5704
5754
  try {
@@ -5714,17 +5764,17 @@ class V2StoreReader {
5714
5764
  }
5715
5765
  }
5716
5766
  sessionExists(sessionID) {
5717
- return this.db.prepare("SELECT 1 FROM session_v2 WHERE id = ?").get(sessionID) != null;
5767
+ return this.prepare("SELECT 1 FROM session_v2 WHERE id = ?").get(sessionID) != null;
5718
5768
  }
5719
5769
  rowStampsThrough(sessionID, throughSeq) {
5720
- return this.db.prepare(`SELECT id, type, seq, time_created FROM session_message
5770
+ return this.prepare(`SELECT id, type, seq, time_created FROM session_message
5721
5771
  WHERE session_id = ? AND seq <= ? ORDER BY seq ASC`).all(sessionID, throughSeq);
5722
5772
  }
5723
5773
  latestSequenceForIds(sessionID, ids) {
5724
5774
  let latest = -1;
5725
5775
  for (let offset = 0;offset < ids.length; offset += 500) {
5726
5776
  const chunk = ids.slice(offset, offset + 500);
5727
- const row = this.db.prepare(`SELECT MAX(seq) AS seq FROM session_message
5777
+ const row = this.prepare(`SELECT MAX(seq) AS seq FROM session_message
5728
5778
  WHERE session_id = ? AND id IN (${chunk.map(() => "?").join(", ")})`).get(sessionID, ...chunk);
5729
5779
  if (typeof row?.seq === "number")
5730
5780
  latest = Math.max(latest, row.seq);
@@ -5732,7 +5782,7 @@ class V2StoreReader {
5732
5782
  return latest;
5733
5783
  }
5734
5784
  compactionByStatus(sessionID, status) {
5735
- const row = this.db.prepare(`SELECT id, session_id, type, seq, time_created, data FROM session_message
5785
+ const row = this.prepare(`SELECT id, session_id, type, seq, time_created, data FROM session_message
5736
5786
  WHERE session_id = ? AND type = 'compaction'
5737
5787
  AND json_extract(data, '$.status') = ?
5738
5788
  ORDER BY seq DESC LIMIT 1`).get(sessionID, status);
@@ -5748,16 +5798,16 @@ class V2StoreReader {
5748
5798
  return trackDecodeOperation("idleRows", () => this.all(sessionID, after, "idle"));
5749
5799
  }
5750
5800
  earliestSequence(sessionID) {
5751
- const row = this.db.prepare("SELECT MIN(seq) AS seq FROM session_message WHERE session_id = ?").get(sessionID);
5801
+ const row = this.prepare("SELECT MIN(seq) AS seq FROM session_message WHERE session_id = ?").get(sessionID);
5752
5802
  return typeof row?.seq === "number" ? row.seq : undefined;
5753
5803
  }
5754
5804
  latestSequence(sessionID) {
5755
- const row = this.db.prepare("SELECT MAX(seq) AS seq FROM session_message WHERE session_id = ?").get(sessionID);
5805
+ const row = this.prepare("SELECT MAX(seq) AS seq FROM session_message WHERE session_id = ?").get(sessionID);
5756
5806
  return typeof row?.seq === "number" ? row.seq : -1;
5757
5807
  }
5758
5808
  assistantSince(sessionID, afterSeq) {
5759
5809
  return trackDecodeOperation("assistantSince", () => {
5760
- const rows = this.db.prepare(`SELECT id, session_id, type, seq, time_created, data FROM session_message
5810
+ const rows = this.prepare(`SELECT id, session_id, type, seq, time_created, data FROM session_message
5761
5811
  WHERE session_id = ? AND type = 'assistant' AND seq > ?
5762
5812
  ORDER BY seq ASC`).all(sessionID, afterSeq);
5763
5813
  return rows.map((row) => decode(row));
@@ -5765,7 +5815,7 @@ class V2StoreReader {
5765
5815
  }
5766
5816
  latestAssistant(sessionID) {
5767
5817
  return trackDecodeOperation("latestAssistant", () => {
5768
- const row = this.db.prepare(`SELECT id, session_id, type, seq, time_created, data FROM session_message
5818
+ const row = this.prepare(`SELECT id, session_id, type, seq, time_created, data FROM session_message
5769
5819
  WHERE session_id = ? AND type = 'assistant'
5770
5820
  ORDER BY seq DESC LIMIT 1`).get(sessionID);
5771
5821
  return row ? decode(row) : undefined;
@@ -5773,7 +5823,7 @@ class V2StoreReader {
5773
5823
  }
5774
5824
  latestIdle(sessionID) {
5775
5825
  return trackDecodeOperation("latestIdle", () => {
5776
- const row = this.db.prepare(`SELECT id, session_id, type, seq, time_created, data FROM session_message
5826
+ const row = this.prepare(`SELECT id, session_id, type, seq, time_created, data FROM session_message
5777
5827
  WHERE session_id = ? AND type = 'idle'
5778
5828
  ORDER BY seq DESC LIMIT 1`).get(sessionID);
5779
5829
  return row ? decode(row) : undefined;
@@ -6919,6 +6969,10 @@ var SESSION_SCOPED_TABLES = [
6919
6969
  { table: "tool_owner_backfill_state" },
6920
6970
  { table: "tags", harnessScoped: true },
6921
6971
  { table: "session_meta", harnessScoped: true },
6972
+ {
6973
+ table: "temporal_decisions",
6974
+ extraPredicate: "NOT EXISTS (SELECT 1 FROM session_meta AS remaining WHERE remaining.session_id = temporal_decisions.session_id)"
6975
+ },
6922
6976
  {
6923
6977
  table: "session_replay_decisions",
6924
6978
  extraPredicate: "NOT EXISTS (SELECT 1 FROM session_meta AS remaining WHERE remaining.session_id = session_replay_decisions.session_id)"
@@ -7158,6 +7212,19 @@ function clearSession(db, sessionId, rustModuleCleanupAcknowledged = false) {
7158
7212
  }).immediate()));
7159
7213
  logSlowWriteTransaction("clear-session", transactionStartedAt);
7160
7214
  }
7215
+ // ../plugin/src/shared/provider-response-completion.ts
7216
+ function providerResponseFailed(input) {
7217
+ if (input.error !== undefined && input.error !== null && input.error !== "")
7218
+ return true;
7219
+ const finish = typeof input.finish === "string" ? input.finish.trim().toLowerCase() : "";
7220
+ return ["error", "failed", "abort", "aborted", "interrupted", "cancelled", "canceled"].includes(finish);
7221
+ }
7222
+ function isSuccessfulProviderCompletion(input) {
7223
+ if (providerResponseFailed(input))
7224
+ return false;
7225
+ return typeof input.completedAt === "number" && Number.isFinite(input.completedAt) && input.completedAt > 0 || typeof input.finish === "string" && input.finish.trim().length > 0;
7226
+ }
7227
+
7161
7228
  // ../plugin/src/hooks/magic-context/embed-session-state.ts
7162
7229
  var embedPauseBySession = new Set;
7163
7230
  var embedRunStateBySession = new Map;
@@ -7372,7 +7439,31 @@ function toCompartment(row) {
7372
7439
  };
7373
7440
  }
7374
7441
  function getCompartments(db, sessionId) {
7375
- const rows = db.prepare("SELECT * FROM compartments WHERE session_id = ? ORDER BY sequence ASC").all(sessionId).filter(isCompartmentRow);
7442
+ const presentColumns = getTableColumnNames(db, "compartments");
7443
+ const columns = [
7444
+ "id",
7445
+ "session_id",
7446
+ "sequence",
7447
+ "start_message",
7448
+ "end_message",
7449
+ "start_message_id",
7450
+ "end_message_id",
7451
+ "start_block_index",
7452
+ "end_block_index",
7453
+ "title",
7454
+ "content",
7455
+ "p1",
7456
+ "p2",
7457
+ "p3",
7458
+ "p4",
7459
+ "importance",
7460
+ "episode_type",
7461
+ "legacy",
7462
+ "created_at",
7463
+ "rebase_status"
7464
+ ].filter((column) => presentColumns.has(column));
7465
+ const rows = db.prepare(`SELECT ${columns.length ? columns.join(", ") : "NULL AS id"}
7466
+ FROM compartments WHERE session_id = ? ORDER BY sequence ASC`).all(sessionId).filter(isCompartmentRow);
7376
7467
  return rows.map(toCompartment);
7377
7468
  }
7378
7469
  function getLastCompartmentEndMessage(db, sessionId) {
@@ -7486,8 +7577,25 @@ function escapeXmlAttr(s) {
7486
7577
  function escapeXmlContent(s) {
7487
7578
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
7488
7579
  }
7489
- function hasPartialCompartmentEndThrough(db, sessionId, endOrdinal) {
7490
- return Boolean(db.prepare("SELECT 1 FROM compartments WHERE session_id=? AND end_message<=? AND end_block_index IS NOT NULL LIMIT 1").get(sessionId, endOrdinal));
7580
+ function getUncoveredCompartmentEndThrough(db, sessionId, endOrdinal = Number.MAX_SAFE_INTEGER) {
7581
+ const end = getUncoveredCompartmentEndsThrough(db, sessionId, endOrdinal)[0];
7582
+ return end ? { endMessageId: end.endMessageId, endMessage: end.endMessage } : null;
7583
+ }
7584
+ function getUncoveredCompartmentEndsThrough(db, sessionId, endOrdinal = Number.MAX_SAFE_INTEGER, afterOrdinal = -1) {
7585
+ const rows = db.prepare(`SELECT k.end_message_id, k.end_message,
7586
+ n.start_message_id AS successor_id, n.start_message AS successor_start FROM compartments k
7587
+ LEFT JOIN compartments n ON n.session_id = k.session_id AND n.sequence = k.sequence + 1
7588
+ WHERE k.session_id = ?1 AND k.end_message <= ?2 AND k.end_message > ?3 AND k.end_block_index IS NOT NULL
7589
+ AND NOT COALESCE(n.sequence IS NOT NULL AND (
7590
+ (n.start_message_id = k.end_message_id AND n.start_block_index > k.end_block_index)
7591
+ OR n.start_message = k.end_message + 1), 0)
7592
+ ORDER BY k.sequence`).all(sessionId, endOrdinal, afterOrdinal);
7593
+ return rows.map((row) => ({
7594
+ endMessageId: row.end_message_id,
7595
+ endMessage: row.end_message,
7596
+ successorStartMessageId: row.successor_id,
7597
+ successorStartMessage: row.successor_start
7598
+ }));
7491
7599
  }
7492
7600
  function isPartialCompartmentEnd(db, sessionId, messageId) {
7493
7601
  return Boolean(db.prepare("SELECT 1 FROM compartments WHERE session_id=? AND end_message_id=? AND end_block_index IS NOT NULL LIMIT 1").get(sessionId, messageId));
@@ -7859,7 +7967,7 @@ function indexItemsAfterOrdinal(db, sessionId, items, finalWatermark, toSource)
7859
7967
  return inserted;
7860
7968
  }
7861
7969
  function harnessSupportsOpenCodeOrphanSweep(harness) {
7862
- return harness === "opencode" || harness === "opencode2";
7970
+ return harness === "opencode";
7863
7971
  }
7864
7972
  function getMessageHistoryOrphanSweepState(db, harness) {
7865
7973
  return db.prepare("SELECT cursor_session_id, last_swept_at FROM message_history_orphan_sweep WHERE harness = ?").get(harness) ?? {};
@@ -7895,6 +8003,15 @@ function sweepOrphanedOpenCodeMessageIndexesInBackground(db, openReadableOpenCod
7895
8003
  }
7896
8004
  if (!harnessSupportsOpenCodeOrphanSweep(harness)) {
7897
8005
  persistMessageHistoryOrphanSweepState(db, cursor, now + unavailableReprobeMs - cooldownMs, harness);
8006
+ if (harness === "opencode2") {
8007
+ return {
8008
+ status: "unavailable",
8009
+ scanned: 0,
8010
+ deleted: 0,
8011
+ cursor,
8012
+ reason: "OpenCode 2 keeps its sessions in session_v2, which this sweep does not read"
8013
+ };
8014
+ }
7898
8015
  return { status: "unavailable", scanned: 0, deleted: 0, cursor };
7899
8016
  }
7900
8017
  let openCodeDb = null;
@@ -8141,6 +8258,14 @@ class BoundedSessionMap {
8141
8258
  }
8142
8259
  }
8143
8260
 
8261
+ // ../plugin/src/hooks/magic-context/lkg-measured-request.ts
8262
+ var requests = new BoundedSessionMap(1000);
8263
+ var claimedRequests = new WeakSet;
8264
+ var captures = new BoundedSessionMap(1000);
8265
+ function clearCapturedLkgMeasurement(sessionId) {
8266
+ captures.delete(sessionId);
8267
+ }
8268
+
8144
8269
  // ../plugin/src/hooks/magic-context/lkg-slot.ts
8145
8270
  var LKG_TOTAL_BYTES = 64 * 1024 * 1024;
8146
8271
  var LKG_SINGLE_SLOT_BYTES = 24 * 1024 * 1024;
@@ -8256,6 +8381,35 @@ function lkgContentDigestFromFields(fields) {
8256
8381
  }
8257
8382
  return hash.digest("base64url");
8258
8383
  }
8384
+ var digestMemo = new Map;
8385
+ var DIGEST_MEMO_MAX_BYTES = 16 * 1024 * 1024;
8386
+ var digestMemoBytes = 0;
8387
+ function memoizedLkgContentDigestFromFields(id, fields) {
8388
+ const prior = digestMemo.get(id);
8389
+ if (prior && equalContentFields(fields, prior.fields)) {
8390
+ digestMemo.delete(id);
8391
+ digestMemo.set(id, prior);
8392
+ return prior.digest;
8393
+ }
8394
+ const digest = lkgContentDigestFromFields(fields);
8395
+ if (prior) {
8396
+ digestMemo.delete(id);
8397
+ digestMemoBytes -= prior.bytes;
8398
+ }
8399
+ const bytes = 128 + id.length * 2 + fields.reduce((sum, field) => sum + 16 + (typeof field === "string" ? field.length * 2 : 0), 0);
8400
+ if (bytes <= DIGEST_MEMO_MAX_BYTES) {
8401
+ while (digestMemoBytes + bytes > DIGEST_MEMO_MAX_BYTES || digestMemo.size >= 20000) {
8402
+ const oldest = digestMemo.entries().next().value;
8403
+ if (!oldest)
8404
+ break;
8405
+ digestMemo.delete(oldest[0]);
8406
+ digestMemoBytes -= oldest[1].bytes;
8407
+ }
8408
+ digestMemo.set(id, { fields: [...fields], digest, bytes });
8409
+ digestMemoBytes += bytes;
8410
+ }
8411
+ return digest;
8412
+ }
8259
8413
  function equalContentFields(left, right) {
8260
8414
  if (left === right)
8261
8415
  return true;
@@ -8295,10 +8449,6 @@ function incrementalLkgContentDigests(entries, prior) {
8295
8449
  }
8296
8450
  return { digests, reusedPrefix };
8297
8451
  }
8298
- function lkgContentDigest(message) {
8299
- const fields = lkgContentFields(message);
8300
- return fields ? lkgContentDigestFromFields(fields) : null;
8301
- }
8302
8452
  function touch(sessionId, entry) {
8303
8453
  lkgHeapHolder.entries.delete(sessionId);
8304
8454
  lkgHeapHolder.entries.set(sessionId, entry);
@@ -8430,6 +8580,10 @@ function copySlotForRead(slot) {
8430
8580
  inputContentSignatures: slot.inputContentSignatures ? [...slot.inputContentSignatures] : undefined
8431
8581
  };
8432
8582
  }
8583
+ function getInMemorySlot(sessionId) {
8584
+ const entry = lkgHeapHolder.entries.get(sessionId);
8585
+ return entry ? copySlotForRead(entry.slot) : undefined;
8586
+ }
8433
8587
  function getSlot(sessionId) {
8434
8588
  const entry = lkgHeapHolder.entries.get(sessionId);
8435
8589
  if (!entry) {
@@ -8444,12 +8598,16 @@ function getSlot(sessionId) {
8444
8598
  touch(sessionId, entry);
8445
8599
  return copySlotForRead(entry.slot);
8446
8600
  }
8447
- function dropSlot(sessionId, _reason) {
8601
+ function forgetInMemorySlot(sessionId) {
8448
8602
  const entry = lkgHeapHolder.entries.get(sessionId);
8449
8603
  if (entry) {
8450
8604
  lkgHeapHolder.entries.delete(sessionId);
8451
8605
  totalBytes -= entry.bytes;
8452
8606
  }
8607
+ }
8608
+ function dropSlot(sessionId, _reason) {
8609
+ clearCapturedLkgMeasurement(sessionId);
8610
+ forgetInMemorySlot(sessionId);
8453
8611
  const backend = persistenceBackend;
8454
8612
  if (!backend)
8455
8613
  return;
@@ -8473,7 +8631,10 @@ function noteEntry(sessionId, messages) {
8473
8631
  const anchorIndex = entryInputIds.indexOf(slot.lastInputMessageId);
8474
8632
  if (anchorIndex < 0)
8475
8633
  return null;
8476
- const entryContentDigests = messages.slice(0, anchorIndex + 1).map((message) => lkgContentDigest(message));
8634
+ const entryContentDigests = messages.slice(0, anchorIndex + 1).map((message, index) => {
8635
+ const fields = lkgContentFields(message);
8636
+ return fields ? memoizedLkgContentDigestFromFields(entryInputIds[index] ?? "", fields) : null;
8637
+ });
8477
8638
  if (entryContentDigests.some((digest) => digest === null))
8478
8639
  return null;
8479
8640
  const pristineTail = structuredClone(messages.slice(anchorIndex + 1));
@@ -8927,7 +9088,8 @@ function clampWatermark(value, maxCopiedTag) {
8927
9088
  }
8928
9089
  function copySessionStateForClone(db, sourceSessionId, destinationSessionId, filter) {
8929
9090
  return runImmediate(db, () => {
8930
- if (countRows(db, "compartments", destinationSessionId) > 0 || countRows(db, "tags", destinationSessionId) > 0 || filter.copySessionNotesAndFacts === true && (tableExists(db, "notes") && countRows(db, "notes", destinationSessionId) > 0 || tableExists(db, "session_facts") && countRows(db, "session_facts", destinationSessionId) > 0)) {
9091
+ const hasTemporalDecisions = tableExists(db, "temporal_decisions");
9092
+ if (countRows(db, "compartments", destinationSessionId) > 0 || countRows(db, "tags", destinationSessionId) > 0 || hasTemporalDecisions && countRows(db, "temporal_decisions", destinationSessionId) > 0 || filter.copySessionNotesAndFacts === true && (tableExists(db, "notes") && countRows(db, "notes", destinationSessionId) > 0 || tableExists(db, "session_facts") && countRows(db, "session_facts", destinationSessionId) > 0)) {
8931
9093
  return {
8932
9094
  kind: "destination-not-empty",
8933
9095
  compartmentsCopied: 0,
@@ -9019,6 +9181,14 @@ function copySessionStateForClone(db, sourceSessionId, destinationSessionId, fil
9019
9181
  insertPendingOp.run(destinationSessionId, row.tag_id, row.operation, row.queued_at, row.harness);
9020
9182
  }
9021
9183
  }
9184
+ if (hasTemporalDecisions) {
9185
+ const temporalRows = db.prepare("SELECT message_id,marker FROM temporal_decisions WHERE session_id=?").all(sourceSessionId);
9186
+ const insertTemporal = db.prepare("INSERT INTO temporal_decisions(session_id,message_id,marker) VALUES (?,?,?)");
9187
+ for (const row of temporalRows) {
9188
+ if (filter.includeMessageId(row.message_id))
9189
+ insertTemporal.run(destinationSessionId, mapMessageId(filter, row.message_id), row.marker);
9190
+ }
9191
+ }
9022
9192
  const inherited = filter.copySessionNotesAndFacts === true ? copyPiSessionNotesAndFacts(db, sourceSessionId, destinationSessionId, filter) : { notesCopied: 0, factsCopied: 0 };
9023
9193
  const meta = db.prepare(`SELECT cleared_reasoning_through_tag, tool_reclaim_watermark,
9024
9194
  pi_stable_id_scheme, stripped_placeholder_ids,
@@ -9552,89 +9722,6 @@ function markNoteChecked(db, noteId) {
9552
9722
  const now = Date.now();
9553
9723
  db.prepare("UPDATE notes SET last_checked_at = ?, updated_at = ? WHERE id = ? AND type = 'smart'").run(now, now, noteId);
9554
9724
  }
9555
- // ../plugin/src/features/magic-context/storage-ops.ts
9556
- var queuePendingOpStatements = new WeakMap;
9557
- var getPendingOpsStatements = new WeakMap;
9558
- var getPendingOpsCountStatements = new WeakMap;
9559
- var clearPendingOpsStatements = new WeakMap;
9560
- var removePendingOpStatements = new WeakMap;
9561
- function getQueuePendingOpStatement(db) {
9562
- let stmt = queuePendingOpStatements.get(db);
9563
- if (!stmt) {
9564
- stmt = db.prepare("INSERT INTO pending_ops (session_id, tag_id, operation, queued_at, harness) VALUES (?, ?, ?, ?, ?)");
9565
- queuePendingOpStatements.set(db, stmt);
9566
- }
9567
- return stmt;
9568
- }
9569
- function getPendingOpsStatement(db) {
9570
- let stmt = getPendingOpsStatements.get(db);
9571
- if (!stmt) {
9572
- stmt = db.prepare("SELECT id, session_id, tag_id, operation, queued_at FROM pending_ops WHERE session_id = ? ORDER BY queued_at ASC, id ASC");
9573
- getPendingOpsStatements.set(db, stmt);
9574
- }
9575
- return stmt;
9576
- }
9577
- function getClearPendingOpsStatement(db) {
9578
- let stmt = clearPendingOpsStatements.get(db);
9579
- if (!stmt) {
9580
- stmt = db.prepare("DELETE FROM pending_ops WHERE session_id = ?");
9581
- clearPendingOpsStatements.set(db, stmt);
9582
- }
9583
- return stmt;
9584
- }
9585
- function getRemovePendingOpStatement(db) {
9586
- let stmt = removePendingOpStatements.get(db);
9587
- if (!stmt) {
9588
- stmt = db.prepare("DELETE FROM pending_ops WHERE session_id = ? AND tag_id = ?");
9589
- removePendingOpStatements.set(db, stmt);
9590
- }
9591
- return stmt;
9592
- }
9593
- function isPendingOpRow(row) {
9594
- if (row === null || typeof row !== "object")
9595
- return false;
9596
- const r = row;
9597
- return typeof r.id === "number" && typeof r.session_id === "string" && typeof r.tag_id === "number" && typeof r.operation === "string" && typeof r.queued_at === "number";
9598
- }
9599
- function toPendingOp(row) {
9600
- if (row.operation !== "drop") {
9601
- sessionLog(row.session_id, `unknown pending operation "${row.operation}"; ignoring`);
9602
- return null;
9603
- }
9604
- return {
9605
- id: row.id,
9606
- sessionId: row.session_id,
9607
- tagId: row.tag_id,
9608
- operation: row.operation,
9609
- queuedAt: row.queued_at
9610
- };
9611
- }
9612
- function queuePendingOp(db, sessionId, tagId, operation, queuedAt = Date.now()) {
9613
- getQueuePendingOpStatement(db).run(sessionId, tagId, operation, queuedAt, getHarness());
9614
- }
9615
- function getPendingOps(db, sessionId) {
9616
- const rows = getPendingOpsStatement(db).all(sessionId).filter(isPendingOpRow);
9617
- return rows.map(toPendingOp).filter((op) => op !== null);
9618
- }
9619
- function getPendingOpsCount(db, sessionId) {
9620
- try {
9621
- let statement = getPendingOpsCountStatements.get(db);
9622
- if (!statement) {
9623
- statement = db.prepare("SELECT COUNT(*) AS count FROM pending_ops WHERE session_id = ?");
9624
- getPendingOpsCountStatements.set(db, statement);
9625
- }
9626
- const row = statement.get(sessionId);
9627
- return typeof row?.count === "number" && Number.isFinite(row.count) ? row.count : null;
9628
- } catch {
9629
- return null;
9630
- }
9631
- }
9632
- function clearPendingOps(db, sessionId) {
9633
- getClearPendingOpsStatement(db).run(sessionId);
9634
- }
9635
- function removePendingOp(db, sessionId, tagId) {
9636
- getRemovePendingOpStatement(db).run(sessionId, tagId);
9637
- }
9638
9725
  // ../plugin/src/features/magic-context/storage-primers.ts
9639
9726
  var PRIMER_CANDIDATE_TTL_MS = 90 * 24 * 60 * 60 * 1000;
9640
9727
  var PRIMER_CANDIDATE_MAX_AGE_MS = 180 * 24 * 60 * 60 * 1000;
@@ -9925,6 +10012,7 @@ function bumpProjectUserProfileVersion(db, projectPath = GLOBAL_USER_PROFILE_PRO
9925
10012
  return state;
9926
10013
  }
9927
10014
  // ../plugin/src/features/magic-context/storage-source.ts
10015
+ var sourceReadStatements = new WeakMap;
9928
10016
  function isSourceContentRow(row) {
9929
10017
  if (row === null || typeof row !== "object")
9930
10018
  return false;
@@ -9938,8 +10026,12 @@ function getSourceContents(db, sessionId, tagIds) {
9938
10026
  if (tagIds.length === 0) {
9939
10027
  return new Map;
9940
10028
  }
9941
- const placeholders = tagIds.map(() => "?").join(", ");
9942
- const rows = db.prepare(`SELECT tag_id, content FROM source_contents WHERE session_id = ? AND tag_id IN (${placeholders})`).all(sessionId, ...tagIds).filter(isSourceContentRow);
10029
+ let statement = sourceReadStatements.get(db);
10030
+ if (!statement) {
10031
+ statement = db.prepare("SELECT tag_id, content FROM source_contents WHERE session_id = ? AND tag_id IN (SELECT value FROM json_each(?))");
10032
+ sourceReadStatements.set(db, statement);
10033
+ }
10034
+ const rows = statement.all(sessionId, JSON.stringify(tagIds)).filter(isSourceContentRow);
9943
10035
  const sources = new Map;
9944
10036
  for (const row of rows) {
9945
10037
  sources.set(row.tag_id, row.content);
@@ -10319,752 +10411,424 @@ function createPromptSurfaceGuidanceEpochCache(runtime) {
10319
10411
  return cache;
10320
10412
  }
10321
10413
 
10322
- // src/read-session-pi.ts
10323
- var SYNTH_USER_ID_PREFIX = "synth-user-";
10324
- function resolvePiStableId(msg, index, entryIds, entryIdByRef) {
10325
- if (!msg || typeof msg !== "object")
10326
- return;
10327
- const byRef = entryIdByRef?.get(msg);
10328
- if (typeof byRef === "string" && byRef.length > 0)
10329
- return byRef;
10330
- const positional = entryIds?.[index];
10331
- if (typeof positional === "string" && positional.length > 0)
10332
- return positional;
10333
- const m = msg;
10334
- const role = m.role ?? "unknown";
10335
- return typeof m.timestamp === "number" ? `pi-msg-${index}-${m.timestamp}-${role}` : `pi-msg-${index}-${role}`;
10414
+ // ../plugin/src/config/prune-config-leaf.ts
10415
+ function isPlainObject2(value) {
10416
+ return typeof value === "object" && value !== null && !Array.isArray(value);
10336
10417
  }
10337
- function readPiSessionSnapshot(ctx) {
10338
- const sm = ctx.sessionManager;
10339
- if (sm === undefined)
10340
- return { branchEntries: [], rawMessages: [] };
10341
- const getBranch = sm.getBranch;
10342
- if (typeof getBranch !== "function")
10343
- return { branchEntries: [], rawMessages: [] };
10344
- let entries;
10345
- try {
10346
- entries = getBranch.call(sm);
10347
- } catch {
10348
- return { branchEntries: [], rawMessages: [] };
10418
+ function pruneNestedConfigLeaf(block, relativePath) {
10419
+ if (relativePath.length === 0)
10420
+ return null;
10421
+ const result = { ...block };
10422
+ let cursor = result;
10423
+ for (let i = 0;i < relativePath.length - 1; i++) {
10424
+ const seg = String(relativePath[i]);
10425
+ const child = cursor[seg];
10426
+ if (!isPlainObject2(child)) {
10427
+ if (!(seg in cursor))
10428
+ return null;
10429
+ delete cursor[seg];
10430
+ return {
10431
+ block: result,
10432
+ removed: relativePath.slice(0, i + 1).map(String).join(".")
10433
+ };
10434
+ }
10435
+ const clonedChild = { ...child };
10436
+ cursor[seg] = clonedChild;
10437
+ cursor = clonedChild;
10349
10438
  }
10350
- if (!Array.isArray(entries))
10351
- return { branchEntries: [], rawMessages: [] };
10352
- return {
10353
- branchEntries: entries,
10354
- rawMessages: convertEntriesToRawMessages(entries)
10355
- };
10439
+ const leaf = String(relativePath[relativePath.length - 1]);
10440
+ if (!(leaf in cursor))
10441
+ return null;
10442
+ delete cursor[leaf];
10443
+ return { block: result, removed: relativePath.map(String).join(".") };
10356
10444
  }
10357
- function readPiSessionMessages(ctx) {
10358
- return readPiSessionSnapshot(ctx).rawMessages;
10445
+
10446
+ // src/config/index.ts
10447
+ import { existsSync as existsSync6 } from "node:fs";
10448
+
10449
+ // ../plugin/src/config/migrate-dreamer-v2.ts
10450
+ var OLD_VERIFY_TASK = "verify";
10451
+ var OLD_CURATE_TASKS = ["consolidate", "archive-stale", "improve"];
10452
+ var RETIRED_OBJECT_MEMORY_TASKS = ["maintain-memory", ...OLD_CURATE_TASKS];
10453
+ var CANONICAL = [
10454
+ "map-memories",
10455
+ "verify",
10456
+ "verify-broad",
10457
+ "curate",
10458
+ "classify-memories",
10459
+ "retrospective",
10460
+ "maintain-docs",
10461
+ "evaluate-smart-notes",
10462
+ "review-user-memories",
10463
+ "promote-primers",
10464
+ "refresh-primers"
10465
+ ];
10466
+ var DEFAULT_BASE_CRON = "0 2 * * *";
10467
+ var DEFAULT_CLASSIFY_CRON = "0 6 * * *";
10468
+ var DEFAULT_RETROSPECTIVE_CRON = "0 5 * * *";
10469
+ var DEFAULT_VERIFY_BROAD_CRON = "0 4 * * 0";
10470
+ function windowToCron(schedule) {
10471
+ if (typeof schedule !== "string")
10472
+ return DEFAULT_BASE_CRON;
10473
+ const m = /^(\d{1,2}):(\d{2})\s*-/.exec(schedule.trim());
10474
+ if (!m)
10475
+ return DEFAULT_BASE_CRON;
10476
+ const hour = Number(m[1]);
10477
+ const minute = Number(m[2]);
10478
+ if (hour >= 24 || minute >= 60)
10479
+ return DEFAULT_BASE_CRON;
10480
+ return `${minute} ${hour} * * *`;
10359
10481
  }
10360
- function readPiSessionMessagePage(ctx, afterOrdinal, limit, finalWatermark) {
10361
- const sessionManager = ctx.sessionManager;
10362
- const getBranch = sessionManager?.getBranch;
10363
- if (typeof getBranch !== "function")
10364
- return [];
10365
- try {
10366
- const entries = getBranch.call(sessionManager);
10367
- return Array.isArray(entries) ? convertEntriesToRawMessagePage(entries, afterOrdinal, limit, finalWatermark) : [];
10368
- } catch {
10369
- return [];
10482
+ function asObject(value) {
10483
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : undefined;
10484
+ }
10485
+ function cronIntervalScore(schedule) {
10486
+ const parts = schedule.trim().split(/\s+/);
10487
+ if (parts.length !== 5)
10488
+ return Number.POSITIVE_INFINITY;
10489
+ const [minute, hour, dayOfMonth, month, dayOfWeek] = parts;
10490
+ if (month !== "*")
10491
+ return 366 * 24 * 60;
10492
+ if (dayOfMonth !== "*")
10493
+ return 31 * 24 * 60;
10494
+ if (dayOfWeek !== "*")
10495
+ return 7 * 24 * 60;
10496
+ const everyHour = /^\*\/(\d+)$/.exec(hour ?? "");
10497
+ if (everyHour)
10498
+ return Math.max(1, Number(everyHour[1])) * 60;
10499
+ if (hour === "*") {
10500
+ const everyMinute = /^\*\/(\d+)$/.exec(minute ?? "");
10501
+ return everyMinute ? Math.max(1, Number(everyMinute[1])) : 60;
10370
10502
  }
10503
+ return 24 * 60;
10371
10504
  }
10372
- function findLastModelKeyFromBranch(entries) {
10373
- if (!Array.isArray(entries))
10374
- return;
10375
- for (let i = entries.length - 1;i >= 0; i--) {
10376
- const e = entries[i];
10377
- if (!e || typeof e !== "object")
10378
- continue;
10379
- const v = e;
10380
- if (v.type !== "model_change")
10505
+ function mostFrequentSchedule(schedules) {
10506
+ const enabled = schedules.map((s) => s.trim()).filter(Boolean);
10507
+ if (enabled.length === 0)
10508
+ return "";
10509
+ return enabled.sort((a, b) => cronIntervalScore(a) - cronIntervalScore(b))[0] ?? "";
10510
+ }
10511
+ function withoutBroadInterval(entry) {
10512
+ const { broad_interval_days: _broad, ...rest } = entry;
10513
+ return rest;
10514
+ }
10515
+ function reconcileV2TasksObject(rawConfig, dreamer, tasksObject) {
10516
+ const hasVerifyBroad = "verify-broad" in tasksObject;
10517
+ const hasBroadIntervalAnywhere = Object.values(tasksObject).some((v) => asObject(v) && ("broad_interval_days" in v));
10518
+ const hasStaleKeyFiles = "key-files" in tasksObject;
10519
+ if (hasVerifyBroad && !hasBroadIntervalAnywhere && !hasStaleKeyFiles)
10520
+ return rawConfig;
10521
+ const nextTasks = {};
10522
+ for (const [key, value] of Object.entries(tasksObject)) {
10523
+ if (key === "key-files")
10381
10524
  continue;
10382
- if (typeof v.provider === "string" && v.provider.length > 0 && typeof v.modelId === "string" && v.modelId.length > 0) {
10383
- return `${v.provider}/${v.modelId}`;
10384
- }
10525
+ const obj = asObject(value);
10526
+ nextTasks[key] = obj ? withoutBroadInterval(obj) : value;
10385
10527
  }
10386
- return;
10528
+ if (!hasVerifyBroad) {
10529
+ const verify = asObject(tasksObject.verify);
10530
+ const verifyEnabled = typeof verify?.schedule === "string" && verify.schedule.trim() !== "";
10531
+ nextTasks["verify-broad"] = {
10532
+ schedule: verifyEnabled ? DEFAULT_VERIFY_BROAD_CRON : ""
10533
+ };
10534
+ }
10535
+ return { ...rawConfig, dreamer: { ...dreamer, tasks: nextTasks } };
10387
10536
  }
10388
- function findRestartModelSeedFromBranch(entries) {
10389
- if (!Array.isArray(entries))
10390
- return;
10391
- let switchedAfterLastReply = false;
10392
- for (let i = entries.length - 1;i >= 0; i--) {
10393
- const e = entries[i];
10394
- if (e?.type === "model_change") {
10395
- if (typeof e.provider === "string" && typeof e.modelId === "string")
10396
- switchedAfterLastReply = true;
10397
- continue;
10398
- }
10399
- if (e?.type !== "message")
10400
- continue;
10401
- const m = e.message;
10402
- if (m?.role !== "assistant")
10403
- continue;
10404
- if (typeof m.provider !== "string" || m.provider.length === 0 || typeof m.model !== "string" || m.model.length === 0) {
10405
- continue;
10537
+ function migrateDreamerV2(rawConfig, warnings) {
10538
+ const dreamer = asObject(rawConfig.dreamer);
10539
+ if (!dreamer)
10540
+ return rawConfig;
10541
+ const tasksObject = asObject(dreamer.tasks);
10542
+ const hasRetiredObjectTasks = tasksObject ? RETIRED_OBJECT_MEMORY_TASKS.some((task) => (task in tasksObject)) : false;
10543
+ if (tasksObject && !hasRetiredObjectTasks) {
10544
+ const hasLegacyOutsideTasks = "schedule" in dreamer || "user_memories" in dreamer || "pin_key_files" in dreamer || "task_timeout_minutes" in dreamer || "max_runtime_minutes" in dreamer;
10545
+ if (!hasLegacyOutsideTasks) {
10546
+ return reconcileV2TasksObject(rawConfig, dreamer, tasksObject);
10406
10547
  }
10407
- return switchedAfterLastReply ? `${m.provider}/${m.model}` : findLastModelKeyFromBranch(entries);
10408
10548
  }
10409
- return findLastModelKeyFromBranch(entries);
10410
- }
10411
- function rawEntryVersion(entry) {
10412
- const record = entry;
10413
- const updated = record.updatedAt ?? record.updated_at ?? record.timestamp;
10414
- return typeof updated === "string" || typeof updated === "number" ? updated : entry.id;
10415
- }
10416
- function parsePiEntryTimestamp(entry) {
10417
- const record = entry;
10418
- const raw = record.timestamp;
10419
- if (typeof raw === "number" && Number.isSafeInteger(raw) && raw >= 0)
10420
- return raw;
10421
- if (typeof raw !== "string" || raw.trim().length === 0)
10422
- return null;
10423
- const parsed = Date.parse(raw);
10424
- return Number.isSafeInteger(parsed) && parsed >= 0 ? parsed : null;
10425
- }
10426
- function attachPiPartVersion(parts, version) {
10427
- return parts.map((part) => {
10428
- if (part === null || typeof part !== "object" || Array.isArray(part))
10429
- return part;
10430
- try {
10431
- Object.defineProperty(part, "__magicContextPartUpdatedAt", {
10432
- value: version,
10433
- enumerable: false,
10434
- configurable: true
10549
+ const hasLegacy = "schedule" in dreamer || Array.isArray(dreamer.tasks) || hasRetiredObjectTasks || "user_memories" in dreamer || "pin_key_files" in dreamer || "task_timeout_minutes" in dreamer || "max_runtime_minutes" in dreamer;
10550
+ if (!hasLegacy)
10551
+ return rawConfig;
10552
+ const baseCron = windowToCron(dreamer.schedule);
10553
+ const timeout = typeof dreamer.task_timeout_minutes === "number" ? dreamer.task_timeout_minutes : undefined;
10554
+ const withTimeout = (entry) => timeout !== undefined ? { ...entry, timeout_minutes: timeout } : entry;
10555
+ const classifySchedule = dreamer.disable === true ? "" : DEFAULT_CLASSIFY_CRON;
10556
+ const retrospectiveSchedule = dreamer.disable === true ? "" : DEFAULT_RETROSPECTIVE_CRON;
10557
+ const tasks = {};
10558
+ if (tasksObject) {
10559
+ for (const [key, value] of Object.entries(tasksObject)) {
10560
+ if (RETIRED_OBJECT_MEMORY_TASKS.includes(key))
10561
+ continue;
10562
+ if (asObject(value))
10563
+ tasks[key] = { ...value };
10564
+ }
10565
+ const maintainMemoryEntry = asObject(tasksObject["maintain-memory"]);
10566
+ if (maintainMemoryEntry) {
10567
+ const schedule = typeof maintainMemoryEntry.schedule === "string" ? maintainMemoryEntry.schedule : baseCron;
10568
+ tasks.verify = withTimeout({
10569
+ ...withoutBroadInterval(maintainMemoryEntry),
10570
+ ...tasks.verify ?? {},
10571
+ schedule: tasks.verify?.schedule ?? schedule
10572
+ });
10573
+ tasks.curate = withTimeout({
10574
+ ...withoutBroadInterval(maintainMemoryEntry),
10575
+ ...tasks.curate ?? {},
10576
+ schedule: tasks.curate?.schedule ?? schedule
10435
10577
  });
10436
- } catch {}
10437
- return part;
10438
- });
10439
- }
10440
- function* iterateEntriesToRawMessageRange(entries, afterOrdinal, limit, finalWatermark) {
10441
- let emitted = 0;
10442
- const normalizedAfter = Math.max(0, Math.floor(afterOrdinal));
10443
- const normalizedLimit = Math.max(1, Math.floor(limit));
10444
- const normalizedWatermark = Math.max(normalizedAfter, Math.floor(finalWatermark));
10445
- let nextOrdinal = 1;
10446
- let pendingToolResults = [];
10447
- const buildToolParts = (results) => results.flatMap(({ msg, version }) => attachPiPartVersion(synthesizeToolResultParts(msg), version));
10448
- let hasPendingToolParts = false;
10449
- let pendingFirstRealId = "";
10450
- let pendingFirstRealVersion = "";
10451
- let pendingFirstCreatedAt = null;
10452
- const appendMessage = function* (id, role, version, createdAt, parts) {
10453
- const ordinal = nextOrdinal++;
10454
- if (ordinal > normalizedAfter && ordinal <= normalizedWatermark) {
10455
- emitted++;
10456
- yield {
10457
- ordinal,
10458
- id,
10459
- role,
10460
- parts: parts(),
10461
- version,
10462
- ...createdAt === null ? {} : { createdAt }
10463
- };
10464
10578
  }
10465
- return emitted >= normalizedLimit || nextOrdinal > normalizedWatermark;
10466
- };
10467
- for (const entry of entries) {
10468
- if (!isMessageEntry(entry))
10469
- continue;
10470
- const msg = entry.message;
10471
- const role = msg.role;
10472
- if (role === "toolResult") {
10473
- const callId = msg.toolCallId;
10474
- if (typeof callId !== "string" || callId.length === 0)
10475
- continue;
10476
- const version = rawEntryVersion(entry);
10477
- hasPendingToolParts = true;
10478
- pendingToolResults.push({ msg, version });
10479
- if (pendingFirstRealId === "") {
10480
- pendingFirstRealId = entry.id;
10481
- pendingFirstRealVersion = version;
10482
- pendingFirstCreatedAt = parsePiEntryTimestamp(entry);
10483
- }
10484
- continue;
10579
+ const oldVerifyEntry = asObject(tasksObject[OLD_VERIFY_TASK]);
10580
+ if (oldVerifyEntry) {
10581
+ tasks.verify = withTimeout({
10582
+ ...withoutBroadInterval(oldVerifyEntry),
10583
+ ...tasks.verify ?? {},
10584
+ schedule: tasks.verify?.schedule ?? (typeof oldVerifyEntry.schedule === "string" ? oldVerifyEntry.schedule : baseCron)
10585
+ });
10485
10586
  }
10486
- if (role === "user") {
10487
- const version = rawEntryVersion(entry);
10488
- const bufferedToolResults = pendingToolResults;
10489
- const done = yield* appendMessage(entry.id, "user", version, parsePiEntryTimestamp(entry), () => [
10490
- ...buildToolParts(bufferedToolResults),
10491
- ...attachPiPartVersion(synthesizeUserParts(msg), version)
10492
- ]);
10493
- pendingToolResults = [];
10494
- hasPendingToolParts = false;
10495
- pendingFirstRealId = "";
10496
- pendingFirstRealVersion = "";
10497
- pendingFirstCreatedAt = null;
10498
- if (done)
10499
- break;
10500
- continue;
10587
+ if (!tasks["verify-broad"]) {
10588
+ const verifyEnabled = typeof tasks.verify?.schedule === "string" && tasks.verify.schedule.trim() !== "";
10589
+ tasks["verify-broad"] = withTimeout({
10590
+ schedule: verifyEnabled ? DEFAULT_VERIFY_BROAD_CRON : ""
10591
+ });
10501
10592
  }
10502
- if (role === "assistant") {
10503
- if (hasPendingToolParts) {
10504
- const bufferedToolResults = pendingToolResults;
10505
- const pendingId = pendingFirstRealId;
10506
- const pendingVersion = pendingFirstRealVersion;
10507
- const done = yield* appendMessage(`${SYNTH_USER_ID_PREFIX}${pendingId}`, "user", pendingVersion, pendingFirstCreatedAt, () => buildToolParts(bufferedToolResults));
10508
- pendingToolResults = [];
10509
- hasPendingToolParts = false;
10510
- pendingFirstRealId = "";
10511
- pendingFirstRealVersion = "";
10512
- pendingFirstCreatedAt = null;
10513
- if (done)
10514
- break;
10515
- }
10516
- const version = rawEntryVersion(entry);
10517
- if (yield* appendMessage(entry.id, "assistant", version, parsePiEntryTimestamp(entry), () => attachPiPartVersion(synthesizeAssistantParts(msg), version))) {
10518
- break;
10519
- }
10520
- continue;
10593
+ const oldCurateEntries = OLD_CURATE_TASKS.map((task) => asObject(tasksObject[task])).filter((entry) => Boolean(entry));
10594
+ if (oldCurateEntries.length > 0) {
10595
+ const oldSchedules = oldCurateEntries.map((entry) => typeof entry.schedule === "string" ? entry.schedule : baseCron);
10596
+ tasks.curate = withTimeout({
10597
+ ...tasks.curate ?? {},
10598
+ schedule: mostFrequentSchedule(oldSchedules)
10599
+ });
10521
10600
  }
10522
- if (yield* appendMessage(entry.id, typeof role === "string" ? role : "unknown", rawEntryVersion(entry), parsePiEntryTimestamp(entry), () => [])) {
10523
- break;
10601
+ for (const task of CANONICAL) {
10602
+ if (!tasks[task]) {
10603
+ const schedule = task === "verify" || task === "curate" || task === "verify-broad" ? "" : task === "classify-memories" ? classifySchedule : task === "retrospective" ? retrospectiveSchedule : task === "maintain-docs" ? "" : baseCron;
10604
+ tasks[task] = withTimeout({ schedule });
10605
+ }
10524
10606
  }
10607
+ } else {
10608
+ const legacyArray = Array.isArray(dreamer.tasks) ? dreamer.tasks.filter((t) => typeof t === "string") : null;
10609
+ const verifySelected = legacyArray ? legacyArray.includes(OLD_VERIFY_TASK) : true;
10610
+ const curateSelected = legacyArray ? legacyArray.some((task) => OLD_CURATE_TASKS.includes(task)) : true;
10611
+ tasks.verify = withTimeout({
10612
+ schedule: verifySelected ? baseCron : ""
10613
+ });
10614
+ tasks["verify-broad"] = withTimeout({
10615
+ schedule: verifySelected ? DEFAULT_VERIFY_BROAD_CRON : ""
10616
+ });
10617
+ tasks.curate = withTimeout({
10618
+ schedule: curateSelected ? baseCron : ""
10619
+ });
10620
+ tasks["classify-memories"] = withTimeout({
10621
+ schedule: classifySchedule
10622
+ });
10623
+ tasks.retrospective = withTimeout({
10624
+ schedule: retrospectiveSchedule
10625
+ });
10626
+ tasks["maintain-docs"] = withTimeout({
10627
+ schedule: legacyArray?.includes("maintain-docs") ? baseCron : ""
10628
+ });
10525
10629
  }
10526
- if (hasPendingToolParts && emitted < normalizedLimit && nextOrdinal <= normalizedWatermark) {
10527
- yield* appendMessage(`${SYNTH_USER_ID_PREFIX}${pendingFirstRealId}`, "user", pendingFirstRealVersion, pendingFirstCreatedAt, () => buildToolParts(pendingToolResults));
10528
- }
10529
- }
10530
- function convertEntriesToRawMessages(entries) {
10531
- return [
10532
- ...iterateEntriesToRawMessageRange(entries, 0, Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER)
10533
- ];
10534
- }
10535
- function convertEntriesToRawMessagePage(entries, afterOrdinal, limit, finalWatermark) {
10536
- return [
10537
- ...iterateEntriesToRawMessageRange(entries, afterOrdinal, limit, finalWatermark)
10538
- ];
10539
- }
10540
- function isMessageEntry(value) {
10541
- if (value === null || typeof value !== "object")
10542
- return false;
10543
- const v = value;
10544
- if (v.type !== "message")
10545
- return false;
10546
- if (typeof v.id !== "string")
10547
- return false;
10548
- if (v.message === null || typeof v.message !== "object")
10549
- return false;
10550
- return true;
10630
+ tasks["map-memories"] ??= withTimeout({ schedule: baseCron });
10631
+ tasks["evaluate-smart-notes"] ??= withTimeout({ schedule: baseCron });
10632
+ const um = asObject(dreamer.user_memories);
10633
+ const umEnabled = um ? um.enabled !== false : true;
10634
+ if (um || !tasks["review-user-memories"]) {
10635
+ tasks["review-user-memories"] = withTimeout({
10636
+ ...tasks["review-user-memories"] ?? {},
10637
+ schedule: umEnabled ? baseCron : "",
10638
+ ...um && typeof um.promotion_threshold === "number" ? { promotion_threshold: um.promotion_threshold } : {}
10639
+ });
10640
+ }
10641
+ const {
10642
+ schedule: _schedule,
10643
+ tasks: _tasks,
10644
+ task_timeout_minutes: _tto,
10645
+ max_runtime_minutes: _max,
10646
+ user_memories: _um,
10647
+ pin_key_files: _pkf,
10648
+ ...rest
10649
+ } = dreamer;
10650
+ warnings.push('Migrated legacy dreamer scheduling (schedule window / tasks array / user_memories / pin_key_files) → per-task "dreamer.tasks" in-memory (run `doctor` to persist).');
10651
+ return { ...rawConfig, dreamer: { ...rest, tasks } };
10551
10652
  }
10552
- function synthesizeUserParts(msg) {
10553
- const m = msg;
10554
- if (typeof m.content === "string") {
10555
- if (m.content.trim().length === 0)
10556
- return [];
10557
- return [{ type: "text", text: m.content }];
10653
+
10654
+ // ../plugin/src/config/migrate-experimental.ts
10655
+ function migrateLegacyExperimental(rawConfig, warnings) {
10656
+ const experimental = rawConfig.experimental;
10657
+ if (typeof experimental !== "object" || experimental === null) {
10658
+ return rawConfig;
10558
10659
  }
10559
- if (!Array.isArray(m.content))
10560
- return [];
10561
- const parts = [];
10562
- for (const c of m.content) {
10563
- if (c === null || typeof c !== "object")
10564
- continue;
10565
- const cc = c;
10566
- if (cc.type === "text" && typeof cc.text === "string") {
10567
- parts.push({ type: "text", text: cc.text });
10568
- }
10660
+ const exp = experimental;
10661
+ const hasUM = "user_memories" in exp;
10662
+ const hasPKF = "pin_key_files" in exp;
10663
+ const hasMural = "mural" in exp;
10664
+ const TOP_LEVEL_GRADUATED = ["temporal_awareness", "caveman_text_compression"];
10665
+ const MEMORY_GRADUATED = ["auto_search", "git_commit_indexing"];
10666
+ const hasGraduated = TOP_LEVEL_GRADUATED.some((k) => (k in exp)) || MEMORY_GRADUATED.some((k) => (k in exp)) || hasMural;
10667
+ if (!hasUM && !hasPKF && !hasGraduated) {
10668
+ return rawConfig;
10569
10669
  }
10570
- return parts;
10571
- }
10572
- function synthesizeAssistantParts(msg) {
10573
- const m = msg;
10574
- if (!Array.isArray(m.content))
10575
- return [];
10576
- const parts = [];
10577
- for (const c of m.content) {
10578
- if (c === null || typeof c !== "object")
10579
- continue;
10580
- const cc = c;
10581
- if (cc.type === "text" && typeof cc.text === "string") {
10582
- parts.push({ type: "text", text: cc.text });
10583
- } else if (cc.type === "toolCall" && typeof cc.id === "string") {
10584
- parts.push({
10585
- type: "tool",
10586
- tool: typeof cc.name === "string" ? cc.name : "unknown",
10587
- callID: cc.id,
10588
- state: {
10589
- input: cc.arguments ?? {}
10590
- }
10591
- });
10670
+ const patched = { ...rawConfig };
10671
+ const dreamer = typeof patched.dreamer === "object" && patched.dreamer !== null ? { ...patched.dreamer } : {};
10672
+ const memory = typeof patched.memory === "object" && patched.memory !== null ? { ...patched.memory } : {};
10673
+ const newExperimental = { ...exp };
10674
+ const coerceToObject = (value) => {
10675
+ if (typeof value === "boolean") {
10676
+ return { enabled: value };
10677
+ }
10678
+ if (typeof value === "object" && value !== null) {
10679
+ return { ...value };
10680
+ }
10681
+ return;
10682
+ };
10683
+ const relocate = (key, dest, destLabel) => {
10684
+ if (!(key in exp))
10685
+ return;
10686
+ const oldValue = exp[key];
10687
+ const existing = dest[key];
10688
+ if (existing === undefined) {
10689
+ dest[key] = oldValue;
10690
+ warnings.push(`Migrated "experimental.${key}" → "${destLabel}${key}" in-memory (run \`doctor\` to persist).`);
10691
+ } else if (typeof oldValue === "object" && oldValue !== null && typeof existing === "object" && existing !== null) {
10692
+ dest[key] = {
10693
+ ...oldValue,
10694
+ ...existing
10695
+ };
10696
+ }
10697
+ delete newExperimental[key];
10698
+ };
10699
+ for (const key of TOP_LEVEL_GRADUATED)
10700
+ relocate(key, patched, "");
10701
+ for (const key of MEMORY_GRADUATED)
10702
+ relocate(key, memory, "memory.");
10703
+ if (hasMural) {
10704
+ const oldMural = coerceToObject(exp.mural);
10705
+ const existingMural = patched.mural;
10706
+ if (existingMural === undefined) {
10707
+ patched.mural = oldMural ?? exp.mural;
10708
+ warnings.push('Deprecated "experimental.mural"; use top-level "mural" instead (migrated in memory; run `doctor` to persist).');
10709
+ } else if (oldMural !== undefined && typeof existingMural === "object" && existingMural !== null && !Array.isArray(existingMural)) {
10710
+ patched.mural = {
10711
+ ...oldMural,
10712
+ ...existingMural
10713
+ };
10592
10714
  }
10715
+ delete newExperimental.mural;
10593
10716
  }
10594
- return parts;
10595
- }
10596
- function synthesizeToolResultParts(msg) {
10597
- const m = msg;
10598
- const callID = typeof m.toolCallId === "string" ? m.toolCallId : "";
10599
- const tool = typeof m.toolName === "string" ? m.toolName : "unknown";
10600
- if (!callID)
10601
- return [];
10602
- let output = "";
10603
- if (Array.isArray(m.content)) {
10604
- const fragments = [];
10605
- for (const c of m.content) {
10606
- if (c === null || typeof c !== "object")
10607
- continue;
10608
- const cc = c;
10609
- if (cc.type === "text" && typeof cc.text === "string") {
10610
- fragments.push(cc.text);
10717
+ if (hasUM) {
10718
+ const oldUM = coerceToObject(exp.user_memories);
10719
+ if (oldUM !== undefined) {
10720
+ if (dreamer.user_memories === undefined) {
10721
+ dreamer.user_memories = oldUM;
10722
+ warnings.push('Migrated "experimental.user_memories" → "dreamer.user_memories" in-memory (run `doctor` to persist).');
10723
+ } else if (typeof dreamer.user_memories === "object" && dreamer.user_memories !== null) {
10724
+ dreamer.user_memories = {
10725
+ ...oldUM,
10726
+ ...dreamer.user_memories
10727
+ };
10611
10728
  }
10612
10729
  }
10613
- output = fragments.join(`
10614
- `);
10730
+ delete newExperimental.user_memories;
10615
10731
  }
10616
- return [
10617
- {
10618
- type: "tool",
10619
- tool,
10620
- callID,
10621
- state: {
10622
- output
10732
+ if (hasPKF) {
10733
+ const oldPKF = coerceToObject(exp.pin_key_files);
10734
+ if (oldPKF !== undefined) {
10735
+ if (dreamer.pin_key_files === undefined) {
10736
+ dreamer.pin_key_files = oldPKF;
10737
+ warnings.push('Migrated "experimental.pin_key_files" → "dreamer.pin_key_files" in-memory (run `doctor` to persist).');
10738
+ } else if (typeof dreamer.pin_key_files === "object" && dreamer.pin_key_files !== null) {
10739
+ dreamer.pin_key_files = {
10740
+ ...oldPKF,
10741
+ ...dreamer.pin_key_files
10742
+ };
10743
+ } else if (typeof dreamer.pin_key_files === "boolean") {
10744
+ dreamer.pin_key_files = { ...oldPKF, enabled: dreamer.pin_key_files };
10623
10745
  }
10624
10746
  }
10625
- ];
10626
- }
10627
- function countPiRawMessages(entries) {
10628
- let count = 0;
10629
- let pendingTools = false;
10630
- for (const entry of entries) {
10631
- if (!isMessageEntry(entry))
10632
- continue;
10633
- const message = entry.message;
10634
- if (message.role === "toolResult") {
10635
- if (typeof message.toolCallId === "string" && message.toolCallId.length > 0)
10636
- pendingTools = true;
10637
- continue;
10638
- }
10639
- if (message.role === "user")
10640
- pendingTools = false;
10641
- else if (message.role === "assistant" && pendingTools) {
10642
- count++;
10643
- pendingTools = false;
10644
- }
10645
- count++;
10747
+ delete newExperimental.pin_key_files;
10646
10748
  }
10647
- return count + Number(pendingTools);
10648
- }
10649
-
10650
- // ../plugin/src/config/prune-config-leaf.ts
10651
- function isPlainObject2(value) {
10652
- return typeof value === "object" && value !== null && !Array.isArray(value);
10653
- }
10654
- function pruneNestedConfigLeaf(block, relativePath) {
10655
- if (relativePath.length === 0)
10656
- return null;
10657
- const result = { ...block };
10658
- let cursor = result;
10659
- for (let i = 0;i < relativePath.length - 1; i++) {
10660
- const seg = String(relativePath[i]);
10661
- const child = cursor[seg];
10662
- if (!isPlainObject2(child)) {
10663
- if (!(seg in cursor))
10664
- return null;
10665
- delete cursor[seg];
10666
- return {
10667
- block: result,
10668
- removed: relativePath.slice(0, i + 1).map(String).join(".")
10669
- };
10670
- }
10671
- const clonedChild = { ...child };
10672
- cursor[seg] = clonedChild;
10673
- cursor = clonedChild;
10749
+ patched.experimental = newExperimental;
10750
+ patched.dreamer = dreamer;
10751
+ if (Object.keys(memory).length > 0) {
10752
+ patched.memory = memory;
10674
10753
  }
10675
- const leaf = String(relativePath[relativePath.length - 1]);
10676
- if (!(leaf in cursor))
10677
- return null;
10678
- delete cursor[leaf];
10679
- return { block: result, removed: relativePath.map(String).join(".") };
10754
+ return patched;
10680
10755
  }
10681
10756
 
10682
- // src/config/index.ts
10683
- import { existsSync as existsSync6 } from "node:fs";
10684
-
10685
- // ../plugin/src/config/migrate-dreamer-v2.ts
10686
- var OLD_VERIFY_TASK = "verify";
10687
- var OLD_CURATE_TASKS = ["consolidate", "archive-stale", "improve"];
10688
- var RETIRED_OBJECT_MEMORY_TASKS = ["maintain-memory", ...OLD_CURATE_TASKS];
10689
- var CANONICAL = [
10690
- "map-memories",
10691
- "verify",
10692
- "verify-broad",
10693
- "curate",
10694
- "classify-memories",
10695
- "retrospective",
10696
- "maintain-docs",
10697
- "evaluate-smart-notes",
10698
- "review-user-memories",
10699
- "promote-primers",
10700
- "refresh-primers"
10701
- ];
10702
- var DEFAULT_BASE_CRON = "0 2 * * *";
10703
- var DEFAULT_CLASSIFY_CRON = "0 6 * * *";
10704
- var DEFAULT_RETROSPECTIVE_CRON = "0 5 * * *";
10705
- var DEFAULT_VERIFY_BROAD_CRON = "0 4 * * 0";
10706
- function windowToCron(schedule) {
10707
- if (typeof schedule !== "string")
10708
- return DEFAULT_BASE_CRON;
10709
- const m = /^(\d{1,2}):(\d{2})\s*-/.exec(schedule.trim());
10710
- if (!m)
10711
- return DEFAULT_BASE_CRON;
10712
- const hour = Number(m[1]);
10713
- const minute = Number(m[2]);
10714
- if (hour >= 24 || minute >= 60)
10715
- return DEFAULT_BASE_CRON;
10716
- return `${minute} ${hour} * * *`;
10717
- }
10718
- function asObject(value) {
10719
- return typeof value === "object" && value !== null && !Array.isArray(value) ? value : undefined;
10720
- }
10721
- function cronIntervalScore(schedule) {
10722
- const parts = schedule.trim().split(/\s+/);
10723
- if (parts.length !== 5)
10724
- return Number.POSITIVE_INFINITY;
10725
- const [minute, hour, dayOfMonth, month, dayOfWeek] = parts;
10726
- if (month !== "*")
10727
- return 366 * 24 * 60;
10728
- if (dayOfMonth !== "*")
10729
- return 31 * 24 * 60;
10730
- if (dayOfWeek !== "*")
10731
- return 7 * 24 * 60;
10732
- const everyHour = /^\*\/(\d+)$/.exec(hour ?? "");
10733
- if (everyHour)
10734
- return Math.max(1, Number(everyHour[1])) * 60;
10735
- if (hour === "*") {
10736
- const everyMinute = /^\*\/(\d+)$/.exec(minute ?? "");
10737
- return everyMinute ? Math.max(1, Number(everyMinute[1])) : 60;
10738
- }
10739
- return 24 * 60;
10740
- }
10741
- function mostFrequentSchedule(schedules) {
10742
- const enabled = schedules.map((s) => s.trim()).filter(Boolean);
10743
- if (enabled.length === 0)
10744
- return "";
10745
- return enabled.sort((a, b) => cronIntervalScore(a) - cronIntervalScore(b))[0] ?? "";
10757
+ // ../plugin/src/config/profiles.ts
10758
+ function withoutProfileFields(raw) {
10759
+ const copy = { ...raw };
10760
+ delete copy.profile;
10761
+ delete copy.profiles;
10762
+ return copy;
10746
10763
  }
10747
- function withoutBroadInterval(entry) {
10748
- const { broad_interval_days: _broad, ...rest } = entry;
10749
- return rest;
10764
+ function readProfileSelection(raw) {
10765
+ if (!Object.hasOwn(raw, "profile"))
10766
+ return { declared: false };
10767
+ const value = raw.profile;
10768
+ if (typeof value !== "string")
10769
+ return { declared: true };
10770
+ const name = value.trim();
10771
+ return name.length > 0 ? { declared: true, name } : { declared: true };
10750
10772
  }
10751
- function reconcileV2TasksObject(rawConfig, dreamer, tasksObject) {
10752
- const hasVerifyBroad = "verify-broad" in tasksObject;
10753
- const hasBroadIntervalAnywhere = Object.values(tasksObject).some((v) => asObject(v) && ("broad_interval_days" in v));
10754
- const hasStaleKeyFiles = "key-files" in tasksObject;
10755
- if (hasVerifyBroad && !hasBroadIntervalAnywhere && !hasStaleKeyFiles)
10756
- return rawConfig;
10757
- const nextTasks = {};
10758
- for (const [key, value] of Object.entries(tasksObject)) {
10759
- if (key === "key-files")
10760
- continue;
10761
- const obj = asObject(value);
10762
- nextTasks[key] = obj ? withoutBroadInterval(obj) : value;
10773
+ function resolveConfigProfile(args) {
10774
+ const warnings = [];
10775
+ const userSelection = readProfileSelection(args.userRaw);
10776
+ const projectSelection = readProfileSelection(args.projectRaw);
10777
+ const selection = projectSelection.name ? { name: projectSelection.name, source: "project" } : userSelection.name ? { name: userSelection.name, source: "user" } : undefined;
10778
+ if (projectSelection.declared && !projectSelection.name) {
10779
+ warnings.push("Ignoring invalid profile selection from project config; expected a non-empty string.");
10763
10780
  }
10764
- if (!hasVerifyBroad) {
10765
- const verify = asObject(tasksObject.verify);
10766
- const verifyEnabled = typeof verify?.schedule === "string" && verify.schedule.trim() !== "";
10767
- nextTasks["verify-broad"] = {
10768
- schedule: verifyEnabled ? DEFAULT_VERIFY_BROAD_CRON : ""
10769
- };
10781
+ if (!projectSelection.declared && userSelection.declared && !userSelection.name) {
10782
+ warnings.push("Ignoring invalid profile selection from user config; expected a non-empty string.");
10770
10783
  }
10771
- return { ...rawConfig, dreamer: { ...dreamer, tasks: nextTasks } };
10772
- }
10773
- function migrateDreamerV2(rawConfig, warnings) {
10774
- const dreamer = asObject(rawConfig.dreamer);
10775
- if (!dreamer)
10776
- return rawConfig;
10777
- const tasksObject = asObject(dreamer.tasks);
10778
- const hasRetiredObjectTasks = tasksObject ? RETIRED_OBJECT_MEMORY_TASKS.some((task) => (task in tasksObject)) : false;
10779
- if (tasksObject && !hasRetiredObjectTasks) {
10780
- const hasLegacyOutsideTasks = "schedule" in dreamer || "user_memories" in dreamer || "pin_key_files" in dreamer || "task_timeout_minutes" in dreamer || "max_runtime_minutes" in dreamer;
10781
- if (!hasLegacyOutsideTasks) {
10782
- return reconcileV2TasksObject(rawConfig, dreamer, tasksObject);
10784
+ let profiles = {};
10785
+ if (Object.hasOwn(args.userRaw, "profiles")) {
10786
+ const parsed = ConfigProfilesSchema.safeParse(args.userRaw.profiles);
10787
+ if (parsed.success) {
10788
+ profiles = parsed.data;
10789
+ } else {
10790
+ warnings.push("Ignoring profiles from user config: invalid profile configuration; profiles may contain only historian/dreamer harness model blocks.");
10783
10791
  }
10784
10792
  }
10785
- const hasLegacy = "schedule" in dreamer || Array.isArray(dreamer.tasks) || hasRetiredObjectTasks || "user_memories" in dreamer || "pin_key_files" in dreamer || "task_timeout_minutes" in dreamer || "max_runtime_minutes" in dreamer;
10786
- if (!hasLegacy)
10787
- return rawConfig;
10788
- const baseCron = windowToCron(dreamer.schedule);
10789
- const timeout = typeof dreamer.task_timeout_minutes === "number" ? dreamer.task_timeout_minutes : undefined;
10790
- const withTimeout = (entry) => timeout !== undefined ? { ...entry, timeout_minutes: timeout } : entry;
10791
- const classifySchedule = dreamer.disable === true ? "" : DEFAULT_CLASSIFY_CRON;
10792
- const retrospectiveSchedule = dreamer.disable === true ? "" : DEFAULT_RETROSPECTIVE_CRON;
10793
- const tasks = {};
10794
- if (tasksObject) {
10795
- for (const [key, value] of Object.entries(tasksObject)) {
10796
- if (RETIRED_OBJECT_MEMORY_TASKS.includes(key))
10797
- continue;
10798
- if (asObject(value))
10799
- tasks[key] = { ...value };
10800
- }
10801
- const maintainMemoryEntry = asObject(tasksObject["maintain-memory"]);
10802
- if (maintainMemoryEntry) {
10803
- const schedule = typeof maintainMemoryEntry.schedule === "string" ? maintainMemoryEntry.schedule : baseCron;
10804
- tasks.verify = withTimeout({
10805
- ...withoutBroadInterval(maintainMemoryEntry),
10806
- ...tasks.verify ?? {},
10807
- schedule: tasks.verify?.schedule ?? schedule
10808
- });
10809
- tasks.curate = withTimeout({
10810
- ...withoutBroadInterval(maintainMemoryEntry),
10811
- ...tasks.curate ?? {},
10812
- schedule: tasks.curate?.schedule ?? schedule
10813
- });
10814
- }
10815
- const oldVerifyEntry = asObject(tasksObject[OLD_VERIFY_TASK]);
10816
- if (oldVerifyEntry) {
10817
- tasks.verify = withTimeout({
10818
- ...withoutBroadInterval(oldVerifyEntry),
10819
- ...tasks.verify ?? {},
10820
- schedule: tasks.verify?.schedule ?? (typeof oldVerifyEntry.schedule === "string" ? oldVerifyEntry.schedule : baseCron)
10821
- });
10822
- }
10823
- if (!tasks["verify-broad"]) {
10824
- const verifyEnabled = typeof tasks.verify?.schedule === "string" && tasks.verify.schedule.trim() !== "";
10825
- tasks["verify-broad"] = withTimeout({
10826
- schedule: verifyEnabled ? DEFAULT_VERIFY_BROAD_CRON : ""
10827
- });
10828
- }
10829
- const oldCurateEntries = OLD_CURATE_TASKS.map((task) => asObject(tasksObject[task])).filter((entry) => Boolean(entry));
10830
- if (oldCurateEntries.length > 0) {
10831
- const oldSchedules = oldCurateEntries.map((entry) => typeof entry.schedule === "string" ? entry.schedule : baseCron);
10832
- tasks.curate = withTimeout({
10833
- ...tasks.curate ?? {},
10834
- schedule: mostFrequentSchedule(oldSchedules)
10835
- });
10836
- }
10837
- for (const task of CANONICAL) {
10838
- if (!tasks[task]) {
10839
- const schedule = task === "verify" || task === "curate" || task === "verify-broad" ? "" : task === "classify-memories" ? classifySchedule : task === "retrospective" ? retrospectiveSchedule : task === "maintain-docs" ? "" : baseCron;
10840
- tasks[task] = withTimeout({ schedule });
10841
- }
10842
- }
10843
- } else {
10844
- const legacyArray = Array.isArray(dreamer.tasks) ? dreamer.tasks.filter((t) => typeof t === "string") : null;
10845
- const verifySelected = legacyArray ? legacyArray.includes(OLD_VERIFY_TASK) : true;
10846
- const curateSelected = legacyArray ? legacyArray.some((task) => OLD_CURATE_TASKS.includes(task)) : true;
10847
- tasks.verify = withTimeout({
10848
- schedule: verifySelected ? baseCron : ""
10849
- });
10850
- tasks["verify-broad"] = withTimeout({
10851
- schedule: verifySelected ? DEFAULT_VERIFY_BROAD_CRON : ""
10852
- });
10853
- tasks.curate = withTimeout({
10854
- schedule: curateSelected ? baseCron : ""
10855
- });
10856
- tasks["classify-memories"] = withTimeout({
10857
- schedule: classifySchedule
10858
- });
10859
- tasks.retrospective = withTimeout({
10860
- schedule: retrospectiveSchedule
10861
- });
10862
- tasks["maintain-docs"] = withTimeout({
10863
- schedule: legacyArray?.includes("maintain-docs") ? baseCron : ""
10864
- });
10793
+ if (!selection) {
10794
+ return {
10795
+ userBase: withoutProfileFields(args.userRaw),
10796
+ projectBase: withoutProfileFields(args.projectRaw),
10797
+ overlay: {},
10798
+ warnings
10799
+ };
10865
10800
  }
10866
- tasks["map-memories"] ??= withTimeout({ schedule: baseCron });
10867
- tasks["evaluate-smart-notes"] ??= withTimeout({ schedule: baseCron });
10868
- const um = asObject(dreamer.user_memories);
10869
- const umEnabled = um ? um.enabled !== false : true;
10870
- if (um || !tasks["review-user-memories"]) {
10871
- tasks["review-user-memories"] = withTimeout({
10872
- ...tasks["review-user-memories"] ?? {},
10873
- schedule: umEnabled ? baseCron : "",
10874
- ...um && typeof um.promotion_threshold === "number" ? { promotion_threshold: um.promotion_threshold } : {}
10875
- });
10801
+ if (!Object.hasOwn(profiles, selection.name)) {
10802
+ warnings.push(`Unknown profile "${selection.name}" selected by ${selection.source} config; using base config without a profile.`);
10803
+ return {
10804
+ userBase: withoutProfileFields(args.userRaw),
10805
+ projectBase: withoutProfileFields(args.projectRaw),
10806
+ overlay: {},
10807
+ warnings
10808
+ };
10876
10809
  }
10877
- const {
10878
- schedule: _schedule,
10879
- tasks: _tasks,
10880
- task_timeout_minutes: _tto,
10881
- max_runtime_minutes: _max,
10882
- user_memories: _um,
10883
- pin_key_files: _pkf,
10884
- ...rest
10885
- } = dreamer;
10886
- warnings.push('Migrated legacy dreamer scheduling (schedule window / tasks array / user_memories / pin_key_files) → per-task "dreamer.tasks" in-memory (run `doctor` to persist).');
10887
- return { ...rawConfig, dreamer: { ...rest, tasks } };
10888
- }
10889
-
10890
- // ../plugin/src/config/migrate-experimental.ts
10891
- function migrateLegacyExperimental(rawConfig, warnings) {
10892
- const experimental = rawConfig.experimental;
10893
- if (typeof experimental !== "object" || experimental === null) {
10894
- return rawConfig;
10895
- }
10896
- const exp = experimental;
10897
- const hasUM = "user_memories" in exp;
10898
- const hasPKF = "pin_key_files" in exp;
10899
- const hasMural = "mural" in exp;
10900
- const TOP_LEVEL_GRADUATED = ["temporal_awareness", "caveman_text_compression"];
10901
- const MEMORY_GRADUATED = ["auto_search", "git_commit_indexing"];
10902
- const hasGraduated = TOP_LEVEL_GRADUATED.some((k) => (k in exp)) || MEMORY_GRADUATED.some((k) => (k in exp)) || hasMural;
10903
- if (!hasUM && !hasPKF && !hasGraduated) {
10904
- return rawConfig;
10905
- }
10906
- const patched = { ...rawConfig };
10907
- const dreamer = typeof patched.dreamer === "object" && patched.dreamer !== null ? { ...patched.dreamer } : {};
10908
- const memory = typeof patched.memory === "object" && patched.memory !== null ? { ...patched.memory } : {};
10909
- const newExperimental = { ...exp };
10910
- const coerceToObject = (value) => {
10911
- if (typeof value === "boolean") {
10912
- return { enabled: value };
10913
- }
10914
- if (typeof value === "object" && value !== null) {
10915
- return { ...value };
10916
- }
10917
- return;
10918
- };
10919
- const relocate = (key, dest, destLabel) => {
10920
- if (!(key in exp))
10921
- return;
10922
- const oldValue = exp[key];
10923
- const existing = dest[key];
10924
- if (existing === undefined) {
10925
- dest[key] = oldValue;
10926
- warnings.push(`Migrated "experimental.${key}" → "${destLabel}${key}" in-memory (run \`doctor\` to persist).`);
10927
- } else if (typeof oldValue === "object" && oldValue !== null && typeof existing === "object" && existing !== null) {
10928
- dest[key] = {
10929
- ...oldValue,
10930
- ...existing
10931
- };
10932
- }
10933
- delete newExperimental[key];
10934
- };
10935
- for (const key of TOP_LEVEL_GRADUATED)
10936
- relocate(key, patched, "");
10937
- for (const key of MEMORY_GRADUATED)
10938
- relocate(key, memory, "memory.");
10939
- if (hasMural) {
10940
- const oldMural = coerceToObject(exp.mural);
10941
- const existingMural = patched.mural;
10942
- if (existingMural === undefined) {
10943
- patched.mural = oldMural ?? exp.mural;
10944
- warnings.push('Deprecated "experimental.mural"; use top-level "mural" instead (migrated in memory; run `doctor` to persist).');
10945
- } else if (oldMural !== undefined && typeof existingMural === "object" && existingMural !== null && !Array.isArray(existingMural)) {
10946
- patched.mural = {
10947
- ...oldMural,
10948
- ...existingMural
10949
- };
10950
- }
10951
- delete newExperimental.mural;
10952
- }
10953
- if (hasUM) {
10954
- const oldUM = coerceToObject(exp.user_memories);
10955
- if (oldUM !== undefined) {
10956
- if (dreamer.user_memories === undefined) {
10957
- dreamer.user_memories = oldUM;
10958
- warnings.push('Migrated "experimental.user_memories" → "dreamer.user_memories" in-memory (run `doctor` to persist).');
10959
- } else if (typeof dreamer.user_memories === "object" && dreamer.user_memories !== null) {
10960
- dreamer.user_memories = {
10961
- ...oldUM,
10962
- ...dreamer.user_memories
10963
- };
10964
- }
10965
- }
10966
- delete newExperimental.user_memories;
10967
- }
10968
- if (hasPKF) {
10969
- const oldPKF = coerceToObject(exp.pin_key_files);
10970
- if (oldPKF !== undefined) {
10971
- if (dreamer.pin_key_files === undefined) {
10972
- dreamer.pin_key_files = oldPKF;
10973
- warnings.push('Migrated "experimental.pin_key_files" → "dreamer.pin_key_files" in-memory (run `doctor` to persist).');
10974
- } else if (typeof dreamer.pin_key_files === "object" && dreamer.pin_key_files !== null) {
10975
- dreamer.pin_key_files = {
10976
- ...oldPKF,
10977
- ...dreamer.pin_key_files
10978
- };
10979
- } else if (typeof dreamer.pin_key_files === "boolean") {
10980
- dreamer.pin_key_files = { ...oldPKF, enabled: dreamer.pin_key_files };
10981
- }
10982
- }
10983
- delete newExperimental.pin_key_files;
10984
- }
10985
- patched.experimental = newExperimental;
10986
- patched.dreamer = dreamer;
10987
- if (Object.keys(memory).length > 0) {
10988
- patched.memory = memory;
10989
- }
10990
- return patched;
10991
- }
10992
-
10993
- // ../plugin/src/config/profiles.ts
10994
- function withoutProfileFields(raw) {
10995
- const copy = { ...raw };
10996
- delete copy.profile;
10997
- delete copy.profiles;
10998
- return copy;
10999
- }
11000
- function readProfileSelection(raw) {
11001
- if (!Object.hasOwn(raw, "profile"))
11002
- return { declared: false };
11003
- const value = raw.profile;
11004
- if (typeof value !== "string")
11005
- return { declared: true };
11006
- const name = value.trim();
11007
- return name.length > 0 ? { declared: true, name } : { declared: true };
11008
- }
11009
- function resolveConfigProfile(args) {
11010
- const warnings = [];
11011
- const userSelection = readProfileSelection(args.userRaw);
11012
- const projectSelection = readProfileSelection(args.projectRaw);
11013
- const selection = projectSelection.name ? { name: projectSelection.name, source: "project" } : userSelection.name ? { name: userSelection.name, source: "user" } : undefined;
11014
- if (projectSelection.declared && !projectSelection.name) {
11015
- warnings.push("Ignoring invalid profile selection from project config; expected a non-empty string.");
11016
- }
11017
- if (!projectSelection.declared && userSelection.declared && !userSelection.name) {
11018
- warnings.push("Ignoring invalid profile selection from user config; expected a non-empty string.");
11019
- }
11020
- let profiles = {};
11021
- if (Object.hasOwn(args.userRaw, "profiles")) {
11022
- const parsed = ConfigProfilesSchema.safeParse(args.userRaw.profiles);
11023
- if (parsed.success) {
11024
- profiles = parsed.data;
11025
- } else {
11026
- warnings.push("Ignoring profiles from user config: invalid profile configuration; profiles may contain only historian/dreamer harness model blocks.");
11027
- }
11028
- }
11029
- if (!selection) {
11030
- return {
11031
- userBase: withoutProfileFields(args.userRaw),
11032
- projectBase: withoutProfileFields(args.projectRaw),
11033
- overlay: {},
11034
- warnings
11035
- };
11036
- }
11037
- if (!Object.hasOwn(profiles, selection.name)) {
11038
- warnings.push(`Unknown profile "${selection.name}" selected by ${selection.source} config; using base config without a profile.`);
11039
- return {
11040
- userBase: withoutProfileFields(args.userRaw),
11041
- projectBase: withoutProfileFields(args.projectRaw),
11042
- overlay: {},
11043
- warnings
11044
- };
11045
- }
11046
- const overlay = profiles[selection.name];
11047
- return {
11048
- userBase: withoutProfileFields(args.userRaw),
11049
- projectBase: withoutProfileFields(args.projectRaw),
11050
- overlay,
11051
- activeProfile: selection.name,
11052
- warnings
11053
- };
10810
+ const overlay = profiles[selection.name];
10811
+ return {
10812
+ userBase: withoutProfileFields(args.userRaw),
10813
+ projectBase: withoutProfileFields(args.projectRaw),
10814
+ overlay,
10815
+ activeProfile: selection.name,
10816
+ warnings
10817
+ };
11054
10818
  }
11055
10819
 
11056
10820
  // ../plugin/src/config/raw-loader.ts
11057
10821
  import {
11058
- closeSync as closeSync2,
10822
+ closeSync,
11059
10823
  existsSync as existsSync4,
11060
10824
  linkSync,
11061
- openSync as openSync2,
10825
+ openSync,
11062
10826
  readFileSync as readFileSync6,
11063
10827
  realpathSync,
11064
- renameSync as renameSync2,
10828
+ renameSync,
11065
10829
  statSync as statSync4,
11066
10830
  unlinkSync as unlinkSync2,
11067
- writeFileSync as writeFileSync2
10831
+ writeFileSync
11068
10832
  } from "node:fs";
11069
10833
  import { basename as basename2, dirname as dirname3, join as join3 } from "node:path";
11070
10834
  var MODEL_FIELDS = ["model", "fallback_models"];
@@ -11269,7 +11033,7 @@ function writeExclusiveBackup(backupPath, bytes, mode) {
11269
11033
  if (existingBytes.equals(bytes))
11270
11034
  return;
11271
11035
  if (bytes.subarray(0, existingBytes.length).equals(existingBytes)) {
11272
- renameSync2(temporaryPath, backupPath);
11036
+ renameSync(temporaryPath, backupPath);
11273
11037
  return;
11274
11038
  }
11275
11039
  } finally {
@@ -11286,14 +11050,14 @@ function writeTemporaryCandidate(configPath, bytes, mode) {
11286
11050
  const path = join3(directory, `.${stem}.per-harness-${process.pid}-${temporaryFileSequence}.tmp`);
11287
11051
  let descriptor;
11288
11052
  try {
11289
- descriptor = openSync2(path, "wx", mode);
11290
- writeFileSync2(descriptor, bytes);
11291
- closeSync2(descriptor);
11053
+ descriptor = openSync(path, "wx", mode);
11054
+ writeFileSync(descriptor, bytes);
11055
+ closeSync(descriptor);
11292
11056
  return path;
11293
11057
  } catch (error) {
11294
11058
  if (descriptor !== undefined) {
11295
11059
  try {
11296
- closeSync2(descriptor);
11060
+ closeSync(descriptor);
11297
11061
  } catch {}
11298
11062
  }
11299
11063
  try {
@@ -11354,7 +11118,7 @@ function loadRawConfigFile(options) {
11354
11118
  let temporaryPath;
11355
11119
  try {
11356
11120
  const writePath = realpathSync(options.configPath);
11357
- const mode = statSync4(writePath).mode & 511;
11121
+ const mode = options.tier === "user" ? 384 : statSync4(writePath).mode & 511;
11358
11122
  writeExclusiveBackup(backupPath, observedBytes, mode);
11359
11123
  temporaryPath = writeTemporaryCandidate(writePath, migration.bytes, mode);
11360
11124
  options.afterTemporaryWrite?.();
@@ -11374,7 +11138,7 @@ function loadRawConfigFile(options) {
11374
11138
  observedBytes = currentBytes;
11375
11139
  continue;
11376
11140
  }
11377
- renameSync2(temporaryPath, writePath);
11141
+ renameSync(temporaryPath, writePath);
11378
11142
  return {
11379
11143
  configPath: options.configPath,
11380
11144
  bytes: migration.bytes,
@@ -11536,7 +11300,7 @@ function substituteConfigVariables(input) {
11536
11300
  }
11537
11301
 
11538
11302
  // ../plugin/src/shared/models-dev-cache.ts
11539
- import { mkdirSync as mkdirSync2, readFileSync as readFileSync8, renameSync as renameSync3, writeFileSync as writeFileSync3 } from "node:fs";
11303
+ import { readFileSync as readFileSync8 } from "node:fs";
11540
11304
  import { join as join4 } from "node:path";
11541
11305
  var MIN_SANE_LIMIT = 20000;
11542
11306
  var MAX_SANE_LIMIT = 3000000;
@@ -12127,6 +11891,9 @@ function loadPiConfigDetailed(opts = {}, applyRuntimeGlobals = true) {
12127
11891
  const recoveredTopLevelKeys = [];
12128
11892
  const cacheTtlConfigured = Object.hasOwn(rawConfig, "cache_ttl");
12129
11893
  const parsed = parsePiConfig(rawConfig, recoveredTopLevelKeys);
11894
+ Object.defineProperty(parsed.config, "cacheTtlConfigured", {
11895
+ value: cacheTtlConfigured
11896
+ });
12130
11897
  for (const key of projectRestoredTopLevelKeys) {
12131
11898
  if (!recoveredTopLevelKeys.includes(key))
12132
11899
  recoveredTopLevelKeys.push(key);
@@ -16438,16 +16205,13 @@ function renderItemByTag(db, sessionId, number, textIndexDomain = "part") {
16438
16205
  return `Tag ${number}'s original tool owner is no longer in stored history.`;
16439
16206
  const parts = message?.parts.filter((part) => isRecord4(part) && asToolPart(part)?.callId === tag.messageId) ?? [];
16440
16207
  if (!parts.some((part) => isRecord4(part) && asToolPart(part)?.output !== null)) {
16441
- const messages = readRawSessionMessages2(sessionId);
16442
- const ownerIndex = messages.findIndex((candidate) => candidate.id === owner);
16443
- for (const candidate of messages.slice(Math.max(0, ownerIndex + 1))) {
16208
+ visitRawSessionMessages2(sessionId, message.ordinal + 1, Number.MAX_SAFE_INTEGER, (candidate) => {
16444
16209
  const matching = candidate.parts.filter((part) => isRecord4(part) && asToolPart(part)?.callId === tag.messageId);
16445
16210
  if (matching.some((part) => isRecord4(part) && part.type === "tool_use"))
16446
- break;
16211
+ return false;
16447
16212
  parts.push(...matching);
16448
- if (matching.length > 0)
16449
- break;
16450
- }
16213
+ return matching.length === 0;
16214
+ });
16451
16215
  }
16452
16216
  const rendered = parts.map(renderPartFull).filter((part) => part !== null);
16453
16217
  return rendered.length ? rendered.join(`
@@ -16782,77 +16546,418 @@ var encoder = new TextEncoder;
16782
16546
  function Boolean2(options) {
16783
16547
  return Create({ "~kind": "Boolean" }, { type: "boolean" }, options);
16784
16548
  }
16785
- // ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/types/integer.mjs
16786
- var IntegerPattern = "-?(?:0|[1-9][0-9]*)";
16787
- function Integer(options) {
16788
- return Create({ "~kind": "Integer" }, { type: "integer" }, options);
16549
+ // ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/types/integer.mjs
16550
+ var IntegerPattern = "-?(?:0|[1-9][0-9]*)";
16551
+ function Integer(options) {
16552
+ return Create({ "~kind": "Integer" }, { type: "integer" }, options);
16553
+ }
16554
+ // ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/types/literal.mjs
16555
+ class InvalidLiteralValue extends Error {
16556
+ constructor(value) {
16557
+ super(`Invalid Literal value`);
16558
+ Object.defineProperty(this, "cause", {
16559
+ value: { value },
16560
+ writable: false,
16561
+ configurable: false,
16562
+ enumerable: false
16563
+ });
16564
+ }
16565
+ }
16566
+ function LiteralTypeName(value) {
16567
+ return IsBigInt(value) ? "bigint" : IsBoolean(value) ? "boolean" : IsNumber(value) ? "number" : IsString(value) ? "string" : (() => {
16568
+ throw new InvalidLiteralValue(value);
16569
+ })();
16570
+ }
16571
+ function Literal(value, options) {
16572
+ return Create({ "~kind": "Literal" }, { type: LiteralTypeName(value), const: value }, options);
16573
+ }
16574
+ // ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/types/number.mjs
16575
+ var NumberPattern = "-?(?:0|[1-9][0-9]*)(?:\\.[0-9]+)?";
16576
+ function Number2(options) {
16577
+ return Create({ "~kind": "Number" }, { type: "number" }, options);
16578
+ }
16579
+ // ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/types/string.mjs
16580
+ var StringPattern = ".*";
16581
+ function String2(options) {
16582
+ return Create({ "~kind": "String" }, { type: "string" }, options);
16583
+ }
16584
+
16585
+ // ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/types/union.mjs
16586
+ function Union(anyOf, options = {}) {
16587
+ return Create({ "~kind": "Union" }, { anyOf }, options);
16588
+ }
16589
+
16590
+ // ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/types/record.mjs
16591
+ var IntegerKey = `^${IntegerPattern}$`;
16592
+ var NumberKey = `^${NumberPattern}$`;
16593
+ var StringKey = `^${StringPattern}$`;
16594
+ // ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/script/token/internal/char.mjs
16595
+ function Range(start, end) {
16596
+ return Array.from({ length: end - start + 1 }, (_, i) => String.fromCharCode(start + i));
16597
+ }
16598
+ var Alpha = [
16599
+ ...Range(97, 122),
16600
+ ...Range(65, 90)
16601
+ ];
16602
+ var Zero = "0";
16603
+ var NonZero = Range(49, 57);
16604
+ var Digit = [Zero, ...NonZero];
16605
+ var UnderScore = "_";
16606
+ var DollarSign = "$";
16607
+
16608
+ // ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/script/token/unsigned_integer.mjs
16609
+ var AllowedDigits = [...Digit, UnderScore];
16610
+ // ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/script/token/ident.mjs
16611
+ var Initial = [...Alpha, UnderScore, DollarSign];
16612
+ var Remaining = [...Initial, ...Digit];
16613
+ // ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/script/token/unsigned_number.mjs
16614
+ var AllowedDigits2 = [...Digit, UnderScore];
16615
+ // ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/engine/helpers/keys.mjs
16616
+ var integerKeyPattern = new RegExp("^(?:0|[1-9][0-9]*)$");
16617
+
16618
+ // ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/engine/indexed/from_object.mjs
16619
+ var NumericKeyPattern = new RegExp(IntegerKey);
16620
+ // src/read-session-pi.ts
16621
+ var SYNTH_USER_ID_PREFIX = "synth-user-";
16622
+ function resolvePiStableId(msg, index, entryIds, entryIdByRef) {
16623
+ if (!msg || typeof msg !== "object")
16624
+ return;
16625
+ const byRef = entryIdByRef?.get(msg);
16626
+ if (typeof byRef === "string" && byRef.length > 0)
16627
+ return byRef;
16628
+ const positional = entryIds?.[index];
16629
+ if (typeof positional === "string" && positional.length > 0)
16630
+ return positional;
16631
+ const m = msg;
16632
+ const role = m.role ?? "unknown";
16633
+ return typeof m.timestamp === "number" ? `pi-msg-${index}-${m.timestamp}-${role}` : `pi-msg-${index}-${role}`;
16634
+ }
16635
+ function readPiSessionSnapshot(ctx) {
16636
+ const sm = ctx.sessionManager;
16637
+ if (sm === undefined)
16638
+ return { branchEntries: [], rawMessages: [] };
16639
+ const getBranch = sm.getBranch;
16640
+ if (typeof getBranch !== "function")
16641
+ return { branchEntries: [], rawMessages: [] };
16642
+ let entries;
16643
+ try {
16644
+ entries = getBranch.call(sm);
16645
+ } catch {
16646
+ return { branchEntries: [], rawMessages: [] };
16647
+ }
16648
+ if (!Array.isArray(entries))
16649
+ return { branchEntries: [], rawMessages: [] };
16650
+ return {
16651
+ branchEntries: entries,
16652
+ rawMessages: convertEntriesToRawMessages(entries)
16653
+ };
16654
+ }
16655
+ function readPiSessionMessages(ctx) {
16656
+ return readPiSessionSnapshot(ctx).rawMessages;
16657
+ }
16658
+ function readPiSessionMessagePage(ctx, afterOrdinal, limit, finalWatermark) {
16659
+ const sessionManager = ctx.sessionManager;
16660
+ const getBranch = sessionManager?.getBranch;
16661
+ if (typeof getBranch !== "function")
16662
+ return [];
16663
+ try {
16664
+ const entries = getBranch.call(sessionManager);
16665
+ return Array.isArray(entries) ? convertEntriesToRawMessagePage(entries, afterOrdinal, limit, finalWatermark) : [];
16666
+ } catch {
16667
+ return [];
16668
+ }
16669
+ }
16670
+ function findLastModelKeyFromBranch(entries) {
16671
+ if (!Array.isArray(entries))
16672
+ return;
16673
+ for (let i = entries.length - 1;i >= 0; i--) {
16674
+ const e = entries[i];
16675
+ if (!e || typeof e !== "object")
16676
+ continue;
16677
+ const v = e;
16678
+ if (v.type !== "model_change")
16679
+ continue;
16680
+ if (typeof v.provider === "string" && v.provider.length > 0 && typeof v.modelId === "string" && v.modelId.length > 0) {
16681
+ return `${v.provider}/${v.modelId}`;
16682
+ }
16683
+ }
16684
+ return;
16685
+ }
16686
+ function findRestartModelSeedFromBranch(entries) {
16687
+ if (!Array.isArray(entries))
16688
+ return;
16689
+ let switchedAfterLastReply = false;
16690
+ for (let i = entries.length - 1;i >= 0; i--) {
16691
+ const e = entries[i];
16692
+ if (e?.type === "model_change") {
16693
+ if (typeof e.provider === "string" && typeof e.modelId === "string")
16694
+ switchedAfterLastReply = true;
16695
+ continue;
16696
+ }
16697
+ if (e?.type !== "message")
16698
+ continue;
16699
+ const m = e.message;
16700
+ if (m?.role !== "assistant")
16701
+ continue;
16702
+ if (typeof m.provider !== "string" || m.provider.length === 0 || typeof m.model !== "string" || m.model.length === 0) {
16703
+ continue;
16704
+ }
16705
+ return switchedAfterLastReply ? `${m.provider}/${m.model}` : findLastModelKeyFromBranch(entries);
16706
+ }
16707
+ return findLastModelKeyFromBranch(entries);
16708
+ }
16709
+ function rawEntryVersion(entry) {
16710
+ const record = entry;
16711
+ const updated = record.updatedAt ?? record.updated_at ?? record.timestamp;
16712
+ return typeof updated === "string" || typeof updated === "number" ? updated : entry.id;
16713
+ }
16714
+ function parsePiEntryTimestamp(entry) {
16715
+ const record = entry;
16716
+ const raw = record.timestamp;
16717
+ if (typeof raw === "number" && Number.isSafeInteger(raw) && raw >= 0)
16718
+ return raw;
16719
+ if (typeof raw !== "string" || raw.trim().length === 0)
16720
+ return null;
16721
+ const parsed = Date.parse(raw);
16722
+ return Number.isSafeInteger(parsed) && parsed >= 0 ? parsed : null;
16723
+ }
16724
+ function attachPiPartVersion(parts, version) {
16725
+ return parts.map((part) => {
16726
+ if (part === null || typeof part !== "object" || Array.isArray(part))
16727
+ return part;
16728
+ try {
16729
+ Object.defineProperty(part, "__magicContextPartUpdatedAt", {
16730
+ value: version,
16731
+ enumerable: false,
16732
+ configurable: true
16733
+ });
16734
+ } catch {}
16735
+ return part;
16736
+ });
16737
+ }
16738
+ function* iterateEntriesToRawMessageRange(entries, afterOrdinal, limit, finalWatermark) {
16739
+ let emitted = 0;
16740
+ const normalizedAfter = Math.max(0, Math.floor(afterOrdinal));
16741
+ const normalizedLimit = Math.max(1, Math.floor(limit));
16742
+ const normalizedWatermark = Math.max(normalizedAfter, Math.floor(finalWatermark));
16743
+ let nextOrdinal = 1;
16744
+ let pendingToolResults = [];
16745
+ const buildToolParts = (results) => results.flatMap(({ msg, version }) => attachPiPartVersion(synthesizeToolResultParts(msg), version));
16746
+ let hasPendingToolParts = false;
16747
+ let pendingFirstRealId = "";
16748
+ let pendingFirstRealVersion = "";
16749
+ let pendingFirstCreatedAt = null;
16750
+ const appendMessage = function* (id, role, version, createdAt, parts) {
16751
+ const ordinal = nextOrdinal++;
16752
+ if (ordinal > normalizedAfter && ordinal <= normalizedWatermark) {
16753
+ emitted++;
16754
+ yield {
16755
+ ordinal,
16756
+ id,
16757
+ role,
16758
+ parts: parts(),
16759
+ version,
16760
+ ...createdAt === null ? {} : { createdAt }
16761
+ };
16762
+ }
16763
+ return emitted >= normalizedLimit || nextOrdinal > normalizedWatermark;
16764
+ };
16765
+ for (const entry of entries) {
16766
+ if (!isMessageEntry(entry))
16767
+ continue;
16768
+ const msg = entry.message;
16769
+ const role = msg.role;
16770
+ if (role === "toolResult") {
16771
+ const callId = msg.toolCallId;
16772
+ if (typeof callId !== "string" || callId.length === 0)
16773
+ continue;
16774
+ const version = rawEntryVersion(entry);
16775
+ hasPendingToolParts = true;
16776
+ pendingToolResults.push({ msg, version });
16777
+ if (pendingFirstRealId === "") {
16778
+ pendingFirstRealId = entry.id;
16779
+ pendingFirstRealVersion = version;
16780
+ pendingFirstCreatedAt = parsePiEntryTimestamp(entry);
16781
+ }
16782
+ continue;
16783
+ }
16784
+ if (role === "user") {
16785
+ const version = rawEntryVersion(entry);
16786
+ const bufferedToolResults = pendingToolResults;
16787
+ const done = yield* appendMessage(entry.id, "user", version, parsePiEntryTimestamp(entry), () => [
16788
+ ...buildToolParts(bufferedToolResults),
16789
+ ...attachPiPartVersion(synthesizeUserParts(msg), version)
16790
+ ]);
16791
+ pendingToolResults = [];
16792
+ hasPendingToolParts = false;
16793
+ pendingFirstRealId = "";
16794
+ pendingFirstRealVersion = "";
16795
+ pendingFirstCreatedAt = null;
16796
+ if (done)
16797
+ break;
16798
+ continue;
16799
+ }
16800
+ if (role === "assistant") {
16801
+ if (hasPendingToolParts) {
16802
+ const bufferedToolResults = pendingToolResults;
16803
+ const pendingId = pendingFirstRealId;
16804
+ const pendingVersion = pendingFirstRealVersion;
16805
+ const done = yield* appendMessage(`${SYNTH_USER_ID_PREFIX}${pendingId}`, "user", pendingVersion, pendingFirstCreatedAt, () => buildToolParts(bufferedToolResults));
16806
+ pendingToolResults = [];
16807
+ hasPendingToolParts = false;
16808
+ pendingFirstRealId = "";
16809
+ pendingFirstRealVersion = "";
16810
+ pendingFirstCreatedAt = null;
16811
+ if (done)
16812
+ break;
16813
+ }
16814
+ const version = rawEntryVersion(entry);
16815
+ if (yield* appendMessage(entry.id, "assistant", version, parsePiEntryTimestamp(entry), () => attachPiPartVersion(synthesizeAssistantParts(msg), version))) {
16816
+ break;
16817
+ }
16818
+ continue;
16819
+ }
16820
+ if (yield* appendMessage(entry.id, typeof role === "string" ? role : "unknown", rawEntryVersion(entry), parsePiEntryTimestamp(entry), () => [])) {
16821
+ break;
16822
+ }
16823
+ }
16824
+ if (hasPendingToolParts && emitted < normalizedLimit && nextOrdinal <= normalizedWatermark) {
16825
+ yield* appendMessage(`${SYNTH_USER_ID_PREFIX}${pendingFirstRealId}`, "user", pendingFirstRealVersion, pendingFirstCreatedAt, () => buildToolParts(pendingToolResults));
16826
+ }
16827
+ }
16828
+ function convertEntriesToRawMessages(entries) {
16829
+ return [
16830
+ ...iterateEntriesToRawMessageRange(entries, 0, Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER)
16831
+ ];
16789
16832
  }
16790
- // ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/types/literal.mjs
16791
- class InvalidLiteralValue extends Error {
16792
- constructor(value) {
16793
- super(`Invalid Literal value`);
16794
- Object.defineProperty(this, "cause", {
16795
- value: { value },
16796
- writable: false,
16797
- configurable: false,
16798
- enumerable: false
16799
- });
16833
+ function convertPiAssistantEntryById(entries, entryId) {
16834
+ for (let index = 0;index < entries.length; index++) {
16835
+ const entry = entries[index];
16836
+ if (!isMessageEntry(entry) || entry.id !== entryId)
16837
+ continue;
16838
+ if (entry.message.role !== "assistant" || entryId.startsWith(SYNTH_USER_ID_PREFIX)) {
16839
+ return convertEntriesToRawMessages(entries).find((message) => message.id === entryId) ?? null;
16840
+ }
16841
+ const raw = convertEntriesToRawMessages([entry])[0];
16842
+ return raw ? { ...raw, ordinal: countPiRawMessages(entries.slice(0, index + 1)) } : null;
16800
16843
  }
16844
+ return null;
16801
16845
  }
16802
- function LiteralTypeName(value) {
16803
- return IsBigInt(value) ? "bigint" : IsBoolean(value) ? "boolean" : IsNumber(value) ? "number" : IsString(value) ? "string" : (() => {
16804
- throw new InvalidLiteralValue(value);
16805
- })();
16846
+ function convertEntriesToRawMessagePage(entries, afterOrdinal, limit, finalWatermark) {
16847
+ return [
16848
+ ...iterateEntriesToRawMessageRange(entries, afterOrdinal, limit, finalWatermark)
16849
+ ];
16806
16850
  }
16807
- function Literal(value, options) {
16808
- return Create({ "~kind": "Literal" }, { type: LiteralTypeName(value), const: value }, options);
16851
+ function isMessageEntry(value) {
16852
+ if (value === null || typeof value !== "object")
16853
+ return false;
16854
+ const v = value;
16855
+ if (v.type !== "message")
16856
+ return false;
16857
+ if (typeof v.id !== "string")
16858
+ return false;
16859
+ if (v.message === null || typeof v.message !== "object")
16860
+ return false;
16861
+ return true;
16809
16862
  }
16810
- // ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/types/number.mjs
16811
- var NumberPattern = "-?(?:0|[1-9][0-9]*)(?:\\.[0-9]+)?";
16812
- function Number2(options) {
16813
- return Create({ "~kind": "Number" }, { type: "number" }, options);
16863
+ function synthesizeUserParts(msg) {
16864
+ const m = msg;
16865
+ if (typeof m.content === "string") {
16866
+ if (m.content.trim().length === 0)
16867
+ return [];
16868
+ return [{ type: "text", text: m.content }];
16869
+ }
16870
+ if (!Array.isArray(m.content))
16871
+ return [];
16872
+ const parts = [];
16873
+ for (const c of m.content) {
16874
+ if (c === null || typeof c !== "object")
16875
+ continue;
16876
+ const cc = c;
16877
+ if (cc.type === "text" && typeof cc.text === "string") {
16878
+ parts.push({ type: "text", text: cc.text });
16879
+ }
16880
+ }
16881
+ return parts;
16814
16882
  }
16815
- // ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/types/string.mjs
16816
- var StringPattern = ".*";
16817
- function String2(options) {
16818
- return Create({ "~kind": "String" }, { type: "string" }, options);
16883
+ function synthesizeAssistantParts(msg) {
16884
+ const m = msg;
16885
+ if (!Array.isArray(m.content))
16886
+ return [];
16887
+ const parts = [];
16888
+ for (const c of m.content) {
16889
+ if (c === null || typeof c !== "object")
16890
+ continue;
16891
+ const cc = c;
16892
+ if (cc.type === "text" && typeof cc.text === "string") {
16893
+ parts.push({ type: "text", text: cc.text });
16894
+ } else if (cc.type === "toolCall" && typeof cc.id === "string") {
16895
+ parts.push({
16896
+ type: "tool",
16897
+ tool: typeof cc.name === "string" ? cc.name : "unknown",
16898
+ callID: cc.id,
16899
+ state: {
16900
+ input: cc.arguments ?? {}
16901
+ }
16902
+ });
16903
+ }
16904
+ }
16905
+ return parts;
16819
16906
  }
16820
-
16821
- // ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/types/union.mjs
16822
- function Union(anyOf, options = {}) {
16823
- return Create({ "~kind": "Union" }, { anyOf }, options);
16907
+ function synthesizeToolResultParts(msg) {
16908
+ const m = msg;
16909
+ const callID = typeof m.toolCallId === "string" ? m.toolCallId : "";
16910
+ const tool = typeof m.toolName === "string" ? m.toolName : "unknown";
16911
+ if (!callID)
16912
+ return [];
16913
+ let output = "";
16914
+ if (Array.isArray(m.content)) {
16915
+ const fragments = [];
16916
+ for (const c of m.content) {
16917
+ if (c === null || typeof c !== "object")
16918
+ continue;
16919
+ const cc = c;
16920
+ if (cc.type === "text" && typeof cc.text === "string") {
16921
+ fragments.push(cc.text);
16922
+ }
16923
+ }
16924
+ output = fragments.join(`
16925
+ `);
16926
+ }
16927
+ return [
16928
+ {
16929
+ type: "tool",
16930
+ tool,
16931
+ callID,
16932
+ state: {
16933
+ output
16934
+ }
16935
+ }
16936
+ ];
16824
16937
  }
16825
-
16826
- // ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/types/record.mjs
16827
- var IntegerKey = `^${IntegerPattern}$`;
16828
- var NumberKey = `^${NumberPattern}$`;
16829
- var StringKey = `^${StringPattern}$`;
16830
- // ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/script/token/internal/char.mjs
16831
- function Range(start, end) {
16832
- return Array.from({ length: end - start + 1 }, (_, i) => String.fromCharCode(start + i));
16938
+ function countPiRawMessages(entries) {
16939
+ let count = 0;
16940
+ let pendingTools = false;
16941
+ for (const entry of entries) {
16942
+ if (!isMessageEntry(entry))
16943
+ continue;
16944
+ const message = entry.message;
16945
+ if (message.role === "toolResult") {
16946
+ if (typeof message.toolCallId === "string" && message.toolCallId.length > 0)
16947
+ pendingTools = true;
16948
+ continue;
16949
+ }
16950
+ if (message.role === "user")
16951
+ pendingTools = false;
16952
+ else if (message.role === "assistant" && pendingTools) {
16953
+ count++;
16954
+ pendingTools = false;
16955
+ }
16956
+ count++;
16957
+ }
16958
+ return count + Number(pendingTools);
16833
16959
  }
16834
- var Alpha = [
16835
- ...Range(97, 122),
16836
- ...Range(65, 90)
16837
- ];
16838
- var Zero = "0";
16839
- var NonZero = Range(49, 57);
16840
- var Digit = [Zero, ...NonZero];
16841
- var UnderScore = "_";
16842
- var DollarSign = "$";
16843
-
16844
- // ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/script/token/unsigned_integer.mjs
16845
- var AllowedDigits = [...Digit, UnderScore];
16846
- // ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/script/token/ident.mjs
16847
- var Initial = [...Alpha, UnderScore, DollarSign];
16848
- var Remaining = [...Initial, ...Digit];
16849
- // ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/script/token/unsigned_number.mjs
16850
- var AllowedDigits2 = [...Digit, UnderScore];
16851
- // ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/engine/helpers/keys.mjs
16852
- var integerKeyPattern = new RegExp("^(?:0|[1-9][0-9]*)$");
16853
16960
 
16854
- // ../../node_modules/.bun/typebox@1.3.27/node_modules/typebox/build/type/engine/indexed/from_object.mjs
16855
- var NumericKeyPattern = new RegExp(IntegerKey);
16856
16961
  // src/tools/ctx-expand.ts
16857
16962
  var ParamsSchema = _Object_({
16858
16963
  tag: Optional(Union([Number2(), String2()], {
@@ -17282,9 +17387,8 @@ function getMuralCueState(db, memoryIds) {
17282
17387
  const ids = Array.from(new Set(memoryIds.filter(Number.isInteger)));
17283
17388
  if (ids.length === 0)
17284
17389
  return out;
17285
- const placeholders = ids.map(() => "?").join(", ");
17286
17390
  const rejectionCountColumn = hasMuralCueRejectionCountColumn(db) ? "COALESCE(mural_cue_rejection_count, 0) AS mural_cue_rejection_count" : "0 AS mural_cue_rejection_count";
17287
- const rows = db.prepare(`SELECT id, mural_cue, mural_cue_hash, ${rejectionCountColumn} FROM memories WHERE id IN (${placeholders})`).all(...ids);
17391
+ const rows = db.prepare(`SELECT id, mural_cue, mural_cue_hash, ${rejectionCountColumn} FROM memories WHERE id IN (SELECT value FROM json_each(?))`).all(JSON.stringify(ids));
17288
17392
  for (const row of rows) {
17289
17393
  out.set(row.id, {
17290
17394
  cue: row.mural_cue ?? null,
@@ -17468,8 +17572,7 @@ function getUnclassifiedMemoryIds(db, memoryIds) {
17468
17572
  const ids = Array.from(new Set(memoryIds.filter(Number.isInteger)));
17469
17573
  if (ids.length === 0)
17470
17574
  return [];
17471
- const ph = ids.map(() => "?").join(", ");
17472
- const rows = db.prepare(`SELECT id FROM memories WHERE id IN (${ph}) AND classified_at IS NOT NULL`).all(...ids);
17575
+ const rows = db.prepare("SELECT id FROM memories WHERE id IN (SELECT value FROM json_each(?)) AND classified_at IS NOT NULL").all(JSON.stringify(ids));
17473
17576
  const classified = new Set(rows.map((r) => r.id));
17474
17577
  return ids.filter((id) => !classified.has(id));
17475
17578
  }
@@ -17749,6 +17852,7 @@ function getMemoriesByProject(db, projectPath, statuses = ["active", "permanent"
17749
17852
  const rows = getMemoriesByProjectStatement(db, statuses).all(projectPath, ...statuses, expiryCutoff).filter(isMemoryRow);
17750
17853
  return rows.map(toMemory);
17751
17854
  }
17855
+ var memoryListStatements = new WeakMap;
17752
17856
  function sqlPlaceholders(values) {
17753
17857
  return values.map(() => "?").join(", ");
17754
17858
  }
@@ -18181,9 +18285,6 @@ function searchMemoriesFTSUnion(db, projectPaths, query, limit = DEFAULT_SEARCH_
18181
18285
  }
18182
18286
  // ../plugin/src/features/magic-context/memory/storage-memory-verifications.ts
18183
18287
  var MEMORY_VERIFICATION_SENTINEL = "";
18184
- function placeholders2(values) {
18185
- return values.map(() => "?").join(", ");
18186
- }
18187
18288
  function uniqueSortedFiles(files) {
18188
18289
  return Array.from(new Set(files.filter((file) => file !== MEMORY_VERIFICATION_SENTINEL))).sort();
18189
18290
  }
@@ -18211,7 +18312,7 @@ function getUnmappedMemoryIds(db, memoryIds) {
18211
18312
  const ids = Array.from(new Set(memoryIds.filter(Number.isInteger)));
18212
18313
  if (ids.length === 0)
18213
18314
  return [];
18214
- const rows = db.prepare(`SELECT DISTINCT memory_id FROM memory_verifications WHERE memory_id IN (${placeholders2(ids)})`).all(...ids);
18315
+ const rows = db.prepare("SELECT DISTINCT memory_id FROM memory_verifications WHERE memory_id IN (SELECT value FROM json_each(?))").all(JSON.stringify(ids));
18215
18316
  const mapped = new Set(rows.map((r) => r.memory_id));
18216
18317
  return ids.filter((id) => !mapped.has(id));
18217
18318
  }
@@ -18225,8 +18326,8 @@ function getMemoryVerifications(db, memoryIds) {
18225
18326
  return result;
18226
18327
  const rows = db.prepare(`SELECT memory_id, file_path, verified_at, mapped_at, mapping_origin
18227
18328
  FROM memory_verifications
18228
- WHERE memory_id IN (${placeholders2(ids)})
18229
- ORDER BY memory_id, file_path`).all(...ids);
18329
+ WHERE memory_id IN (SELECT value FROM json_each(?))
18330
+ ORDER BY memory_id, file_path`).all(JSON.stringify(ids));
18230
18331
  for (const row of rows) {
18231
18332
  const existing = result.get(row.memory_id) ?? {
18232
18333
  files: [],
@@ -18307,10 +18408,10 @@ async function readGitHead(cwd) {
18307
18408
  const head = stdout?.trim();
18308
18409
  return head && /^[0-9a-f]{40}$/i.test(head) ? head : null;
18309
18410
  }
18310
- async function readGitChangedFilesSince(cwd, revision) {
18411
+ async function readGitChangedFilesSince(cwd, revision, knownGitRoot) {
18311
18412
  if (!/^[0-9a-f]{7,40}$/i.test(revision))
18312
18413
  return null;
18313
- const gitRoot = await resolveGitTopLevel(cwd);
18414
+ const gitRoot = knownGitRoot ?? await resolveGitTopLevel(cwd);
18314
18415
  if (!gitRoot)
18315
18416
  return null;
18316
18417
  const stdout = await runGit(gitRoot, ["diff", "--name-only", "-z", revision]);
@@ -18318,8 +18419,8 @@ async function readGitChangedFilesSince(cwd, revision) {
18318
18419
  return null;
18319
18420
  return new Set(stdout.split("\x00").filter(Boolean));
18320
18421
  }
18321
- async function readGitFileChangeTimesSince(cwd, sinceMs) {
18322
- const gitRoot = await resolveGitTopLevel(cwd);
18422
+ async function readGitFileChangeTimesSince(cwd, sinceMs, knownGitRoot) {
18423
+ const gitRoot = knownGitRoot ?? await resolveGitTopLevel(cwd);
18323
18424
  if (!gitRoot)
18324
18425
  return null;
18325
18426
  const sinceSec = Math.max(0, Math.floor(sinceMs / 1000));
@@ -18379,6 +18480,7 @@ async function normalizeVerificationFiles(args) {
18379
18480
  const rootReal = safeRealpath(root) ?? root;
18380
18481
  const warnings = [];
18381
18482
  const normalized = [];
18483
+ let trackedPaths;
18382
18484
  for (const raw of args.files) {
18383
18485
  const value = typeof raw === "string" ? raw.trim() : "";
18384
18486
  if (!value) {
@@ -18420,7 +18522,14 @@ async function normalizeVerificationFiles(args) {
18420
18522
  warnings.push(`Skipped verification path "${value}" because it is not inside the git repo.`);
18421
18523
  continue;
18422
18524
  }
18423
- const tracked = await gitTrackedPath(gitRoot, repoRelative);
18525
+ if (!trackedPaths) {
18526
+ let trackedOutput = null;
18527
+ try {
18528
+ trackedOutput = await runGit(gitRoot, ["ls-files", "-z", "--full-name"]);
18529
+ } catch {}
18530
+ trackedPaths = new Set(trackedOutput?.split("\x00").filter(Boolean) ?? []);
18531
+ }
18532
+ const tracked = trackedPaths.has(repoRelative) ? repoRelative : await gitTrackedPath(gitRoot, repoRelative);
18424
18533
  if (!tracked) {
18425
18534
  warnings.push(`Skipped verification path "${value}" because it is not a tracked git file.`);
18426
18535
  continue;
@@ -20060,6 +20169,10 @@ Stamp: file reads, search results and tool outputs the work ahead no longer need
20060
20169
  Keep: user messages (never stamp one for its directive), your own conversation text, unresolved errors, raw evidence you haven't extracted yet, and outputs whose exact wording may still matter.
20061
20170
 
20062
20171
  Look at each tag before stamping it; never blanket-stamp a range like "1-50". Many small targeted stamps beat one sweep. \`drop\` accepts "3-5", "1,2,9", "1-5,8,12-15".`;
20172
+ var CTX_REDUCE_SELF_STAMP_MESSAGE_TEMPLATE = "§N§ is a ctx_reduce call; leave those alone, they are cleaned up automatically.";
20173
+ function ctxReduceSelfStampMessage(tagNumber) {
20174
+ return CTX_REDUCE_SELF_STAMP_MESSAGE_TEMPLATE.replace("§N§", `§${tagNumber}§`);
20175
+ }
20063
20176
 
20064
20177
  // src/tools/ctx-reduce.ts
20065
20178
  var ParamsSchema3 = _Object_({
@@ -20105,11 +20218,18 @@ function createCtxReduceTool(deps) {
20105
20218
  if (unknownIds.length > 0) {
20106
20219
  return err4(`Error: Unknown tag(s) ${formatIds(unknownIds)}. Check available tags in conversation.`);
20107
20220
  }
20221
+ const ctxReduceSelfStampIds = new Set(allTags.filter((tag) => tag.toolName?.toLowerCase() === "ctx_reduce").map((tag) => tag.tagNumber));
20222
+ const ctxReduceSelfStampNote = dropIds.filter((id) => ctxReduceSelfStampIds.has(id)).filter((id, index, ids) => ids.indexOf(id) === index).map(ctxReduceSelfStampMessage).join(" ");
20223
+ dropIds = dropIds.filter((id) => !ctxReduceSelfStampIds.has(id));
20108
20224
  const activeTags = allTags.filter((tag) => tag.status === "active");
20109
20225
  const effectiveFloor = readEpochFloorSnapshot(deps.db, sessionId) ?? deps.resolveFloor?.(ctx) ?? deps.floor ?? deps.protectedTokens ?? 16000;
20110
20226
  const windowResult = getProtectionWindowForSession(deps.db, sessionId, effectiveFloor);
20111
20227
  const hasToolTags = allTags.some((t) => t.type === "tool");
20112
- const protectedSet = hasToolTags ? windowResult.tagNumberSet.tagNumbers : typeof deps.protectedTags === "number" && deps.protectedTags > 0 ? new Set(activeTags.map((tag) => tag.tagNumber).sort((left, right) => right - left).slice(0, deps.protectedTags)) : new Set;
20228
+ const windowSet = hasToolTags ? windowResult.tagNumberSet.tagNumbers : typeof deps.protectedTags === "number" && deps.protectedTags > 0 ? new Set(activeTags.map((tag) => tag.tagNumber).sort((left, right) => right - left).slice(0, deps.protectedTags)) : new Set;
20229
+ const protectedSet = new Set([
20230
+ ...windowSet,
20231
+ ...protectedToolTagNumbers(activeTags, deps.resolveProtectedTools?.(ctx) ?? deps.protectedTools)
20232
+ ]);
20113
20233
  const tagStatusMap = new Map(allTags.map((tag) => [tag.tagNumber, tag.status]));
20114
20234
  const inertWhitespaceTagNumbers = new Set(getInertWhitespaceAssistantTags(deps.db, sessionId).map((tag) => tag.tagNumber));
20115
20235
  const inertDropIds = [
@@ -20139,7 +20259,14 @@ function createCtxReduceTool(deps) {
20139
20259
  ].filter(Boolean).join(" ");
20140
20260
  dropIds = dropIds.filter((id) => !inertWhitespaceTagNumbers.has(id) && tagStatusMap.get(id) !== "dropped" && pendingMap.get(id) !== "drop");
20141
20261
  if (dropIds.length === 0) {
20142
- return ok4([inertNote, skippedNote, "No new action is needed."].filter(Boolean).join(" "));
20262
+ const noActionNotes = [
20263
+ ctxReduceSelfStampNote,
20264
+ inertNote,
20265
+ skippedNote
20266
+ ].filter(Boolean);
20267
+ if (!ctxReduceSelfStampNote)
20268
+ noActionNotes.push("No new action is needed.");
20269
+ return ok4(noActionNotes.join(" "));
20143
20270
  }
20144
20271
  try {
20145
20272
  deps.db.transaction(() => {
@@ -20164,7 +20291,8 @@ function createCtxReduceTool(deps) {
20164
20291
  parts.push(`drop ${formatIds(immediateDropIds)}`);
20165
20292
  if (deferredDropIds.length > 0)
20166
20293
  parts.push(`deferred drop ${formatIds(deferredDropIds)}`);
20167
- return ok4(`Queued: ${parts.join(", ")}.${skippedNote ? ` ${skippedNote}` : ""}${inertNote ? ` ${inertNote}` : ""}`);
20294
+ const held = deferredDropIds.length === 1 ? `Held: §${deferredDropIds[0]} is inside the protected working set; it applies once newer work displaces it.` : deferredDropIds.length > 1 ? `Held: ${deferredDropIds.map((id) => `§${id}`).join(", ")} are inside the protected working set; they apply once newer work displaces them.` : "";
20295
+ return ok4(`Queued: ${parts.join(", ")}.${held ? ` ${held}` : ""}${skippedNote ? ` ${skippedNote}` : ""}${inertNote ? ` ${inertNote}` : ""}${ctxReduceSelfStampNote ? ` ${ctxReduceSelfStampNote}` : ""}`);
20168
20296
  }
20169
20297
  };
20170
20298
  }
@@ -20395,6 +20523,47 @@ var ftsPlainStatements = new WeakMap;
20395
20523
  var datedFtsPlainStatements = new WeakMap;
20396
20524
  var getBySHAsStatements = new WeakMap;
20397
20525
  var datedGetBySHAsStatements = new WeakMap;
20526
+ var embeddingCache = new WeakMap;
20527
+ function getSearchEmbeddings(db, projectPath, modelId) {
20528
+ if (!isKnownAutocommit(db)) {
20529
+ embeddingCache.delete(db);
20530
+ return loadProjectCommitEmbeddings(db, projectPath, modelId);
20531
+ }
20532
+ let cache = embeddingCache.get(db);
20533
+ if (!cache) {
20534
+ cache = {
20535
+ revisionStatement: db.prepare(`SELECT total_changes() AS writes,
20536
+ (SELECT data_version FROM pragma_data_version) AS dataVersion,
20537
+ (SELECT schema_version FROM pragma_schema_version) AS schemaVersion`),
20538
+ revision: "",
20539
+ entries: new Map
20540
+ };
20541
+ embeddingCache.set(db, cache);
20542
+ }
20543
+ const revision = JSON.stringify(cache.revisionStatement.get());
20544
+ if (revision !== cache.revision) {
20545
+ cache.entries.clear();
20546
+ cache.revision = revision;
20547
+ }
20548
+ const key = JSON.stringify([projectPath, modelId]);
20549
+ const cached = cache.entries.get(key);
20550
+ if (cached) {
20551
+ cache.entries.delete(key);
20552
+ cache.entries.set(key, cached);
20553
+ return cached;
20554
+ }
20555
+ const vectors = loadProjectCommitEmbeddings(db, projectPath, modelId);
20556
+ const size = (entries) => [...entries.values()].reduce((sum, vector) => sum + vector.byteLength, 0);
20557
+ if (size(vectors) <= 32 * 1024 * 1024)
20558
+ cache.entries.set(key, vectors);
20559
+ while (cache.entries.size > 16 || [...cache.entries.values()].reduce((sum, entry) => sum + size(entry), 0) > 32 * 1024 * 1024) {
20560
+ const oldest = cache.entries.keys().next().value;
20561
+ if (oldest === undefined)
20562
+ break;
20563
+ cache.entries.delete(oldest);
20564
+ }
20565
+ return vectors;
20566
+ }
20398
20567
  function rowToCommit(row) {
20399
20568
  return {
20400
20569
  sha: row.sha,
@@ -20491,7 +20660,7 @@ function searchGitCommitsSync(db, projectPath, query, options) {
20491
20660
  });
20492
20661
  const semanticScores = new Map;
20493
20662
  if (options.queryEmbedding && options.queryModelId && options.queryModelId !== "off") {
20494
- const embeddings = loadProjectCommitEmbeddings(db, projectPath, options.queryModelId);
20663
+ const embeddings = getSearchEmbeddings(db, projectPath, options.queryModelId);
20495
20664
  for (const [sha, embedding] of embeddings.entries()) {
20496
20665
  const similarity = clamp01(cosineSimilarity(options.queryEmbedding, embedding));
20497
20666
  if (similarity > 0) {
@@ -22861,30 +23030,45 @@ function muralImageTokenEstimateForDimensions(width, height) {
22861
23030
  var muralImageTokenEstimate = muralImageTokenEstimateForDimensions(MURAL_WIDTH, MURAL_HEIGHT);
22862
23031
 
22863
23032
  // ../plugin/src/features/magic-context/mural/resolve-mural.ts
22864
- function getMuralCoverage(db, projectIdentity) {
23033
+ function readMuralPool(db, projectIdentity) {
22865
23034
  const memories = getMemoriesByProject(db, projectIdentity, ["active", "permanent"]);
22866
- const cueState = getMuralCueState(db, memories.map((memory) => memory.id));
23035
+ return {
23036
+ memories,
23037
+ cueState: getMuralCueState(db, memories.map((memory) => memory.id)),
23038
+ contentHashes: new Map
23039
+ };
23040
+ }
23041
+ function poolContentHash(pool, memory) {
23042
+ const cached = pool?.contentHashes.get(memory.id);
23043
+ if (cached?.content === memory.content)
23044
+ return cached.hash;
23045
+ const value = computeCueContentHash(memory.content);
23046
+ pool?.contentHashes.set(memory.id, { content: memory.content, hash: value });
23047
+ return value;
23048
+ }
23049
+ function getMuralCoverage(db, projectIdentity, pool) {
23050
+ const { memories, cueState } = pool ?? readMuralPool(db, projectIdentity);
22867
23051
  let cuedMemoryCount = 0;
22868
23052
  for (const memory of memories) {
22869
23053
  const state = cueState.get(memory.id);
22870
- if (state && typeof state.cue === "string" && state.cue.trim() !== "" && state.hash !== null && state.hash === computeCueContentHash(memory.content)) {
23054
+ if (state && typeof state.cue === "string" && state.cue.trim() !== "" && state.hash !== null && state.hash === poolContentHash(pool, memory)) {
22871
23055
  cuedMemoryCount += 1;
22872
23056
  }
22873
23057
  }
22874
23058
  return { activeMemoryCount: memories.length, cuedMemoryCount };
22875
23059
  }
22876
- function resolveMural(db, projectIdentity, budgetTokens = DEFAULT_MURAL_MEMORY_BUDGET) {
22877
- const memories = getMemoriesByProject(db, projectIdentity, ["active", "permanent"]);
23060
+ function resolveMural(db, projectIdentity, budgetTokens = DEFAULT_MURAL_MEMORY_BUDGET, pool) {
23061
+ const memories = pool?.memories ?? getMemoriesByProject(db, projectIdentity, ["active", "permanent"]);
22878
23062
  const overflow = muralOverflowMemories(memories, budgetTokens);
22879
23063
  if (overflow.length === 0)
22880
23064
  return [];
22881
- const cueState = getMuralCueState(db, overflow.map((memory) => memory.id));
23065
+ const cueState = pool?.cueState ?? getMuralCueState(db, overflow.map((memory) => memory.id));
22882
23066
  const entries = [];
22883
23067
  for (const memory of overflow) {
22884
23068
  const state = cueState.get(memory.id);
22885
23069
  if (!state || state.cue === null || state.hash === null)
22886
23070
  continue;
22887
- if (state.hash !== computeCueContentHash(memory.content))
23071
+ if (state.hash !== poolContentHash(pool, memory))
22888
23072
  continue;
22889
23073
  entries.push({
22890
23074
  id: memory.id,
@@ -22971,13 +23155,14 @@ function muralCoverageGate(cuedMemoryCount, activeMemoryCount) {
22971
23155
  return cuedMemoryCount >= MIN_MURAL_CUED_MEMORIES || cuedMemoryCount >= MIN_MURAL_COVERAGE * activeMemoryCount;
22972
23156
  }
22973
23157
  function ensureMuralRendered(db, projectIdentity, budgetTokens = DEFAULT_MURAL_MEMORY_BUDGET) {
22974
- const coverage = getMuralCoverage(db, projectIdentity);
23158
+ const pool = readMuralPool(db, projectIdentity);
23159
+ const coverage = getMuralCoverage(db, projectIdentity, pool);
22975
23160
  if (coverage.activeMemoryCount === 0 || !muralCoverageGate(coverage.cuedMemoryCount, coverage.activeMemoryCount)) {
22976
23161
  const skipReason = coverage.activeMemoryCount === 0 ? "no active memories" : `only ${coverage.cuedMemoryCount}/${coverage.activeMemoryCount} active memories have current cues (requires ${MIN_MURAL_CUED_MEMORIES} cues or ${MIN_MURAL_COVERAGE * 100}% coverage)`;
22977
23162
  log(`[mural] skipped for ${projectIdentity}: ${skipReason}`);
22978
23163
  return { hasMural: false, rerendered: false, skipReason };
22979
23164
  }
22980
- const entries = resolveMural(db, projectIdentity, budgetTokens);
23165
+ const entries = resolveMural(db, projectIdentity, budgetTokens, pool);
22981
23166
  if (entries.length === 0) {
22982
23167
  return { hasMural: false, rerendered: false };
22983
23168
  }
@@ -23206,6 +23391,38 @@ function getOpenCodeDbPath() {
23206
23391
  return resolveOpenCodeDbPath().path;
23207
23392
  }
23208
23393
  var cachedWriteDb = null;
23394
+ var cachedRemovalDb = null;
23395
+ var MARKER_BUSY_TIMEOUT_MS = 250;
23396
+ var MARKER_REMOVAL_BUSY_TIMEOUT_MS = 5000;
23397
+ function runMarkerWriteTransaction(db, site, operation) {
23398
+ if (db.inTransaction)
23399
+ return db.transaction(operation).immediate();
23400
+ const startedAt = performance.now();
23401
+ let acquiredAt;
23402
+ let workFinishedAt;
23403
+ let committed = false;
23404
+ try {
23405
+ const result = db.transaction(() => {
23406
+ acquiredAt = performance.now();
23407
+ try {
23408
+ return operation();
23409
+ } finally {
23410
+ workFinishedAt = performance.now();
23411
+ }
23412
+ }).immediate();
23413
+ committed = true;
23414
+ return result;
23415
+ } finally {
23416
+ const finishedAt = performance.now();
23417
+ const acquireMs = (acquiredAt ?? finishedAt) - startedAt;
23418
+ const holdMs = acquiredAt === undefined ? 0 : finishedAt - acquiredAt;
23419
+ const workMs = acquiredAt === undefined ? 0 : (workFinishedAt ?? finishedAt) - acquiredAt;
23420
+ const endMs = workFinishedAt === undefined ? 0 : finishedAt - workFinishedAt;
23421
+ try {
23422
+ log(`[magic-context] sqlite writer site=${site} db=opencode acquire_ms=${Math.round(acquireMs)} hold_ms=${Math.round(holdMs)} work_ms=${Math.round(workMs)} end_ms=${Math.round(endMs)} outcome=${acquiredAt === undefined ? "not_acquired" : committed ? "committed" : "failed"}`);
23423
+ } catch {}
23424
+ }
23425
+ }
23209
23426
  var REQUIRED_MESSAGE_COLUMNS = ["id", "session_id", "time_created", "time_updated", "data"];
23210
23427
  var REQUIRED_PART_COLUMNS = [
23211
23428
  "id",
@@ -23238,18 +23455,19 @@ function isOpenCodeSchemaCompatible(db, dbPath) {
23238
23455
  return false;
23239
23456
  }
23240
23457
  }
23241
- function getWritableOpenCodeDb() {
23458
+ function getWritableOpenCodeDb(purpose = "publication") {
23242
23459
  if (!harnessOwnsOpenCodeStore()) {
23243
23460
  throw new Error("OpenCode database is not writable from a Pi-compatible process");
23244
23461
  }
23245
23462
  const resolution = resolveOpenCodeDbPath();
23246
23463
  const dbPath = resolution.path;
23247
- if (cachedWriteDb?.path === dbPath) {
23248
- return cachedWriteDb.db;
23464
+ const cached = purpose === "removal" ? cachedRemovalDb : cachedWriteDb;
23465
+ if (cached?.path === dbPath) {
23466
+ return cached.db;
23249
23467
  }
23250
- if (cachedWriteDb) {
23468
+ if (cached) {
23251
23469
  try {
23252
- closeQuietly(cachedWriteDb.db);
23470
+ closeQuietly(cached.db);
23253
23471
  } catch {}
23254
23472
  }
23255
23473
  if (!existsSync10(dbPath)) {
@@ -23262,9 +23480,13 @@ function getWritableOpenCodeDb() {
23262
23480
  closeQuietly(db);
23263
23481
  throw error;
23264
23482
  }
23265
- db.exec("PRAGMA busy_timeout=5000");
23483
+ const timeoutMs = purpose === "removal" ? MARKER_REMOVAL_BUSY_TIMEOUT_MS : MARKER_BUSY_TIMEOUT_MS;
23484
+ db.exec(`PRAGMA busy_timeout=${timeoutMs}`);
23266
23485
  db.exec("PRAGMA journal_mode=WAL");
23267
- cachedWriteDb = { path: dbPath, db };
23486
+ if (purpose === "removal")
23487
+ cachedRemovalDb = { path: dbPath, db };
23488
+ else
23489
+ cachedWriteDb = { path: dbPath, db };
23268
23490
  return db;
23269
23491
  }
23270
23492
  function getNonSummaryMessageSortKey(sessionId, messageId) {
@@ -23292,19 +23514,19 @@ function findBoundaryUserMessage(sessionId, endMessageId) {
23292
23514
  AND NOT (COALESCE(json_extract(data, '$.summary'), 0) = 1
23293
23515
  AND COALESCE(json_extract(data, '$.finish'), '') = 'stop')
23294
23516
  AND COALESCE(json_extract(data, '$.role'), '') = 'user'
23295
- AND (time_created < ? OR (time_created = ? AND id <= ?))
23517
+ AND (time_created, id) <= (?, ?)
23296
23518
  AND NOT (
23297
23519
  EXISTS (SELECT 1 FROM part p
23298
- WHERE p.message_id = message.id AND p.session_id = message.session_id
23520
+ WHERE likelihood(p.message_id = message.id, 0.000001) AND +p.session_id = message.session_id
23299
23521
  AND COALESCE(json_extract(p.data, '$.type'), '') <> 'compaction')
23300
23522
  AND NOT EXISTS (SELECT 1 FROM part p
23301
- WHERE p.message_id = message.id AND p.session_id = message.session_id
23523
+ WHERE likelihood(p.message_id = message.id, 0.000001) AND +p.session_id = message.session_id
23302
23524
  AND COALESCE(json_extract(p.data, '$.type'), '') <> 'compaction'
23303
23525
  AND COALESCE(json_extract(p.data, '$.synthetic'), 0) <> 1
23304
23526
  AND COALESCE(json_extract(p.data, '$.syntheticTodoMarker'), 0) <> 1)
23305
23527
  )
23306
23528
  ORDER BY time_created DESC, id DESC
23307
- LIMIT 1`).get(sessionId, target.timeCreated, target.timeCreated, target.id);
23529
+ LIMIT 1`).get(sessionId, target.timeCreated, target.id);
23308
23530
  if (typeof boundary?.id !== "string" || typeof boundary.time_created !== "number") {
23309
23531
  return null;
23310
23532
  }
@@ -23325,6 +23547,25 @@ function compareOpenCodeMessagesByCanonicalOrder(sessionId, leftMessageId, right
23325
23547
  return 1;
23326
23548
  return 0;
23327
23549
  }
23550
+ function isOpenCodeGapHistorianAbsent(sessionId, endId, nextId) {
23551
+ const end = getNonSummaryMessageSortKey(sessionId, endId);
23552
+ const next = getNonSummaryMessageSortKey(sessionId, nextId);
23553
+ if (!end || !next || end.timeCreated > next.timeCreated || end.timeCreated === next.timeCreated && end.id >= next.id)
23554
+ return false;
23555
+ const row = getWritableOpenCodeDb().prepare(`SELECT 1 FROM message m
23556
+ WHERE m.session_id=?
23557
+ AND (m.time_created, m.id) > (?, ?)
23558
+ AND (m.time_created, m.id) < (?, ?)
23559
+ AND NOT (COALESCE(json_type(m.data,'$.summary'),'')='true' AND COALESCE(json_extract(m.data,'$.finish'),'')='stop')
23560
+ AND NOT (
23561
+ EXISTS (SELECT 1 FROM part p WHERE likelihood(p.message_id=m.id, 0.000001) AND +p.session_id=m.session_id AND COALESCE(json_extract(p.data,'$.type'),'')<>'compaction')
23562
+ AND NOT EXISTS (SELECT 1 FROM part p WHERE likelihood(p.message_id=m.id, 0.000001) AND +p.session_id=m.session_id
23563
+ AND COALESCE(json_extract(p.data,'$.type'),'')<>'compaction'
23564
+ AND COALESCE(json_type(p.data,'$.synthetic'),'')<>'true'
23565
+ AND COALESCE(json_type(p.data,'$.syntheticTodoMarker'),'')<>'true')
23566
+ ) LIMIT 1`).get(sessionId, end.timeCreated, end.id, next.timeCreated, next.id);
23567
+ return !row;
23568
+ }
23328
23569
  function removeLegacyMarkerLineageRows(db, args) {
23329
23570
  const legacySummaries = db.prepare(`SELECT m.id
23330
23571
  FROM message m
@@ -23387,7 +23628,7 @@ function injectCompactionMarker(args) {
23387
23628
  time: { created: boundaryTime + 1, completed: boundaryTime + 1 }
23388
23629
  });
23389
23630
  try {
23390
- db.transaction(() => {
23631
+ runMarkerWriteTransaction(db, "compaction-marker-inject", () => {
23391
23632
  removeLegacyMarkerLineageRows(db, {
23392
23633
  sessionId: args.sessionId,
23393
23634
  boundaryMessageId: boundary.id,
@@ -23418,7 +23659,7 @@ function injectCompactionMarker(args) {
23418
23659
  time_created = excluded.time_created,
23419
23660
  time_updated = excluded.time_updated,
23420
23661
  data = excluded.data`).run(summaryPartId, summaryMsgId, args.sessionId, boundaryTime + 1, boundaryTime + 1, JSON.stringify({ type: "text", text: args.summaryText }));
23421
- }).immediate();
23662
+ });
23422
23663
  log(`[magic-context] compaction-marker: injected boundary at user msg ${boundary.id} (ordinal ~${args.endOrdinal}), summary msg ${summaryMsgId}`);
23423
23664
  return {
23424
23665
  boundaryMessageId: boundary.id,
@@ -23432,9 +23673,14 @@ function injectCompactionMarker(args) {
23432
23673
  }
23433
23674
  }
23434
23675
  function replaceCompactionMarker(existing, args) {
23435
- const db = getWritableOpenCodeDb();
23676
+ let connection;
23677
+ let entered = false;
23678
+ let readyToCommit = false;
23436
23679
  try {
23437
- return db.transaction(() => {
23680
+ const db = getWritableOpenCodeDb();
23681
+ connection = db;
23682
+ const marker = runMarkerWriteTransaction(db, "compaction-marker-replace", () => {
23683
+ entered = true;
23438
23684
  if (existing) {
23439
23685
  db.prepare("DELETE FROM part WHERE id = ?").run(existing.summaryPartId);
23440
23686
  db.prepare("DELETE FROM message WHERE id = ?").run(existing.summaryMessageId);
@@ -23444,11 +23690,17 @@ function replaceCompactionMarker(existing, args) {
23444
23690
  if (!replacement) {
23445
23691
  throw new Error(`failed to inject replacement marker at ordinal ${args.endOrdinal}`);
23446
23692
  }
23693
+ readyToCommit = true;
23447
23694
  return replacement;
23448
- }).immediate();
23695
+ });
23696
+ return { kind: "committed", marker };
23449
23697
  } catch (error) {
23450
23698
  log(`[magic-context] compaction-marker: atomic replacement failed: ${error instanceof Error ? error.message : String(error)}`);
23451
- return null;
23699
+ const definitelyNoCut = !entered || !readyToCommit && connection?.inTransaction === false;
23700
+ return {
23701
+ kind: definitelyNoCut ? "definitely-no-cut" : "uncertain",
23702
+ error: error instanceof Error ? error : new Error(String(error))
23703
+ };
23452
23704
  }
23453
23705
  }
23454
23706
 
@@ -23500,6 +23752,21 @@ function existingMarkerAlreadyCoversTarget(sessionId, existing, targetOrdinal, t
23500
23752
  }
23501
23753
  return true;
23502
23754
  }
23755
+ function boundaryWouldDiscardUncoveredMessage(db, sessionId, ordinal, boundaryMessageId) {
23756
+ const current = getPersistedCompactionMarkerState(db, sessionId);
23757
+ const partials = getUncoveredCompartmentEndsThrough(db, sessionId, ordinal);
23758
+ for (const partial of partials) {
23759
+ if (current && compareOpenCodeMessagesByCanonicalOrder(sessionId, partial.endMessageId, current.boundaryMessageId) === -1)
23760
+ continue;
23761
+ const ordering = compareOpenCodeMessagesByCanonicalOrder(sessionId, boundaryMessageId, partial.endMessageId);
23762
+ if (ordering !== null && ordering <= 0)
23763
+ continue;
23764
+ if (partial.successorStartMessageId && partial.successorStartMessage !== null && partial.successorStartMessage > partial.endMessage + 1 && isOpenCodeGapHistorianAbsent(sessionId, partial.endMessageId, partial.successorStartMessageId))
23765
+ continue;
23766
+ return true;
23767
+ }
23768
+ return false;
23769
+ }
23503
23770
  function updateCompactionMarkerAfterPublication(db, sessionId, lastCompartmentEnd, directory) {
23504
23771
  if (getHarness() !== "opencode") {
23505
23772
  return true;
@@ -23509,9 +23776,6 @@ function updateCompactionMarkerAfterPublication(db, sessionId, lastCompartmentEn
23509
23776
  sessionLog(sessionId, `compaction-marker: no compartment endMessageId for ordinal ${lastCompartmentEnd}; preserving existing marker`);
23510
23777
  return false;
23511
23778
  }
23512
- if (hasPartialCompartmentEndThrough(db, sessionId, lastCompartmentEnd)) {
23513
- return false;
23514
- }
23515
23779
  const existing = getPersistedCompactionMarkerState(db, sessionId);
23516
23780
  const removedSummaryMessageId = existing?.summaryMessageId ?? null;
23517
23781
  if (existing) {
@@ -23524,7 +23788,10 @@ function updateCompactionMarkerAfterPublication(db, sessionId, lastCompartmentEn
23524
23788
  sessionLog(sessionId, `compaction-marker: no user boundary found at or before endMessageId ${targetEndMessageId} (ordinal ${lastCompartmentEnd}); preserving existing marker`);
23525
23789
  return false;
23526
23790
  }
23527
- const result = replaceCompactionMarker(existing, {
23791
+ if (boundaryWouldDiscardUncoveredMessage(db, sessionId, lastCompartmentEnd, boundary.id)) {
23792
+ return false;
23793
+ }
23794
+ const replacement = replaceCompactionMarker(existing, {
23528
23795
  sessionId,
23529
23796
  endOrdinal: lastCompartmentEnd,
23530
23797
  endMessageId: targetEndMessageId,
@@ -23532,7 +23799,8 @@ function updateCompactionMarkerAfterPublication(db, sessionId, lastCompartmentEn
23532
23799
  directory: directory ?? process.cwd(),
23533
23800
  resolvedBoundary: boundary
23534
23801
  });
23535
- if (result) {
23802
+ if (replacement.kind === "committed") {
23803
+ const result = replacement.marker;
23536
23804
  persistMarkerStateAndDropReplacedTag(db, sessionId, {
23537
23805
  ...result,
23538
23806
  boundaryOrdinal: lastCompartmentEnd,
@@ -23552,6 +23820,7 @@ var MEMORY_EPOCH_COMPONENT_PREFIX = "|memory-render:";
23552
23820
  var MURAL_COMPONENT_PREFIX = "|mural-enabled:";
23553
23821
  var BUDGET_COMPONENT_PREFIX = "|render-budgets:";
23554
23822
  var RENDERED_BUDGETS_COMPONENT_PREFIX = "|rendered-budgets:";
23823
+ var M0_MEMORY_IDS_COMPONENT_PREFIX = "|m0-memory-ids:";
23555
23824
  function encodeCachedM0UpgradeIdentity(upgradeState, compartmentRenderEpoch = COMPARTMENT_RENDER_EPOCH, muralEnabled = null, renderBudgetIdentity = null, memoryRenderEpoch = MEMORY_RENDER_FORMAT_EPOCH, renderedBudgets = null) {
23556
23825
  let encoded = upgradeState ?? "";
23557
23826
  if (compartmentRenderEpoch !== null) {
@@ -23596,7 +23865,8 @@ function decodeCachedM0UpgradeIdentity(value) {
23596
23865
  value.indexOf(MEMORY_EPOCH_COMPONENT_PREFIX),
23597
23866
  value.indexOf(MURAL_COMPONENT_PREFIX),
23598
23867
  value.indexOf(BUDGET_COMPONENT_PREFIX),
23599
- value.indexOf(RENDERED_BUDGETS_COMPONENT_PREFIX)
23868
+ value.indexOf(RENDERED_BUDGETS_COMPONENT_PREFIX),
23869
+ value.indexOf(M0_MEMORY_IDS_COMPONENT_PREFIX)
23600
23870
  ].filter((index) => index >= 0);
23601
23871
  const identityEnd = componentIndexes.length > 0 ? Math.min(...componentIndexes) : value.length;
23602
23872
  const upgradeState = value.slice(0, identityEnd);
@@ -23610,6 +23880,22 @@ function decodeCachedM0UpgradeIdentity(value) {
23610
23880
  renderedBudgets: component(value, RENDERED_BUDGETS_COMPONENT_PREFIX)
23611
23881
  };
23612
23882
  }
23883
+ function withCachedM0MemoryIds(identity, ids) {
23884
+ const withoutIds = (identity ?? "").replace(/\|m0-memory-ids:[^|]*/g, "");
23885
+ return `${withoutIds}${M0_MEMORY_IDS_COMPONENT_PREFIX}${JSON.stringify(ids)}`;
23886
+ }
23887
+ function readCachedM0MemoryIds(identity, legacyVisibleIds, maxMemoryId) {
23888
+ const encoded = component(identity ?? "", M0_MEMORY_IDS_COMPONENT_PREFIX);
23889
+ if (encoded !== null) {
23890
+ try {
23891
+ const ids = JSON.parse(encoded);
23892
+ if (Array.isArray(ids) && ids.every((id) => Number.isSafeInteger(id) && id > 0)) {
23893
+ return ids;
23894
+ }
23895
+ } catch {}
23896
+ }
23897
+ return legacyVisibleIds.filter((id) => id <= maxMemoryId);
23898
+ }
23613
23899
  function renderBudgetIdentityChanged(cached, current) {
23614
23900
  const legacy = /^(m[^-]+)-h\d+$/.exec(cached);
23615
23901
  if (legacy && current.startsWith("m") && current.includes("-hp")) {
@@ -23890,6 +24176,7 @@ function formatGap(seconds) {
23890
24176
  return days === 0 ? `+${weeks}w` : `+${weeks}w ${days}d`;
23891
24177
  }
23892
24178
  var TEMPORAL_MARKER_PATTERN = /^<!-- \+[\d]+[mhdw](?: [\d]+[mhdw])? -->\n/;
24179
+ var TEMPORAL_MARKER_REPLAY_PATTERN = /^<!-- \+[\d]+[mhdw](?: [\d]+[mhdw])? -->(?:\n|$)/;
23893
24180
  function temporalMarkerPrefix(seconds) {
23894
24181
  const marker = formatGap(seconds);
23895
24182
  if (!marker)
@@ -24503,9 +24790,11 @@ function registerMagicContextTools(pi, opts) {
24503
24790
  pi.registerTool(surfaceTool(createCtxReduceTool({
24504
24791
  db: opts.db,
24505
24792
  protectedTags: opts.protectedTags ?? 20,
24793
+ protectedTools: opts.protectedTools,
24794
+ resolveProtectedTools: opts.resolveProtectedTools,
24506
24795
  resolveProtectedTags: opts.resolveProtectedTags
24507
24796
  })));
24508
24797
  }
24509
24798
  }
24510
24799
 
24511
- export { COMPACTION_ENABLED_PATH, isDreamerRunnable, isCompactionEnabled, formatConfigParseStatusLine, formatConfigParseNotice, claimConfigParseFailuresOnce, parseJsoncRecovering, detectConfigFile, MIN_PLAUSIBLE_CONTEXT_LIMIT, catalogOutputReserve, reloadWindowOverlay, getWindowOverlay, resolveWindowOverlayFacts, deriveWindowGeometry, hasTrustedAbsoluteWall, applyProvenInputFloor, formatWindowDerivationLine, isSaneLimit, resolveOutputReserve, getSdkWindowGeometry, getSdkContextLimit, getSdkOutputLimit, getSdkInputLimit, cortexKitUserConfigBasePath, cortexKitProjectConfigBasePath, migrateMagicContextConfigLocations, getProtectedTokensTierOverrides, MAX_EXECUTE_THRESHOLD, escalationBands, HYGIENE_PROVIDER_UNITS_VERSION, sessionDecisionCalibration, transitionSessionHygieneUnits, computeProtectionWindow, readEpochFloorSnapshot, getProtectionWindowForSession, persistCachedM0, clearCachedM0M1, ReplayDocumentError, readReplayEnvelope, updateReplayDocument, isProviderOverflowFailClosedProven, describeProtectedTailDrainBudgetSkip, loadProtectedTailMeta, markProtectedTailPolicyV3Seeded, recordProtectedTailPublicationFloor, recordProtectedTailNoEligibleHead, getWrapupInProgressState, isWrapupInProgress, acquireWrapupInProgress, updateWrapupInProgress, releaseWrapupInProgress, resolveCompactionModeRecord, getCompactionModeRecord, setCompactionModeRecord, reserveProtectedTailDrainTokens, clearEmergencyDrainLatch, recordHistorianDrainFailure, clearHistorianDrainFailure, rollbackProtectedTailDrainReservation, clearPersistedReasoningWatermark, getEmergencyInputSample, setEmergencyDropSample, clearEmergencyDropSample, getLastNudgeUndropped, setLastNudgeUndropped, getChannel1NudgeState, setChannel1NudgeState, markChannel1PostReduceGracePending, captureChannel1PostReduceGraceBaseline, getChannel2NudgeState, getChannel2NudgeClaim, setChannel2NudgeState, casChannel2NudgeState, claimChannel2NudgeState, casChannel2NudgeClaim, getPersistedNoteNudge, setPersistedNoteNudgeTrigger, setPersistedNoteNudgeTriggerMessageId, getNoteNudgeAnchors, getAutoSearchHintDecisions, deliverNoteNudgeAtomic, appendAutoSearchHintDecision, pruneNoteNudgeAnchors, pruneAutoSearchHintDecisions, getPersistedTodoSyntheticAnchor, setPersistedTodoSyntheticAnchor, clearPersistedTodoSyntheticAnchor, getNoteLastReadAt, getHistorianFailureState, incrementHistorianFailure, clearHistorianFailureState, getOverflowState, recordOverflowDetected, clearEmergencyRecovery, clearDetectedContextLimit, getStrippedPlaceholderIds, applyStrippedPlaceholderDelta, THINKING_BINDING_RECOVERY_FROZEN_PREFIX, THINKING_BINDING_STRIP_ORDER_END_MARKER, thinkingBindingRecoveryFrozenId, getThinkingBindingRecoveryTarget, armThinkingBindingRecovery, clearThinkingBindingRecoveryIf, getMergedReasoningStrippedIds, addMergedReasoningStrippedIds, getProcessedImageStrippedIds, addProcessedImageStrippedIds, getPendingCompactionMarkerState, getCompactionMarkerHealth, clearPendingCompactionMarkerStateIf, getPendingPiCompactionMarkerState, setPendingPiCompactionMarkerState, clearPendingPiCompactionMarkerStateIf, getSessionsWithPendingPiMarker, setSessionWorkMetrics, getSessionWorkMetrics, resolveEpochFloorForPass, buildCanonicalChunkTextFromFts, buildCompartmentSummaryFallbackText, canonicalizeInMemoryChunkTextForEmbedding, chunkCanonicalText, chunkEmbeddingWindowsAreCurrent, replaceCompartmentChunkEmbeddings, deleteChunkEmbedBackoffForSession, chunkWindowSourceKey, readSessionActivity, observeSessionActivity, backfillSessionActivity, getOrCreateSessionMeta, updateSessionMeta, advanceToolReclaimWatermark, retryPendingSessionCleanups, retryPendingRustSessionCleanupsForProject, recordSessionProjectIdentity, embedPauseBySession, embedRunStateBySession, autoEmbedAttemptedBySession, autoEmbedIdentityBySession, invalidateAutoEmbedSession, getEmbedDrainUiStatus, COMPARTMENT_LEASE_RENEWAL_MS, acquireCompartmentLease, renewCompartmentLease, releaseCompartmentLease, releaseCompartmentLeaseBestEffort, isCompartmentLeaseHeld, clearCompressionDepth, clearCompressionDepthRange, isNoContentCompartment, HAS_COMPARTMENT_CONTENT_SQL, queueM0Mutation, getMaxM0MutationId, getCompartments, getLastCompartmentEndMessage, getLastCompartmentEndMessageId, getCompartmentsByEndMessageId, appendCompartments, saveRecompStagingPass, getRecompStaging, clearRecompStaging, getRecompPartialRange, setRecompPartialRange, escapeXmlAttr, escapeXmlContent, isPartialCompartmentEnd, getMessageIndexSourceIdentity, isMessageIndexSourceCurrent, getLastIndexedOrdinal, getMessageIndexReconciliationStartOrdinal, isMessageIndexReconciledThrough, indexSingleMessage, indexMessagesAfterOrdinal, sweepOrphanedOpenCodeMessageIndexes, readProjectDocsCanonical, BoundedSessionMap, registerLkgPersistence, signatureForFields, lkgContentFields, lkgContentDigestFromFields, exactReusablePrefix, incrementalLkgContentDigests, captureSlot, getSlot, dropSlot, noteEntry, encodePiContentDecision, getPiContentDecisions, freezePiContentDecision, getNativeReplayState, saveNativeToolInputs, addNativeReasoningIds, copySessionStateForClone, queueMemoryMutation, getMemoryMutationsForRender, getMemoryMutationsForRenderByProjects, getMaxMemoryMutationId, getMaxMemoryMutationIdForProjects, getNotes, addNote, getSessionNotes, getPendingSmartNotes, getReadySmartNotes, markNoteReady, markNoteChecked, queuePendingOp, getPendingOps, getPendingOpsCount, clearPendingOps, removePendingOp, PRIMER_CANDIDATE_TTL_MS, PRIMER_CANDIDATE_MAX_AGE_MS, primerOccurrenceKey, primerOccurrenceUtcDay, insertPrimerCandidates, updatePrimerCandidateEmbedding, getPrimerCandidatesByIds, getPrimerCandidatesForPromotion, countPrimerCandidatesForProject, getActivePrimers, createPrimer, updatePrimerSupport, updatePrimerAnswer, GLOBAL_USER_PROFILE_PROJECT_PATH, getProjectState, bumpProjectUserProfileVersion, saveSourceContent, getSourceContents, recordSubagentInvocation, getLatestHistorianInvocationId, noteTouchedAt, noteNudgePickIndex, formatNoteNudge, setEmbeddingSessionBusy, promptSurfaceHashMaterial, createPromptSurfaceRuntime, createPromptSurfaceGuidanceEpochCache, SYNTH_USER_ID_PREFIX, resolvePiStableId, readPiSessionSnapshot, readPiSessionMessages, readPiSessionMessagePage, findRestartModelSeedFromBranch, iterateEntriesToRawMessageRange, convertEntriesToRawMessages, convertEntriesToRawMessagePage, countPiRawMessages, computeCueContentHash, hasMuralCueColumns, getMuralCueState, memoryNeedsCue, setMuralCue, recordMuralCueRejection, invalidateMemory, hasMemoryShareableColumn, hasMemoryClassifiedAtColumn, getUnclassifiedMemoryIds, insertMemory, getMemoryByHash, getMemoriesByProject, getMemoriesByProjects, getMaxMemoryIdForProjects, getMemoryById, setMemoryClassification, archiveMemory, getMemoryCountsByStatus, USER_MEMORY_CANDIDATE_TTL_MS, insertUserMemoryCandidates, getUserMemoryCandidates, deleteUserMemoryCandidates, pruneExpiredUserMemoryCandidates, insertUserMemory, getActiveUserMemories, updateUserMemoryContent, dismissUserMemory, getTaskScheduleState, getFailingDreamTasks, getSkippedDreamTasks, getMostRecentTaskRunAt, pruneNonCanonicalTaskRows, deleteTaskScheduleRowsForProject, seedTaskScheduleState, writeTaskScheduleState, isRetrospectiveWindowProcessed, recordRetrospectiveWindowProcessed, curateCategoryForMemoryCategory, peekCurateCategoryScope, beginCurateCategoryRun, curateTaskStateAfterSuccess, cosineSimilarity, drainBackgroundBatches, GIT_SWEEP_LEASE_RENEWAL_MS, acquireGitSweepLease, renewGitSweepLease, markGitSweepSuccessAndRelease, parkGitSweepNonIndexable, releaseGitSweepLease, describeShadowBackfillWriteRefusal, contentSha256, drainProjectEmbeddingIdentityMaintenance, drainStaleEmbeddingIdentitiesForProject, enqueueShadowEmbeddingItems, getProjectEmbeddingSnapshot, getProjectChunkEmbeddingModelId, getProjectEmbeddingMaxInputTokens, embedTextForProject, embedBatchForProject, embedItemsForProject, embedUnembeddedMemoriesForProject, drainCommitBacklogForProject, embedSessionCompartmentChunks, getEmbeddingCoverageStatus, getAutoEmbeddingSessionCoverage, promoteSessionFactsDurable, embedPromotedFacts, recordMemoryMapping, recordMemoryVerifications, getUnmappedMemoryIds, clearMemoryVerifications, getMemoryVerifications, resolveGitTopLevel, readGitHead, readGitChangedFilesSince, readGitFileChangeTimesSince, verificationFileExists, normalizeVerificationFiles, isDirectiveShapedProjectRule, takeCurateSafetyRefusalCount, wakePlaneStatus, indexCommitsForProject, embedUnembeddedCommits, loadPiConfig, loadPiConfigDetailed, unregisterPiProjectEmbeddings, ensureProjectRegisteredFromPiDirectory, resolvePiHarnessDetection, resolvePiHarnessKind, MEMORY_MURAL_BLOCK, buildMagicContextSection, resolveMuralWire, updateCompactionMarkerAfterPublication, COMPARTMENT_RENDER_EPOCH, MEMORY_RENDER_FORMAT_EPOCH, encodeCachedM0UpgradeIdentity, decodeCachedM0UpgradeIdentity, renderBudgetIdentityChanged, renderedBudgetSnapshot, renderedBudgetShrinkReason, DEFAULT_HISTORY_BUDGET_TOKENS, renderCompartmentAtTier, renderDecayedCompartments, extractM0Block, TEMPORAL_MARKER_PATTERN, temporalMarkerPrefix, renderUserProfileContent, clearInjectionCache, getVisibleMemoryIds, orderHistorianMemories, renderHistorianMemoryBlock, DEFAULT_MEMORY_BUDGET_TOKENS, DEFAULT_USER_PROFILE_BUDGET_TOKENS, trimMemoriesToBudgetV2, trimWorkspaceMemoriesToBudgetV2, trimUserMemoriesToBudget, renderMemoryBlockV2, stripMemoryMuralBlock, unifiedSearch, rememberTodowriteToolCallTodos, parseTodos, setTodoSnapshot, registerTodoOverlay, registerTodoStateLifecycle, syncCtxMemoryToolEnabled, registerMagicContextTools };
24800
+ export { COMPACTION_ENABLED_PATH, isDreamerRunnable, isCompactionEnabled, formatConfigParseStatusLine, formatConfigParseNotice, claimConfigParseFailuresOnce, parseJsoncRecovering, detectConfigFile, MIN_PLAUSIBLE_CONTEXT_LIMIT, catalogOutputReserve, reloadWindowOverlay, getWindowOverlay, resolveWindowOverlayFacts, deriveWindowGeometry, hasTrustedAbsoluteWall, applyProvenInputFloor, formatWindowDerivationLine, isSaneLimit, resolveOutputReserve, getSdkWindowGeometry, getSdkContextLimit, getSdkOutputLimit, getSdkInputLimit, cortexKitUserConfigBasePath, cortexKitProjectConfigBasePath, migrateMagicContextConfigLocations, getProtectedTokensTierOverrides, BoundedSessionMap, MAX_EXECUTE_THRESHOLD, escalationBands, HYGIENE_PROVIDER_UNITS_VERSION, sessionDecisionCalibration, transitionSessionHygieneUnits, computeProtectionWindow, readEpochFloorSnapshot, getProtectionWindowForSession, persistCachedM0, clearCachedM0M1, isRustMarkerAdmissionFenced, ReplayDocumentError, readReplayEnvelope, updateReplayDocument, isProviderOverflowFailClosedProven, describeProtectedTailDrainBudgetSkip, loadProtectedTailMeta, markProtectedTailPolicyV3Seeded, recordProtectedTailPublicationFloor, recordProtectedTailNoEligibleHead, getWrapupInProgressState, isWrapupInProgress, acquireWrapupInProgress, updateWrapupInProgress, releaseWrapupInProgress, resolveCompactionModeRecord, getCompactionModeRecord, setCompactionModeRecord, reserveProtectedTailDrainTokens, clearEmergencyDrainLatch, recordHistorianDrainFailure, clearHistorianDrainFailure, rollbackProtectedTailDrainReservation, clearPersistedReasoningWatermark, getEmergencyInputSample, setEmergencyDropSample, clearEmergencyDropSample, getLastNudgeUndropped, setLastNudgeUndropped, getChannel1NudgeState, setChannel1NudgeState, markChannel1PostReduceGracePending, captureChannel1PostReduceGraceBaseline, getChannel2NudgeState, getChannel2NudgeClaim, setChannel2NudgeState, casChannel2NudgeState, claimChannel2NudgeState, casChannel2NudgeClaim, getPersistedNoteNudge, setPersistedNoteNudgeTrigger, setPersistedNoteNudgeTriggerMessageId, getNoteNudgeAnchors, getAutoSearchHintDecisions, deliverNoteNudgeAtomic, appendAutoSearchHintDecision, pruneNoteNudgeAnchors, pruneAutoSearchHintDecisions, getPersistedTodoSyntheticAnchor, setPersistedTodoSyntheticAnchor, clearPersistedTodoSyntheticAnchor, getNoteLastReadAt, getHistorianFailureState, incrementHistorianFailure, clearHistorianFailureState, getOverflowState, recordOverflowDetected, clearEmergencyRecovery, clearDetectedContextLimit, getStrippedPlaceholderIds, applyStrippedPlaceholderDelta, THINKING_BINDING_RECOVERY_FROZEN_PREFIX, THINKING_BINDING_STRIP_ORDER_END_MARKER, thinkingBindingRecoveryFrozenId, getThinkingBindingRecoveryTarget, armThinkingBindingRecovery, clearThinkingBindingRecoveryIf, getMergedReasoningStrippedIds, addMergedReasoningStrippedIds, getProcessedImageStrippedIds, addProcessedImageStrippedIds, getPendingCompactionMarkerState, getCompactionMarkerHealth, clearPendingCompactionMarkerStateIf, getPendingPiCompactionMarkerState, setPendingPiCompactionMarkerState, clearPendingPiCompactionMarkerStateIf, getSessionsWithPendingPiMarker, setSessionWorkMetrics, getSessionWorkMetrics, resolveEpochFloorForPass, buildCanonicalChunkTextFromFts, buildCompartmentSummaryFallbackText, canonicalizeInMemoryChunkTextForEmbedding, chunkCanonicalText, chunkEmbeddingWindowsAreCurrent, replaceCompartmentChunkEmbeddings, deleteChunkEmbedBackoffForSession, chunkWindowSourceKey, readSessionActivity, observeSessionActivity, backfillSessionActivity, getOrCreateSessionMeta, updateSessionMeta, advanceToolReclaimWatermark, retryPendingSessionCleanups, retryPendingRustSessionCleanupsForProject, recordSessionProjectIdentity, embedPauseBySession, embedRunStateBySession, autoEmbedAttemptedBySession, autoEmbedIdentityBySession, invalidateAutoEmbedSession, getEmbedDrainUiStatus, COMPARTMENT_LEASE_RENEWAL_MS, acquireCompartmentLease, renewCompartmentLease, releaseCompartmentLease, releaseCompartmentLeaseBestEffort, isCompartmentLeaseHeld, clearCompressionDepth, clearCompressionDepthRange, isNoContentCompartment, HAS_COMPARTMENT_CONTENT_SQL, queueM0Mutation, getMaxM0MutationId, getCompartments, getLastCompartmentEndMessage, getLastCompartmentEndMessageId, getCompartmentsByEndMessageId, appendCompartments, saveRecompStagingPass, getRecompStaging, clearRecompStaging, getRecompPartialRange, setRecompPartialRange, escapeXmlAttr, escapeXmlContent, getUncoveredCompartmentEndThrough, isPartialCompartmentEnd, getMessageIndexSourceIdentity, isMessageIndexSourceCurrent, getLastIndexedOrdinal, getMessageIndexReconciliationStartOrdinal, isMessageIndexReconciledThrough, indexSingleMessage, indexMessagesAfterOrdinal, sweepOrphanedOpenCodeMessageIndexes, readProjectDocsCanonical, providerResponseFailed, isSuccessfulProviderCompletion, registerLkgPersistence, LKG_SNAPSHOT_ARRAY, LKG_SNAPSHOT_OBJECT, LKG_SNAPSHOT_KEY, LKG_SNAPSHOT_STRING, LKG_SNAPSHOT_NUMBER, LKG_SNAPSHOT_BOOLEAN, LKG_SNAPSHOT_NULL, LKG_SNAPSHOT_UNDEFINED, contentSnapshotValue, signatureForFields, lkgContentFields, lkgContentDigestFromFields, exactReusablePrefix, incrementalLkgContentDigests, captureSlot, getInMemorySlot, getSlot, dropSlot, noteEntry, encodePiContentDecision, decodePiContentDecision, getPiContentDecisions, freezePiContentDecision, getNativeReplayState, saveNativeToolInputs, addNativeReasoningIds, copySessionStateForClone, queueMemoryMutation, getMemoryMutationsForRender, getMemoryMutationsForRenderByProjects, getMaxMemoryMutationId, getMaxMemoryMutationIdForProjects, getNotes, addNote, getSessionNotes, getPendingSmartNotes, getReadySmartNotes, markNoteReady, markNoteChecked, PRIMER_CANDIDATE_TTL_MS, PRIMER_CANDIDATE_MAX_AGE_MS, primerOccurrenceKey, primerOccurrenceUtcDay, insertPrimerCandidates, updatePrimerCandidateEmbedding, getPrimerCandidatesByIds, getPrimerCandidatesForPromotion, countPrimerCandidatesForProject, getActivePrimers, createPrimer, updatePrimerSupport, updatePrimerAnswer, GLOBAL_USER_PROFILE_PROJECT_PATH, getProjectState, bumpProjectUserProfileVersion, saveSourceContent, getSourceContents, recordSubagentInvocation, getLatestHistorianInvocationId, noteTouchedAt, noteNudgePickIndex, formatNoteNudge, setEmbeddingSessionBusy, promptSurfaceHashMaterial, createPromptSurfaceRuntime, createPromptSurfaceGuidanceEpochCache, SYNTH_USER_ID_PREFIX, resolvePiStableId, readPiSessionSnapshot, readPiSessionMessages, readPiSessionMessagePage, findRestartModelSeedFromBranch, iterateEntriesToRawMessageRange, convertEntriesToRawMessages, convertPiAssistantEntryById, convertEntriesToRawMessagePage, countPiRawMessages, computeCueContentHash, hasMuralCueColumns, getMuralCueState, memoryNeedsCue, setMuralCue, recordMuralCueRejection, invalidateMemory, hasMemoryShareableColumn, hasMemoryClassifiedAtColumn, getUnclassifiedMemoryIds, insertMemory, getMemoryByHash, getMemoriesByProject, getMemoriesByProjects, getMaxMemoryIdForProjects, getMemoryById, setMemoryClassification, archiveMemory, getMemoryCountsByStatus, USER_MEMORY_CANDIDATE_TTL_MS, insertUserMemoryCandidates, getUserMemoryCandidates, deleteUserMemoryCandidates, pruneExpiredUserMemoryCandidates, insertUserMemory, getActiveUserMemories, updateUserMemoryContent, dismissUserMemory, getTaskScheduleState, getFailingDreamTasks, getSkippedDreamTasks, getMostRecentTaskRunAt, pruneNonCanonicalTaskRows, deleteTaskScheduleRowsForProject, seedTaskScheduleState, writeTaskScheduleState, isRetrospectiveWindowProcessed, recordRetrospectiveWindowProcessed, curateCategoryForMemoryCategory, peekCurateCategoryScope, beginCurateCategoryRun, curateTaskStateAfterSuccess, cosineSimilarity, drainBackgroundBatches, GIT_SWEEP_LEASE_RENEWAL_MS, acquireGitSweepLease, renewGitSweepLease, markGitSweepSuccessAndRelease, parkGitSweepNonIndexable, releaseGitSweepLease, describeShadowBackfillWriteRefusal, contentSha256, drainProjectEmbeddingIdentityMaintenance, drainStaleEmbeddingIdentitiesForProject, enqueueShadowEmbeddingItems, getProjectEmbeddingSnapshot, getProjectChunkEmbeddingModelId, getProjectEmbeddingMaxInputTokens, embedTextForProject, embedBatchForProject, embedItemsForProject, embedUnembeddedMemoriesForProject, drainCommitBacklogForProject, embedSessionCompartmentChunks, getEmbeddingCoverageStatus, getAutoEmbeddingSessionCoverage, promoteSessionFactsDurable, embedPromotedFacts, recordMemoryMapping, recordMemoryVerifications, getUnmappedMemoryIds, clearMemoryVerifications, getMemoryVerifications, resolveGitTopLevel, readGitHead, readGitChangedFilesSince, readGitFileChangeTimesSince, verificationFileExists, normalizeVerificationFiles, isDirectiveShapedProjectRule, takeCurateSafetyRefusalCount, wakePlaneStatus, indexCommitsForProject, embedUnembeddedCommits, loadPiConfig, loadPiConfigDetailed, unregisterPiProjectEmbeddings, ensureProjectRegisteredFromPiDirectory, resolvePiHarnessDetection, resolvePiHarnessKind, MEMORY_MURAL_BLOCK, buildMagicContextSection, resolveMuralWire, updateCompactionMarkerAfterPublication, COMPARTMENT_RENDER_EPOCH, MEMORY_RENDER_FORMAT_EPOCH, encodeCachedM0UpgradeIdentity, decodeCachedM0UpgradeIdentity, withCachedM0MemoryIds, readCachedM0MemoryIds, renderBudgetIdentityChanged, renderedBudgetSnapshot, renderedBudgetShrinkReason, DEFAULT_HISTORY_BUDGET_TOKENS, renderCompartmentAtTier, renderDecayedCompartments, extractM0Block, TEMPORAL_MARKER_PATTERN, TEMPORAL_MARKER_REPLAY_PATTERN, temporalMarkerPrefix, renderUserProfileContent, clearInjectionCache, getVisibleMemoryIds, orderHistorianMemories, renderHistorianMemoryBlock, DEFAULT_MEMORY_BUDGET_TOKENS, DEFAULT_USER_PROFILE_BUDGET_TOKENS, trimMemoriesToBudgetV2, trimWorkspaceMemoriesToBudgetV2, trimUserMemoriesToBudget, renderMemoryBlockV2, stripMemoryMuralBlock, unifiedSearch, rememberTodowriteToolCallTodos, parseTodos, setTodoSnapshot, registerTodoOverlay, registerTodoStateLifecycle, syncCtxMemoryToolEnabled, registerMagicContextTools };