@cortexkit/opencode-magic-context 0.25.0 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/dist/agents/permissions.d.ts +6 -0
  2. package/dist/agents/permissions.d.ts.map +1 -1
  3. package/dist/config/schema/magic-context.d.ts +22 -0
  4. package/dist/config/schema/magic-context.d.ts.map +1 -1
  5. package/dist/features/magic-context/compartment-chunk-embedding.d.ts +17 -0
  6. package/dist/features/magic-context/compartment-chunk-embedding.d.ts.map +1 -1
  7. package/dist/features/magic-context/compartment-embedding.d.ts.map +1 -1
  8. package/dist/features/magic-context/dreamer/task-prompts.d.ts.map +1 -1
  9. package/dist/features/magic-context/memory/embedding-local.d.ts +3 -3
  10. package/dist/features/magic-context/memory/embedding-local.d.ts.map +1 -1
  11. package/dist/features/magic-context/memory/embedding-openai.d.ts +8 -4
  12. package/dist/features/magic-context/memory/embedding-openai.d.ts.map +1 -1
  13. package/dist/features/magic-context/memory/embedding-provider.d.ts +8 -4
  14. package/dist/features/magic-context/memory/embedding-provider.d.ts.map +1 -1
  15. package/dist/features/magic-context/memory/embedding.d.ts.map +1 -1
  16. package/dist/features/magic-context/memory/relocate-memory.d.ts +58 -0
  17. package/dist/features/magic-context/memory/relocate-memory.d.ts.map +1 -0
  18. package/dist/features/magic-context/migrations.d.ts.map +1 -1
  19. package/dist/features/magic-context/project-embedding-registry.d.ts +3 -3
  20. package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
  21. package/dist/features/magic-context/storage-db.d.ts +2 -1
  22. package/dist/features/magic-context/storage-db.d.ts.map +1 -1
  23. package/dist/features/magic-context/storage-meta-persisted.d.ts +37 -0
  24. package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
  25. package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -1
  26. package/dist/features/magic-context/storage-meta-shared.d.ts +3 -1
  27. package/dist/features/magic-context/storage-meta-shared.d.ts.map +1 -1
  28. package/dist/features/magic-context/storage-meta.d.ts +1 -1
  29. package/dist/features/magic-context/storage-meta.d.ts.map +1 -1
  30. package/dist/features/magic-context/storage-tags.d.ts +48 -2
  31. package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
  32. package/dist/features/magic-context/storage.d.ts +3 -3
  33. package/dist/features/magic-context/storage.d.ts.map +1 -1
  34. package/dist/features/magic-context/tagger.d.ts +1 -1
  35. package/dist/features/magic-context/tagger.d.ts.map +1 -1
  36. package/dist/features/magic-context/transform-decision-log.d.ts +49 -0
  37. package/dist/features/magic-context/transform-decision-log.d.ts.map +1 -0
  38. package/dist/features/magic-context/v22-deferred-backfill.d.ts.map +1 -1
  39. package/dist/hooks/magic-context/auto-search-runner.d.ts.map +1 -1
  40. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
  41. package/dist/hooks/magic-context/compartment-trigger.d.ts +1 -1
  42. package/dist/hooks/magic-context/compartment-trigger.d.ts.map +1 -1
  43. package/dist/hooks/magic-context/derive-budgets.d.ts +5 -9
  44. package/dist/hooks/magic-context/derive-budgets.d.ts.map +1 -1
  45. package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
  46. package/dist/hooks/magic-context/event-payloads.d.ts +1 -0
  47. package/dist/hooks/magic-context/event-payloads.d.ts.map +1 -1
  48. package/dist/hooks/magic-context/heuristic-cleanup.d.ts +1 -0
  49. package/dist/hooks/magic-context/heuristic-cleanup.d.ts.map +1 -1
  50. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  51. package/dist/hooks/magic-context/protected-tail-boundary.d.ts +10 -0
  52. package/dist/hooks/magic-context/protected-tail-boundary.d.ts.map +1 -1
  53. package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
  54. package/dist/hooks/magic-context/tag-id-fallback.d.ts.map +1 -1
  55. package/dist/hooks/magic-context/tag-messages.d.ts +10 -0
  56. package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
  57. package/dist/hooks/magic-context/transform-compartment-phase.d.ts +32 -1
  58. package/dist/hooks/magic-context/transform-compartment-phase.d.ts.map +1 -1
  59. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +6 -0
  60. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  61. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  62. package/dist/index.d.ts.map +1 -1
  63. package/dist/index.js +675 -216
  64. package/dist/plugin/dream-timer.d.ts.map +1 -1
  65. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  66. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  67. package/dist/shared/announcement.d.ts +1 -1
  68. package/dist/shared/index.d.ts +0 -1
  69. package/dist/shared/index.d.ts.map +1 -1
  70. package/dist/shared/resolve-fallbacks.d.ts +16 -16
  71. package/dist/shared/resolve-fallbacks.d.ts.map +1 -1
  72. package/dist/tools/ctx-search/tools.d.ts.map +1 -1
  73. package/package.json +1 -1
  74. package/src/shared/announcement.ts +6 -6
  75. package/src/shared/index.ts +0 -1
  76. package/src/shared/resolve-fallbacks.test.ts +37 -71
  77. package/src/shared/resolve-fallbacks.ts +16 -26
  78. package/src/tui/slots/sidebar-content.tsx +11 -7
  79. package/dist/shared/model-requirements.d.ts +0 -26
  80. package/dist/shared/model-requirements.d.ts.map +0 -1
  81. package/src/shared/model-requirements.ts +0 -86
package/dist/index.js CHANGED
@@ -47,20 +47,9 @@ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
47
47
  var __promiseAll = (args) => Promise.all(args);
48
48
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
49
49
 
50
- // src/agents/dreamer.ts
51
- var DREAMER_AGENT = "dreamer";
52
-
53
50
  // src/agents/historian.ts
54
- var exports_historian = {};
55
- __export(exports_historian, {
56
- HISTORIAN_EDITOR_AGENT: () => HISTORIAN_EDITOR_AGENT,
57
- HISTORIAN_AGENT: () => HISTORIAN_AGENT
58
- });
59
51
  var HISTORIAN_AGENT = "historian", HISTORIAN_EDITOR_AGENT = "historian-editor";
60
52
 
61
- // src/agents/sidekick.ts
62
- var SIDEKICK_AGENT = "sidekick";
63
-
64
53
  // src/shared/jsonc-parser.ts
65
54
  import { existsSync, readFileSync } from "node:fs";
66
55
  function stripJsonComments(content) {
@@ -14879,14 +14868,16 @@ var init_magic_context = __esm(() => {
14879
14868
  }).optional();
14880
14869
  HistorianConfigSchema = AgentOverrideConfigSchema.extend({
14881
14870
  two_pass: exports_external.boolean().default(false).describe("Run a second editor pass over historian output to clean low-signal U: lines and cross-compartment duplicates. Adds ~1 extra API call and ~1.3x cost per historian run. Useful for models without extended thinking support. (default: false)"),
14882
- thinking_level: PiThinkingLevelSchema.describe("Pi only: explicit thinking level passed as --thinking <level> to Pi historian subagent invocations. Required when using reasoning models (e.g. github-copilot/gpt-5.4) because Pi's default thinking-level resolution can pick a value the provider rejects. OpenCode users set variant instead. Valid: off | minimal | low | medium | high | xhigh")
14871
+ thinking_level: PiThinkingLevelSchema.describe("Pi only: explicit thinking level passed as --thinking <level> to Pi historian subagent invocations. Required when using reasoning models (e.g. github-copilot/gpt-5.4) because Pi's default thinking-level resolution can pick a value the provider rejects. OpenCode users set variant instead. Valid: off | minimal | low | medium | high | xhigh"),
14872
+ disallowed_tools: exports_external.array(exports_external.enum(["*", "read", "aft_outline", "aft_zoom", "aft_search"])).default([]).describe(`OpenCode only. Tools to REMOVE from the historian's default allow-list [read, aft_outline, aft_zoom, aft_search]. Applies to both historian and historian-editor agents. Use ["*"] to strip all tool definitions from the model request — this prevents weak instruction-following models (e.g. mistral-small-latest) from entering tool-calling loops. Individual tool names remove just that tool. Note: a user-supplied historian.permission override can re-allow a tool that disallowed_tools removed — disallowed_tools sets the baseline, permission overrides take precedence. (default: [])`)
14883
14873
  }).optional();
14884
14874
  BaseEmbeddingConfigSchema = exports_external.object({
14885
14875
  provider: exports_external.enum(["local", "openai-compatible", "off"]).default("local").describe("Embedding provider. 'local' uses Xenova/all-MiniLM-L6-v2, 'openai-compatible' requires endpoint and model, 'off' disables embeddings."),
14886
14876
  model: exports_external.string().optional().describe("Embedding model name. Required for openai-compatible, ignored for local."),
14887
14877
  endpoint: exports_external.string().optional().describe("API endpoint URL. Required when provider is openai-compatible."),
14888
14878
  api_key: exports_external.string().optional().describe("API key for remote embedding provider (optional)"),
14889
- input_type: exports_external.string().optional().describe("Optional input_type sent in the embedding request body. Required by some openai-compatible providers (e.g. NVIDIA NIM expects 'query' or 'passage'). Omitted from the request when unset."),
14879
+ input_type: exports_external.string().optional().describe("Default input_type for stored/indexed (passage) embeddings in the request body. Required by some openai-compatible providers (e.g. NVIDIA NIM). Omitted from the request when unset."),
14880
+ query_input_type: exports_external.string().optional().describe("Optional input_type for query (search) embeddings on asymmetric models (e.g. NVIDIA NIM 'query'). When unset, query embeddings use embedding.input_type. Passage/stored content always uses embedding.input_type."),
14890
14881
  truncate: exports_external.string().optional().describe("Optional truncate mode sent in the embedding request body (e.g. NVIDIA NIM accepts 'NONE' | 'START' | 'END'). Omitted from the request when unset."),
14891
14882
  max_input_tokens: exports_external.number().int().positive().optional().describe("Optional maximum input tokens for chunk embeddings. Defaults conservatively to 512 when omitted.")
14892
14883
  }).superRefine((data, ctx) => {
@@ -14916,6 +14907,7 @@ var init_magic_context = __esm(() => {
14916
14907
  if (data.provider === "openai-compatible") {
14917
14908
  const apiKey = data.api_key?.trim();
14918
14909
  const inputType = data.input_type?.trim();
14910
+ const queryInputType = data.query_input_type?.trim();
14919
14911
  const truncate = data.truncate?.trim();
14920
14912
  return {
14921
14913
  provider: "openai-compatible",
@@ -14923,6 +14915,7 @@ var init_magic_context = __esm(() => {
14923
14915
  endpoint: data.endpoint?.trim() ?? "",
14924
14916
  ...apiKey ? { api_key: apiKey } : {},
14925
14917
  ...inputType ? { input_type: inputType } : {},
14918
+ ...queryInputType ? { query_input_type: queryInputType } : {},
14926
14919
  ...truncate ? { truncate } : {},
14927
14920
  ...data.max_input_tokens ? { max_input_tokens: data.max_input_tokens } : {}
14928
14921
  };
@@ -15281,58 +15274,6 @@ var init_logger = __esm(() => {
15281
15274
  }
15282
15275
  });
15283
15276
 
15284
- // src/shared/model-requirements.ts
15285
- function expandFallbackChain(chain) {
15286
- const models = [];
15287
- for (const entry of chain) {
15288
- for (const provider of entry.providers) {
15289
- models.push(`${provider}/${entry.model}`);
15290
- }
15291
- }
15292
- return models;
15293
- }
15294
- function getAgentFallbackModels(agent) {
15295
- const requirement = AGENT_MODEL_REQUIREMENTS[agent];
15296
- if (!requirement)
15297
- return;
15298
- return expandFallbackChain(requirement.fallbackChain);
15299
- }
15300
- var HISTORIAN_FALLBACK_CHAIN, DREAMER_FALLBACK_CHAIN, SIDEKICK_FALLBACK_CHAIN, AGENT_MODEL_REQUIREMENTS;
15301
- var init_model_requirements = __esm(() => {
15302
- HISTORIAN_FALLBACK_CHAIN = [
15303
- { providers: ["github-copilot", "anthropic", "opencode"], model: "claude-sonnet-4-6" },
15304
- { providers: ["opencode-go"], model: "minimax-m2.7" },
15305
- {
15306
- providers: ["zai-coding-plan", "bailian-coding-plan", "opencode-go", "opencode"],
15307
- model: "glm-5"
15308
- },
15309
- { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.4" },
15310
- { providers: ["google", "github-copilot", "opencode"], model: "gemini-3.1-pro" }
15311
- ];
15312
- DREAMER_FALLBACK_CHAIN = [
15313
- { providers: ["github-copilot", "anthropic", "opencode"], model: "claude-sonnet-4-6" },
15314
- { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-flash" },
15315
- {
15316
- providers: ["zai-coding-plan", "bailian-coding-plan", "opencode-go", "opencode"],
15317
- model: "glm-5"
15318
- },
15319
- { providers: ["opencode-go"], model: "minimax-m2.7" },
15320
- { providers: ["github-copilot", "openai", "opencode"], model: "gpt-5.4-mini" }
15321
- ];
15322
- SIDEKICK_FALLBACK_CHAIN = [
15323
- { providers: ["cerebras"], model: "qwen-3-235b-a22b-instruct-2507" },
15324
- { providers: ["google", "github-copilot", "opencode"], model: "gemini-3-flash" },
15325
- { providers: ["openai", "github-copilot", "opencode"], model: "gpt-5.4-mini" },
15326
- { providers: ["opencode"], model: "gpt-5-nano" }
15327
- ];
15328
- AGENT_MODEL_REQUIREMENTS = {
15329
- [HISTORIAN_AGENT]: { fallbackChain: HISTORIAN_FALLBACK_CHAIN },
15330
- [HISTORIAN_EDITOR_AGENT]: { fallbackChain: HISTORIAN_FALLBACK_CHAIN },
15331
- [DREAMER_AGENT]: { fallbackChain: DREAMER_FALLBACK_CHAIN },
15332
- [SIDEKICK_AGENT]: { fallbackChain: SIDEKICK_FALLBACK_CHAIN }
15333
- };
15334
- });
15335
-
15336
15277
  // src/features/magic-context/overflow-detection.ts
15337
15278
  function extractErrorMessage(error51) {
15338
15279
  if (!error51)
@@ -15446,15 +15387,9 @@ __export(exports_resolve_fallbacks, {
15446
15387
  resolveFallbackChain: () => resolveFallbackChain,
15447
15388
  parseProviderModel: () => parseProviderModel
15448
15389
  });
15449
- function resolveFallbackChain(agentName, userFallbacks) {
15390
+ function resolveFallbackChain(userFallbacks) {
15450
15391
  const userList = normalizeUserFallbacks(userFallbacks);
15451
- if (userList.length > 0) {
15452
- return dedupe(userList.filter(isValidModelSpec));
15453
- }
15454
- const builtin = getAgentFallbackModels(agentName);
15455
- if (!builtin || builtin.length === 0)
15456
- return [];
15457
- return dedupe(builtin.filter(isValidModelSpec));
15392
+ return dedupe(userList.filter(isValidModelSpec));
15458
15393
  }
15459
15394
  function normalizeUserFallbacks(userFallbacks) {
15460
15395
  if (!userFallbacks)
@@ -15489,9 +15424,6 @@ function parseProviderModel(spec) {
15489
15424
  modelID: spec.slice(slash + 1).trim()
15490
15425
  };
15491
15426
  }
15492
- var init_resolve_fallbacks = __esm(() => {
15493
- init_model_requirements();
15494
- });
15495
15427
 
15496
15428
  // src/shared/model-suggestion-retry.ts
15497
15429
  function extractMessage(error51) {
@@ -15679,7 +15611,6 @@ async function promptSyncWithModelSuggestionRetry(client, args, options = {}) {
15679
15611
  var init_model_suggestion_retry = __esm(() => {
15680
15612
  init_overflow_detection();
15681
15613
  init_logger();
15682
- init_resolve_fallbacks();
15683
15614
  });
15684
15615
 
15685
15616
  // src/shared/normalize-sdk-response.ts
@@ -15709,9 +15640,7 @@ function normalizeSDKResponse(response, fallback, options) {
15709
15640
  // src/shared/index.ts
15710
15641
  var init_shared = __esm(() => {
15711
15642
  init_logger();
15712
- init_model_requirements();
15713
15643
  init_model_suggestion_retry();
15714
- init_resolve_fallbacks();
15715
15644
  });
15716
15645
 
15717
15646
  // src/shared/record-type-guard.ts
@@ -16077,6 +16006,8 @@ var init_storage_meta_shared = __esm(() => {
16077
16006
  "recovery_no_eligible_head_count",
16078
16007
  "force_emergency_bypass_window_start",
16079
16008
  "force_emergency_bypass_used",
16009
+ "emergency_drain_active",
16010
+ "historian_drain_failure_at",
16080
16011
  "upgrade_reminded_at",
16081
16012
  "pi_stable_id_scheme"
16082
16013
  ];
@@ -16126,6 +16057,8 @@ var init_storage_meta_shared = __esm(() => {
16126
16057
  recoveryNoEligibleHeadCount: "recovery_no_eligible_head_count",
16127
16058
  forceEmergencyBypassWindowStart: "force_emergency_bypass_window_start",
16128
16059
  forceEmergencyBypassUsed: "force_emergency_bypass_used",
16060
+ emergencyDrainActive: "emergency_drain_active",
16061
+ historianDrainFailureAt: "historian_drain_failure_at",
16129
16062
  upgradeRemindedAt: "upgrade_reminded_at",
16130
16063
  piStableIdScheme: "pi_stable_id_scheme"
16131
16064
  };
@@ -149677,6 +149610,22 @@ var init_tool_drop_target = __esm(() => {
149677
149610
  });
149678
149611
 
149679
149612
  // src/hooks/magic-context/read-session-chunk.ts
149613
+ function estimateBlockTokens(blockText) {
149614
+ const cached2 = blockTokenMemo.get(blockText);
149615
+ if (cached2 !== undefined) {
149616
+ blockTokenMemo.delete(blockText);
149617
+ blockTokenMemo.set(blockText, cached2);
149618
+ return cached2;
149619
+ }
149620
+ const count = estimateTokens(blockText);
149621
+ if (blockTokenMemo.size >= BLOCK_TOKEN_MEMO_MAX) {
149622
+ const oldest = blockTokenMemo.keys().next().value;
149623
+ if (oldest !== undefined)
149624
+ blockTokenMemo.delete(oldest);
149625
+ }
149626
+ blockTokenMemo.set(blockText, count);
149627
+ return count;
149628
+ }
149680
149629
  function cleanUserText(text) {
149681
149630
  return removeSystemReminders(text).replace(OMO_INTERNAL_INITIATOR_MARKER, "").trim();
149682
149631
  }
@@ -149844,7 +149793,7 @@ function readSessionChunk(sessionId, tokenBudget, offset = 1, eligibleEndOrdinal
149844
149793
  if (!currentBlock)
149845
149794
  return true;
149846
149795
  const blockText = formatBlock(currentBlock);
149847
- const blockTokens = estimateTokens(blockText);
149796
+ const blockTokens = estimateBlockTokens(blockText);
149848
149797
  if (totalTokens + blockTokens > tokenBudget && totalTokens > 0) {
149849
149798
  return false;
149850
149799
  }
@@ -149962,13 +149911,14 @@ function readSessionChunk(sessionId, tokenBudget, offset = 1, eligibleEndOrdinal
149962
149911
  toolOnlyRanges
149963
149912
  };
149964
149913
  }
149965
- var activeRawMessageCache = null, activeAbsoluteCountCache = null, sessionProviders, PROTECTED_TAIL_USER_TURNS = 5;
149914
+ var BLOCK_TOKEN_MEMO_MAX = 2048, blockTokenMemo, activeRawMessageCache = null, activeAbsoluteCountCache = null, sessionProviders, PROTECTED_TAIL_USER_TURNS = 5;
149966
149915
  var init_read_session_chunk = __esm(async () => {
149967
149916
  init_read_session_formatting();
149968
149917
  init_tag_part_guards();
149969
149918
  init_tool_drop_target();
149970
149919
  init_read_session_formatting();
149971
149920
  await init_read_session_db();
149921
+ blockTokenMemo = new Map;
149972
149922
  sessionProviders = new Map;
149973
149923
  });
149974
149924
 
@@ -150713,6 +150663,9 @@ function resolveDatabasePath(dbPathOverride) {
150713
150663
  const dbDir = getMagicContextStorageDir();
150714
150664
  return { dbDir, dbPath: join6(dbDir, "context.db") };
150715
150665
  }
150666
+ function getDatabasePath(db) {
150667
+ return pathByDatabase.get(db) ?? null;
150668
+ }
150716
150669
  function migrateLegacyStorageIfNeeded(targetDbPath, targetDbDir) {
150717
150670
  if (existsSync7(targetDbPath))
150718
150671
  return;
@@ -151223,6 +151176,8 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
151223
151176
  recovery_no_eligible_head_count INTEGER NOT NULL DEFAULT 0,
151224
151177
  force_emergency_bypass_window_start INTEGER NOT NULL DEFAULT 0,
151225
151178
  force_emergency_bypass_used INTEGER NOT NULL DEFAULT 0,
151179
+ emergency_drain_active INTEGER NOT NULL DEFAULT 0,
151180
+ historian_drain_failure_at INTEGER NOT NULL DEFAULT 0,
151226
151181
  cached_m0_materialized_at INTEGER,
151227
151182
  cached_m0_session_facts_version INTEGER,
151228
151183
  cached_m0_upgrade_state TEXT,
@@ -151286,6 +151241,23 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
151286
151241
  CREATE INDEX IF NOT EXISTS idx_historian_runs_status
151287
151242
  ON historian_runs(status, created_at DESC);
151288
151243
 
151244
+ CREATE TABLE IF NOT EXISTS transform_decisions (
151245
+ session_id TEXT NOT NULL,
151246
+ harness TEXT NOT NULL DEFAULT 'opencode',
151247
+ message_id TEXT NOT NULL,
151248
+ ts_ms INTEGER NOT NULL,
151249
+ decision TEXT NOT NULL,
151250
+ materialized INTEGER NOT NULL DEFAULT 0,
151251
+ materialize_reason TEXT,
151252
+ emergency INTEGER NOT NULL DEFAULT 0,
151253
+ dropped_tokens INTEGER NOT NULL DEFAULT 0,
151254
+ dropped_count INTEGER NOT NULL DEFAULT 0,
151255
+ input_tokens INTEGER NOT NULL DEFAULT 0,
151256
+ PRIMARY KEY (session_id, harness, message_id)
151257
+ );
151258
+ CREATE INDEX IF NOT EXISTS idx_transform_decisions_session_harness
151259
+ ON transform_decisions(session_id, harness);
151260
+
151289
151261
  CREATE INDEX IF NOT EXISTS idx_tags_session_tag_number ON tags(session_id, tag_number);
151290
151262
  CREATE INDEX IF NOT EXISTS idx_tags_session_message_id ON tags(session_id, message_id);
151291
151263
  CREATE INDEX IF NOT EXISTS idx_pending_ops_session ON pending_ops(session_id);
@@ -151437,6 +151409,8 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
151437
151409
  ensureColumn(db, "session_meta", "recovery_no_eligible_head_count", "INTEGER NOT NULL DEFAULT 0");
151438
151410
  ensureColumn(db, "session_meta", "force_emergency_bypass_window_start", "INTEGER NOT NULL DEFAULT 0");
151439
151411
  ensureColumn(db, "session_meta", "force_emergency_bypass_used", "INTEGER NOT NULL DEFAULT 0");
151412
+ ensureColumn(db, "session_meta", "emergency_drain_active", "INTEGER NOT NULL DEFAULT 0");
151413
+ ensureColumn(db, "session_meta", "historian_drain_failure_at", "INTEGER NOT NULL DEFAULT 0");
151440
151414
  ensureColumn(db, "session_meta", "cached_m0_materialized_at", "INTEGER");
151441
151415
  ensureColumn(db, "session_meta", "cached_m0_session_facts_version", "INTEGER");
151442
151416
  ensureColumn(db, "session_meta", "cached_m0_upgrade_state", "TEXT");
@@ -151515,6 +151489,22 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
151515
151489
  failed_at INTEGER NOT NULL,
151516
151490
  UNIQUE(table_name, row_id)
151517
151491
  );
151492
+ CREATE TABLE IF NOT EXISTS transform_decisions (
151493
+ session_id TEXT NOT NULL,
151494
+ harness TEXT NOT NULL DEFAULT 'opencode',
151495
+ message_id TEXT NOT NULL,
151496
+ ts_ms INTEGER NOT NULL,
151497
+ decision TEXT NOT NULL,
151498
+ materialized INTEGER NOT NULL DEFAULT 0,
151499
+ materialize_reason TEXT,
151500
+ emergency INTEGER NOT NULL DEFAULT 0,
151501
+ dropped_tokens INTEGER NOT NULL DEFAULT 0,
151502
+ dropped_count INTEGER NOT NULL DEFAULT 0,
151503
+ input_tokens INTEGER NOT NULL DEFAULT 0,
151504
+ PRIMARY KEY (session_id, harness, message_id)
151505
+ );
151506
+ CREATE INDEX IF NOT EXISTS idx_transform_decisions_session_harness
151507
+ ON transform_decisions(session_id, harness);
151518
151508
  `);
151519
151509
  ensureColumn(db, "tags", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
151520
151510
  ensureColumn(db, "pending_ops", "harness", "TEXT NOT NULL DEFAULT 'opencode'");
@@ -151600,7 +151590,9 @@ function healNullIntegerColumns(db) {
151600
151590
  ["protected_tail_drain_tokens", 0],
151601
151591
  ["recovery_no_eligible_head_count", 0],
151602
151592
  ["force_emergency_bypass_window_start", 0],
151603
- ["force_emergency_bypass_used", 0]
151593
+ ["force_emergency_bypass_used", 0],
151594
+ ["emergency_drain_active", 0],
151595
+ ["historian_drain_failure_at", 0]
151604
151596
  ];
151605
151597
  for (const [column, fallback] of columns) {
151606
151598
  try {
@@ -151676,6 +151668,7 @@ function openDatabase(dbPathOrOptions) {
151676
151668
  setDatabase(db);
151677
151669
  loadToolDefinitionMeasurements(db);
151678
151670
  databases.set(dbPath, db);
151671
+ pathByDatabase.set(db, dbPath);
151679
151672
  persistenceByDatabase.set(db, true);
151680
151673
  persistenceErrorByDatabase.delete(db);
151681
151674
  return db;
@@ -151695,7 +151688,7 @@ function getDatabasePersistenceError(db) {
151695
151688
  return null;
151696
151689
  return persistenceErrorByDatabase.get(db) ?? null;
151697
151690
  }
151698
- var databases, persistenceByDatabase, persistenceErrorByDatabase, lastSchemaFenceRejection = null, LATEST_SUPPORTED_VERSION = 36, sqlitePragmaConfig, CHANNEL2_CLAIM_TTL_MS = 120000;
151691
+ var databases, persistenceByDatabase, persistenceErrorByDatabase, pathByDatabase, lastSchemaFenceRejection = null, LATEST_SUPPORTED_VERSION = 38, sqlitePragmaConfig, CHANNEL2_CLAIM_TTL_MS = 120000;
151699
151692
  var init_storage_db = __esm(async () => {
151700
151693
  init_data_path();
151701
151694
  init_logger();
@@ -151709,6 +151702,7 @@ var init_storage_db = __esm(async () => {
151709
151702
  databases = new Map;
151710
151703
  persistenceByDatabase = new WeakMap;
151711
151704
  persistenceErrorByDatabase = new WeakMap;
151705
+ pathByDatabase = new WeakMap;
151712
151706
  sqlitePragmaConfig = {
151713
151707
  cacheSizeMb: 64,
151714
151708
  mmapSizeMb: 0
@@ -153027,6 +153021,41 @@ var init_migrations = __esm(async () => {
153027
153021
  `);
153028
153022
  }
153029
153023
  }
153024
+ },
153025
+ {
153026
+ version: 37,
153027
+ description: "emergency drain catch-up latch + historian drain failure backoff",
153028
+ up: (db) => {
153029
+ const hasSessionMeta = db.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name='session_meta'").get();
153030
+ if (!hasSessionMeta)
153031
+ return;
153032
+ ensureColumn(db, "session_meta", "emergency_drain_active", "INTEGER NOT NULL DEFAULT 0");
153033
+ ensureColumn(db, "session_meta", "historian_drain_failure_at", "INTEGER NOT NULL DEFAULT 0");
153034
+ }
153035
+ },
153036
+ {
153037
+ version: 38,
153038
+ description: "durable transform decisions for cache-event cause attribution",
153039
+ up: (db) => {
153040
+ db.exec(`
153041
+ CREATE TABLE IF NOT EXISTS transform_decisions (
153042
+ session_id TEXT NOT NULL,
153043
+ harness TEXT NOT NULL DEFAULT 'opencode',
153044
+ message_id TEXT NOT NULL,
153045
+ ts_ms INTEGER NOT NULL,
153046
+ decision TEXT NOT NULL,
153047
+ materialized INTEGER NOT NULL DEFAULT 0,
153048
+ materialize_reason TEXT,
153049
+ emergency INTEGER NOT NULL DEFAULT 0,
153050
+ dropped_tokens INTEGER NOT NULL DEFAULT 0,
153051
+ dropped_count INTEGER NOT NULL DEFAULT 0,
153052
+ input_tokens INTEGER NOT NULL DEFAULT 0,
153053
+ PRIMARY KEY (session_id, harness, message_id)
153054
+ );
153055
+ CREATE INDEX IF NOT EXISTS idx_transform_decisions_session_harness
153056
+ ON transform_decisions(session_id, harness);
153057
+ `);
153058
+ }
153030
153059
  }
153031
153060
  ];
153032
153061
  LATEST_MIGRATION_VERSION = MIGRATIONS.reduce((max, m) => Math.max(max, m.version), 0);
@@ -153431,7 +153460,9 @@ function toProtectedTailMeta(row) {
153431
153460
  protectedTailDrainTokens: numberOr(r.protected_tail_drain_tokens, 0),
153432
153461
  recoveryNoEligibleHeadCount: numberOr(r.recovery_no_eligible_head_count, 0),
153433
153462
  forceEmergencyBypassWindowStart: numberOr(r.force_emergency_bypass_window_start, 0),
153434
- forceEmergencyBypassUsed: numberOr(r.force_emergency_bypass_used, 0)
153463
+ forceEmergencyBypassUsed: numberOr(r.force_emergency_bypass_used, 0),
153464
+ emergencyDrainActive: numberOr(r.emergency_drain_active, 0),
153465
+ historianDrainFailureAt: numberOr(r.historian_drain_failure_at, 0)
153435
153466
  };
153436
153467
  }
153437
153468
  function loadProtectedTailMeta(db, sessionId) {
@@ -153439,7 +153470,7 @@ function loadProtectedTailMeta(db, sessionId) {
153439
153470
  const row = db.prepare(`SELECT prior_boundary_ordinal, protected_tail_policy_version,
153440
153471
  protected_tail_drain_window_started_at, protected_tail_drain_tokens,
153441
153472
  recovery_no_eligible_head_count, force_emergency_bypass_window_start,
153442
- force_emergency_bypass_used
153473
+ force_emergency_bypass_used, emergency_drain_active, historian_drain_failure_at
153443
153474
  FROM session_meta WHERE session_id = ?`).get(sessionId);
153444
153475
  return toProtectedTailMeta(row);
153445
153476
  }
@@ -153488,6 +153519,12 @@ function protectedTailWindowBudget(usagePercentage, usable, perRunCap) {
153488
153519
  return Math.min(750000, Math.max(3 * perRunCap, Math.round(0.35 * usable)));
153489
153520
  return Math.min(500000, Math.max(perRunCap, Math.round(0.2 * usable)));
153490
153521
  }
153522
+ function emergencyDrainExitThreshold(executeThresholdPercentage) {
153523
+ if (!Number.isFinite(executeThresholdPercentage) || executeThresholdPercentage <= 0) {
153524
+ return EMERGENCY_DRAIN_FALLBACK_EXIT_PERCENTAGE;
153525
+ }
153526
+ return Math.max(0, executeThresholdPercentage - EMERGENCY_DRAIN_EXIT_MARGIN);
153527
+ }
153491
153528
  function reserveProtectedTailDrainTokens(args) {
153492
153529
  const now = args.now ?? Date.now();
153493
153530
  const requested = Math.max(0, Math.floor(args.trueRawTokens));
@@ -153506,18 +153543,30 @@ function reserveProtectedTailDrainTokens(args) {
153506
153543
  let meta3 = loadProtectedTailMeta(args.db, args.sessionId);
153507
153544
  if (now - meta3.protectedTailDrainWindowStartedAt > DRAIN_WINDOW_MS) {
153508
153545
  args.db.prepare(`UPDATE session_meta
153509
- SET protected_tail_drain_window_started_at = ?, protected_tail_drain_tokens = 0,
153510
- force_emergency_bypass_window_start = ?, force_emergency_bypass_used = 0
153511
- WHERE session_id = ?`).run(now, now, args.sessionId);
153546
+ SET protected_tail_drain_window_started_at = ?, protected_tail_drain_tokens = 0
153547
+ WHERE session_id = ?`).run(now, args.sessionId);
153512
153548
  meta3 = loadProtectedTailMeta(args.db, args.sessionId);
153513
153549
  }
153550
+ const exitThreshold = emergencyDrainExitThreshold(args.executeThresholdPercentage);
153551
+ let latchActiveSince = meta3.emergencyDrainActive;
153552
+ if (args.usagePercentage >= EMERGENCY_DRAIN_ENTER_PERCENTAGE) {
153553
+ if (latchActiveSince <= 0)
153554
+ latchActiveSince = now;
153555
+ } else if (latchActiveSince > 0) {
153556
+ const expired = now - latchActiveSince > EMERGENCY_DRAIN_MAX_LATCH_MS;
153557
+ if (args.usagePercentage < exitThreshold || expired)
153558
+ latchActiveSince = 0;
153559
+ }
153560
+ if (latchActiveSince !== meta3.emergencyDrainActive) {
153561
+ args.db.prepare("UPDATE session_meta SET emergency_drain_active = ? WHERE session_id = ?").run(latchActiveSince, args.sessionId);
153562
+ }
153563
+ const latchActive = latchActiveSince > 0;
153514
153564
  const budget = protectedTailWindowBudget(args.usagePercentage, args.usable, args.perRunCap);
153515
153565
  const remaining = Math.max(0, budget - meta3.protectedTailDrainTokens);
153516
153566
  let reserved = Math.min(requested, args.perRunCap, remaining);
153517
153567
  let bypass = false;
153518
- const bypassWindowExpired = now - meta3.forceEmergencyBypassWindowStart > DRAIN_WINDOW_MS;
153519
- const bypassUsed = bypassWindowExpired ? 0 : meta3.forceEmergencyBypassUsed;
153520
- if (reserved <= 0 && args.usagePercentage >= 95 && bypassUsed === 0) {
153568
+ const inFailureBackoff = meta3.historianDrainFailureAt > 0 && now - meta3.historianDrainFailureAt < EMERGENCY_DRAIN_FAILURE_BACKOFF_MS;
153569
+ if (reserved <= 0 && latchActive && !inFailureBackoff) {
153521
153570
  reserved = Math.min(requested, args.perRunCap);
153522
153571
  bypass = true;
153523
153572
  }
@@ -153525,10 +153574,8 @@ function reserveProtectedTailDrainTokens(args) {
153525
153574
  return;
153526
153575
  args.db.prepare(`UPDATE session_meta
153527
153576
  SET protected_tail_drain_window_started_at = CASE WHEN protected_tail_drain_window_started_at = 0 THEN ? ELSE protected_tail_drain_window_started_at END,
153528
- protected_tail_drain_tokens = COALESCE(protected_tail_drain_tokens, 0) + ?,
153529
- force_emergency_bypass_window_start = CASE WHEN ? THEN ? ELSE force_emergency_bypass_window_start END,
153530
- force_emergency_bypass_used = CASE WHEN ? THEN 1 ELSE force_emergency_bypass_used END
153531
- WHERE session_id = ?`).run(now, reserved, bypass ? 1 : 0, now, bypass ? 1 : 0, args.sessionId);
153577
+ protected_tail_drain_tokens = COALESCE(protected_tail_drain_tokens, 0) + ?
153578
+ WHERE session_id = ?`).run(now, reserved, args.sessionId);
153532
153579
  result = {
153533
153580
  ok: true,
153534
153581
  reservedTokens: reserved,
@@ -153538,6 +153585,25 @@ function reserveProtectedTailDrainTokens(args) {
153538
153585
  })();
153539
153586
  return result;
153540
153587
  }
153588
+ function clearEmergencyDrainLatch(db, sessionId) {
153589
+ db.transaction(() => {
153590
+ ensureSessionMetaRow(db, sessionId);
153591
+ db.prepare("UPDATE session_meta SET emergency_drain_active = 0 WHERE session_id = ?").run(sessionId);
153592
+ })();
153593
+ }
153594
+ function recordHistorianDrainFailure(db, sessionId, now) {
153595
+ const ts = now ?? Date.now();
153596
+ db.transaction(() => {
153597
+ ensureSessionMetaRow(db, sessionId);
153598
+ db.prepare("UPDATE session_meta SET historian_drain_failure_at = ? WHERE session_id = ?").run(ts, sessionId);
153599
+ })();
153600
+ }
153601
+ function clearHistorianDrainFailure(db, sessionId) {
153602
+ db.transaction(() => {
153603
+ ensureSessionMetaRow(db, sessionId);
153604
+ db.prepare("UPDATE session_meta SET historian_drain_failure_at = 0 WHERE session_id = ?").run(sessionId);
153605
+ })();
153606
+ }
153541
153607
  function rollbackProtectedTailDrainReservation(db, reservation) {
153542
153608
  if (!reservation || reservation.tokens <= 0)
153543
153609
  return;
@@ -154105,7 +154171,7 @@ function setSessionWorkMetrics(db, sessionId, newWorkTokens, totalInputTokens) {
154105
154171
  SET new_work_tokens = ?, total_input_tokens = ?
154106
154172
  WHERE session_id = ?`).run(Math.max(0, Math.floor(newWorkTokens)), Math.max(0, Math.floor(totalInputTokens)), sessionId);
154107
154173
  }
154108
- var CAS_RETRY_LIMIT = 5, AUTO_SEARCH_NO_HINT_REASONS, DEFAULT_PROTECTED_TAIL_META, DRAIN_WINDOW_MS;
154174
+ var CAS_RETRY_LIMIT = 5, AUTO_SEARCH_NO_HINT_REASONS, DEFAULT_PROTECTED_TAIL_META, DRAIN_WINDOW_MS, EMERGENCY_DRAIN_ENTER_PERCENTAGE = 95, EMERGENCY_DRAIN_EXIT_MARGIN = 10, EMERGENCY_DRAIN_FALLBACK_EXIT_PERCENTAGE = 55, EMERGENCY_DRAIN_FAILURE_BACKOFF_MS = 60000, EMERGENCY_DRAIN_MAX_LATCH_MS;
154109
154175
  var init_storage_meta_persisted = __esm(() => {
154110
154176
  init_logger();
154111
154177
  init_storage_meta_shared();
@@ -154124,9 +154190,12 @@ var init_storage_meta_persisted = __esm(() => {
154124
154190
  protectedTailDrainTokens: 0,
154125
154191
  recoveryNoEligibleHeadCount: 0,
154126
154192
  forceEmergencyBypassWindowStart: 0,
154127
- forceEmergencyBypassUsed: 0
154193
+ forceEmergencyBypassUsed: 0,
154194
+ emergencyDrainActive: 0,
154195
+ historianDrainFailureAt: 0
154128
154196
  };
154129
154197
  DRAIN_WINDOW_MS = 10 * 60 * 1000;
154198
+ EMERGENCY_DRAIN_MAX_LATCH_MS = 30 * 60 * 1000;
154130
154199
  });
154131
154200
 
154132
154201
  // src/features/magic-context/resolve-subagent-fallback.ts
@@ -154244,6 +154313,7 @@ function clearSession(db, sessionId) {
154244
154313
  db.prepare("DELETE FROM subagent_invocations WHERE session_id = ?").run(sessionId);
154245
154314
  db.prepare("DELETE FROM historian_runs WHERE session_id = ?").run(sessionId);
154246
154315
  db.prepare("DELETE FROM plugin_messages WHERE session_id = ?").run(sessionId);
154316
+ db.prepare("DELETE FROM transform_decisions WHERE session_id = ?").run(sessionId);
154247
154317
  clearIndexedMessages(db, sessionId);
154248
154318
  })();
154249
154319
  }
@@ -154689,12 +154759,17 @@ function getOldestActiveUnprotectedToolTags(db, sessionId, protectedTags = 0, li
154689
154759
  toolName: typeof row.tool_name === "string" ? row.tool_name : null
154690
154760
  }));
154691
154761
  }
154692
- function getTriggerTagTokenUpperBound(db, sessionId) {
154693
- const row = db.prepare(`SELECT
154762
+ function getTriggerTagTokenUpperBound(db, sessionId, floor = 0) {
154763
+ const sql = floor > 0 ? `SELECT
154694
154764
  COALESCE(SUM(COALESCE(token_count, 0) + COALESCE(input_token_count, 0) + COALESCE(reasoning_token_count, 0)), 0) AS bound,
154695
154765
  COALESCE(SUM(CASE WHEN token_count IS NULL THEN 1 ELSE 0 END), 0) AS null_count
154696
154766
  FROM tags
154697
- WHERE session_id = ? AND status IN ('active', 'dropped')`).get(sessionId);
154767
+ WHERE session_id = ? AND status IN ('active', 'dropped') AND tag_number >= ?` : `SELECT
154768
+ COALESCE(SUM(COALESCE(token_count, 0) + COALESCE(input_token_count, 0) + COALESCE(reasoning_token_count, 0)), 0) AS bound,
154769
+ COALESCE(SUM(CASE WHEN token_count IS NULL THEN 1 ELSE 0 END), 0) AS null_count
154770
+ FROM tags
154771
+ WHERE session_id = ? AND status IN ('active', 'dropped')`;
154772
+ const row = floor > 0 ? db.prepare(sql).get(sessionId, floor) : db.prepare(sql).get(sessionId);
154698
154773
  return { bound: row?.bound ?? 0, nullCount: row?.null_count ?? 0 };
154699
154774
  }
154700
154775
  function getActiveTagTokenTotalsByMessage(db, sessionId) {
@@ -154723,10 +154798,12 @@ function getActiveTagTokenTotalsByMessage(db, sessionId) {
154723
154798
  }
154724
154799
  return out;
154725
154800
  }
154726
- function getAllStatusTagTokenTotalsFlat(db, sessionId) {
154727
- const rows = db.prepare(`SELECT type, message_id, tool_owner_message_id, token_count, input_token_count, reasoning_token_count
154728
- FROM tags
154729
- WHERE session_id = ?`).all(sessionId);
154801
+ function getAllStatusTagTokenTotalsFlat(db, sessionId, floor = 0) {
154802
+ const rows = floor > 0 ? db.prepare(`SELECT type, message_id, tool_owner_message_id, token_count, input_token_count, reasoning_token_count
154803
+ FROM tags
154804
+ WHERE session_id = ? AND tag_number >= ?`).all(sessionId, floor) : db.prepare(`SELECT type, message_id, tool_owner_message_id, token_count, input_token_count, reasoning_token_count
154805
+ FROM tags
154806
+ WHERE session_id = ?`).all(sessionId);
154730
154807
  const totals = new Map;
154731
154808
  const nullMessageIds = new Set;
154732
154809
  for (const row of rows) {
@@ -154885,6 +154962,47 @@ function getTagNumberByMessageId(db, sessionId, messageId) {
154885
154962
  const row = getTagNumberByMessageIdStatement(db).get(sessionId, messageId);
154886
154963
  return isTagNumberRow(row) ? row.tag_number : null;
154887
154964
  }
154965
+ function isMinTagNumberRow(row) {
154966
+ return row !== null && typeof row === "object" && "m" in row;
154967
+ }
154968
+ function getMinMessageTagNumberForRawId(db, sessionId, rawId) {
154969
+ if (rawId.includes(":"))
154970
+ return null;
154971
+ let stmt = getMinMessageTagNumberForRawIdStatements.get(db);
154972
+ if (!stmt) {
154973
+ stmt = db.prepare("SELECT MIN(tag_number) AS m FROM tags WHERE session_id = ? AND message_id >= ? AND message_id < ?");
154974
+ getMinMessageTagNumberForRawIdStatements.set(db, stmt);
154975
+ }
154976
+ const row = stmt.get(sessionId, `${rawId}:`, `${rawId};`);
154977
+ return isMinTagNumberRow(row) && typeof row.m === "number" ? row.m : null;
154978
+ }
154979
+ function deriveTagLoadFloor(db, sessionId, rawIds) {
154980
+ let min = Number.POSITIVE_INFINITY;
154981
+ let probes = 0;
154982
+ let hits = 0;
154983
+ let skippedBeforeFirstHit = 0;
154984
+ for (const rawId of rawIds) {
154985
+ if (typeof rawId !== "string" || rawId.length === 0)
154986
+ continue;
154987
+ if (probes >= TAGGER_FLOOR_MAX_PROBES)
154988
+ break;
154989
+ probes++;
154990
+ const m = getMinMessageTagNumberForRawId(db, sessionId, rawId);
154991
+ if (m === null) {
154992
+ if (hits === 0)
154993
+ skippedBeforeFirstHit++;
154994
+ continue;
154995
+ }
154996
+ if (m < min)
154997
+ min = m;
154998
+ if (++hits >= TAGGER_FLOOR_SCAN_MESSAGES)
154999
+ break;
155000
+ }
155001
+ if (!Number.isFinite(min))
155002
+ return 0;
155003
+ const margin = TAGGER_FLOOR_SAFETY_MARGIN + skippedBeforeFirstHit * TAGGER_FLOOR_PER_SKIP_MARGIN;
155004
+ return Math.max(0, min - margin);
155005
+ }
154888
155006
  function getTagsBySession(db, sessionId) {
154889
155007
  const rows = db.prepare(`SELECT ${TAG_SELECT_COLUMNS} FROM tags WHERE session_id = ? ORDER BY tag_number ASC, id ASC`).all(sessionId).filter(isTagRow);
154890
155008
  return rows.map(toTagEntry);
@@ -155023,7 +155141,7 @@ function deleteToolTagsByOwner(db, sessionId, ownerMsgId) {
155023
155141
  const result = getDeleteToolTagsByOwnerStatement(db).run(sessionId, ownerMsgId);
155024
155142
  return result.changes ?? 0;
155025
155143
  }
155026
- var insertTagStatements, updateTagStatusStatements, updateTagDropModeStatements, updateTagMessageIdStatements, getTagNumbersByMessageIdStatements, deleteTagsByMessageIdStatements, getMaxTagNumberBySessionStatements, getTagNumberByMessageIdStatements, updateTagByteSizeStatements, updateTagInputByteSizeStatements, CONTENT_ID_SUFFIX, updateTagTokenCountStatements, updateTagInputTokenCountStatements, getOwnerScopedToolTagNumbersStatements, TAG_SELECT_COLUMNS = "id, message_id, type, status, drop_mode, tool_name, input_byte_size, byte_size, reasoning_byte_size, session_id, tag_number, caveman_depth, tool_owner_message_id", getActiveTagsBySessionStatements, getMaxDroppedTagNumberStatements, getToolTagNumberByOwnerStatements, getNullOwnerToolTagStatements, adoptNullOwnerToolTagStatements, deleteToolTagsByOwnerStatements;
155144
+ var insertTagStatements, updateTagStatusStatements, updateTagDropModeStatements, updateTagMessageIdStatements, getTagNumbersByMessageIdStatements, deleteTagsByMessageIdStatements, getMaxTagNumberBySessionStatements, getTagNumberByMessageIdStatements, updateTagByteSizeStatements, updateTagInputByteSizeStatements, CONTENT_ID_SUFFIX, updateTagTokenCountStatements, updateTagInputTokenCountStatements, getOwnerScopedToolTagNumbersStatements, getMinMessageTagNumberForRawIdStatements, TAGGER_FLOOR_SCAN_MESSAGES = 8, TAGGER_FLOOR_MAX_PROBES = 64, TAGGER_FLOOR_SAFETY_MARGIN = 256, TAGGER_FLOOR_PER_SKIP_MARGIN = 64, TAG_SELECT_COLUMNS = "id, message_id, type, status, drop_mode, tool_name, input_byte_size, byte_size, reasoning_byte_size, session_id, tag_number, caveman_depth, tool_owner_message_id", getActiveTagsBySessionStatements, getMaxDroppedTagNumberStatements, getToolTagNumberByOwnerStatements, getNullOwnerToolTagStatements, adoptNullOwnerToolTagStatements, deleteToolTagsByOwnerStatements;
155027
155145
  var init_storage_tags = __esm(() => {
155028
155146
  insertTagStatements = new WeakMap;
155029
155147
  updateTagStatusStatements = new WeakMap;
@@ -155039,6 +155157,7 @@ var init_storage_tags = __esm(() => {
155039
155157
  updateTagTokenCountStatements = new WeakMap;
155040
155158
  updateTagInputTokenCountStatements = new WeakMap;
155041
155159
  getOwnerScopedToolTagNumbersStatements = new WeakMap;
155160
+ getMinMessageTagNumberForRawIdStatements = new WeakMap;
155042
155161
  getActiveTagsBySessionStatements = new WeakMap;
155043
155162
  getMaxDroppedTagNumberStatements = new WeakMap;
155044
155163
  getToolTagNumberByOwnerStatements = new WeakMap;
@@ -165459,6 +165578,16 @@ function buildCanonicalChunkTextFromFts(db, sessionId, startOrdinal, endOrdinal)
165459
165578
  return lines.join(`
165460
165579
  `);
165461
165580
  }
165581
+ function buildCompartmentSummaryFallbackText(db, compartmentId) {
165582
+ const row = db.prepare("SELECT title, p1, content FROM compartments WHERE id = ?").get(compartmentId);
165583
+ if (!row)
165584
+ return "";
165585
+ const title = typeof row.title === "string" ? row.title.trim() : "";
165586
+ const p1 = typeof row.p1 === "string" ? row.p1.trim() : "";
165587
+ const body = p1.length > 0 ? p1 : typeof row.content === "string" ? row.content.trim() : "";
165588
+ return [title, body].filter((s) => s.length > 0).join(`
165589
+ `);
165590
+ }
165462
165591
  function canonicalizeInMemoryChunkTextForEmbedding(chunkText, startOrdinal, endOrdinal) {
165463
165592
  const lines = [];
165464
165593
  for (const rawLine of chunkText.split(/\r?\n/)) {
@@ -166056,7 +166185,7 @@ class LocalEmbeddingProvider {
166056
166185
  waiter();
166057
166186
  }
166058
166187
  }
166059
- async embed(text, signal) {
166188
+ async embed(text, signal, _purpose) {
166060
166189
  if (signal?.aborted)
166061
166190
  return null;
166062
166191
  if (this.disposing)
@@ -166082,7 +166211,7 @@ class LocalEmbeddingProvider {
166082
166211
  this.finishInFlight();
166083
166212
  }
166084
166213
  }
166085
- async embedBatch(texts, signal) {
166214
+ async embedBatch(texts, signal, _purpose) {
166086
166215
  if (texts.length === 0) {
166087
166216
  return [];
166088
166217
  }
@@ -166226,6 +166355,7 @@ class OpenAICompatibleEmbeddingProvider {
166226
166355
  model;
166227
166356
  apiKey;
166228
166357
  inputType;
166358
+ queryInputType;
166229
166359
  truncate;
166230
166360
  initialized = false;
166231
166361
  failureTimes = [];
@@ -166238,6 +166368,7 @@ class OpenAICompatibleEmbeddingProvider {
166238
166368
  this.model = options.model?.trim() ?? "";
166239
166369
  this.apiKey = options.apiKey?.trim() ?? "";
166240
166370
  this.inputType = options.inputType?.trim() ?? "";
166371
+ this.queryInputType = options.queryInputType?.trim() ?? "";
166241
166372
  this.truncate = options.truncate?.trim() ?? "";
166242
166373
  this.maxInputTokens = typeof options.maxInputTokens === "number" && Number.isFinite(options.maxInputTokens) ? Math.max(1, Math.floor(options.maxInputTokens)) : 512;
166243
166374
  this.modelId = getEmbeddingProviderIdentity({
@@ -166265,11 +166396,17 @@ class OpenAICompatibleEmbeddingProvider {
166265
166396
  this.initialized = true;
166266
166397
  return true;
166267
166398
  }
166268
- async embed(text, signal) {
166269
- const [embedding] = await this.embedBatch([text], signal);
166399
+ resolveInputTypeForPurpose(purpose = "passage") {
166400
+ if (purpose === "query") {
166401
+ return this.queryInputType || this.inputType;
166402
+ }
166403
+ return this.inputType;
166404
+ }
166405
+ async embed(text, signal, purpose) {
166406
+ const [embedding] = await this.embedBatch([text], signal, purpose);
166270
166407
  return embedding ?? null;
166271
166408
  }
166272
- async embedBatch(texts, signal) {
166409
+ async embedBatch(texts, signal, purpose) {
166273
166410
  if (texts.length === 0) {
166274
166411
  return [];
166275
166412
  }
@@ -166295,6 +166432,7 @@ class OpenAICompatibleEmbeddingProvider {
166295
166432
  if (signal) {
166296
166433
  signal.addEventListener("abort", onOuterAbort, { once: true });
166297
166434
  }
166435
+ const inputTypeForRequest = this.resolveInputTypeForPurpose(purpose);
166298
166436
  const response = await fetch(`${this.endpoint}/embeddings`, {
166299
166437
  method: "POST",
166300
166438
  headers: {
@@ -166304,7 +166442,7 @@ class OpenAICompatibleEmbeddingProvider {
166304
166442
  body: JSON.stringify({
166305
166443
  model: this.model,
166306
166444
  input: texts,
166307
- ...this.inputType ? { input_type: this.inputType } : {},
166445
+ ...inputTypeForRequest ? { input_type: inputTypeForRequest } : {},
166308
166446
  ...this.truncate ? { truncate: this.truncate } : {}
166309
166447
  }),
166310
166448
  redirect: "error",
@@ -166881,6 +167019,7 @@ function resolveEmbeddingConfig(config2) {
166881
167019
  if (config2.provider === "openai-compatible") {
166882
167020
  const apiKey = config2.api_key?.trim();
166883
167021
  const inputType = config2.input_type?.trim();
167022
+ const queryInputType = config2.query_input_type?.trim();
166884
167023
  const truncate = config2.truncate?.trim();
166885
167024
  return {
166886
167025
  provider: "openai-compatible",
@@ -166888,6 +167027,7 @@ function resolveEmbeddingConfig(config2) {
166888
167027
  endpoint: config2.endpoint.trim(),
166889
167028
  ...apiKey ? { api_key: apiKey } : {},
166890
167029
  ...inputType ? { input_type: inputType } : {},
167030
+ ...queryInputType ? { query_input_type: queryInputType } : {},
166891
167031
  ...truncate ? { truncate } : {},
166892
167032
  ...config2.max_input_tokens ? {
166893
167033
  max_input_tokens: normalizeCompartmentChunkMaxInputTokens(config2.max_input_tokens)
@@ -166909,6 +167049,7 @@ function createProvider(config2) {
166909
167049
  model: config2.model,
166910
167050
  apiKey: config2.api_key,
166911
167051
  inputType: config2.input_type,
167052
+ queryInputType: config2.query_input_type,
166912
167053
  truncate: config2.truncate,
166913
167054
  maxInputTokens: config2.max_input_tokens
166914
167055
  });
@@ -167091,7 +167232,7 @@ function getOrCreateProjectProvider(registration) {
167091
167232
  registration.provider = provider;
167092
167233
  return provider;
167093
167234
  }
167094
- async function embedTextForProject(projectIdentity, text, signal) {
167235
+ async function embedTextForProject(projectIdentity, text, signal, purpose = "passage") {
167095
167236
  const registration = projectRegistrations.get(projectIdentity);
167096
167237
  if (!registration)
167097
167238
  return null;
@@ -167100,7 +167241,7 @@ async function embedTextForProject(projectIdentity, text, signal) {
167100
167241
  const provider = getOrCreateProjectProvider(registration);
167101
167242
  if (!provider)
167102
167243
  return null;
167103
- const vector = await provider.embed(text, signal);
167244
+ const vector = await provider.embed(text, signal, purpose);
167104
167245
  if (!vector)
167105
167246
  return null;
167106
167247
  const current = projectRegistrations.get(projectIdentity);
@@ -167109,7 +167250,7 @@ async function embedTextForProject(projectIdentity, text, signal) {
167109
167250
  }
167110
167251
  return { vector, modelId, generation };
167111
167252
  }
167112
- async function embedBatchForProject(projectIdentity, texts, signal) {
167253
+ async function embedBatchForProject(projectIdentity, texts, signal, purpose = "passage") {
167113
167254
  if (texts.length === 0) {
167114
167255
  const registration2 = projectRegistrations.get(projectIdentity);
167115
167256
  if (!registration2 || registration2.observationMode)
@@ -167125,7 +167266,7 @@ async function embedBatchForProject(projectIdentity, texts, signal) {
167125
167266
  const provider = getOrCreateProjectProvider(registration);
167126
167267
  if (!provider)
167127
167268
  return null;
167128
- const vectors = await provider.embedBatch(texts, signal);
167269
+ const vectors = await provider.embedBatch(texts, signal, purpose);
167129
167270
  const current = projectRegistrations.get(projectIdentity);
167130
167271
  if (!current || current.generation !== generation || current.runtimeFingerprint !== runtimeFingerprint) {
167131
167272
  return null;
@@ -167182,7 +167323,7 @@ async function embedCandidateChunkBatch(db, projectIdentity, modelId, candidates
167182
167323
  const maxInputTokens = getProjectEmbeddingMaxInputTokens(projectIdentity);
167183
167324
  const prepared = [];
167184
167325
  for (const candidate of candidates) {
167185
- const canonicalText = buildCanonicalChunkTextFromFts(db, candidate.sessionId, candidate.startMessage, candidate.endMessage);
167326
+ const canonicalText = buildCanonicalChunkTextFromFts(db, candidate.sessionId, candidate.startMessage, candidate.endMessage) || buildCompartmentSummaryFallbackText(db, candidate.id);
167186
167327
  if (canonicalText.length === 0) {
167187
167328
  noWork.push(candidate.id);
167188
167329
  continue;
@@ -167403,6 +167544,7 @@ function createProvider2(config2) {
167403
167544
  model: config2.model,
167404
167545
  apiKey: config2.api_key,
167405
167546
  inputType: config2.input_type,
167547
+ queryInputType: config2.query_input_type,
167406
167548
  truncate: config2.truncate,
167407
167549
  maxInputTokens: config2.max_input_tokens
167408
167550
  });
@@ -167667,7 +167809,7 @@ async function embedAndStoreCompartmentChunks(db, sessionId, projectPath, compar
167667
167809
  for (const compartment of compartments) {
167668
167810
  try {
167669
167811
  const fromMemory = compartment.sourceChunkText ? canonicalizeInMemoryChunkTextForEmbedding(compartment.sourceChunkText, compartment.startMessage, compartment.endMessage) : "";
167670
- const canonicalText = fromMemory || buildCanonicalChunkTextFromFts(db, sessionId, compartment.startMessage, compartment.endMessage);
167812
+ const canonicalText = fromMemory || buildCanonicalChunkTextFromFts(db, sessionId, compartment.startMessage, compartment.endMessage) || buildCompartmentSummaryFallbackText(db, compartment.id);
167671
167813
  if (canonicalText.length === 0)
167672
167814
  continue;
167673
167815
  const windows = chunkCanonicalText(canonicalText, compartment.startMessage, compartment.endMessage, maxInputTokens);
@@ -170867,29 +171009,12 @@ function resolveHistorianContextLimit(historianModelOverride) {
170867
171009
  return DEFAULT_HISTORIAN_CONTEXT_FALLBACK;
170868
171010
  }
170869
171011
  if (typeof historianModelOverride === "string" && historianModelOverride.trim() !== "") {
170870
- console.warn(`[magic-context] historian.model "${historianModelOverride}" lacks provider prefix ("provider/model-id"); using fallback chain for chunk-budget derivation.`);
170871
- }
170872
- const chain = AGENT_MODEL_REQUIREMENTS[HISTORIAN_AGENT]?.fallbackChain;
170873
- if (!chain || chain.length === 0)
170874
- return DEFAULT_HISTORIAN_CONTEXT_FALLBACK;
170875
- const expanded = expandFallbackChain(chain);
170876
- let minLimit;
170877
- for (const key of expanded) {
170878
- const [providerID, ...rest] = key.split("/");
170879
- const modelID = rest.join("/");
170880
- if (!providerID || !modelID)
170881
- continue;
170882
- const limit = getSdkContextLimit(providerID, modelID);
170883
- if (typeof limit !== "number" || limit <= 0)
170884
- continue;
170885
- if (minLimit === undefined || limit < minLimit)
170886
- minLimit = limit;
171012
+ console.warn(`[magic-context] historian.model "${historianModelOverride}" lacks provider prefix ("provider/model-id"); using the default context limit for chunk-budget derivation.`);
170887
171013
  }
170888
- return minLimit ?? DEFAULT_HISTORIAN_CONTEXT_FALLBACK;
171014
+ return DEFAULT_HISTORIAN_CONTEXT_FALLBACK;
170889
171015
  }
170890
171016
  var TRIGGER_BUDGET_PERCENTAGE = 0.05, TRIGGER_BUDGET_MIN = 5000, TRIGGER_BUDGET_MAX = 50000, HISTORIAN_CHUNK_PERCENTAGE = 0.25, HISTORIAN_CHUNK_MIN = 8000, HISTORIAN_CHUNK_MAX = 50000, DEFAULT_HISTORIAN_CONTEXT_FALLBACK = 128000;
170891
171017
  var init_derive_budgets = __esm(() => {
170892
- init_model_requirements();
170893
171018
  init_models_dev_cache();
170894
171019
  });
170895
171020
 
@@ -171689,7 +171814,7 @@ function resolveBoundaryContext(args) {
171689
171814
  }
171690
171815
  let storedTokenTotals;
171691
171816
  try {
171692
- storedTokenTotals = getAllStatusTagTokenTotalsFlat(args.db, args.sessionId).totals;
171817
+ storedTokenTotals = getAllStatusTagTokenTotalsFlat(args.db, args.sessionId, args.taggerFloor ?? 0).totals;
171693
171818
  } catch (error51) {
171694
171819
  sessionLog(args.sessionId, "protected-tail stored-token map unavailable (live fallback):", error51);
171695
171820
  }
@@ -173893,6 +174018,7 @@ async function runCompartmentAgent(deps) {
173893
174018
  const count = recordHighPressureNoEligibleHead(db, boundarySnapshot);
173894
174019
  sessionLog(sessionId, `historian high-pressure no-op: recovery remains armed (noEligibleHeadCount=${count})`);
173895
174020
  }
174021
+ clearEmergencyDrainLatch(db, sessionId);
173896
174022
  telemetry.status = "noop";
173897
174023
  telemetry.failureReason = "nothing to compact before protected tail";
173898
174024
  rollbackDrainReservation();
@@ -173907,7 +174033,8 @@ async function runCompartmentAgent(deps) {
173907
174033
  trueRawTokens: boundarySnapshot.trueRawEligibleTokens,
173908
174034
  usagePercentage: boundarySnapshot.usagePercentage,
173909
174035
  usable,
173910
- perRunCap
174036
+ perRunCap,
174037
+ executeThresholdPercentage: boundarySnapshot.executeThresholdPercentage
173911
174038
  });
173912
174039
  if (!reserve.ok) {
173913
174040
  sessionLog(sessionId, `historian rate-limit skip: ${reserve.skippedReason ?? "quota exhausted"}`);
@@ -173926,6 +174053,7 @@ async function runCompartmentAgent(deps) {
173926
174053
  } else {
173927
174054
  recordHighPressureNoEligibleHead(db, boundarySnapshot);
173928
174055
  }
174056
+ clearEmergencyDrainLatch(db, sessionId);
173929
174057
  telemetry.status = "noop";
173930
174058
  telemetry.failureReason = "chunk empty after filtering";
173931
174059
  rollbackDrainReservation();
@@ -174033,6 +174161,7 @@ ${chunkText}`,
174033
174161
  }
174034
174162
  appendCompartments(db, sessionId, persistedCompartments);
174035
174163
  clearHistorianFailureState(db, sessionId);
174164
+ clearHistorianDrainFailure(db, sessionId);
174036
174165
  recordProtectedTailPublicationFloor(db, sessionId, lastCompartmentEnd + 1);
174037
174166
  clearEmergencyRecovery(db, sessionId);
174038
174167
  drainReservation = null;
@@ -174136,8 +174265,11 @@ ${chunkText}`,
174136
174265
  }
174137
174266
  } finally {
174138
174267
  if (!completedSuccessfully) {
174139
- if (!retainDrainReservationForRetryThrottle)
174268
+ if (!retainDrainReservationForRetryThrottle) {
174140
174269
  rollbackDrainReservation();
174270
+ } else {
174271
+ recordHistorianDrainFailure(db, sessionId);
174272
+ }
174141
174273
  updateSessionMeta(db, sessionId, { compartmentInProgress: false });
174142
174274
  }
174143
174275
  recordTelemetry();
@@ -177279,7 +177411,6 @@ var init_memory_migration = __esm(async () => {
177279
177411
  init_shared();
177280
177412
  init_assistant_message_extractor();
177281
177413
  init_logger();
177282
- init_resolve_fallbacks();
177283
177414
  init_project_identity();
177284
177415
  init_storage_memory();
177285
177416
  await init_storage();
@@ -177595,15 +177726,15 @@ function shouldShowAnnouncement() {
177595
177726
  }
177596
177727
  return state.version !== ANNOUNCEMENT_VERSION;
177597
177728
  }
177598
- var ANNOUNCEMENT_VERSION = "0.25.0", ANNOUNCEMENT_FEATURES, ANNOUNCEMENT_FOOTER = "Join us on Discord: https://discord.gg/F2uWxjGnU", STATE_FILENAME = "last_announced_version";
177729
+ var ANNOUNCEMENT_VERSION = "0.26.0", ANNOUNCEMENT_FEATURES, ANNOUNCEMENT_FOOTER = "Join us on Discord: https://discord.gg/F2uWxjGnU", STATE_FILENAME = "last_announced_version";
177599
177730
  var init_announcement = __esm(() => {
177600
177731
  init_data_path();
177601
177732
  ANNOUNCEMENT_FEATURES = [
177602
- "Old tool output is now reclaimed automatically: once a file read / search / command output has gone a full execute cycle unused, it's dropped on the next one — no need to call ctx_reduce for stale results.",
177603
- "Recover anything that was dropped: ctx_expand({ message: N }) returns a dropped message's full content (every tool call's input + output) from storage. ctx_expand({ start, end, verbose: true }) lists a range message-by-message to find it.",
177604
- "Searchable history made reliable: /ctx-embed shows embedding coverage and runs a resilient backfill (retries transient failures, no longer bails on the first hiccup); the active session now auto-embeds in the background. ctx_reduce guidance also reframed as deferred + recoverable so models trim spent output earlier.",
177605
- "Pi: fixed /ctx-dream (was failing with 'Unknown named parameter') and local-embedding load failures on Windows/Desktop (#151, #128).",
177606
- "Runaway background agents on weak/local models are now capped and force-stopped (#154, #152). Plus several prompt-cache busts removed."
177733
+ "Faster on large sessions: per-message transform overhead is at least 2x lower on typical passes and up to ~10x lower when history summarization fires (no more multi-second pause on big sessions).",
177734
+ "No more surprise models: the built-in fallback chain is gone. Hidden agents only use the model (and fallback_models) you configure — no confusing 'model not found' for providers you never set up. `doctor` now records every historian run so real failures are visible.",
177735
+ "Anthropic thinking-block fix: clearing old reasoning no longer risks a stale-signature rejection on Claude / Bedrock / proxied-Claude routes. Plus fewer prompt-cache busts.",
177736
+ "Community fixes: TUI crash on the upgrade progress panel (#168), historian.disallowed_tools for weak models that loop on tool calls (#166), and a Pi-only config key leak (#167).",
177737
+ "New: doctor migrate-session re-homes a session (and optionally its memories) to another project, with a dry-run preview."
177607
177738
  ];
177608
177739
  });
177609
177740
 
@@ -177676,6 +177807,9 @@ var init_tui_config = __esm(() => {
177676
177807
  import_comment_json4 = __toESM(require_src2(), 1);
177677
177808
  PLUGIN_ENTRY = `${PLUGIN_NAME}@latest`;
177678
177809
  });
177810
+
177811
+ // src/agents/dreamer.ts
177812
+ var DREAMER_AGENT = "dreamer";
177679
177813
  // src/agents/permissions.ts
177680
177814
  function buildAllowOnlyPermission(allowedTools) {
177681
177815
  const permission = { "*": "deny" };
@@ -177685,6 +177819,11 @@ function buildAllowOnlyPermission(allowedTools) {
177685
177819
  return permission;
177686
177820
  }
177687
177821
  var HISTORIAN_ALLOWED_TOOLS = ["read", "aft_outline", "aft_zoom", "aft_search"];
177822
+ function applyDisallowedTools(defaults, disallowed) {
177823
+ if (disallowed.includes("*"))
177824
+ return [];
177825
+ return defaults.filter((t) => !disallowed.includes(t));
177826
+ }
177688
177827
  var DREAMER_ALLOWED_TOOLS = [
177689
177828
  "read",
177690
177829
  "grep",
@@ -177700,6 +177839,10 @@ var DREAMER_ALLOWED_TOOLS = [
177700
177839
  "ctx_note"
177701
177840
  ];
177702
177841
  var SIDEKICK_ALLOWED_TOOLS = ["ctx_search", "aft_outline", "aft_zoom"];
177842
+
177843
+ // src/agents/sidekick.ts
177844
+ var SIDEKICK_AGENT = "sidekick";
177845
+
177703
177846
  // src/config/index.ts
177704
177847
  init_jsonc_parser();
177705
177848
  import { existsSync as existsSync3, readFileSync as readFileSync3 } from "node:fs";
@@ -178649,6 +178792,7 @@ ${modeIntro}
178649
178792
  4. **Write or update** using the Write tool. Always write to project root, NOT to .planning/.
178650
178793
 
178651
178794
  ### Rules
178795
+ - **NEVER touch protected regions**: any content between \`<!-- mc:protected START ... -->\` and \`<!-- mc:protected END -->\` is hand-authored and cache-critical. Reproduce it BYTE-FOR-BYTE in your rewrite — do not edit, reword, reorder, summarize, trim, or drop a single line of it, and keep the marker comments themselves. Only a human edits that region.
178652
178796
  - **Be prescriptive**: "Use X pattern" not "X pattern is used"
178653
178797
  - **Always include file paths** in backticks
178654
178798
  - **Write current state only**: no temporal language, no history
@@ -178785,7 +178929,6 @@ init_project_identity();
178785
178929
  init_shared();
178786
178930
  init_assistant_message_extractor();
178787
178931
  init_logger();
178788
- init_resolve_fallbacks();
178789
178932
  init_subagent_token_capture();
178790
178933
  await init_storage();
178791
178934
 
@@ -178807,7 +178950,7 @@ function stripThinkingBlocks(text) {
178807
178950
 
178808
178951
  // src/features/magic-context/sidekick/agent.ts
178809
178952
  async function runSidekick(deps) {
178810
- const fallbackModels = resolveFallbackChain(SIDEKICK_AGENT, deps.config.fallback_models);
178953
+ const fallbackModels = resolveFallbackChain(deps.config.fallback_models);
178811
178954
  let agentSessionId = null;
178812
178955
  const startedAt = Date.now();
178813
178956
  let invocationRecorded = false;
@@ -178897,6 +179040,11 @@ init_project_identity();
178897
179040
  import { createHash as createHash6 } from "node:crypto";
178898
179041
  import { realpathSync as realpathSync2 } from "node:fs";
178899
179042
  import path5 from "node:path";
179043
+
179044
+ // src/features/magic-context/memory/relocate-memory.ts
179045
+ var memoryCopyColumnsCache = new WeakMap;
179046
+
179047
+ // src/features/magic-context/v22-deferred-backfill.ts
178900
179048
  var BATCH_SIZE = 25;
178901
179049
  var YIELD_EVERY_N_ROWS = 5;
178902
179050
  var BACKFILL_META_KEY = "v22_legacy_memory_backfill";
@@ -179731,6 +179879,7 @@ function createLiveSessionState() {
179731
179879
 
179732
179880
  // src/index.ts
179733
179881
  init_conflict_warning_hook();
179882
+
179734
179883
  // src/features/magic-context/dreamer/storage-dream-state.ts
179735
179884
  var getDreamStateStatements = new WeakMap;
179736
179885
  var setDreamStateStatements = new WeakMap;
@@ -179924,21 +180073,21 @@ function clearStaleEntries(db, maxAgeMs, projectIdentity) {
179924
180073
  return result.changes;
179925
180074
  }
179926
180075
  // src/features/magic-context/dreamer/runner.ts
180076
+ import { existsSync as existsSync13 } from "node:fs";
180077
+ import { join as join16 } from "node:path";
179927
180078
  init_shared();
179928
180079
  init_assistant_message_extractor();
179929
180080
  init_data_path();
179930
180081
  init_logger();
179931
180082
  await init_sqlite();
179932
- import { existsSync as existsSync13 } from "node:fs";
179933
- import { join as join16 } from "node:path";
179934
180083
 
179935
180084
  // src/features/magic-context/key-files/identify-key-files.ts
180085
+ import { readFileSync as readFileSync11 } from "node:fs";
180086
+ import { isAbsolute as isAbsolute4, join as join15, relative as relative2 } from "node:path";
179936
180087
  init_read_session_formatting();
179937
180088
  init_shared();
179938
180089
  init_assistant_message_extractor();
179939
180090
  init_logger();
179940
- import { readFileSync as readFileSync11 } from "node:fs";
179941
- import { isAbsolute as isAbsolute4, join as join15, relative as relative2 } from "node:path";
179942
180091
  init_subagent_token_capture();
179943
180092
  init_aft_availability();
179944
180093
  init_project_key_files();
@@ -181807,7 +181956,6 @@ init_sweep_coordinator();
181807
181956
  // src/plugin/dream-timer.ts
181808
181957
  init_embedding();
181809
181958
  init_logger();
181810
- init_resolve_fallbacks();
181811
181959
  await init_storage();
181812
181960
  var DREAM_TIMER_INTERVAL_MS = 15 * 60 * 1000;
181813
181961
  var activeTimer = null;
@@ -181910,7 +182058,7 @@ async function sweepProject(reg, origin, db, gitCommitEnabled = getProjectEmbedd
181910
182058
  experimentalPinKeyFiles: reg.experimentalPinKeyFiles,
181911
182059
  projectIdentity: reg.projectIdentity,
181912
182060
  sessionDirectoryOverride: reg.directory,
181913
- fallbackModels: resolveFallbackChain(DREAMER_AGENT, reg.dreamerConfig.fallback_models)
182061
+ fallbackModels: resolveFallbackChain(reg.dreamerConfig.fallback_models)
181914
182062
  });
181915
182063
  } catch (error51) {
181916
182064
  log(`[dreamer] timer-triggered queue processing failed for ${reg.projectIdentity}:`, error51);
@@ -182360,10 +182508,9 @@ function makeToolCompositeKey(ownerMsgId, callId) {
182360
182508
  }
182361
182509
  var GET_COUNTER_SQL = `SELECT counter FROM session_meta WHERE session_id = ?`;
182362
182510
  var GET_ASSIGNMENTS_SQL = "SELECT message_id, tag_number, type, tool_owner_message_id FROM tags WHERE session_id = ? ORDER BY tag_number ASC";
182511
+ var GET_ASSIGNMENTS_SCOPED_SQL = "SELECT message_id, tag_number, type, tool_owner_message_id FROM tags WHERE session_id = ? AND tag_number >= ? ORDER BY tag_number ASC";
182363
182512
  var PROBE_DATA_VERSION_SQL = "PRAGMA main.data_version";
182364
- var PROBE_TOTAL_CHANGES_SQL = "SELECT total_changes() AS tc";
182365
182513
  var probeDataVersionStatements = new WeakMap;
182366
- var probeTotalChangesStatements = new WeakMap;
182367
182514
  function getProbeDataVersionStatement(db) {
182368
182515
  let stmt = probeDataVersionStatements.get(db);
182369
182516
  if (!stmt) {
@@ -182372,14 +182519,6 @@ function getProbeDataVersionStatement(db) {
182372
182519
  }
182373
182520
  return stmt;
182374
182521
  }
182375
- function getProbeTotalChangesStatement(db) {
182376
- let stmt = probeTotalChangesStatements.get(db);
182377
- if (!stmt) {
182378
- stmt = db.prepare(PROBE_TOTAL_CHANGES_SQL);
182379
- probeTotalChangesStatements.set(db, stmt);
182380
- }
182381
- return stmt;
182382
- }
182383
182522
  function isAssignmentRow(row) {
182384
182523
  if (row === null || typeof row !== "object") {
182385
182524
  return false;
@@ -182572,20 +182711,18 @@ function createTagger() {
182572
182711
  }
182573
182712
  function probeSignature(db) {
182574
182713
  const dvRow = getProbeDataVersionStatement(db).get();
182575
- const tcRow = getProbeTotalChangesStatement(db).get();
182576
182714
  return {
182577
- dataVersion: dvRow?.data_version ?? 0,
182578
- totalChanges: tcRow?.tc ?? 0
182715
+ dataVersion: dvRow?.data_version ?? 0
182579
182716
  };
182580
182717
  }
182581
- function initFromDb(sessionId, db) {
182718
+ function initFromDb(sessionId, db, floor = 0) {
182582
182719
  const probe = probeSignature(db);
182583
182720
  const cached2 = loadSignatures.get(sessionId);
182584
- if (cached2 !== undefined && cached2.db === db && cached2.dataVersion === probe.dataVersion && cached2.totalChanges === probe.totalChanges) {
182721
+ if (cached2 !== undefined && cached2.db === db && cached2.dataVersion === probe.dataVersion && cached2.floor === floor) {
182585
182722
  return;
182586
182723
  }
182587
182724
  const row = db.prepare(GET_COUNTER_SQL).get(sessionId);
182588
- const assignmentRows = db.prepare(GET_ASSIGNMENTS_SQL).all(sessionId).filter(isAssignmentRow);
182725
+ const assignmentRows = (floor > 0 ? db.prepare(GET_ASSIGNMENTS_SCOPED_SQL).all(sessionId, floor) : db.prepare(GET_ASSIGNMENTS_SQL).all(sessionId)).filter(isAssignmentRow);
182589
182726
  const sessionAssignments = getSessionAssignments(sessionId);
182590
182727
  sessionAssignments.clear();
182591
182728
  let maxTagNumber = 0;
@@ -182606,7 +182743,7 @@ function createTagger() {
182606
182743
  loadSignatures.set(sessionId, {
182607
182744
  db,
182608
182745
  dataVersion: probe.dataVersion,
182609
- totalChanges: probe.totalChanges
182746
+ floor
182610
182747
  });
182611
182748
  }
182612
182749
  function cleanup(sessionId) {
@@ -182629,13 +182766,13 @@ function createTagger() {
182629
182766
  cleanup
182630
182767
  };
182631
182768
  }
182769
+
182632
182770
  // src/hooks/magic-context/hook.ts
182633
182771
  init_magic_context();
182634
182772
  init_project_identity();
182635
182773
  init_project_embedding_registry();
182636
182774
  await init_storage();
182637
182775
  init_logger();
182638
- init_resolve_fallbacks();
182639
182776
  init_rpc_notifications();
182640
182777
 
182641
182778
  // src/hooks/magic-context/command-handler.ts
@@ -182686,6 +182823,7 @@ await __promiseAll([
182686
182823
  // src/hooks/magic-context/compartment-trigger.ts
182687
182824
  init_compartment_storage();
182688
182825
  init_logger();
182826
+ init_read_session_true_raw_tokens();
182689
182827
  await __promiseAll([
182690
182828
  init_storage(),
182691
182829
  init_protected_tail_boundary(),
@@ -182700,6 +182838,38 @@ var TAIL_SIZE_TRIGGER_MULTIPLIER = 3;
182700
182838
  var FORCE_COMPARTMENT_PERCENTAGE = 80;
182701
182839
  var BLOCK_UNTIL_DONE_PERCENTAGE = 95;
182702
182840
  var FORCE_MATERIALIZE_PERCENTAGE = 85;
182841
+ var CONTENT_TAG_OWNER_SUFFIX = /:(?:p|file)\d+$/;
182842
+ function tagOwnerMessageId(row) {
182843
+ if (row.type === "tool")
182844
+ return row.tool_owner_message_id ?? row.message_id;
182845
+ return row.message_id.replace(CONTENT_TAG_OWNER_SUFFIX, "");
182846
+ }
182847
+ function getActiveOrDroppedTagOwnerMessageIds(db, sessionId, floor = 0) {
182848
+ const rows = floor > 0 ? db.prepare(`SELECT type, message_id, tool_owner_message_id
182849
+ FROM tags
182850
+ WHERE session_id = ? AND status IN ('active', 'dropped') AND tag_number >= ?`).all(sessionId, floor) : db.prepare(`SELECT type, message_id, tool_owner_message_id
182851
+ FROM tags
182852
+ WHERE session_id = ? AND status IN ('active', 'dropped')`).all(sessionId);
182853
+ const owners = new Set;
182854
+ for (const row of rows)
182855
+ owners.add(tagOwnerMessageId(row));
182856
+ return owners;
182857
+ }
182858
+ function estimateUntaggedInMemoryTailUpperBound(db, sessionId, inMemoryTail, taggerFloor = 0) {
182859
+ const lastCompartmentEnd = getLastCompartmentEndMessage(db, sessionId);
182860
+ const coveredOwnerMessageIds = getActiveOrDroppedTagOwnerMessageIds(db, sessionId, taggerFloor);
182861
+ let total = 0;
182862
+ for (const message of inMemoryTail.messages) {
182863
+ if (message.ordinal <= lastCompartmentEnd)
182864
+ continue;
182865
+ if (coveredOwnerMessageIds.has(message.id))
182866
+ continue;
182867
+ total += estimateTrueRawMessageTokens(message, {
182868
+ providerShapeVersion: "opencode-v1"
182869
+ }).total;
182870
+ }
182871
+ return total;
182872
+ }
182703
182873
  function buildTriggerInMemoryTail(db, sessionId, messages) {
182704
182874
  if (messages.length === 0)
182705
182875
  return;
@@ -182771,7 +182941,7 @@ function resolveBoundaryContextLimit(usage, fallbackContextLimit) {
182771
182941
  }
182772
182942
  return 128000;
182773
182943
  }
182774
- function getUnsummarizedTailInfo(db, sessionId, triggerBudget, usage, executeThresholdPercentage, contextLimit, inMemoryTail) {
182944
+ function getUnsummarizedTailInfo(db, sessionId, triggerBudget, usage, executeThresholdPercentage, contextLimit, inMemoryTail, taggerFloor = 0) {
182775
182945
  return withRawSessionMessageCache(() => {
182776
182946
  try {
182777
182947
  const memoryPrimed = inMemoryTail ? primeInMemoryTailRawMessageCache({
@@ -182800,7 +182970,8 @@ function getUnsummarizedTailInfo(db, sessionId, triggerBudget, usage, executeThr
182800
182970
  contextLimit: resolveBoundaryContextLimit(usage, contextLimit),
182801
182971
  executeThresholdPercentage,
182802
182972
  usage,
182803
- usageSource: "live"
182973
+ usageSource: "live",
182974
+ taggerFloor
182804
182975
  });
182805
182976
  const hasProtectedEligibleHead = boundary.offset < boundary.protectedTailStart;
182806
182977
  if (!hasProtectedEligibleHead) {
@@ -182831,7 +183002,7 @@ function getUnsummarizedTailInfo(db, sessionId, triggerBudget, usage, executeThr
182831
183002
  }
182832
183003
  });
182833
183004
  }
182834
- function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPercentage, executeThresholdPercentage, triggerBudget, clearReasoningAge, commitClusterTrigger, preloadedActiveTags, contextLimit, inMemoryTail) {
183005
+ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPercentage, executeThresholdPercentage, triggerBudget, clearReasoningAge, commitClusterTrigger, preloadedActiveTags, contextLimit, inMemoryTail, taggerFloorOverride) {
182835
183006
  if (sessionMeta.compartmentInProgress) {
182836
183007
  sessionLog(sessionId, `compartment trigger: skipped — historian already in progress (usage=${usage.percentage.toFixed(1)}%)`);
182837
183008
  return { shouldFire: false };
@@ -182845,14 +183016,17 @@ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPer
182845
183016
  inMemoryTail = undefined;
182846
183017
  }
182847
183018
  }
183019
+ const taggerFloor = taggerFloorOverride !== undefined && taggerFloorOverride > 0 ? taggerFloorOverride : inMemoryTail ? deriveTagLoadFloor(db, sessionId, inMemoryTail.messages.map((m) => m.id)) : 0;
182848
183020
  const proactiveFloorForGate = getProactiveCompartmentTriggerPercentage(executeThresholdPercentage);
182849
- if (!inMemoryTail && usage.percentage < proactiveFloorForGate) {
183021
+ if (usage.percentage < proactiveFloorForGate) {
182850
183022
  try {
182851
- const { bound, nullCount } = getTriggerTagTokenUpperBound(db, sessionId);
183023
+ const { bound: persistedBound, nullCount } = getTriggerTagTokenUpperBound(db, sessionId, taggerFloor);
182852
183024
  if (nullCount === 0) {
182853
- const eligibleUpperBound = bound;
183025
+ const untaggedUpperBound = inMemoryTail ? estimateUntaggedInMemoryTailUpperBound(db, sessionId, inMemoryTail, taggerFloor) : 0;
183026
+ const eligibleUpperBound = persistedBound + untaggedUpperBound;
182854
183027
  if (eligibleUpperBound < triggerBudget) {
182855
- sessionLog(sessionId, `compartment trigger: cheap-skip at ${usage.percentage.toFixed(1)}% (below proactive floor ${proactiveFloorForGate}%) — live-tail upper bound ${eligibleUpperBound} < triggerBudget ${triggerBudget}; no size trigger possible, skipped full raw read`);
183028
+ const memorySuffix = inMemoryTail ? ` (persisted=${persistedBound}, untagged-memory≤${untaggedUpperBound})` : "";
183029
+ sessionLog(sessionId, `compartment trigger: cheap-skip at ${usage.percentage.toFixed(1)}% (below proactive floor ${proactiveFloorForGate}%) — live-tail upper bound ${eligibleUpperBound}${memorySuffix} < triggerBudget ${triggerBudget}; no size trigger possible, skipped full raw read`);
182856
183030
  return { shouldFire: false };
182857
183031
  }
182858
183032
  }
@@ -182860,7 +183034,7 @@ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPer
182860
183034
  sessionLog(sessionId, `compartment trigger: cheap-gate skipped (falling through to full read): ${error51 instanceof Error ? error51.message : String(error51)}`);
182861
183035
  }
182862
183036
  }
182863
- const tailInfo = getUnsummarizedTailInfo(db, sessionId, triggerBudget, usage, executeThresholdPercentage, contextLimit, inMemoryTail);
183037
+ const tailInfo = getUnsummarizedTailInfo(db, sessionId, triggerBudget, usage, executeThresholdPercentage, contextLimit, inMemoryTail, taggerFloor);
182864
183038
  if (!tailInfo.hasNewRawHistory) {
182865
183039
  try {
182866
183040
  const lastCompartmentEnd = getLastCompartmentEndMessage(db, sessionId);
@@ -183595,9 +183769,142 @@ function clearSessionTracking(sessionId) {
183595
183769
  // src/hooks/magic-context/event-handler.ts
183596
183770
  init_overflow_detection();
183597
183771
  init_storage_meta_persisted();
183772
+ await init_storage();
183773
+
183774
+ // src/features/magic-context/transform-decision-log.ts
183775
+ await __promiseAll([
183776
+ init_sqlite(),
183777
+ init_storage_db()
183778
+ ]);
183779
+ var canonicalReasons = new Set([
183780
+ "system_hash",
183781
+ "model_change",
183782
+ "project_memory_epoch",
183783
+ "ttl_idle",
183784
+ "explicit_flush",
183785
+ "max_mutation_id",
183786
+ "first_render",
183787
+ "pressure_refold",
183788
+ "upgrade_state",
183789
+ "cached_m1_missing"
183790
+ ]);
183791
+ var piReasonAliases = {
183792
+ project_memory_change: "project_memory_epoch",
183793
+ pending_mutations: "max_mutation_id",
183794
+ renderer_upgrade: "upgrade_state",
183795
+ cache_invalid: "cached_m1_missing",
183796
+ drift: "pressure_refold"
183797
+ };
183798
+ var sharedReasonAliases = {
183799
+ model_key: "model_change",
183800
+ pressure: "pressure_refold"
183801
+ };
183802
+ var pendingDecisionBySession = new Map;
183803
+ var pendingPiDecisionBySession = new Map;
183804
+ var lastBoundMessageIdBySession = new Map;
183805
+ var scheduledWriteTokensBySession = new Map;
183806
+ var writerOverrideForTests = null;
183807
+ function normalizeMaterializeReason(harness, reason, rematerialized) {
183808
+ const raw = typeof reason === "string" ? reason.trim() : "";
183809
+ if (raw.length > 0) {
183810
+ const alias = sharedReasonAliases[raw] ?? (harness === "pi" ? piReasonAliases[raw] : undefined) ?? undefined;
183811
+ if (alias)
183812
+ return alias;
183813
+ if (canonicalReasons.has(raw))
183814
+ return raw;
183815
+ return null;
183816
+ }
183817
+ return rematerialized ? "pressure_refold" : null;
183818
+ }
183819
+ function clearOpenCodePendingTransformDecision(sessionId) {
183820
+ pendingDecisionBySession.delete(sessionId);
183821
+ }
183822
+ function clearTransformDecisionSession(sessionId) {
183823
+ pendingDecisionBySession.delete(sessionId);
183824
+ pendingPiDecisionBySession.delete(sessionId);
183825
+ lastBoundMessageIdBySession.delete(sessionId);
183826
+ scheduledWriteTokensBySession.delete(sessionId);
183827
+ }
183828
+ function recordPendingTransformDecision(sessionId, decision) {
183829
+ if (!decision.bustedThisPass) {
183830
+ pendingDecisionBySession.delete(sessionId);
183831
+ return;
183832
+ }
183833
+ pendingDecisionBySession.set(sessionId, decision);
183834
+ }
183835
+ function scheduleOpenCodeTransformDecisionWrite(args) {
183836
+ const pending = pendingDecisionBySession.get(args.sessionId);
183837
+ if (!pending)
183838
+ return false;
183839
+ if (lastBoundMessageIdBySession.get(args.sessionId) === args.messageId) {
183840
+ return false;
183841
+ }
183842
+ const dbPath = getDatabasePath(args.db);
183843
+ if (!dbPath)
183844
+ return false;
183845
+ lastBoundMessageIdBySession.set(args.sessionId, args.messageId);
183846
+ pendingDecisionBySession.delete(args.sessionId);
183847
+ const token = addScheduledWriteToken(args.sessionId);
183848
+ setTimeout(() => {
183849
+ try {
183850
+ if (!hasScheduledWriteToken(args.sessionId, token))
183851
+ return;
183852
+ writeTransformDecisionBestEffort(dbPath, {
183853
+ ...pending,
183854
+ sessionId: args.sessionId,
183855
+ harness: "opencode",
183856
+ messageId: args.messageId,
183857
+ inputTokens: args.inputTokens
183858
+ });
183859
+ } finally {
183860
+ deleteScheduledWriteToken(args.sessionId, token);
183861
+ }
183862
+ }, 0);
183863
+ return true;
183864
+ }
183865
+ function addScheduledWriteToken(sessionId) {
183866
+ const token = Symbol(sessionId);
183867
+ let tokens = scheduledWriteTokensBySession.get(sessionId);
183868
+ if (!tokens) {
183869
+ tokens = new Set;
183870
+ scheduledWriteTokensBySession.set(sessionId, tokens);
183871
+ }
183872
+ tokens.add(token);
183873
+ return token;
183874
+ }
183875
+ function hasScheduledWriteToken(sessionId, token) {
183876
+ return scheduledWriteTokensBySession.get(sessionId)?.has(token) === true;
183877
+ }
183878
+ function deleteScheduledWriteToken(sessionId, token) {
183879
+ const tokens = scheduledWriteTokensBySession.get(sessionId);
183880
+ if (!tokens)
183881
+ return;
183882
+ tokens.delete(token);
183883
+ if (tokens.size === 0)
183884
+ scheduledWriteTokensBySession.delete(sessionId);
183885
+ }
183886
+ function writeTransformDecisionBestEffort(dbPath, row) {
183887
+ try {
183888
+ const writer = writerOverrideForTests ?? writeTransformDecisionRow;
183889
+ writer(dbPath, row);
183890
+ } catch {}
183891
+ }
183892
+ function writeTransformDecisionRow(dbPath, row) {
183893
+ const db = new Database(dbPath);
183894
+ try {
183895
+ db.exec("PRAGMA busy_timeout=0");
183896
+ db.prepare(`INSERT OR REPLACE INTO transform_decisions (
183897
+ session_id, harness, message_id, ts_ms, decision, materialized,
183898
+ materialize_reason, emergency, dropped_tokens, dropped_count, input_tokens
183899
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(row.sessionId, row.harness, row.messageId, row.tsMs, row.decision, row.materialized ? 1 : 0, row.materializeReason, row.emergency ? 1 : 0, Math.max(0, Math.floor(row.droppedTokens)), Math.max(0, Math.floor(row.droppedCount)), Math.max(0, Math.floor(row.inputTokens)));
183900
+ } finally {
183901
+ closeQuietly(db);
183902
+ }
183903
+ }
183904
+
183905
+ // src/hooks/magic-context/event-handler.ts
183598
183906
  init_logger();
183599
183907
  init_models_dev_cache();
183600
- await init_storage();
183601
183908
 
183602
183909
  // src/hooks/magic-context/channel2-delivery.ts
183603
183910
  init_storage_meta_persisted();
@@ -184001,11 +184308,13 @@ function getMessageUpdatedAssistantInfo(properties) {
184001
184308
  }
184002
184309
  const tokens = isRecord(info.tokens) ? info.tokens : undefined;
184003
184310
  const cache = tokens && isRecord(tokens.cache) ? tokens.cache : undefined;
184311
+ const time3 = isRecord(info.time) ? info.time : undefined;
184004
184312
  return {
184005
184313
  role: "assistant",
184006
184314
  finish: typeof info.finish === "string" ? info.finish : undefined,
184007
184315
  sessionID: info.sessionID,
184008
184316
  messageID: typeof info.id === "string" ? info.id : undefined,
184317
+ completedAt: typeof time3?.completed === "number" ? time3.completed : undefined,
184009
184318
  providerID: typeof info.providerID === "string" ? info.providerID : undefined,
184010
184319
  modelID: typeof info.modelID === "string" ? info.modelID : undefined,
184011
184320
  tokens: {
@@ -184068,8 +184377,8 @@ init_project_identity();
184068
184377
  import * as crypto2 from "node:crypto";
184069
184378
  init_session_project_storage();
184070
184379
  init_storage_meta_persisted();
184071
- init_logger();
184072
184380
  await init_storage();
184381
+ init_logger();
184073
184382
 
184074
184383
  // src/hooks/magic-context/boundary-execution.ts
184075
184384
  var FORCE_MATERIALIZE_PERCENTAGE2 = 85;
@@ -185105,6 +185414,7 @@ function stripProcessedImages(messages, frozenIds, options) {
185105
185414
  init_temporal_awareness();
185106
185415
 
185107
185416
  // src/hooks/magic-context/transform-compartment-phase.ts
185417
+ init_compartment_storage();
185108
185418
  init_logger();
185109
185419
  await __promiseAll([
185110
185420
  init_storage(),
@@ -185113,9 +185423,29 @@ await __promiseAll([
185113
185423
  init_send_session_notification();
185114
185424
  await __promiseAll([
185115
185425
  init_inject_compartments(),
185116
- init_protected_tail_boundary()
185426
+ init_protected_tail_boundary(),
185427
+ init_read_session_chunk()
185117
185428
  ]);
185118
- async function runCompartmentPhase(args) {
185429
+ function runCompartmentPhase(args) {
185430
+ const historianRunnable = args.historianRunnable !== false;
185431
+ const willReadRawHistory = historianRunnable && args.canRunCompartments && getActiveCompartmentRun(args.sessionId) === undefined && (args.sessionMeta.compartmentInProgress || !args.skipAwaitForThisPass && args.contextUsage.percentage >= BLOCK_UNTIL_DONE_PERCENTAGE);
185432
+ if (!willReadRawHistory) {
185433
+ return runCompartmentPhaseImpl(args);
185434
+ }
185435
+ return withRawSessionMessageCache(() => {
185436
+ try {
185437
+ primeTailRawMessageCache({
185438
+ sessionId: args.resolvedSessionId,
185439
+ lastCompartmentEnd: getLastCompartmentEndMessage(args.db, args.resolvedSessionId),
185440
+ anchorMessageId: getLastCompartmentEndMessageId(args.db, args.resolvedSessionId)
185441
+ });
185442
+ } catch (error51) {
185443
+ sessionLog(args.sessionId, "compartment phase: tail prime failed (non-fatal):", error51);
185444
+ }
185445
+ return runCompartmentPhaseImpl(args);
185446
+ });
185447
+ }
185448
+ async function runCompartmentPhaseImpl(args) {
185119
185449
  let pendingCompartmentInjection = args.pendingCompartmentInjection;
185120
185450
  let compartmentInProgress = args.sessionMeta.compartmentInProgress;
185121
185451
  let published = false;
@@ -185681,6 +186011,7 @@ function createExistingTagResolver(sessionId, tagger, db) {
185681
186011
  return;
185682
186012
  }
185683
186013
  updateTagMessageId(db, sessionId, fallback.tagNumber, currentContentId);
186014
+ tagger.unbindTag(sessionId, fallback.contentId);
185684
186015
  tagger.bindTag(sessionId, currentContentId, fallback.tagNumber);
185685
186016
  usedTagNumbers.add(fallback.tagNumber);
185686
186017
  return fallback.tagNumber;
@@ -185701,7 +186032,45 @@ function logTransformTiming(sessionId, stage, startMs, extra) {
185701
186032
  }
185702
186033
 
185703
186034
  // src/hooks/magic-context/tag-messages.ts
185704
- function deriveToolOwnerMessageId(sessionId, db, message, obs, unpaired) {
186035
+ var TOOL_OWNER_CACHE_KEY_SEP = "\x00";
186036
+ function makeToolOwnerCacheKey(sessionId, callId) {
186037
+ return `${sessionId}${TOOL_OWNER_CACHE_KEY_SEP}${callId}`;
186038
+ }
186039
+ function getCachedCandidateToolOwners(db, sessionId, callId, cache, onLookup) {
186040
+ const key = makeToolOwnerCacheKey(sessionId, callId);
186041
+ const cached2 = cache.candidateOwnersByCallId.get(key);
186042
+ if (cached2 !== undefined)
186043
+ return cached2;
186044
+ onLookup?.({ kind: "candidates", callId });
186045
+ const candidates = getCandidateToolOwners(db, sessionId, callId);
186046
+ cache.candidateOwnersByCallId.set(key, candidates);
186047
+ return candidates;
186048
+ }
186049
+ function getCachedMessageTimesFromOpenCodeDb(sessionId, messageIds, cache, onLookup) {
186050
+ const uncached = [...new Set(messageIds)].filter((id) => !cache.messageTimesById.has(id));
186051
+ if (uncached.length > 0) {
186052
+ onLookup?.({ kind: "messageTimes", messageIds: uncached });
186053
+ const resolved = getMessageTimesFromOpenCodeDb(sessionId, uncached);
186054
+ for (const id of uncached) {
186055
+ cache.messageTimesById.set(id, resolved.get(id) ?? null);
186056
+ }
186057
+ }
186058
+ const times = new Map;
186059
+ for (const id of messageIds) {
186060
+ const time3 = cache.messageTimesById.get(id);
186061
+ if (typeof time3 === "number")
186062
+ times.set(id, time3);
186063
+ }
186064
+ return times;
186065
+ }
186066
+ function invalidateCachedCandidateToolOwnersIfNewOwner(cache, sessionId, callId, ownerMsgId) {
186067
+ const key = makeToolOwnerCacheKey(sessionId, callId);
186068
+ const cached2 = cache.candidateOwnersByCallId.get(key);
186069
+ if (cached2 !== undefined && !cached2.includes(ownerMsgId)) {
186070
+ cache.candidateOwnersByCallId.delete(key);
186071
+ }
186072
+ }
186073
+ function deriveToolOwnerMessageId(sessionId, db, message, obs, unpaired, cache, onFallbackLookup) {
185705
186074
  const messageId = typeof message.info.id === "string" ? message.info.id : "";
185706
186075
  if (obs.kind === "invocation") {
185707
186076
  if (messageId) {
@@ -185721,10 +186090,10 @@ function deriveToolOwnerMessageId(sessionId, db, message, obs, unpaired) {
185721
186090
  return popped;
185722
186091
  }
185723
186092
  if (messageId) {
185724
- const candidates = getCandidateToolOwners(db, sessionId, obs.callId);
186093
+ const candidates = getCachedCandidateToolOwners(db, sessionId, obs.callId, cache, onFallbackLookup);
185725
186094
  if (candidates.length > 0) {
185726
186095
  const ids = [...candidates, messageId];
185727
- const times = getMessageTimesFromOpenCodeDb(sessionId, ids);
186096
+ const times = getCachedMessageTimesFromOpenCodeDb(sessionId, ids, cache, onFallbackLookup);
185728
186097
  const persisted = pickNearestPriorOwner(candidates, messageId, times);
185729
186098
  if (persisted !== null)
185730
186099
  return persisted;
@@ -185805,6 +186174,7 @@ function extractToolTagMetadata(part) {
185805
186174
  }
185806
186175
  function tagMessages(sessionId, messages, tagger, db, options = {}) {
185807
186176
  const skipPrefixInjection = options.skipPrefixInjection === true;
186177
+ const onToolOwnerFallbackLookup = options.onToolOwnerFallbackLookup;
185808
186178
  const targets = new Map;
185809
186179
  const reasoningByMessage = new Map;
185810
186180
  const messageTagNumbers = new Map;
@@ -185812,6 +186182,10 @@ function tagMessages(sessionId, messages, tagger, db, options = {}) {
185812
186182
  const toolThinkingByCallId = new Map;
185813
186183
  const toolCallIndex = new Map;
185814
186184
  const unpairedInvocations = new Map;
186185
+ const ownerDerivationCache = {
186186
+ candidateOwnersByCallId: new Map,
186187
+ messageTimesById: new Map
186188
+ };
185815
186189
  const ownerByPartKey = new Map;
185816
186190
  const batch = new ToolMutationBatch(messages);
185817
186191
  const assignments = tagger.getAssignments(sessionId);
@@ -185852,7 +186226,7 @@ function tagMessages(sessionId, messages, tagger, db, options = {}) {
185852
186226
  const toolObservation = extractToolCallObservation(part);
185853
186227
  if (toolObservation) {
185854
186228
  const _tDerive = performance.now();
185855
- const ownerMsgId = deriveToolOwnerMessageId(sessionId, db, message, toolObservation, unpairedInvocations);
186229
+ const ownerMsgId = deriveToolOwnerMessageId(sessionId, db, message, toolObservation, unpairedInvocations, ownerDerivationCache, onToolOwnerFallbackLookup);
185856
186230
  accDerive += performance.now() - _tDerive;
185857
186231
  const compositeKey = makeToolCompositeKey(ownerMsgId, toolObservation.callId);
185858
186232
  const entry = toolCallIndex.get(compositeKey) ?? {
@@ -185871,6 +186245,7 @@ function tagMessages(sessionId, messages, tagger, db, options = {}) {
185871
186245
  if (orphan !== null) {
185872
186246
  const claimed = adoptNullOwnerToolTag(db, orphan.id, ownerMsgId);
185873
186247
  if (claimed) {
186248
+ invalidateCachedCandidateToolOwnersIfNewOwner(ownerDerivationCache, sessionId, toolObservation.callId, ownerMsgId);
185874
186249
  tagger.bindToolTag(sessionId, toolObservation.callId, ownerMsgId, orphan.tagNumber);
185875
186250
  existingTagId = orphan.tagNumber;
185876
186251
  } else {
@@ -185878,6 +186253,13 @@ function tagMessages(sessionId, messages, tagger, db, options = {}) {
185878
186253
  }
185879
186254
  }
185880
186255
  }
186256
+ if (existingTagId === undefined) {
186257
+ const persisted = getToolTagNumberByOwner(db, sessionId, toolObservation.callId, ownerMsgId);
186258
+ if (persisted !== null) {
186259
+ tagger.bindToolTag(sessionId, toolObservation.callId, ownerMsgId, persisted);
186260
+ existingTagId = persisted;
186261
+ }
186262
+ }
185881
186263
  if (existingTagId !== undefined) {
185882
186264
  toolTagByCallId.set(compositeKey, existingTagId);
185883
186265
  messageTagNumbers.set(message, Math.max(messageTagNumbers.get(message) ?? 0, existingTagId));
@@ -185950,6 +186332,7 @@ function tagMessages(sessionId, messages, tagger, db, options = {}) {
185950
186332
  inputTokenCount,
185951
186333
  reasoningTokenCount: reasoningTokens
185952
186334
  }));
186335
+ invalidateCachedCandidateToolOwnersIfNewOwner(ownerDerivationCache, sessionId, toolPart.callID, ownerMsgId);
185953
186336
  accAssignToolTag += performance.now() - _tAssignTool;
185954
186337
  messageTagNumbers.set(message, Math.max(messageTagNumbers.get(message) ?? 0, tagId));
185955
186338
  if (!skipPrefixInjection) {
@@ -186948,7 +187331,7 @@ async function runAutoSearchHint(args) {
186948
187331
  embeddingEnabled,
186949
187332
  gitCommitsEnabled,
186950
187333
  embedQuery: async (text, signal) => {
186951
- const result = await embedTextForProject(options.projectPath, text, signal);
187334
+ const result = await embedTextForProject(options.projectPath, text, signal, "query");
186952
187335
  return result?.vector ?? null;
186953
187336
  },
186954
187337
  isEmbeddingRuntimeEnabled: () => embeddingEnabled === true,
@@ -187192,6 +187575,7 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
187192
187575
  const maxTag = getMaxTagNumberBySession(db, sessionId);
187193
187576
  const protectedCutoff = maxTag - config2.protectedTags;
187194
187577
  let droppedTools = 0;
187578
+ let emergencyDroppedTools = 0;
187195
187579
  let deduplicatedTools = 0;
187196
187580
  let droppedInjections = 0;
187197
187581
  if (config2.emergency) {
@@ -187223,6 +187607,7 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
187223
187607
  updateTagStatus(db, sessionId, tag.tagNumber, "dropped");
187224
187608
  updateTagDropMode(db, sessionId, tag.tagNumber, "full");
187225
187609
  droppedTools++;
187610
+ emergencyDroppedTools++;
187226
187611
  }
187227
187612
  }
187228
187613
  setEmergencyDropSample(db, sessionId, emergency.currentTotalInputTokens);
@@ -187326,6 +187711,7 @@ function applyHeuristicCleanup(sessionId, db, targets, messageTagNumbers, config
187326
187711
  droppedTools,
187327
187712
  deduplicatedTools,
187328
187713
  droppedInjections,
187714
+ emergencyDroppedTools,
187329
187715
  compressedTextTags,
187330
187716
  mutatedTextTags
187331
187717
  };
@@ -187554,7 +187940,6 @@ async function runPostTransformPhase(args) {
187554
187940
  const emergencyDropEligible = args.contextUsage.percentage >= args.forceMaterializationPercentage;
187555
187941
  const activeCompartmentRun = args.canRunCompartments ? getActiveCompartmentRun(args.sessionId) : undefined;
187556
187942
  const compartmentRunning = args.canRunCompartments && !args.awaitedCompartmentRun && activeCompartmentRun !== undefined;
187557
- const emergencyBypassCompartmentGate = forceMaterialization;
187558
187943
  const deferredMaterialize = args.canConsumeDeferredLate && deferredMaterializationWasPending;
187559
187944
  const materializationRequested = isExplicitFlush || deferredMaterialize;
187560
187945
  const m0M1EnabledForFold = args.fullFeatureMode && args.m0M1 !== undefined && (!!args.m0M1.projectPath || !!args.m0M1.projectDirectory);
@@ -187566,11 +187951,12 @@ async function runPostTransformPhase(args) {
187566
187951
  projectDirectory: args.m0M1.projectDirectory,
187567
187952
  hardSignals: args.m0M1.hardSignals
187568
187953
  }).value : false;
187954
+ const bypassCompartmentGate = forceMaterialization || m0HardFoldThisPass;
187569
187955
  const shouldReadPendingOps = materializationRequested || args.schedulerDecision === "execute" || forceMaterialization || m0HardFoldThisPass || compartmentRunning;
187570
187956
  const pendingOps = shouldReadPendingOps ? getPendingOps(args.db, args.sessionId) : [];
187571
187957
  const hasPendingUserOps = pendingOps.length > 0;
187572
- const shouldApplyPendingOps = (args.schedulerDecision === "execute" || materializationRequested || forceMaterialization || m0HardFoldThisPass) && (!compartmentRunning || emergencyBypassCompartmentGate);
187573
- const shouldRunHeuristics = (!compartmentRunning || emergencyBypassCompartmentGate) && (materializationRequested || forceMaterialization || m0HardFoldThisPass || emergencyDropEligible || args.schedulerDecision === "execute" && (!alreadyRanThisTurn || !args.fullFeatureMode));
187958
+ const shouldApplyPendingOps = (args.schedulerDecision === "execute" || materializationRequested || forceMaterialization || m0HardFoldThisPass) && (!compartmentRunning || bypassCompartmentGate);
187959
+ const shouldRunHeuristics = (!compartmentRunning || bypassCompartmentGate) && (materializationRequested || forceMaterialization || m0HardFoldThisPass || emergencyDropEligible || args.schedulerDecision === "execute" && (!alreadyRanThisTurn || !args.fullFeatureMode));
187574
187960
  const isCacheBustingPass = shouldApplyPendingOps || shouldRunHeuristics;
187575
187961
  const canUseEmptySentinels = modelAcceptsEmptyContent(args.resolvedProviderID);
187576
187962
  if (shouldRunHeuristics) {
@@ -187582,8 +187968,9 @@ async function runPostTransformPhase(args) {
187582
187968
  sessionLog(args.sessionId, `transform: skipping heuristics (already ran for turn ${args.currentTurnId})`);
187583
187969
  }
187584
187970
  if (compartmentRunning && hasPendingUserOps) {
187585
- if (emergencyBypassCompartmentGate) {
187586
- sessionLog(args.sessionId, `transform: emergency bypass applying ${pendingOps.length} pending ops while compartment agent runs (${args.contextUsage.percentage.toFixed(1)}%)`);
187971
+ if (bypassCompartmentGate) {
187972
+ const bypassReason = forceMaterialization ? "emergency >=85%" : "m0 hard fold";
187973
+ sessionLog(args.sessionId, `transform: compartment-gate bypass (${bypassReason}) — applying ${pendingOps.length} pending ops while compartment agent runs (${args.contextUsage.percentage.toFixed(1)}%)`);
187587
187974
  } else {
187588
187975
  sessionLog(args.sessionId, "transform: deferring pending ops — compartment agent in progress");
187589
187976
  }
@@ -187594,12 +187981,22 @@ async function runPostTransformPhase(args) {
187594
187981
  let pendingOpsRanSuccessfully = false;
187595
187982
  let pendingOpsDidMutate = false;
187596
187983
  let heuristicOrReasoningDidMutate = false;
187984
+ let droppedCount = 0;
187985
+ const droppedTokens = 0;
187986
+ let emergency = false;
187987
+ let m0RematerializedThisPass = false;
187988
+ let m0MaterializeReason = null;
187989
+ let m0M1InjectedThisPass = false;
187990
+ let autoReclaimDidMutateThisPass = false;
187597
187991
  try {
187598
187992
  if (shouldApplyPendingOps) {
187599
187993
  const applyReason = isExplicitFlush ? "explicit_flush" : deferredMaterialize ? "deferred_materialization" : `scheduler_execute (scheduler=${args.schedulerDecision})`;
187600
187994
  sessionLog(args.sessionId, `pending ops WILL APPLY — reason=${applyReason}, pendingOps=${pendingOps.length}, context=${args.contextUsage.percentage.toFixed(1)}%`);
187601
187995
  const tApply = performance.now();
187602
187996
  pendingOpsDidMutate = applyPendingOperations(args.sessionId, args.db, args.targets, args.protectedTags, undefined, pendingOps);
187997
+ if (pendingOpsDidMutate) {
187998
+ droppedCount += pendingOps.length;
187999
+ }
187603
188000
  logTransformTiming(args.sessionId, "applyPendingOperations", tApply);
187604
188001
  }
187605
188002
  if (shouldRunHeuristics) {
@@ -187619,8 +188016,10 @@ async function runPostTransformPhase(args) {
187619
188016
  }, heuristicTags);
187620
188017
  logTransformTiming(args.sessionId, "applyHeuristicCleanup", t5, `droppedTools=${cleanup.droppedTools} deduplicatedTools=${cleanup.deduplicatedTools} droppedInjections=${cleanup.droppedInjections} compressedTextTags=${cleanup.compressedTextTags} mutatedTextTags=${cleanup.mutatedTextTags}`);
187621
188018
  const heuristicMutationCount = cleanup.droppedTools + cleanup.deduplicatedTools + cleanup.droppedInjections + cleanup.mutatedTextTags;
188019
+ droppedCount += cleanup.droppedTools + cleanup.deduplicatedTools + cleanup.droppedInjections + cleanup.mutatedTextTags;
188020
+ emergency ||= cleanup.emergencyDroppedTools > 0;
187622
188021
  const t7 = performance.now();
187623
- const clearedReasoning = clearOldReasoning(args.messages, args.reasoningByMessage, args.messageTagNumbers, args.clearReasoningAge);
188022
+ const clearedReasoning = canUseEmptySentinels ? clearOldReasoning(args.messages, args.reasoningByMessage, args.messageTagNumbers, args.clearReasoningAge) : 0;
187624
188023
  if (canUseEmptySentinels) {
187625
188024
  stripClearedReasoning(args.messages);
187626
188025
  }
@@ -187645,6 +188044,7 @@ async function runPostTransformPhase(args) {
187645
188044
  }
187646
188045
  logTransformTiming(args.sessionId, "clearOldReasoning", t7);
187647
188046
  heuristicOrReasoningDidMutate = heuristicMutationCount + clearedReasoning + strippedInline > 0;
188047
+ droppedCount += clearedReasoning + strippedInline;
187648
188048
  if (pendingMaterializationAtPassStart) {
187649
188049
  args.pendingMaterializationSessions.delete(args.sessionId);
187650
188050
  }
@@ -187670,6 +188070,10 @@ async function runPostTransformPhase(args) {
187670
188070
  autoReclaimTargetCount = syntheticPendingOps.length;
187671
188071
  if (syntheticPendingOps.length > 0) {
187672
188072
  autoReclaimDidMutate = applyPendingOperations(args.sessionId, args.db, args.targets, args.protectedTags, undefined, [], syntheticPendingOps);
188073
+ if (autoReclaimDidMutate) {
188074
+ droppedCount += syntheticPendingOps.length;
188075
+ autoReclaimDidMutateThisPass = true;
188076
+ }
187673
188077
  }
187674
188078
  }
187675
188079
  args.batch?.finalize();
@@ -187749,6 +188153,9 @@ async function runPostTransformPhase(args) {
187749
188153
  hardSignals: args.m0M1.hardSignals
187750
188154
  });
187751
188155
  if (result.injected) {
188156
+ m0M1InjectedThisPass = true;
188157
+ m0RematerializedThisPass ||= result.m0RematerializedThisPass;
188158
+ m0MaterializeReason = result.decision.reason ?? m0MaterializeReason;
187752
188159
  sessionLog(args.sessionId, `transform: injected m[0]/m[1] (rematerialized=${result.m0RematerializedThisPass}, reason=${result.decision.reason ?? "cache_hit"})`);
187753
188160
  }
187754
188161
  } catch (error51) {
@@ -187957,7 +188364,19 @@ async function runPostTransformPhase(args) {
187957
188364
  sessionLog(args.sessionId, `sticky-injection GC: pruned ${prunedAnchors} note-nudge anchor(s), ${prunedDecisions} auto-search decision(s)`);
187958
188365
  }
187959
188366
  }
187960
- return { explicitMaterializedSuccessfully, deferredMaterializedSuccessfully };
188367
+ const materializeReason = m0MaterializeReason ?? (explicitMaterializedSuccessfully ? "explicit_flush" : null);
188368
+ const materialized = m0RematerializedThisPass || explicitMaterializedSuccessfully || deferredMaterializedSuccessfully;
188369
+ const bustedThisPass = args.didMutateFromFlushedStatuses || pendingOpsDidMutate || heuristicOrReasoningDidMutate || autoReclaimDidMutateThisPass || m0RematerializedThisPass || m0M1InjectedThisPass && historyWasConsumedThisPass || historyWasConsumedThisPass;
188370
+ return {
188371
+ explicitMaterializedSuccessfully,
188372
+ deferredMaterializedSuccessfully,
188373
+ materialized,
188374
+ materializeReason,
188375
+ droppedTokens,
188376
+ droppedCount,
188377
+ emergency,
188378
+ bustedThisPass
188379
+ };
187961
188380
  }
187962
188381
  function checkM0MutationDriftAndSignal(args) {
187963
188382
  const currentMaxMutationId = getMaxM0MutationId(args.db, args.sessionId) ?? 0;
@@ -187992,6 +188411,12 @@ function clearMessageTokensCache(sessionId, messageId) {
187992
188411
  cache.delete(messageId);
187993
188412
  }
187994
188413
  var recordedSessionProjectIdentity = new BoundedSessionMap(MESSAGE_TOKENS_CACHE_MAX);
188414
+ function deriveTaggerLoadFloor(messages, sessionId, db) {
188415
+ return deriveTagLoadFloor(db, sessionId, function* () {
188416
+ for (const message of messages)
188417
+ yield message.info?.id;
188418
+ }());
188419
+ }
187995
188420
  function findLastAssistantModel2(messages) {
187996
188421
  for (let i = messages.length - 1;i >= 0; i--) {
187997
188422
  const info = messages[i].info;
@@ -188014,6 +188439,7 @@ function createTransform(deps) {
188014
188439
  return;
188015
188440
  }
188016
188441
  const resolvedSessionId = sessionId;
188442
+ clearOpenCodePendingTransformDecision(sessionId);
188017
188443
  logTransformTiming(sessionId, "findSessionId", startTime, `messages=${messages.length}`);
188018
188444
  const db = deps.db;
188019
188445
  if (deps.client !== undefined) {
@@ -188316,12 +188742,16 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
188316
188742
  recordSessionProjectIdentity(db, sessionId, sessionProjectIdentity);
188317
188743
  recordedSessionProjectIdentity.set(sessionId, sessionProjectIdentity);
188318
188744
  }
188745
+ const taggerFloor = deriveTaggerLoadFloor(messages, sessionId, db);
188746
+ if (taggerFloor === 0 && messages.length > 0) {
188747
+ sessionLog(sessionId, `tag floor: 0 (full-scan fallback) — no leading wire message resolved a tag across ${messages.length} msgs`);
188748
+ }
188319
188749
  let triggerBoundarySnapshot;
188320
188750
  if (fullFeatureMode && historianRunnable && !sessionMeta.compartmentInProgress) {
188321
188751
  const tTrigger = performance.now();
188322
188752
  try {
188323
188753
  const inMemoryTail = buildTriggerInMemoryTail(db, sessionId, extractInMemoryMessageViews(messages));
188324
- const triggerResult = checkCompartmentTrigger(db, sessionId, sessionMeta, boundaryUsageForProtectedTail, sessionMeta.lastContextPercentage, boundaryExecuteThreshold, deriveTriggerBudget(boundaryContextLimit, boundaryExecuteThreshold), deps.clearReasoningAge, deps.commitClusterTrigger, undefined, boundaryContextLimit, inMemoryTail);
188754
+ const triggerResult = checkCompartmentTrigger(db, sessionId, sessionMeta, boundaryUsageForProtectedTail, sessionMeta.lastContextPercentage, boundaryExecuteThreshold, deriveTriggerBudget(boundaryContextLimit, boundaryExecuteThreshold), deps.clearReasoningAge, deps.commitClusterTrigger, undefined, boundaryContextLimit, inMemoryTail, taggerFloor);
188325
188755
  if (triggerResult.shouldFire) {
188326
188756
  sessionLog(sessionId, `compartment trigger: firing (reason=${triggerResult.reason})`);
188327
188757
  updateSessionMeta(db, sessionId, { compartmentInProgress: true });
@@ -188363,7 +188793,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
188363
188793
  try {
188364
188794
  const t0 = performance.now();
188365
188795
  const tInitFromDb = performance.now();
188366
- deps.tagger.initFromDb(sessionId, db);
188796
+ deps.tagger.initFromDb(sessionId, db, taggerFloor);
188367
188797
  logTransformTiming(sessionId, "tag.initFromDb", tInitFromDb);
188368
188798
  const skipPrefixInjection = !ctxReduceEnabledEffective;
188369
188799
  const result = tagMessages(sessionId, messages, deps.tagger, db, {
@@ -188415,7 +188845,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
188415
188845
  const persistedReasoningWatermark = sessionMeta?.clearedReasoningThroughTag ?? 0;
188416
188846
  if (persistedReasoningWatermark > 0) {
188417
188847
  const tReplay = performance.now();
188418
- const replayed = replayClearedReasoning(messages, reasoningByMessage, messageTagNumbers, persistedReasoningWatermark);
188848
+ const replayed = canUseEmptySentinels ? replayClearedReasoning(messages, reasoningByMessage, messageTagNumbers, persistedReasoningWatermark) : 0;
188419
188849
  const replayedInline = replayStrippedInlineThinking(messages, messageTagNumbers, persistedReasoningWatermark);
188420
188850
  if (replayed > 0 || replayedInline > 0) {
188421
188851
  sessionLog(sessionId, `reasoning replay: cleared=${replayed} inlineStripped=${replayedInline} (watermark=${persistedReasoningWatermark})`);
@@ -188513,7 +188943,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
188513
188943
  const wasEmergencyBlock = contextUsageEarly.percentage >= FORCE_MATERIALIZE_PERCENTAGE && compartmentPhase.justAwaitedPublication;
188514
188944
  const historyRebuiltThisPass = wasEmergencyBlock ? compartmentPhase.rebuiltHistoryThisPass : rebuiltHistoryFromInitialPrepare || compartmentPhase.rebuiltHistoryThisPass;
188515
188945
  const tPostProcess = performance.now();
188516
- await runPostTransformPhase({
188946
+ const postTransformResult = await runPostTransformPhase({
188517
188947
  sessionId,
188518
188948
  db,
188519
188949
  messages,
@@ -188567,6 +188997,19 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
188567
188997
  hardSignals: m0HardSignals
188568
188998
  }
188569
188999
  });
189000
+ if (postTransformResult.bustedThisPass) {
189001
+ recordPendingTransformDecision(sessionId, {
189002
+ tsMs: Date.now(),
189003
+ decision: schedulerDecision,
189004
+ materialized: postTransformResult.materialized,
189005
+ materializeReason: normalizeMaterializeReason("opencode", postTransformResult.materializeReason, postTransformResult.materialized),
189006
+ emergency: postTransformResult.emergency,
189007
+ droppedTokens: postTransformResult.droppedTokens,
189008
+ droppedCount: postTransformResult.droppedCount,
189009
+ inputTokens: contextUsage.inputTokens,
189010
+ bustedThisPass: true
189011
+ });
189012
+ }
188570
189013
  logTransformTiming(sessionId, "postTransformPhase", tPostProcess);
188571
189014
  const msgTokens = getMessageTokensCache(sessionId);
188572
189015
  let storedByMessage;
@@ -188948,6 +189391,15 @@ function createEventHandler2(deps) {
188948
189391
  info.tokens?.cache?.write
188949
189392
  ];
188950
189393
  const hasUsageTokens = usageTokens.some((value) => typeof value === "number" && value > 0);
189394
+ const terminalAssistantUpdate = info.messageID !== undefined && hasUsageTokens && (typeof info.finish === "string" || typeof info.completedAt === "number");
189395
+ if (terminalAssistantUpdate && info.messageID) {
189396
+ scheduleOpenCodeTransformDecisionWrite({
189397
+ db: deps.db,
189398
+ sessionId: info.sessionID,
189399
+ messageId: info.messageID,
189400
+ inputTokens: (info.tokens?.input ?? 0) + (info.tokens?.cache?.read ?? 0) + (info.tokens?.cache?.write ?? 0)
189401
+ });
189402
+ }
188951
189403
  sessionLog(info.sessionID, `event message.updated: provider=${info.providerID} model=${info.modelID} hasUsageTokens=${hasUsageTokens} tokens.input=${info.tokens?.input} cache.read=${info.tokens?.cache?.read} cache.write=${info.tokens?.cache?.write}`);
188952
189404
  const hasKnownUsage = hasUsageTokens || deps.contextUsageMap.has(info.sessionID);
188953
189405
  if (!hasKnownUsage) {
@@ -189105,6 +189557,7 @@ function createEventHandler2(deps) {
189105
189557
  deps.onSessionDeleted?.(sessionId);
189106
189558
  deps.contextUsageMap.delete(sessionId);
189107
189559
  deps.tagger.cleanup(sessionId);
189560
+ clearTransformDecisionSession(sessionId);
189108
189561
  clearMessageTokensCache(sessionId);
189109
189562
  invalidateTrueRawTokenCache({ sessionId, reason: "session.deleted" });
189110
189563
  return;
@@ -189808,7 +190261,7 @@ function createMagicContextHook(deps) {
189808
190261
  }
189809
190262
  let lastScheduleCheckMs = 0;
189810
190263
  const getHistorianChunkTokens = () => deriveHistorianChunkTokens(resolveHistorianContextLimit(deps.config.historian?.model));
189811
- const historianFallbackModels = resolveFallbackChain(HISTORIAN_AGENT, deps.config.historian?.fallback_models);
190264
+ const historianFallbackModels = resolveFallbackChain(deps.config.historian?.fallback_models);
189812
190265
  const historyRefreshSessions = deps.liveSessionState?.historyRefreshSessions ?? new Set;
189813
190266
  const deferredHistoryRefreshSessions = deps.liveSessionState?.deferredHistoryRefreshSessions ?? new Set;
189814
190267
  try {
@@ -190136,7 +190589,7 @@ function createMagicContextHook(deps) {
190136
190589
  token_budget: dreaming.pin_key_files.token_budget,
190137
190590
  min_reads: dreaming.pin_key_files.min_reads
190138
190591
  } : undefined,
190139
- fallbackModels: resolveFallbackChain(DREAMER_AGENT, dreaming.fallback_models),
190592
+ fallbackModels: resolveFallbackChain(dreaming.fallback_models),
190140
190593
  projectIdentity: projectPath
190141
190594
  }).catch((error51) => {
190142
190595
  log("[dreamer] scheduled queue processing failed:", error51);
@@ -190195,7 +190648,7 @@ function createMagicContextHook(deps) {
190195
190648
  token_budget: dreamerConfig.pin_key_files.token_budget,
190196
190649
  min_reads: dreamerConfig.pin_key_files.min_reads
190197
190650
  } : undefined,
190198
- fallbackModels: resolveFallbackChain(DREAMER_AGENT, dreamerConfig.fallback_models)
190651
+ fallbackModels: resolveFallbackChain(dreamerConfig.fallback_models)
190199
190652
  } : undefined
190200
190653
  });
190201
190654
  const systemPromptHash = createSystemPromptHashHandler({
@@ -191170,8 +191623,7 @@ function registerRpcHandlers(rpcServer, args) {
191170
191623
  });
191171
191624
  const buildManagedCtx = async (db) => {
191172
191625
  const { deriveHistorianChunkTokens: deriveHistorianChunkTokens2, resolveHistorianContextLimit: resolveHistorianContextLimit2 } = await Promise.resolve().then(() => (init_derive_budgets(), exports_derive_budgets));
191173
- const { resolveFallbackChain: resolveFallbackChain2 } = await Promise.resolve().then(() => (init_resolve_fallbacks(), exports_resolve_fallbacks));
191174
- const { HISTORIAN_AGENT: HISTORIAN_AGENT2 } = await Promise.resolve().then(() => exports_historian);
191626
+ const { resolveFallbackChain: resolveFallbackChain2 } = await Promise.resolve().then(() => exports_resolve_fallbacks);
191175
191627
  const DEFAULT_HISTORIAN_TIMEOUT_MS2 = 600000;
191176
191628
  return {
191177
191629
  client: args.client,
@@ -191182,7 +191634,7 @@ function registerRpcHandlers(rpcServer, args) {
191182
191634
  historianTimeoutMs: config2.historian_timeout_ms ?? DEFAULT_HISTORIAN_TIMEOUT_MS2,
191183
191635
  memoryEnabled: config2.memory?.enabled ?? true,
191184
191636
  autoPromote: config2.memory?.auto_promote ?? true,
191185
- fallbackModels: resolveFallbackChain2(HISTORIAN_AGENT2, config2.historian?.fallback_models),
191637
+ fallbackModels: resolveFallbackChain2(config2.historian?.fallback_models),
191186
191638
  runMigration: config2.memory?.enabled !== false && !!config2.historian?.model,
191187
191639
  userMemoriesEnabled: config2.dreamer?.user_memories?.enabled === true,
191188
191640
  historianTwoPass: config2.historian?.two_pass === true,
@@ -191534,6 +191986,7 @@ Actions:
191534
191986
  Example: ctx_memory(action="write", category="CONSTRAINTS", content="Pi stores sessions as JSONL under ~/.pi/agent/sessions/, not SQLite")`;
191535
191987
  var DEFAULT_SEARCH_LIMIT2 = 10;
191536
191988
  // src/tools/ctx-memory/tools.ts
191989
+ import { tool as tool2 } from "@opencode-ai/plugin";
191537
191990
  init_memory();
191538
191991
  init_embedding();
191539
191992
  init_embedding_cache();
@@ -191541,7 +191994,6 @@ init_normalize_hash();
191541
191994
  init_workspaces();
191542
191995
  init_logger();
191543
191996
  await init_storage();
191544
- import { tool as tool2 } from "@opencode-ai/plugin";
191545
191997
 
191546
191998
  // src/tools/ctx-memory/types.ts
191547
191999
  var CTX_MEMORY_ACTIONS = ["write", "archive", "update", "merge"];
@@ -192466,7 +192918,7 @@ function createCtxSearchTool(deps) {
192466
192918
  memoryEnabled,
192467
192919
  embeddingEnabled,
192468
192920
  embedQuery: async (text, signal) => {
192469
- const result = await embedTextForProject(projectPath, text, signal);
192921
+ const result = await embedTextForProject(projectPath, text, signal, "query");
192470
192922
  return result?.vector ?? null;
192471
192923
  },
192472
192924
  isEmbeddingRuntimeEnabled: () => embeddingEnabled === true,
@@ -192569,7 +193021,6 @@ function createToolRegistry(args) {
192569
193021
  init_conflict_detector();
192570
193022
  init_data_path();
192571
193023
  init_logger();
192572
- init_model_requirements();
192573
193024
  init_models_dev_cache();
192574
193025
 
192575
193026
  // src/shared/rpc-server.ts
@@ -193001,14 +193452,13 @@ var plugin = async (ctx) => {
193001
193452
  await hooks.magicContext?.["experimental.text.complete"]?.(input, output);
193002
193453
  },
193003
193454
  config: async (config2) => {
193004
- const buildHiddenAgentConfig = (agentId, prompt, allowedTools, maxSteps, overrides) => {
193455
+ const buildHiddenAgentConfig = (prompt, allowedTools, maxSteps, overrides) => {
193005
193456
  const { permission: overridePermission, ...restOverrides } = overrides ?? {};
193006
193457
  const basePermission = buildAllowOnlyPermission(allowedTools);
193007
193458
  return {
193008
193459
  prompt,
193009
193460
  steps: maxSteps,
193010
193461
  maxSteps,
193011
- ...getAgentFallbackModels(agentId) ? { fallback_models: getAgentFallbackModels(agentId) } : {},
193012
193462
  ...restOverrides,
193013
193463
  permission: {
193014
193464
  ...basePermission,
@@ -193030,6 +193480,7 @@ var plugin = async (ctx) => {
193030
193480
  max_runtime_minutes: _max,
193031
193481
  tasks: _tasks,
193032
193482
  task_timeout_minutes: _tto,
193483
+ thinking_level: _thinkingLevel,
193033
193484
  ...agentOverrides
193034
193485
  } = pluginConfig.dreamer;
193035
193486
  return agentOverrides;
@@ -193038,20 +193489,28 @@ var plugin = async (ctx) => {
193038
193489
  const {
193039
193490
  timeout_ms: _timeoutMs,
193040
193491
  system_prompt: _systemPrompt,
193492
+ thinking_level: _thinkingLevel,
193041
193493
  ...agentOverrides
193042
193494
  } = pluginConfig.sidekick;
193043
193495
  return agentOverrides;
193044
193496
  })() : undefined;
193045
193497
  const historianAgentOverrides = pluginConfig.historian ? (() => {
193046
- const { two_pass: _twoPass, ...agentOverrides } = pluginConfig.historian;
193498
+ const {
193499
+ two_pass: _twoPass,
193500
+ disallowed_tools: _disallowedTools,
193501
+ thinking_level: _thinkingLevel,
193502
+ ...agentOverrides
193503
+ } = pluginConfig.historian;
193047
193504
  return agentOverrides;
193048
193505
  })() : undefined;
193506
+ const historianDisallowed = pluginConfig.historian?.disallowed_tools ?? [];
193507
+ const historianAllowedTools = applyDisallowedTools(HISTORIAN_ALLOWED_TOOLS, historianDisallowed);
193049
193508
  config2.agent = {
193050
193509
  ...config2.agent ?? {},
193051
- [DREAMER_AGENT]: buildHiddenAgentConfig(DREAMER_AGENT, DREAMER_SYSTEM_PROMPT, DREAMER_ALLOWED_TOOLS, DREAMER_MAX_STEPS, dreamerAgentOverrides),
193052
- [HISTORIAN_AGENT]: buildHiddenAgentConfig(HISTORIAN_AGENT, COMPARTMENT_AGENT_SYSTEM_PROMPT, HISTORIAN_ALLOWED_TOOLS, HISTORIAN_MAX_STEPS, historianAgentOverrides),
193053
- [HISTORIAN_EDITOR_AGENT]: buildHiddenAgentConfig(HISTORIAN_EDITOR_AGENT, HISTORIAN_EDITOR_SYSTEM_PROMPT, HISTORIAN_ALLOWED_TOOLS, HISTORIAN_MAX_STEPS, historianAgentOverrides),
193054
- [SIDEKICK_AGENT]: buildHiddenAgentConfig(SIDEKICK_AGENT, SIDEKICK_SYSTEM_PROMPT, SIDEKICK_ALLOWED_TOOLS, SIDEKICK_MAX_STEPS, sidekickAgentOverrides)
193510
+ [DREAMER_AGENT]: buildHiddenAgentConfig(DREAMER_SYSTEM_PROMPT, DREAMER_ALLOWED_TOOLS, DREAMER_MAX_STEPS, dreamerAgentOverrides),
193511
+ [HISTORIAN_AGENT]: buildHiddenAgentConfig(COMPARTMENT_AGENT_SYSTEM_PROMPT, historianAllowedTools, HISTORIAN_MAX_STEPS, historianAgentOverrides),
193512
+ [HISTORIAN_EDITOR_AGENT]: buildHiddenAgentConfig(HISTORIAN_EDITOR_SYSTEM_PROMPT, historianAllowedTools, HISTORIAN_MAX_STEPS, historianAgentOverrides),
193513
+ [SIDEKICK_AGENT]: buildHiddenAgentConfig(SIDEKICK_SYSTEM_PROMPT, SIDEKICK_ALLOWED_TOOLS, SIDEKICK_MAX_STEPS, sidekickAgentOverrides)
193055
193514
  };
193056
193515
  }
193057
193516
  };