@cortexkit/opencode-magic-context 0.35.1 → 0.36.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. package/README.md +9 -5
  2. package/dist/agents/permissions.d.ts +17 -0
  3. package/dist/agents/permissions.d.ts.map +1 -1
  4. package/dist/{announcement-gms2nhya.js → announcement-6c1g4es4.js} +2 -2
  5. package/dist/config/index.d.ts.map +1 -1
  6. package/dist/config/schema/magic-context.d.ts +10 -0
  7. package/dist/config/schema/magic-context.d.ts.map +1 -1
  8. package/dist/{conflict-warning-hook-p2pmhvn7.js → conflict-warning-hook-mt0ttc4x.js} +5 -5
  9. package/dist/{derive-budgets-9crp0cvd.js → derive-budgets-88mxk2w1.js} +3 -3
  10. package/dist/features/magic-context/context-authority.d.ts +12 -0
  11. package/dist/features/magic-context/context-authority.d.ts.map +1 -1
  12. package/dist/features/magic-context/dreamer/classify.d.ts +2 -0
  13. package/dist/features/magic-context/dreamer/classify.d.ts.map +1 -1
  14. package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts +4 -0
  15. package/dist/features/magic-context/dreamer/evaluate-smart-notes.d.ts.map +1 -1
  16. package/dist/features/magic-context/dreamer/lease.d.ts +10 -3
  17. package/dist/features/magic-context/dreamer/lease.d.ts.map +1 -1
  18. package/dist/features/magic-context/dreamer/map-memories.d.ts +2 -0
  19. package/dist/features/magic-context/dreamer/map-memories.d.ts.map +1 -1
  20. package/dist/features/magic-context/dreamer/module-apply.d.ts +5 -0
  21. package/dist/features/magic-context/dreamer/module-apply.d.ts.map +1 -1
  22. package/dist/features/magic-context/dreamer/promote-primers.d.ts +2 -0
  23. package/dist/features/magic-context/dreamer/promote-primers.d.ts.map +1 -1
  24. package/dist/features/magic-context/dreamer/refresh-primers.d.ts +2 -0
  25. package/dist/features/magic-context/dreamer/refresh-primers.d.ts.map +1 -1
  26. package/dist/features/magic-context/dreamer/task-executor.d.ts +1 -0
  27. package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
  28. package/dist/features/magic-context/dreamer/task-scheduler.d.ts +5 -2
  29. package/dist/features/magic-context/dreamer/task-scheduler.d.ts.map +1 -1
  30. package/dist/features/magic-context/dreamer/verify.d.ts +2 -0
  31. package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
  32. package/dist/features/magic-context/message-index-async.d.ts.map +1 -1
  33. package/dist/features/magic-context/migrations.d.ts.map +1 -1
  34. package/dist/features/magic-context/mural/compress-cues.d.ts +2 -0
  35. package/dist/features/magic-context/mural/compress-cues.d.ts.map +1 -1
  36. package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
  37. package/dist/features/magic-context/schema-fence-probe.d.ts +1 -0
  38. package/dist/features/magic-context/schema-fence-probe.d.ts.map +1 -1
  39. package/dist/features/magic-context/smart-notes/condition-compiler.d.ts +38 -0
  40. package/dist/features/magic-context/smart-notes/condition-compiler.d.ts.map +1 -0
  41. package/dist/features/magic-context/smart-notes/runner.d.ts +1 -0
  42. package/dist/features/magic-context/smart-notes/runner.d.ts.map +1 -1
  43. package/dist/features/magic-context/smart-notes/storage.d.ts +3 -3
  44. package/dist/features/magic-context/smart-notes/storage.d.ts.map +1 -1
  45. package/dist/features/magic-context/storage-clone.d.ts +6 -0
  46. package/dist/features/magic-context/storage-clone.d.ts.map +1 -1
  47. package/dist/features/magic-context/storage-db.d.ts +2 -2
  48. package/dist/features/magic-context/storage-db.d.ts.map +1 -1
  49. package/dist/features/magic-context/storage-identity-merge.d.ts.map +1 -1
  50. package/dist/features/magic-context/storage-notes.d.ts +13 -0
  51. package/dist/features/magic-context/storage-notes.d.ts.map +1 -1
  52. package/dist/features/magic-context/storage-tags.d.ts +2 -0
  53. package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
  54. package/dist/features/magic-context/storage.d.ts +2 -2
  55. package/dist/features/magic-context/storage.d.ts.map +1 -1
  56. package/dist/features/magic-context/user-memory/review-user-memories.d.ts +2 -0
  57. package/dist/features/magic-context/user-memory/review-user-memories.d.ts.map +1 -1
  58. package/dist/hooks/magic-context/child-session-spawn.d.ts +1 -0
  59. package/dist/hooks/magic-context/child-session-spawn.d.ts.map +1 -1
  60. package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
  61. package/dist/hooks/magic-context/compaction-off-transition.d.ts.map +1 -1
  62. package/dist/hooks/magic-context/compartment-render-epoch.d.ts +5 -3
  63. package/dist/hooks/magic-context/compartment-render-epoch.d.ts.map +1 -1
  64. package/dist/hooks/magic-context/embed-session-state.d.ts +1 -1
  65. package/dist/hooks/magic-context/embed-session-state.d.ts.map +1 -1
  66. package/dist/hooks/magic-context/hook.d.ts +3 -0
  67. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  68. package/dist/hooks/magic-context/inject-compartments.d.ts +8 -0
  69. package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
  70. package/dist/hooks/magic-context/lkg-replay.d.ts +5 -2
  71. package/dist/hooks/magic-context/lkg-replay.d.ts.map +1 -1
  72. package/dist/hooks/magic-context/lkg-slot.d.ts +15 -1
  73. package/dist/hooks/magic-context/lkg-slot.d.ts.map +1 -1
  74. package/dist/hooks/magic-context/module-state-sync.d.ts +7 -0
  75. package/dist/hooks/magic-context/module-state-sync.d.ts.map +1 -1
  76. package/dist/hooks/magic-context/module-transport.d.ts +29 -3
  77. package/dist/hooks/magic-context/module-transport.d.ts.map +1 -1
  78. package/dist/hooks/magic-context/raw-fallback-context-limit.d.ts +10 -0
  79. package/dist/hooks/magic-context/raw-fallback-context-limit.d.ts.map +1 -0
  80. package/dist/hooks/magic-context/read-session-formatting.d.ts +1 -0
  81. package/dist/hooks/magic-context/read-session-formatting.d.ts.map +1 -1
  82. package/dist/hooks/magic-context/rust-mode-transform.d.ts +10 -2
  83. package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
  84. package/dist/hooks/magic-context/strip-content.d.ts +6 -1
  85. package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
  86. package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
  87. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +1 -0
  88. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  89. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  90. package/dist/{index-fkyamz2w.js → index-1skzp4dc.js} +444 -98
  91. package/dist/{index-w0nygb4p.js → index-3tnkymva.js} +2 -2
  92. package/dist/{index-dpdnjawy.js → index-3zqcdwqr.js} +140 -13
  93. package/dist/{index-0c9dmw9m.js → index-8mtsfhyg.js} +33 -3
  94. package/dist/{index-k1esqfwk.js → index-f1tnb3vm.js} +1 -1
  95. package/dist/{index-kvrcg31b.js → index-mmrhhk9a.js} +8 -1
  96. package/dist/{index-h5zjfesc.js → index-nsx2n9eg.js} +3 -3
  97. package/dist/{index-dmr999a2.js → index-qf20mv7e.js} +1 -1
  98. package/dist/{index-73xz0247.js → index-tsgs7td8.js} +1 -1
  99. package/dist/{index-ry8rh8cv.js → index-wgvxkqpx.js} +5 -4
  100. package/dist/{index-8aaadh98.js → index-zp6x6s6a.js} +3 -3
  101. package/dist/index.d.ts.map +1 -1
  102. package/dist/index.js +1556 -619
  103. package/dist/plugin/dream-timer.d.ts +1 -0
  104. package/dist/plugin/dream-timer.d.ts.map +1 -1
  105. package/dist/plugin/hooks/create-session-hooks.d.ts +3 -0
  106. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  107. package/dist/plugin/messages-transform.d.ts +5 -5
  108. package/dist/plugin/messages-transform.d.ts.map +1 -1
  109. package/dist/plugin/rust-tool-backends.d.ts +4 -0
  110. package/dist/plugin/rust-tool-backends.d.ts.map +1 -1
  111. package/dist/{recomp-orchestrator-29f4rqax.js → recomp-orchestrator-a0g9b52q.js} +8 -8
  112. package/dist/{safe-notification-target-q9jk5n44.js → safe-notification-target-c11fdda2.js} +3 -3
  113. package/dist/{send-session-notification-sr5g06hz.js → send-session-notification-bgtf4853.js} +4 -4
  114. package/dist/shared/conflict-fixer.d.ts.map +1 -1
  115. package/dist/shared/data-path.d.ts +27 -0
  116. package/dist/shared/data-path.d.ts.map +1 -1
  117. package/dist/shared/harness-provider-map.d.ts +23 -20
  118. package/dist/shared/harness-provider-map.d.ts.map +1 -1
  119. package/dist/shared/jsonc-edit.d.ts +18 -0
  120. package/dist/shared/jsonc-edit.d.ts.map +1 -0
  121. package/dist/shared/jsonc-parser.d.ts +11 -1
  122. package/dist/shared/jsonc-parser.d.ts.map +1 -1
  123. package/dist/shared/prompt-surface-runtime.d.ts +15 -2
  124. package/dist/shared/prompt-surface-runtime.d.ts.map +1 -1
  125. package/dist/shared/prompt-surface.d.ts +5 -3
  126. package/dist/shared/prompt-surface.d.ts.map +1 -1
  127. package/dist/shared/rpc-utils.d.ts +16 -0
  128. package/dist/shared/rpc-utils.d.ts.map +1 -1
  129. package/dist/shared/tui-preferences.d.ts +9 -0
  130. package/dist/shared/tui-preferences.d.ts.map +1 -1
  131. package/dist/{storage-meta-session-ev8b55a9.js → storage-meta-session-df9tstzr.js} +4 -4
  132. package/dist/tools/ctx-note/tools.d.ts.map +1 -1
  133. package/package.json +4 -3
  134. package/src/agents/permissions.ts +87 -0
  135. package/src/config/compaction-accessor-guard.test.ts +9 -4
  136. package/src/config/index.test.ts +23 -0
  137. package/src/config/index.ts +41 -9
  138. package/src/config/schema/magic-context.test.ts +4 -1
  139. package/src/config/schema/magic-context.ts +18 -3
  140. package/src/shared/conflict-fixer.test.ts +174 -0
  141. package/src/shared/conflict-fixer.ts +66 -70
  142. package/src/shared/data-path.test.ts +65 -9
  143. package/src/shared/data-path.ts +66 -1
  144. package/src/shared/harness-provider-map.test.ts +42 -1
  145. package/src/shared/harness-provider-map.ts +48 -26
  146. package/src/shared/jsonc-edit.ts +295 -0
  147. package/src/shared/jsonc-parser.test.ts +33 -0
  148. package/src/shared/jsonc-parser.ts +54 -2
  149. package/src/shared/prompt-surface-runtime.ts +13 -5
  150. package/src/shared/prompt-surface.test.ts +53 -2
  151. package/src/shared/prompt-surface.ts +20 -9
  152. package/src/shared/rpc-utils.test.ts +36 -0
  153. package/src/shared/rpc-utils.ts +71 -0
  154. package/src/shared/tui-preferences.test.ts +52 -2
  155. package/src/shared/tui-preferences.ts +42 -17
package/dist/index.js CHANGED
@@ -25,6 +25,14 @@ import {
25
25
  GLOBAL_USER_PROFILE_PROJECT_PATH,
26
26
  HISTORIAN_EDITOR_SYSTEM_PROMPT,
27
27
  LATEST_SUPPORTED_VERSION,
28
+ LKG_SNAPSHOT_ARRAY,
29
+ LKG_SNAPSHOT_BOOLEAN,
30
+ LKG_SNAPSHOT_KEY,
31
+ LKG_SNAPSHOT_NULL,
32
+ LKG_SNAPSHOT_NUMBER,
33
+ LKG_SNAPSHOT_OBJECT,
34
+ LKG_SNAPSHOT_STRING,
35
+ LKG_SNAPSHOT_UNDEFINED,
28
36
  MARKER_SUMMARY_TEXT,
29
37
  MAX_EXECUTE_THRESHOLD,
30
38
  MagicContextConfigSchema,
@@ -52,6 +60,7 @@ import {
52
60
  appendAutoSearchHintDecision,
53
61
  applyDeferredCompactionMarker,
54
62
  applyMirrorPage,
63
+ applyMirroredNoteCompileFields,
55
64
  applyStrippedPlaceholderDelta,
56
65
  archiveMemory,
57
66
  backfillTagTokenCounts,
@@ -72,6 +81,7 @@ import {
72
81
  clearEmergencyDropSample,
73
82
  clearEmergencyRecovery,
74
83
  clearHistorianFailureState,
84
+ clearHookInitFailure,
75
85
  clearInjectionCache,
76
86
  clearMemoryVerifications,
77
87
  clearNoteNudgeTriggerAndCooldown,
@@ -91,6 +101,7 @@ import {
91
101
  countEmbeddedCommits,
92
102
  countPrimerCandidatesForProject,
93
103
  createChildSessionWithFence,
104
+ createFailClosedController,
94
105
  createPrimer,
95
106
  createPromptSurfaceGuidanceEpochCache,
96
107
  createPromptSurfaceRuntime,
@@ -145,6 +156,7 @@ import {
145
156
  getHistorianFailureState,
146
157
  getLastCompartmentEndMessage,
147
158
  getLastCompartmentEndMessageId,
159
+ getLastHookInitFailure,
148
160
  getLastNudgeLevel,
149
161
  getLastNudgeUndropped,
150
162
  getLatestIndexedCommitTimeMs,
@@ -227,9 +239,11 @@ import {
227
239
  isDatabasePersisted,
228
240
  isEmbeddingEnabled,
229
241
  isEmergencyRecoveryArmed,
242
+ isFailClosedBlockingError,
230
243
  isPidAlive,
231
244
  isProviderOverflowReconfirmed,
232
245
  lkgContentDigest,
246
+ lkgContentDigestFromFields,
233
247
  loadCompartmentChunkEmbeddingsForSearch,
234
248
  loadPersistedUsage,
235
249
  loadProjectCommitEmbeddings,
@@ -265,6 +279,7 @@ import {
265
279
  prepareCompartmentInjection,
266
280
  primerOccurrenceKey,
267
281
  primerOccurrenceUtcDay,
282
+ promptSurfaceConfigIdentity,
268
283
  promptSurfaceHashMaterial,
269
284
  promptSyncWithValidatedOutputRetry,
270
285
  pruneAutoSearchHintDecisions,
@@ -282,6 +297,7 @@ import {
282
297
  recordDetectedContextLimit,
283
298
  recordEmbeddingMeasurement,
284
299
  recordHighPressureNoEligibleHead,
300
+ recordHookInitFailure,
285
301
  recordMemoryMapping,
286
302
  recordMemoryVerifications,
287
303
  recordMuralCueRejection,
@@ -311,6 +327,7 @@ import {
311
327
  resetLastNudgeCycleIfTailShrank,
312
328
  resetNoteNudgeCooldownOnly,
313
329
  resetProtectedTailNoEligibleHead,
330
+ resolveAgentNameFromMessages,
314
331
  resolveCompactionModeRecord,
315
332
  resolveGitTopLevel,
316
333
  resolveLegacyConfigSources,
@@ -356,6 +373,7 @@ import {
356
373
  setRecompTerminal,
357
374
  setSessionWorkMetrics,
358
375
  setSqlitePragmaConfig,
376
+ shouldBypassFailClosedBlock,
359
377
  shouldKeepSubagents,
360
378
  snapRangeToCompartments,
361
379
  sourceNameForMemory,
@@ -382,7 +400,7 @@ import {
382
400
  upsertCommits,
383
401
  verificationFileExists,
384
402
  withContentLanguageDirective
385
- } from "./index-fkyamz2w.js";
403
+ } from "./index-1skzp4dc.js";
386
404
  import {
387
405
  deriveHistorianChunkTokens,
388
406
  deriveTriggerBudget,
@@ -394,7 +412,7 @@ import {
394
412
  setOutputReserveConfig,
395
413
  setStoragePrivatePermissionEnforcement,
396
414
  shouldEnforcePrivateStoragePermissions
397
- } from "./index-ry8rh8cv.js";
415
+ } from "./index-wgvxkqpx.js";
398
416
  import {
399
417
  modelBodyField,
400
418
  resolveFallbackChain
@@ -406,7 +424,7 @@ import {
406
424
  getErrorMessage,
407
425
  sendIgnoredMessage,
408
426
  sendUserPrompt
409
- } from "./index-h5zjfesc.js";
427
+ } from "./index-nsx2n9eg.js";
410
428
  import {
411
429
  ToolMutationBatch,
412
430
  advanceToolReclaimWatermark,
@@ -446,6 +464,7 @@ import {
446
464
  markSessionCleanupPending,
447
465
  normalizeText,
448
466
  partHasCompletedResult,
467
+ preloadTokenizer,
449
468
  prependTag,
450
469
  primeInMemoryTailRawMessageCache,
451
470
  primeTailRawMessageCache,
@@ -463,7 +482,7 @@ import {
463
482
  textMentionsRecentCommit,
464
483
  updateSessionMeta,
465
484
  withRawSessionMessageCache
466
- } from "./index-dpdnjawy.js";
485
+ } from "./index-3zqcdwqr.js";
467
486
  import {
468
487
  Database,
469
488
  closeQuietly,
@@ -472,17 +491,18 @@ import {
472
491
  isMidTurn,
473
492
  openCodeDbExists,
474
493
  withReadOnlySessionDb
475
- } from "./index-w0nygb4p.js";
494
+ } from "./index-3tnkymva.js";
476
495
  import {
477
496
  cleanupConflictWarnings,
478
497
  detectConflicts,
479
498
  sendConflictWarning
480
- } from "./index-8aaadh98.js";
499
+ } from "./index-zp6x6s6a.js";
481
500
  import {
482
501
  detectConfigFile,
502
+ isPrototypePollutionKey,
483
503
  parseJsonc,
484
504
  stripJsonComments
485
- } from "./index-0c9dmw9m.js";
505
+ } from "./index-8mtsfhyg.js";
486
506
  import {
487
507
  ANNOUNCEMENT_FEATURES,
488
508
  ANNOUNCEMENT_FOOTER,
@@ -491,7 +511,7 @@ import {
491
511
  isValidSemver,
492
512
  markAnnouncementSeen,
493
513
  shouldShowAnnouncement
494
- } from "./index-dmr999a2.js";
514
+ } from "./index-qf20mv7e.js";
495
515
  import {
496
516
  acknowledgeNotifications,
497
517
  drainNotifications,
@@ -499,17 +519,17 @@ import {
499
519
  pushNotification,
500
520
  registerNotificationSink
501
521
  } from "./index-d62ypazr.js";
502
- import"./index-73xz0247.js";
522
+ import"./index-tsgs7td8.js";
503
523
  import {
504
524
  log,
505
525
  sessionLog
506
- } from "./index-k1esqfwk.js";
526
+ } from "./index-f1tnb3vm.js";
507
527
  import {
508
528
  getDataDir,
509
529
  getHarness,
510
530
  getMagicContextStorageDir,
511
531
  getOpenCodeStorageDir
512
- } from "./index-kvrcg31b.js";
532
+ } from "./index-mmrhhk9a.js";
513
533
  import {
514
534
  resolvePromptContext
515
535
  } from "./index-szf8w1p5.js";
@@ -8370,6 +8390,49 @@ function buildAllowOnlyPermission(allowedTools, agentLabel) {
8370
8390
  }
8371
8391
  return permission;
8372
8392
  }
8393
+ function isPermissionAction(value) {
8394
+ return value === "ask" || value === "allow" || value === "deny";
8395
+ }
8396
+ function isPermissionMap(value) {
8397
+ return value !== null && typeof value === "object" && !Array.isArray(value);
8398
+ }
8399
+ function denyTaskRoutingToAgents(permission, internalAgentIds) {
8400
+ const configured = isPermissionAction(permission) ? { "*": permission } : isPermissionMap(permission) ? permission : {};
8401
+ const { task, ...otherPermissions } = configured;
8402
+ const configuredTask = isPermissionAction(task) ? { "*": task } : isPermissionMap(task) ? task : {};
8403
+ const internalAgentIdSet = new Set(internalAgentIds);
8404
+ const retainedTask = Object.fromEntries(Object.entries(configuredTask).filter(([agentId]) => !internalAgentIdSet.has(agentId)));
8405
+ return {
8406
+ ...otherPermissions,
8407
+ task: {
8408
+ ...retainedTask,
8409
+ ...Object.fromEntries(internalAgentIds.map((agentId) => [agentId, "deny"]))
8410
+ }
8411
+ };
8412
+ }
8413
+ var BUILTIN_TASK_CALLER_IDS = ["build", "plan"];
8414
+ function isTaskRoutingCaller(agentId, config) {
8415
+ const mode = config.mode;
8416
+ if (mode === "primary")
8417
+ return true;
8418
+ if (mode === "subagent" || mode === "all")
8419
+ return false;
8420
+ return agentId === "build" || agentId === "plan";
8421
+ }
8422
+ function denyTaskRoutingToCallerAgents(agentConfigs, internalAgentIds) {
8423
+ const result = { ...agentConfigs };
8424
+ const candidateIds = new Set([...BUILTIN_TASK_CALLER_IDS, ...Object.keys(agentConfigs)]);
8425
+ for (const agentId of candidateIds) {
8426
+ const agentConfig = agentConfigs[agentId] ?? {};
8427
+ if (!isTaskRoutingCaller(agentId, agentConfig))
8428
+ continue;
8429
+ result[agentId] = {
8430
+ ...agentConfig,
8431
+ permission: denyTaskRoutingToAgents(agentConfig.permission, internalAgentIds)
8432
+ };
8433
+ }
8434
+ return result;
8435
+ }
8373
8436
  function applyDisallowedTools(defaults, disallowed) {
8374
8437
  if (disallowed.includes("*"))
8375
8438
  return [];
@@ -9463,10 +9526,15 @@ function loadConfigFileDetailed(configPath, source) {
9463
9526
  configPath,
9464
9527
  isProjectConfig: source === "project"
9465
9528
  });
9529
+ const rejectedKeyPaths = [];
9530
+ const config = parseJsonc(substituted.text, {
9531
+ onRejectedKey: (path) => rejectedKeyPaths.push(path.join("."))
9532
+ });
9533
+ const unsafeKeyWarnings = rejectedKeyPaths.map((path) => `Ignored unsafe config key "${path}" (security: prototype-pollution keys are not allowed).`);
9466
9534
  return {
9467
- config: parseJsonc(substituted.text),
9468
- warnings: substituted.warnings.map((w) => `${configPath}: ${w}`),
9469
- outcome: substituted.warnings.length > 0 ? "substitution-failure" : "ok",
9535
+ config,
9536
+ warnings: [...substituted.warnings, ...unsafeKeyWarnings].map((warning) => `${configPath}: ${warning}`),
9537
+ outcome: rejectedKeyPaths.length > 0 ? "schema-recovery" : substituted.warnings.length > 0 ? "substitution-failure" : "ok",
9470
9538
  source
9471
9539
  };
9472
9540
  } catch (error) {
@@ -9480,18 +9548,35 @@ function loadConfigFileDetailed(configPath, source) {
9480
9548
  };
9481
9549
  }
9482
9550
  }
9551
+ function defineOwnConfigValue(target, key, value) {
9552
+ Object.defineProperty(target, key, {
9553
+ value,
9554
+ enumerable: true,
9555
+ configurable: true,
9556
+ writable: true
9557
+ });
9558
+ }
9483
9559
  function deepMergeRawConfig(base, override) {
9484
- const result = { ...base };
9560
+ const result = {};
9561
+ for (const key of Object.keys(base)) {
9562
+ if (isPrototypePollutionKey(key))
9563
+ continue;
9564
+ defineOwnConfigValue(result, key, base[key]);
9565
+ }
9485
9566
  for (const key of Object.keys(override)) {
9486
- const baseVal = base[key];
9567
+ if (isPrototypePollutionKey(key))
9568
+ continue;
9569
+ const baseVal = Object.hasOwn(base, key) ? base[key] : undefined;
9487
9570
  const overrideVal = override[key];
9571
+ let mergedValue;
9488
9572
  if (baseVal !== null && typeof baseVal === "object" && !Array.isArray(baseVal) && overrideVal !== null && typeof overrideVal === "object" && !Array.isArray(overrideVal)) {
9489
- result[key] = deepMergeRawConfig(baseVal, overrideVal);
9573
+ mergedValue = deepMergeRawConfig(baseVal, overrideVal);
9490
9574
  } else if (key === "disabled_hooks" && Array.isArray(baseVal) && Array.isArray(overrideVal)) {
9491
- result[key] = [...new Set([...baseVal, ...overrideVal])];
9575
+ mergedValue = [...new Set([...baseVal, ...overrideVal])];
9492
9576
  } else {
9493
- result[key] = overrideVal;
9577
+ mergedValue = overrideVal;
9494
9578
  }
9579
+ defineOwnConfigValue(result, key, mergedValue);
9495
9580
  }
9496
9581
  return result;
9497
9582
  }
@@ -10105,171 +10190,6 @@ function buildDreamTaskPrompt(task, args) {
10105
10190
  }
10106
10191
  }
10107
10192
 
10108
- // src/features/magic-context/fail-closed-block.ts
10109
- var FAIL_CLOSED_DOCTOR_COMMAND = "npx @cortexkit/magic-context@latest doctor";
10110
- var FAIL_CLOSED_REPROBE_EVERY_N = 5;
10111
-
10112
- class FailClosedBlockingError extends Error {
10113
- code = "FAIL_CLOSED_BLOCKING";
10114
- reason;
10115
- constructor(message, reason, options) {
10116
- super(message, options);
10117
- this.name = "FailClosedBlockingError";
10118
- this.reason = reason;
10119
- }
10120
- }
10121
- var OPENCODE_INTERNAL_AGENT_NAMES = new Set(["title", "summary", "compaction"]);
10122
- function isMagicContextHiddenAgentName(agent) {
10123
- if (agent === "sidekick" || agent === "smart-note-compiler" || agent.startsWith("smart-note-")) {
10124
- return true;
10125
- }
10126
- if (agent === "historian" || agent.startsWith("historian-"))
10127
- return true;
10128
- if (agent === "dreamer" || agent.startsWith("dreamer-"))
10129
- return true;
10130
- return false;
10131
- }
10132
- var MAX_FORMATTED_BLOCKING_PROCESSES = 8;
10133
- function formatFailClosedBlockingProcesses(processes) {
10134
- const uniqueProcesses = new Map;
10135
- for (const process2 of processes) {
10136
- if (!process2.harness.trim() || !Number.isInteger(process2.pid) || process2.pid <= 0)
10137
- continue;
10138
- uniqueProcesses.set(`${process2.harness}\x00${process2.pid}`, {
10139
- harness: process2.harness.trim(),
10140
- pid: process2.pid
10141
- });
10142
- }
10143
- const entries = [...uniqueProcesses.values()];
10144
- const visible = entries.slice(0, MAX_FORMATTED_BLOCKING_PROCESSES);
10145
- const rendered = visible.map(({ harness, pid }) => `${harness} (PID ${pid})`);
10146
- const omitted = entries.length - visible.length;
10147
- if (omitted > 0)
10148
- rendered.push(`${omitted} more blocking process(es)`);
10149
- if (rendered.length === 0)
10150
- return "a live harness process";
10151
- if (rendered.length === 1)
10152
- return rendered[0];
10153
- const last = rendered.pop();
10154
- return `${rendered.join(", ")}, and ${last}`;
10155
- }
10156
- function formatFailClosedBlockingMessage(reason) {
10157
- if (reason.kind === "migration_guard") {
10158
- if (reason.unreadableFile) {
10159
- const arm = reason.unreadableArm ?? "io";
10160
- const recovery = arm === "io" ? `If no OpenCode server is running, it is safe to delete ${reason.unreadableFile} and retry.` : `The file may be a recent incomplete write; retry after the file is older than the ten-minute grace window, or stop OpenCode before deleting it.`;
10161
- return [
10162
- `Magic Context cannot migrate the shared database because RPC discovery file ${reason.unreadableFile} is uncertain (${arm} arm), so the absence of a live OpenCode server cannot be proven.`,
10163
- recovery,
10164
- `Recovery: ${FAIL_CLOSED_DOCTOR_COMMAND}`
10165
- ].join(" ");
10166
- }
10167
- return [
10168
- `Magic Context cannot migrate the shared database because ${formatFailClosedBlockingProcesses(reason.blockingProcesses)} may be running an older Magic Context build that would fail against the migrated database.`,
10169
- "Restart the blocking process (it will pick up the new build and migrate on start), or shut it down and retry.",
10170
- `Recovery: ${FAIL_CLOSED_DOCTOR_COMMAND}`
10171
- ].join(" ");
10172
- }
10173
- if (reason.kind === "schema_fence") {
10174
- return [
10175
- `Magic Context cannot operate: this Magic Context build is older than the database; upgrade/restart this harness (upstream migration lane v${reason.persistedVersion}, build supports through v${reason.supportedVersion}).`,
10176
- `Recovery: ${FAIL_CLOSED_DOCTOR_COMMAND}`
10177
- ].join(" ");
10178
- }
10179
- const cause = reason.cause.trim().length > 0 ? reason.cause.trim() : "unknown storage error";
10180
- return [
10181
- `Magic Context cannot operate: persistent storage failed (${cause}).`,
10182
- "The plugin will not silently degrade to native compaction while enabled.",
10183
- `Recovery: ${FAIL_CLOSED_DOCTOR_COMMAND}`
10184
- ].join(" ");
10185
- }
10186
- function createFailClosedBlockingError(reason, options) {
10187
- return new FailClosedBlockingError(formatFailClosedBlockingMessage(reason), reason, options);
10188
- }
10189
- function isFailClosedBlockingError(error) {
10190
- return error instanceof FailClosedBlockingError || typeof error === "object" && error !== null && error.name === "FailClosedBlockingError" && error.code === "FAIL_CLOSED_BLOCKING";
10191
- }
10192
- function shouldBypassFailClosedBlock(input) {
10193
- if (input.isPiSubagentEnv === true)
10194
- return true;
10195
- if (input.isInternalChildSession === true)
10196
- return true;
10197
- const agent = typeof input.agent === "string" ? input.agent.trim() : "";
10198
- if (agent.length === 0)
10199
- return false;
10200
- if (OPENCODE_INTERNAL_AGENT_NAMES.has(agent))
10201
- return true;
10202
- if (isMagicContextHiddenAgentName(agent))
10203
- return true;
10204
- return false;
10205
- }
10206
- function resolveAgentNameFromMessages(messages) {
10207
- for (let i = messages.length - 1;i >= 0; i -= 1) {
10208
- const info = messages[i]?.info;
10209
- if (!info || typeof info !== "object")
10210
- continue;
10211
- const agent = info.agent;
10212
- if (typeof agent === "string" && agent.length > 0)
10213
- return agent;
10214
- }
10215
- return;
10216
- }
10217
- function createFailClosedController(options) {
10218
- const reprobeEveryN = Math.max(1, options?.reprobeEveryN ?? FAIL_CLOSED_REPROBE_EVERY_N);
10219
- let reason = null;
10220
- let blockedPassCount = 0;
10221
- return {
10222
- arm(next) {
10223
- reason = next;
10224
- blockedPassCount = 0;
10225
- },
10226
- clear() {
10227
- reason = null;
10228
- blockedPassCount = 0;
10229
- },
10230
- isArmed() {
10231
- return reason !== null;
10232
- },
10233
- getReason() {
10234
- return reason;
10235
- },
10236
- async enforce(input) {
10237
- if (!reason)
10238
- return;
10239
- if (!input.blockingEnabled)
10240
- return;
10241
- if (input.exempt)
10242
- return;
10243
- blockedPassCount += 1;
10244
- const shouldReprobe = typeof input.tryReopen === "function" && (blockedPassCount === 1 || blockedPassCount % reprobeEveryN === 0);
10245
- if (shouldReprobe) {
10246
- try {
10247
- const healed = await input.tryReopen?.();
10248
- if (healed) {
10249
- reason = null;
10250
- blockedPassCount = 0;
10251
- return;
10252
- }
10253
- } catch {}
10254
- }
10255
- const blockedReason = reason;
10256
- if (!blockedReason)
10257
- return;
10258
- throw createFailClosedBlockingError(blockedReason);
10259
- }
10260
- };
10261
- }
10262
- var lastHookInitFailure = null;
10263
- function recordHookInitFailure(failure) {
10264
- lastHookInitFailure = failure;
10265
- }
10266
- function clearHookInitFailure() {
10267
- lastHookInitFailure = null;
10268
- }
10269
- function getLastHookInitFailure() {
10270
- return lastHookInitFailure;
10271
- }
10272
-
10273
10193
  // src/features/magic-context/session-project-backfill.ts
10274
10194
  import { randomUUID } from "node:crypto";
10275
10195
  import { existsSync as existsSync4 } from "node:fs";
@@ -11523,7 +11443,10 @@ var CONNECT_BACKOFF_INITIAL_MS = 1000;
11523
11443
  var CONNECT_BACKOFF_MAX_MS = 30000;
11524
11444
  var HANDSHAKE_TIMEOUT_MS = 2000;
11525
11445
  var MODULE_SEND_TIMEOUT_MS = 15000;
11446
+ var TRANSFORM_SEND_TIMEOUT_MS = 5000;
11447
+ var MAX_WRAPUP_REQUEST_BUDGET_MS = 3800000;
11526
11448
  var SERIAL_LANE_MAX_WAITERS = 16;
11449
+ var SERIAL_LANE_MAX_WAITERS_PER_SESSION = 8;
11527
11450
  var SERIAL_LANE_MIN_REMAINING_MS = 25;
11528
11451
  var CANONICAL_ROOT_CACHE_MAX_ENTRIES = 256;
11529
11452
  function getDefaultConnectionFile() {
@@ -11558,15 +11481,24 @@ function isConnectionFailure(error) {
11558
11481
  if (error instanceof SocketClosedError || error instanceof SocketTimeoutError || error instanceof StaleRouteHandleError || isConsumerReconnectTransient(error) || isStaleOrDeadRouteFailure(error)) {
11559
11482
  return true;
11560
11483
  }
11561
- return errorChainSome(error, (current) => [
11562
- "ENOENT",
11563
- "ECONNREFUSED",
11564
- "ECONNRESET",
11565
- "EPIPE",
11566
- "ETIMEDOUT",
11567
- "request_deadline",
11568
- "SUBC_CONNECTION_BACKOFF"
11569
- ].includes(typeof current.code === "string" ? current.code : ""));
11484
+ return errorChainSome(error, (current) => {
11485
+ const code = typeof current.code === "string" ? current.code : "";
11486
+ const message = typeof current.message === "string" ? current.message : "";
11487
+ return [
11488
+ "ENOENT",
11489
+ "ECONNREFUSED",
11490
+ "ECONNRESET",
11491
+ "EPIPE",
11492
+ "ETIMEDOUT",
11493
+ "request_deadline",
11494
+ "deadline_exceeded_no_drop_observed",
11495
+ "connection_dropped",
11496
+ "SUBC_CONNECTION_BACKOFF"
11497
+ ].includes(code) || /\bclient closed\b|\bconnection closed\b|\bclosed the connection\b/i.test(message);
11498
+ });
11499
+ }
11500
+ function isModuleTransportGenerationChangedResult(value) {
11501
+ return isRecord(value) && value.transport_status === "connection_generation_changed" && typeof value.previous_generation === "number" && typeof value.current_generation === "number";
11570
11502
  }
11571
11503
 
11572
11504
  class SubcModuleTransport {
@@ -11576,15 +11508,31 @@ class SubcModuleTransport {
11576
11508
  routeSessionPrefix;
11577
11509
  client = null;
11578
11510
  routes = new Map;
11511
+ routeOpenings = new Map;
11579
11512
  canonicalRootCache = new Map;
11580
- activeSession = null;
11513
+ sessionLanes = new Map;
11514
+ queuedLaneWaiters = 0;
11515
+ wrapupSessions = new Map;
11581
11516
  nextProbeMs = 0;
11582
- laneReleaseCallbacks = [];
11517
+ connectionPromise = null;
11583
11518
  authorityProjectRoot = "";
11584
11519
  authorityBindRoot = "";
11585
11520
  backoffMs = CONNECT_BACKOFF_INITIAL_MS;
11586
11521
  connectionGeneration = 0;
11522
+ stateSyncCapabilityCache = null;
11523
+ getCachedStateSyncCapabilities() {
11524
+ const cached = this.stateSyncCapabilityCache;
11525
+ if (!cached || cached.generation !== this.connectionGeneration)
11526
+ return;
11527
+ return cached.capabilities;
11528
+ }
11529
+ invalidateStateSyncCapabilities() {
11530
+ this.stateSyncCapabilityCache = null;
11531
+ }
11587
11532
  async stateSyncCapabilities(args) {
11533
+ const cached = this.getCachedStateSyncCapabilities();
11534
+ if (cached)
11535
+ return cached;
11588
11536
  const response = await this.call({
11589
11537
  sessionId: args.sessionId,
11590
11538
  projectRoot: args.projectRoot,
@@ -11594,7 +11542,9 @@ class SubcModuleTransport {
11594
11542
  const raw = isRecord(response) ? response : {};
11595
11543
  const value = isRecord(raw.result) ? raw.result : raw;
11596
11544
  const epochs = isRecord(value.epochs) ? value.epochs : {};
11597
- return { state_sync_deltas: epochs.state_sync_deltas === true };
11545
+ const capabilities = { state_sync_deltas: epochs.state_sync_deltas === true };
11546
+ this.stateSyncCapabilityCache = { generation: this.connectionGeneration, capabilities };
11547
+ return capabilities;
11598
11548
  }
11599
11549
  constructor(connectionFile, moduleId = DEFAULT_MODULE_ID, requestTimeoutMs = MODULE_SEND_TIMEOUT_MS, routeSessionPrefix = "") {
11600
11550
  this.connectionFile = connectionFile ?? getDefaultConnectionFile();
@@ -11602,27 +11552,60 @@ class SubcModuleTransport {
11602
11552
  this.requestTimeoutMs = requestTimeoutMs;
11603
11553
  this.routeSessionPrefix = routeSessionPrefix;
11604
11554
  }
11605
- laneTimeoutError() {
11606
- const error = new Error("module transport deadline expired while queued");
11555
+ deadlineError(detail) {
11556
+ const error = new Error(`module transport deadline expired ${detail}`);
11607
11557
  error.code = "ETIMEDOUT";
11608
11558
  return error;
11609
11559
  }
11610
- laneRelease() {
11560
+ laneTimeoutError() {
11561
+ return this.deadlineError("while queued");
11562
+ }
11563
+ connectionChangedError(detail) {
11564
+ const error = new Error(detail);
11565
+ error.code = "ECONNRESET";
11566
+ return error;
11567
+ }
11568
+ async beforeDeadline(operation, deadlineMs, detail) {
11569
+ const remainingMs = deadlineMs - Date.now();
11570
+ if (remainingMs <= 0)
11571
+ throw this.deadlineError(detail);
11572
+ let timer;
11573
+ try {
11574
+ return await Promise.race([
11575
+ operation,
11576
+ new Promise((_resolve, reject) => {
11577
+ timer = setTimeout(() => reject(this.deadlineError(detail)), remainingMs);
11578
+ })
11579
+ ]);
11580
+ } finally {
11581
+ if (timer)
11582
+ clearTimeout(timer);
11583
+ }
11584
+ }
11585
+ cleanupLane(sessionId, lane) {
11586
+ if (!lane.active && lane.waiters.length === 0 && this.sessionLanes.get(sessionId) === lane) {
11587
+ this.sessionLanes.delete(sessionId);
11588
+ }
11589
+ }
11590
+ laneRelease(sessionId, lane) {
11611
11591
  let released = false;
11612
11592
  return () => {
11613
11593
  if (released)
11614
11594
  return;
11615
11595
  released = true;
11616
- this.activeSession = null;
11617
- this.dispatchNextLaneWaiter();
11596
+ lane.active = false;
11597
+ this.dispatchNextLaneWaiter(sessionId, lane);
11618
11598
  };
11619
11599
  }
11620
- dispatchNextLaneWaiter() {
11621
- if (this.activeSession !== null)
11600
+ dispatchNextLaneWaiter(sessionId, lane) {
11601
+ if (lane.active)
11622
11602
  return;
11623
- while (this.laneReleaseCallbacks.length > 0) {
11624
- const waiter = this.laneReleaseCallbacks.shift();
11625
- if (!waiter || waiter.settled)
11603
+ while (lane.waiters.length > 0) {
11604
+ const waiter = lane.waiters.shift();
11605
+ if (!waiter)
11606
+ continue;
11607
+ this.queuedLaneWaiters = Math.max(0, this.queuedLaneWaiters - 1);
11608
+ if (waiter.settled)
11626
11609
  continue;
11627
11610
  waiter.settled = true;
11628
11611
  clearTimeout(waiter.timer);
@@ -11635,10 +11618,16 @@ class SubcModuleTransport {
11635
11618
  waiter.reject(this.laneTimeoutError());
11636
11619
  continue;
11637
11620
  }
11638
- this.activeSession = waiter.sessionId;
11639
- waiter.resolve(this.laneRelease());
11621
+ lane.active = true;
11622
+ waiter.resolve(this.laneRelease(sessionId, lane));
11640
11623
  return;
11641
11624
  }
11625
+ this.cleanupLane(sessionId, lane);
11626
+ }
11627
+ queueFullError() {
11628
+ const error = new Error("module transport queue is full");
11629
+ error.code = "EBUSY";
11630
+ return error;
11642
11631
  }
11643
11632
  acquireCorrectnessLane(sessionId, signal, deadlineMs) {
11644
11633
  if (signal?.aborted) {
@@ -11647,14 +11636,14 @@ class SubcModuleTransport {
11647
11636
  if (deadlineMs - Date.now() < SERIAL_LANE_MIN_REMAINING_MS) {
11648
11637
  return Promise.reject(this.laneTimeoutError());
11649
11638
  }
11650
- if (this.activeSession === null && this.laneReleaseCallbacks.length === 0) {
11651
- this.activeSession = sessionId;
11652
- return Promise.resolve(this.laneRelease());
11639
+ const lane = this.sessionLanes.get(sessionId) ?? { active: false, waiters: [] };
11640
+ this.sessionLanes.set(sessionId, lane);
11641
+ if (!lane.active && lane.waiters.length === 0) {
11642
+ lane.active = true;
11643
+ return Promise.resolve(this.laneRelease(sessionId, lane));
11653
11644
  }
11654
- if (this.laneReleaseCallbacks.length >= SERIAL_LANE_MAX_WAITERS) {
11655
- const error = new Error("module transport queue is full");
11656
- error.code = "EBUSY";
11657
- return Promise.reject(error);
11645
+ if (this.queuedLaneWaiters >= SERIAL_LANE_MAX_WAITERS || lane.waiters.length >= SERIAL_LANE_MAX_WAITERS_PER_SESSION) {
11646
+ return Promise.reject(this.queueFullError());
11658
11647
  }
11659
11648
  return new Promise((resolve3, reject) => {
11660
11649
  const waiter = {};
@@ -11664,14 +11653,14 @@ class SubcModuleTransport {
11664
11653
  waiter.settled = true;
11665
11654
  clearTimeout(waiter.timer);
11666
11655
  signal?.removeEventListener("abort", waiter.onAbort);
11667
- const index = this.laneReleaseCallbacks.indexOf(waiter);
11668
- if (index >= 0)
11669
- this.laneReleaseCallbacks.splice(index, 1);
11656
+ const index = lane.waiters.indexOf(waiter);
11657
+ if (index >= 0) {
11658
+ lane.waiters.splice(index, 1);
11659
+ this.queuedLaneWaiters = Math.max(0, this.queuedLaneWaiters - 1);
11660
+ }
11670
11661
  reject(error);
11671
- if (this.activeSession === null)
11672
- this.dispatchNextLaneWaiter();
11662
+ this.cleanupLane(sessionId, lane);
11673
11663
  };
11674
- waiter.sessionId = sessionId;
11675
11664
  waiter.signal = signal;
11676
11665
  waiter.deadlineMs = deadlineMs;
11677
11666
  waiter.resolve = resolve3;
@@ -11680,46 +11669,78 @@ class SubcModuleTransport {
11680
11669
  waiter.onAbort = () => removeAndReject(signal?.reason ?? new Error("module transport call aborted"));
11681
11670
  waiter.timer = setTimeout(() => removeAndReject(this.laneTimeoutError()), Math.max(0, deadlineMs - Date.now()));
11682
11671
  signal?.addEventListener("abort", waiter.onAbort, { once: true });
11683
- this.laneReleaseCallbacks.push(waiter);
11672
+ lane.waiters.push(waiter);
11673
+ this.queuedLaneWaiters += 1;
11684
11674
  });
11685
11675
  }
11686
11676
  async call(args) {
11687
- const deadlineMs = Date.now() + (args.timeoutMs ?? this.requestTimeoutMs);
11688
- const releaseLane = await this.acquireCorrectnessLane(args.sessionId, args.signal, deadlineMs);
11689
- const onAbort = () => this.invalidateConnection();
11677
+ const wrapupInFlight = (this.wrapupSessions.get(args.sessionId) ?? 0) > 0;
11678
+ const attemptTimeoutMs = args.timeoutMs ?? (args.method === "session.wrapup" || args.method === "session.status" && wrapupInFlight ? MAX_WRAPUP_REQUEST_BUDGET_MS : args.method === "transform" ? Math.min(this.requestTimeoutMs, TRANSFORM_SEND_TIMEOUT_MS) : this.requestTimeoutMs);
11679
+ const tracksWrapup = args.method === "session.wrapup";
11680
+ if (tracksWrapup) {
11681
+ this.wrapupSessions.set(args.sessionId, (this.wrapupSessions.get(args.sessionId) ?? 0) + 1);
11682
+ }
11683
+ const finishWrapupTracking = () => {
11684
+ if (!tracksWrapup)
11685
+ return;
11686
+ const remaining = (this.wrapupSessions.get(args.sessionId) ?? 1) - 1;
11687
+ if (remaining > 0)
11688
+ this.wrapupSessions.set(args.sessionId, remaining);
11689
+ else
11690
+ this.wrapupSessions.delete(args.sessionId);
11691
+ };
11692
+ const laneDeadlineMs = Date.now() + attemptTimeoutMs;
11693
+ let releaseLane;
11694
+ try {
11695
+ releaseLane = await this.acquireCorrectnessLane(args.sessionId, args.signal, laneDeadlineMs);
11696
+ } catch (error) {
11697
+ finishWrapupTracking();
11698
+ throw error;
11699
+ }
11700
+ let activeAttemptClient = null;
11701
+ const onAbort = () => this.invalidateConnection(activeAttemptClient ?? this.client);
11690
11702
  args.signal?.addEventListener("abort", onAbort, { once: true });
11691
11703
  try {
11692
11704
  for (let attempt = 0;attempt < 2; attempt += 1) {
11705
+ activeAttemptClient = null;
11693
11706
  let ensuredRoute = null;
11694
11707
  try {
11695
11708
  if (args.signal?.aborted) {
11696
11709
  throw args.signal.reason ?? new Error("module transport call aborted");
11697
11710
  }
11698
- const remainingMs = deadlineMs - Date.now();
11699
- if (remainingMs < SERIAL_LANE_MIN_REMAINING_MS)
11700
- throw this.laneTimeoutError();
11701
- ensuredRoute = await this.ensureRoute(args.sessionId, args.projectRoot);
11711
+ const attemptDeadlineMs = Date.now() + attemptTimeoutMs;
11712
+ ensuredRoute = await this.ensureRoute(args.sessionId, args.projectRoot, attemptDeadlineMs);
11713
+ activeAttemptClient = ensuredRoute.client;
11702
11714
  if (args.signal?.aborted) {
11703
11715
  throw args.signal.reason ?? new Error("module transport call aborted");
11704
11716
  }
11705
- return await ensuredRoute.client.request(ensuredRoute.route, args.body, {
11717
+ const response = await this.beforeDeadline(ensuredRoute.client.request(ensuredRoute.route, args.body, {
11706
11718
  priority: Priority.Background,
11707
11719
  admissionClass: AdmissionClass.Normal,
11708
- timeoutMs: Math.max(1, deadlineMs - Date.now())
11709
- });
11720
+ timeoutMs: Math.max(1, attemptDeadlineMs - Date.now())
11721
+ }), attemptDeadlineMs, "waiting for the module response");
11722
+ if (this.client !== ensuredRoute.client || this.connectionGeneration !== ensuredRoute.generation) {
11723
+ throw this.connectionChangedError("subc connection changed while awaiting the module response");
11724
+ }
11725
+ return response;
11710
11726
  } catch (error) {
11711
- const staleOrDeadRoute = isStaleOrDeadRouteFailure(error);
11712
- if (staleOrDeadRoute) {
11727
+ if (isConnectionFailure(error)) {
11728
+ const previousGeneration = ensuredRoute?.generation ?? this.connectionGeneration;
11713
11729
  if (ensuredRoute) {
11714
11730
  this.dropRoute(ensuredRoute.routeKey, ensuredRoute.route);
11715
11731
  this.invalidateConnection(ensuredRoute.client);
11716
11732
  } else {
11717
11733
  this.invalidateConnection();
11718
11734
  }
11735
+ if (args.generationSensitive && !args.signal?.aborted) {
11736
+ return {
11737
+ transport_status: "connection_generation_changed",
11738
+ previous_generation: previousGeneration,
11739
+ current_generation: this.connectionGeneration
11740
+ };
11741
+ }
11719
11742
  if (attempt === 0 && !args.signal?.aborted)
11720
11743
  continue;
11721
- } else if (isConnectionFailure(error)) {
11722
- this.invalidateConnection(ensuredRoute?.client);
11723
11744
  }
11724
11745
  throw error;
11725
11746
  }
@@ -11727,6 +11748,7 @@ class SubcModuleTransport {
11727
11748
  throw new Error("module transport route retry exhausted");
11728
11749
  } finally {
11729
11750
  args.signal?.removeEventListener("abort", onAbort);
11751
+ finishWrapupTracking();
11730
11752
  releaseLane();
11731
11753
  }
11732
11754
  }
@@ -11817,11 +11839,11 @@ class SubcModuleTransport {
11817
11839
  });
11818
11840
  }
11819
11841
  }
11820
- if (routes.length === 0 && this.activeSession === sessionId) {
11842
+ if (routes.length === 0 && this.sessionLanes.get(sessionId)?.active) {
11821
11843
  this.invalidateConnection(client);
11822
11844
  }
11823
11845
  }
11824
- async ensureRoute(sessionId, rawProjectRoot) {
11846
+ async ensureRoute(sessionId, rawProjectRoot, deadlineMs = Date.now() + this.requestTimeoutMs) {
11825
11847
  const projectRoot = this.canonicalRoot(rawProjectRoot);
11826
11848
  const routeKey = `${sessionId}\x00${projectRoot}`;
11827
11849
  const client = await this.ensureConnected();
@@ -11832,23 +11854,36 @@ class SubcModuleTransport {
11832
11854
  }
11833
11855
  if (existing)
11834
11856
  this.routes.delete(routeKey);
11835
- const target = { kind: "tool_provider", module_id: this.moduleId };
11836
- const identity = {
11837
- project_root: projectRoot,
11838
- harness: getHarness(),
11839
- session: `${this.routeSessionPrefix}${sessionId}`
11840
- };
11841
- const route = await client.routeOpen(target, identity);
11842
- if (this.client !== client || generation !== this.connectionGeneration) {
11843
- await client.closeRoute(route).catch(() => {
11844
- return;
11845
- });
11846
- const error = new Error("subc connection changed while opening module route");
11847
- error.code = "ECONNRESET";
11848
- throw error;
11857
+ const opening = this.routeOpenings.get(routeKey);
11858
+ if (opening?.client === client && opening.generation === generation) {
11859
+ return await opening.promise;
11860
+ }
11861
+ const promise = (async () => {
11862
+ const target = { kind: "tool_provider", module_id: this.moduleId };
11863
+ const identity = {
11864
+ project_root: projectRoot,
11865
+ harness: getHarness(),
11866
+ session: `${this.routeSessionPrefix}${sessionId}`
11867
+ };
11868
+ const route = await this.beforeDeadline(client.routeOpen(target, identity), deadlineMs, "opening the module route");
11869
+ if (this.client !== client || generation !== this.connectionGeneration) {
11870
+ await client.closeRoute(route).catch(() => {
11871
+ return;
11872
+ });
11873
+ throw this.connectionChangedError("subc connection changed while opening module route");
11874
+ }
11875
+ this.routes.set(routeKey, { route, generation });
11876
+ return { client, route, routeKey, generation };
11877
+ })();
11878
+ const routeOpening = { client, generation, promise };
11879
+ this.routeOpenings.set(routeKey, routeOpening);
11880
+ try {
11881
+ return await promise;
11882
+ } finally {
11883
+ if (this.routeOpenings.get(routeKey) === routeOpening) {
11884
+ this.routeOpenings.delete(routeKey);
11885
+ }
11849
11886
  }
11850
- this.routes.set(routeKey, { route, generation });
11851
- return { client, route, routeKey, generation };
11852
11887
  }
11853
11888
  dropRoute(routeKey, route) {
11854
11889
  const existing = this.routes.get(routeKey);
@@ -11876,9 +11911,17 @@ class SubcModuleTransport {
11876
11911
  }
11877
11912
  return resolved;
11878
11913
  }
11914
+ connectClient() {
11915
+ return SubcClient.connect({
11916
+ connectionFile: this.connectionFile,
11917
+ handshakeTimeoutMs: HANDSHAKE_TIMEOUT_MS
11918
+ });
11919
+ }
11879
11920
  async ensureConnected() {
11880
11921
  if (this.client)
11881
11922
  return this.client;
11923
+ if (this.connectionPromise)
11924
+ return await this.connectionPromise;
11882
11925
  const now = Date.now();
11883
11926
  if (now < this.nextProbeMs) {
11884
11927
  const error = new Error(`subc connection backoff active until ${this.nextProbeMs}`);
@@ -11886,37 +11929,44 @@ class SubcModuleTransport {
11886
11929
  throw error;
11887
11930
  }
11888
11931
  const generation = this.connectionGeneration;
11889
- let candidate = null;
11890
- try {
11891
- candidate = await SubcClient.connect({
11892
- connectionFile: this.connectionFile,
11893
- handshakeTimeoutMs: HANDSHAKE_TIMEOUT_MS
11894
- });
11895
- if (generation !== this.connectionGeneration) {
11896
- candidate.close();
11897
- const error = new Error("subc connection attempt was superseded");
11898
- error.code = "ECONNRESET";
11932
+ const connecting = (async () => {
11933
+ let candidate = null;
11934
+ try {
11935
+ candidate = await this.connectClient();
11936
+ if (generation !== this.connectionGeneration) {
11937
+ candidate.close();
11938
+ throw this.connectionChangedError("subc connection attempt was superseded");
11939
+ }
11940
+ this.client = candidate;
11941
+ this.routes.clear();
11942
+ this.backoffMs = CONNECT_BACKOFF_INITIAL_MS;
11943
+ this.nextProbeMs = 0;
11944
+ return candidate;
11945
+ } catch (error) {
11946
+ candidate?.close();
11947
+ if (generation === this.connectionGeneration)
11948
+ this.invalidateConnection();
11949
+ this.nextProbeMs = Date.now() + this.backoffMs;
11950
+ this.backoffMs = Math.min(this.backoffMs * 2, CONNECT_BACKOFF_MAX_MS);
11899
11951
  throw error;
11900
11952
  }
11901
- this.client = candidate;
11902
- this.routes.clear();
11903
- this.backoffMs = CONNECT_BACKOFF_INITIAL_MS;
11904
- this.nextProbeMs = 0;
11905
- return candidate;
11906
- } catch (error) {
11907
- candidate?.close();
11908
- this.invalidateConnection();
11909
- this.nextProbeMs = Date.now() + this.backoffMs;
11910
- this.backoffMs = Math.min(this.backoffMs * 2, CONNECT_BACKOFF_MAX_MS);
11911
- throw error;
11953
+ })();
11954
+ this.connectionPromise = connecting;
11955
+ try {
11956
+ return await connecting;
11957
+ } finally {
11958
+ if (this.connectionPromise === connecting)
11959
+ this.connectionPromise = null;
11912
11960
  }
11913
11961
  }
11914
11962
  invalidateConnection(client = this.client) {
11915
- if (client && this.client && client !== this.client)
11963
+ if (client && this.client !== client)
11916
11964
  return;
11917
11965
  this.connectionGeneration += 1;
11966
+ this.invalidateStateSyncCapabilities();
11918
11967
  this.client = null;
11919
11968
  this.routes.clear();
11969
+ this.routeOpenings.clear();
11920
11970
  client?.close();
11921
11971
  }
11922
11972
  }
@@ -11971,13 +12021,15 @@ function rowKeys(leaseKey) {
11971
12021
  return {
11972
12022
  holder: "dreaming_lease_holder",
11973
12023
  heartbeat: "dreaming_lease_heartbeat",
11974
- expiry: "dreaming_lease_expiry"
12024
+ expiry: "dreaming_lease_expiry",
12025
+ generation: "dreaming_lease_generation"
11975
12026
  };
11976
12027
  }
11977
12028
  return {
11978
12029
  holder: `lease:${leaseKey}:holder`,
11979
12030
  heartbeat: `lease:${leaseKey}:heartbeat`,
11980
- expiry: `lease:${leaseKey}:expiry`
12031
+ expiry: `lease:${leaseKey}:expiry`,
12032
+ generation: `lease:${leaseKey}:generation`
11981
12033
  };
11982
12034
  }
11983
12035
  function getLeaseExpiry(db, keys) {
@@ -11995,6 +12047,13 @@ function isLeaseActive(db, leaseKey = DREAMING_LEASE_KEY) {
11995
12047
  function getLeaseHolder(db, leaseKey = DREAMING_LEASE_KEY) {
11996
12048
  return getDreamState(db, rowKeys(leaseKey).holder);
11997
12049
  }
12050
+ function getLeaseGeneration(db, leaseKey = DREAMING_LEASE_KEY) {
12051
+ const value = getDreamState(db, rowKeys(leaseKey).generation);
12052
+ if (!value)
12053
+ return null;
12054
+ const generation = Number(value);
12055
+ return Number.isSafeInteger(generation) && generation > 0 ? generation : null;
12056
+ }
11998
12057
  function peekLeaseHolderAndExpiry(db, expectedHolder, leaseKey = DREAMING_LEASE_KEY) {
11999
12058
  const keys = rowKeys(leaseKey);
12000
12059
  const holder = getDreamState(db, keys.holder);
@@ -12006,6 +12065,9 @@ function peekLeaseHolderAndExpiry(db, expectedHolder, leaseKey = DREAMING_LEASE_
12006
12065
  const expiry = Number(expiryStr);
12007
12066
  return Number.isFinite(expiry) && expiry >= Date.now();
12008
12067
  }
12068
+ function leaseOwnershipMatches(db, expectedHolder, expectedGeneration, leaseKey = DREAMING_LEASE_KEY) {
12069
+ return getLeaseGeneration(db, leaseKey) === expectedGeneration && peekLeaseHolderAndExpiry(db, expectedHolder, leaseKey);
12070
+ }
12009
12071
  function runImmediate(db, body) {
12010
12072
  db.exec("BEGIN IMMEDIATE");
12011
12073
  let committed = false;
@@ -12022,26 +12084,30 @@ function runImmediate(db, body) {
12022
12084
  }
12023
12085
  }
12024
12086
  }
12025
- function acquireLease(db, holderId, leaseKey = DREAMING_LEASE_KEY) {
12087
+ function acquireLeaseWithAcquisition(db, holderId, leaseKey = DREAMING_LEASE_KEY) {
12026
12088
  const keys = rowKeys(leaseKey);
12027
12089
  return runImmediate(db, () => {
12028
- if (isLeaseActive(db, leaseKey)) {
12029
- const existingHolder = getLeaseHolder(db, leaseKey);
12030
- if (existingHolder && existingHolder !== holderId) {
12031
- return false;
12032
- }
12090
+ const existingHolder = getLeaseHolder(db, leaseKey);
12091
+ if (isLeaseActive(db, leaseKey) && existingHolder && existingHolder !== holderId) {
12092
+ return null;
12033
12093
  }
12034
12094
  const now = Date.now();
12095
+ const priorGeneration = getLeaseGeneration(db, leaseKey) ?? 0;
12096
+ const generation = existingHolder === holderId ? Math.max(1, priorGeneration) : priorGeneration + 1;
12035
12097
  setDreamState(db, keys.holder, holderId);
12036
12098
  setDreamState(db, keys.heartbeat, String(now));
12037
12099
  setDreamState(db, keys.expiry, String(now + LEASE_DURATION_MS));
12038
- return true;
12100
+ setDreamState(db, keys.generation, String(generation));
12101
+ return { acquiredAt: now, generation };
12039
12102
  });
12040
12103
  }
12041
- function renewLease(db, holderId, leaseKey = DREAMING_LEASE_KEY) {
12104
+ function acquireLease(db, holderId, leaseKey = DREAMING_LEASE_KEY) {
12105
+ return acquireLeaseWithAcquisition(db, holderId, leaseKey) !== null;
12106
+ }
12107
+ function renewLease(db, holderId, leaseKey = DREAMING_LEASE_KEY, expectedGeneration) {
12042
12108
  const keys = rowKeys(leaseKey);
12043
12109
  return runImmediate(db, () => {
12044
- if (getLeaseHolder(db, leaseKey) !== holderId || !isLeaseActive(db, leaseKey)) {
12110
+ if (getLeaseHolder(db, leaseKey) !== holderId || !isLeaseActive(db, leaseKey) || expectedGeneration !== undefined && getLeaseGeneration(db, leaseKey) !== expectedGeneration) {
12045
12111
  return false;
12046
12112
  }
12047
12113
  const now = Date.now();
@@ -12059,9 +12125,12 @@ function runLeaseGuardedWrite(db, holderId, leaseKey, fn) {
12059
12125
  });
12060
12126
  }
12061
12127
  var LEASE_HEARTBEAT_INTERVAL_MS = 60 * 1000;
12062
- function startLeaseHeartbeat(db, holderId, leaseKey, onLost, intervalMs = LEASE_HEARTBEAT_INTERVAL_MS) {
12128
+ function startLeaseHeartbeat(db, holderId, leaseKey, onLost, intervalOrAcquisition = LEASE_HEARTBEAT_INTERVAL_MS) {
12129
+ const intervalMs = typeof intervalOrAcquisition === "number" ? intervalOrAcquisition : LEASE_HEARTBEAT_INTERVAL_MS;
12130
+ const acquisition = typeof intervalOrAcquisition === "number" ? undefined : intervalOrAcquisition;
12063
12131
  let lost = false;
12064
- let lastConfirmedAt = Date.now();
12132
+ let expectedGeneration = acquisition?.generation ?? getLeaseGeneration(db, leaseKey);
12133
+ let lastConfirmedAt = acquisition?.acquiredAt ?? Date.now();
12065
12134
  const declareLost = (reason) => {
12066
12135
  if (lost)
12067
12136
  return;
@@ -12072,15 +12141,25 @@ function startLeaseHeartbeat(db, holderId, leaseKey, onLost, intervalMs = LEASE_
12072
12141
  if (lost)
12073
12142
  return;
12074
12143
  try {
12075
- if (renewLease(db, holderId, leaseKey)) {
12144
+ if (renewLease(db, holderId, leaseKey, expectedGeneration === null ? undefined : expectedGeneration)) {
12076
12145
  lastConfirmedAt = Date.now();
12077
12146
  return;
12078
12147
  }
12148
+ if (expectedGeneration !== null && getLeaseGeneration(db, leaseKey) !== expectedGeneration) {
12149
+ declareLost("lease generation changed — another holder acquired it");
12150
+ return;
12151
+ }
12079
12152
  if (Date.now() - lastConfirmedAt > LEASE_DURATION_MS) {
12080
12153
  declareLost("lease lapsed past TTL — another holder may have run");
12081
12154
  return;
12082
12155
  }
12083
- if (acquireLease(db, holderId, leaseKey)) {
12156
+ const reacquired = acquireLeaseWithAcquisition(db, holderId, leaseKey);
12157
+ if (reacquired) {
12158
+ if (expectedGeneration !== null && reacquired.generation !== expectedGeneration) {
12159
+ declareLost("lease generation changed during reacquisition");
12160
+ return;
12161
+ }
12162
+ expectedGeneration = reacquired.generation;
12084
12163
  lastConfirmedAt = Date.now();
12085
12164
  return;
12086
12165
  }
@@ -12587,7 +12666,7 @@ var DREAMER_DOCS_AGENT = "dreamer-docs";
12587
12666
  var DREAMER_REVIEWER_AGENT = "dreamer-reviewer";
12588
12667
 
12589
12668
  // src/features/magic-context/mural/compress-cues.ts
12590
- import { createHash as createHash2 } from "node:crypto";
12669
+ import { createHash as createHash3 } from "node:crypto";
12591
12670
 
12592
12671
  // src/features/magic-context/dreamer/manifest-parser.ts
12593
12672
  function extractCompleteManifestBody(text, rootName) {
@@ -12623,6 +12702,16 @@ function assertManifestCoversExactly(ids, expectedIds, rootName) {
12623
12702
  }
12624
12703
 
12625
12704
  // src/features/magic-context/dreamer/module-apply.ts
12705
+ class DreamerModuleBusyError extends Error {
12706
+ state;
12707
+ transient = true;
12708
+ constructor(state) {
12709
+ super(`Rust memory authority is ${state}; dreamer mutation deferred until authority settles.`);
12710
+ this.state = state;
12711
+ this.name = "DreamerModuleBusyError";
12712
+ }
12713
+ }
12714
+
12626
12715
  class DreamerModuleFailureError extends Error {
12627
12716
  transient = true;
12628
12717
  constructor(operation, cause) {
@@ -12644,9 +12733,12 @@ async function resolveDreamerModuleRoute(args) {
12644
12733
  projectRoot: args.projectRoot,
12645
12734
  domain: "memories"
12646
12735
  });
12647
- if (result.authority?.state !== "MODULE")
12736
+ const authority = result.authority;
12737
+ if (authority?.state === "DRAINING")
12738
+ throw new DreamerModuleBusyError(authority.state);
12739
+ if (authority?.state !== "MODULE")
12648
12740
  return;
12649
- const generation = result.authority.generation;
12741
+ const generation = authority.generation;
12650
12742
  if (typeof generation !== "number")
12651
12743
  throw new Error("Rust authority status omitted generation");
12652
12744
  return {
@@ -12680,6 +12772,68 @@ function getModuleMemoryIdentities(db, projectIdentity, contextIds) {
12680
12772
  ] : []));
12681
12773
  }
12682
12774
 
12775
+ // src/features/magic-context/dreamer/provider-output-failure.ts
12776
+ import { createHash as createHash2 } from "node:crypto";
12777
+ var MAX_NEAR_ZERO_OUTPUT_TOKENS = 32;
12778
+
12779
+ class DreamerProviderOutputFailureError extends Error {
12780
+ fingerprint;
12781
+ outputTokens;
12782
+ reasoningTokens;
12783
+ transient = true;
12784
+ constructor(fingerprint, outputTokens, reasoningTokens, responseText) {
12785
+ const preview = responseText.trim().replace(/\s+/g, " ").slice(0, 160);
12786
+ super(`dreamer provider-outage completion (output_tokens=${outputTokens}, reasoning_tokens=${reasoningTokens}): ${JSON.stringify(preview)}`);
12787
+ this.fingerprint = fingerprint;
12788
+ this.outputTokens = outputTokens;
12789
+ this.reasoningTokens = reasoningTokens;
12790
+ this.name = "DreamerProviderOutputFailureError";
12791
+ }
12792
+ }
12793
+ function finiteTokenCount(value) {
12794
+ return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : null;
12795
+ }
12796
+ function completionShape(value) {
12797
+ if (!isRecord(value))
12798
+ return null;
12799
+ const info = isRecord(value.info) ? value.info : value;
12800
+ if (info.role !== "assistant")
12801
+ return null;
12802
+ const time = isRecord(info.time) ? info.time : null;
12803
+ const tokens = isRecord(info.tokens) ? info.tokens : null;
12804
+ return {
12805
+ createdAt: typeof time?.created === "number" ? time.created : 0,
12806
+ finish: typeof info.finish === "string" ? info.finish : typeof info.finish_reason === "string" ? info.finish_reason : typeof info.finishReason === "string" ? info.finishReason : null,
12807
+ error: info.error,
12808
+ outputTokens: finiteTokenCount(tokens?.output),
12809
+ reasoningTokens: finiteTokenCount(tokens?.reasoning)
12810
+ };
12811
+ }
12812
+ function latestAssistantCompletion(messages) {
12813
+ if (!Array.isArray(messages))
12814
+ return null;
12815
+ let latest = null;
12816
+ for (const message of messages) {
12817
+ const completion = completionShape(message);
12818
+ if (completion && (!latest || completion.createdAt >= latest.createdAt))
12819
+ latest = completion;
12820
+ }
12821
+ return latest;
12822
+ }
12823
+ function providerOutputFailureFromInvalidManifest(messages, responseText) {
12824
+ const completion = latestAssistantCompletion(messages);
12825
+ if (completion?.finish?.toLowerCase() !== "stop")
12826
+ return null;
12827
+ if (completion.error != null || completion.outputTokens === null || completion.outputTokens > MAX_NEAR_ZERO_OUTPUT_TOKENS || completion.reasoningTokens !== 0) {
12828
+ return null;
12829
+ }
12830
+ const normalized = responseText.trim().replace(/\s+/g, " ").toLowerCase();
12831
+ if (!normalized)
12832
+ return null;
12833
+ const fingerprint = createHash2("sha256").update(normalized).digest("hex").slice(0, 16);
12834
+ return new DreamerProviderOutputFailureError(fingerprint, completion.outputTokens, completion.reasoningTokens, responseText);
12835
+ }
12836
+
12683
12837
  // src/features/magic-context/mural/compress-cues-prompt.ts
12684
12838
  var CUE_BUDGET_HIGH = 90;
12685
12839
  var CUE_BUDGET_LOW = 50;
@@ -12852,7 +13006,7 @@ async function runCompressCues(args) {
12852
13006
  chunks.push(candidates.slice(i, i + COMPRESS_CUES_CHUNK_SIZE));
12853
13007
  }
12854
13008
  const abortController = new AbortController;
12855
- const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => abortController.abort());
13009
+ const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => abortController.abort(), args.leaseAcquisition);
12856
13010
  try {
12857
13011
  let consecutiveTimeouts = 0;
12858
13012
  let timeoutStreakElapsedMs = [];
@@ -12947,7 +13101,14 @@ async function compressOneChunk(args, chunk, sliceMs, signal) {
12947
13101
  const text = extractLatestAssistantText(messages);
12948
13102
  if (!text)
12949
13103
  throw new Error("compress-cues returned no output");
12950
- parseCuesManifest(text);
13104
+ try {
13105
+ parseCuesManifest(text);
13106
+ } catch (error) {
13107
+ const providerFailure = providerOutputFailureFromInvalidManifest(messages, text);
13108
+ if (providerFailure)
13109
+ throw providerFailure;
13110
+ throw error;
13111
+ }
12951
13112
  return text;
12952
13113
  }
12953
13114
  });
@@ -12955,7 +13116,7 @@ async function compressOneChunk(args, chunk, sliceMs, signal) {
12955
13116
  } catch (error) {
12956
13117
  const desc = describeError(error);
12957
13118
  log(`[dreamer] compress-cues chunk failed: ${desc.brief}`, desc.stackHead ? { stackHead: desc.stackHead } : undefined);
12958
- if (signal.aborted)
13119
+ if (signal.aborted || error instanceof DreamerProviderOutputFailureError)
12959
13120
  throw error;
12960
13121
  return {
12961
13122
  compressed: 0,
@@ -13063,7 +13224,7 @@ async function applyCuesThroughModule(args, chunk, manifestText, signal) {
13063
13224
  log(`[dreamer] compress-cues: skipped cue for memory ${entry.id} (${failure.reason}; rejection ${rejectionCount}/${CUE_REJECTION_LATCH_THRESHOLD})`);
13064
13225
  }
13065
13226
  }
13066
- const commandId = `mural-cues:${route.moduleCommandId}:${createHash2("sha256").update(chunk.map((candidate) => candidate.memory.id).join(",")).digest("hex").slice(0, 24)}`;
13227
+ const commandId = `mural-cues:${route.moduleCommandId}:${createHash3("sha256").update(chunk.map((candidate) => candidate.memory.id).join(",")).digest("hex").slice(0, 24)}`;
13067
13228
  let response;
13068
13229
  try {
13069
13230
  response = await route.moduleClient.call({
@@ -13200,7 +13361,7 @@ If no promotions are warranted, return empty arrays. Always consume reviewed can
13200
13361
  const heartbeat = startLeaseHeartbeat(args.db, args.holderId, leaseKey, (reason) => {
13201
13362
  log(`[dreamer] user-memories: lease lost (${reason}) — aborting`);
13202
13363
  abortController.abort();
13203
- });
13364
+ }, args.leaseAcquisition);
13204
13365
  try {
13205
13366
  const createResponse = await createChildSessionWithFence({
13206
13367
  client: args.client,
@@ -13323,7 +13484,7 @@ If no promotions are warranted, return empty arrays. Always consume reviewed can
13323
13484
  }
13324
13485
 
13325
13486
  // src/features/magic-context/dreamer/classify.ts
13326
- import { createHash as createHash3 } from "node:crypto";
13487
+ import { createHash as createHash4 } from "node:crypto";
13327
13488
 
13328
13489
  // src/plugin/rust-tool-backends.ts
13329
13490
  function toolCallIdFromContext(context) {
@@ -13725,7 +13886,7 @@ async function runClassify(args) {
13725
13886
  chunks.push(toClassify.slice(i, i + CLASSIFY_CHUNK_SIZE));
13726
13887
  }
13727
13888
  const abortController = new AbortController;
13728
- const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => abortController.abort());
13889
+ const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => abortController.abort(), args.leaseAcquisition);
13729
13890
  try {
13730
13891
  for (let i = 0;i < chunks.length; i += 1) {
13731
13892
  const remainingMs = Math.max(0, args.deadline - Date.now());
@@ -13805,7 +13966,14 @@ async function classifyOneChunk(args, chunk, anchors, sliceMs, signal) {
13805
13966
  const text = extractLatestAssistantText(messages);
13806
13967
  if (!text)
13807
13968
  throw new Error("classify returned no output");
13808
- parseClassifyManifest(text);
13969
+ try {
13970
+ parseClassifyManifest(text);
13971
+ } catch (error) {
13972
+ const providerFailure = providerOutputFailureFromInvalidManifest(messages, text);
13973
+ if (providerFailure)
13974
+ throw providerFailure;
13975
+ throw error;
13976
+ }
13809
13977
  return text;
13810
13978
  }
13811
13979
  });
@@ -13816,7 +13984,7 @@ async function classifyOneChunk(args, chunk, anchors, sliceMs, signal) {
13816
13984
  const desc = describeError(failure);
13817
13985
  log(`[dreamer] classify chunk failed: ${desc.brief}`, desc.stackHead ? { stackHead: desc.stackHead } : undefined);
13818
13986
  recordInvocation(args, startedAt, { status: "failed", error: failure });
13819
- if (moduleRoute || signal.aborted)
13987
+ if (moduleRoute || signal.aborted || failure instanceof DreamerProviderOutputFailureError)
13820
13988
  throw failure;
13821
13989
  return { classified: 0, changed: 0 };
13822
13990
  } finally {
@@ -13845,7 +14013,7 @@ async function runClassifyThroughModule(args, chunk, anchors, signal) {
13845
14013
  v: 1,
13846
14014
  session_id: args.moduleSessionId,
13847
14015
  task: "classify",
13848
- command_id: `classify:${args.moduleCommandId ?? Date.now()}:${createHash3("sha256").update(chunk.map((candidate) => candidate.id).join(",")).digest("hex").slice(0, 24)}`,
14016
+ command_id: `classify:${args.moduleCommandId ?? Date.now()}:${createHash4("sha256").update(chunk.map((candidate) => candidate.id).join(",")).digest("hex").slice(0, 24)}`,
13849
14017
  authority_generation: args.moduleAuthorityGeneration,
13850
14018
  payload: {
13851
14019
  prompt_body: prompt,
@@ -14541,7 +14709,7 @@ function throwIfAborted2(signal) {
14541
14709
  }
14542
14710
 
14543
14711
  // src/features/magic-context/smart-notes/compiler.ts
14544
- import { createHash as createHash4 } from "node:crypto";
14712
+ import { createHash as createHash5 } from "node:crypto";
14545
14713
 
14546
14714
  // src/features/magic-context/smart-notes/sandbox-runner.ts
14547
14715
  var asyncModulePromise = null;
@@ -14935,7 +15103,7 @@ function manifestAdvisoryWarnings(code, manifest) {
14935
15103
  return warnings;
14936
15104
  }
14937
15105
  function hashCheck(surfaceCondition, compiledCheck, manifest, checkCron) {
14938
- return createHash4("sha256").update(surfaceCondition ?? "").update("\x00").update(compiledCheck).update("\x00").update(JSON.stringify(manifest)).update("\x00").update(checkCron).digest("hex");
15106
+ return createHash5("sha256").update(surfaceCondition ?? "").update("\x00").update(compiledCheck).update("\x00").update(JSON.stringify(manifest)).update("\x00").update(checkCron).digest("hex");
14939
15107
  }
14940
15108
  function extractJsonObject(output) {
14941
15109
  const fenced = output.match(/```(?:json)?\s*([\s\S]*?)```/i);
@@ -15068,16 +15236,16 @@ function claimExpectedState(db, expected) {
15068
15236
  WHERE id = ? AND type = 'smart' AND status = 'pending'
15069
15237
  AND content = ? AND surface_condition IS ? AND updated_at = ?${statusClause}`).run(...params).changes > 0;
15070
15238
  }
15071
- function getDueCompiledSmartNoteChecks(db, projectPath, now, limit) {
15072
- return getPendingSmartNotes(db, projectPath).map(toSmartNote).filter((note) => note.checkStatus === "compiled" && note.compiledCheck !== null && note.policyVersion === SMART_NOTE_CHECK_POLICY_VERSION && (note.checkQuarantinedUntil === null || note.checkQuarantinedUntil <= now) && (note.checkNextDueAt === null || note.checkNextDueAt <= now)).sort((a, b) => (a.checkNextDueAt ?? 0) - (b.checkNextDueAt ?? 0) || a.id - b.id).slice(0, Math.max(1, limit));
15239
+ function getDueCompiledSmartNoteChecks(db, projectPath, now, limit, retinaHandoff = false) {
15240
+ return getPendingSmartNotes(db, projectPath).filter((note) => !retinaHandoff || note.compileStatus !== "compiled").map(toSmartNote).filter((note) => note.checkStatus === "compiled" && note.compiledCheck !== null && note.policyVersion === SMART_NOTE_CHECK_POLICY_VERSION && (note.checkQuarantinedUntil === null || note.checkQuarantinedUntil <= now) && (note.checkNextDueAt === null || note.checkNextDueAt <= now)).sort((a, b) => (a.checkNextDueAt ?? 0) - (b.checkNextDueAt ?? 0) || a.id - b.id).slice(0, Math.max(1, limit));
15073
15241
  }
15074
- function getSmartNotesNeedingCompilation(db, projectPath, now, limit) {
15075
- return getPendingSmartNotes(db, projectPath).map(toSmartNote).filter((note) => (note.checkNextDueAt === null || note.checkNextDueAt <= now) && (note.checkStatus === "uncompiled" || note.checkStatus === "failing" || note.compiledCheck === null || note.policyVersion !== SMART_NOTE_CHECK_POLICY_VERSION)).sort((a, b) => a.createdAt - b.createdAt || a.id - b.id).slice(0, Math.max(1, limit));
15242
+ function getSmartNotesNeedingCompilation(db, projectPath, now, limit, retinaHandoff = false) {
15243
+ return getPendingSmartNotes(db, projectPath).filter((note) => !retinaHandoff || note.compileStatus !== "compiled").map(toSmartNote).filter((note) => (note.checkNextDueAt === null || note.checkNextDueAt <= now) && (note.checkStatus === "uncompiled" || note.checkStatus === "failing" || note.compiledCheck === null || note.policyVersion !== SMART_NOTE_CHECK_POLICY_VERSION)).sort((a, b) => a.createdAt - b.createdAt || a.id - b.id).slice(0, Math.max(1, limit));
15076
15244
  }
15077
- function getStaleCompiledSmartNotes(db, projectPath, now, limit) {
15245
+ function getStaleCompiledSmartNotes(db, projectPath, now, limit, retinaHandoff = false) {
15078
15246
  const staleBefore = now - SMART_NOTE_CHECK_MAX_STALENESS_MS;
15079
15247
  const livenessBefore = now - SMART_NOTE_CHECK_LIVENESS_RECHECK_MS;
15080
- return getPendingSmartNotes(db, projectPath).map(toSmartNote).filter((note) => note.checkStatus === "compiled" && note.compiledCheck !== null && note.policyVersion === SMART_NOTE_CHECK_POLICY_VERSION && note.checkFalseSinceAt !== null && note.checkFalseSinceAt <= staleBefore && (note.checkLastLivenessAt === null || note.checkLastLivenessAt <= livenessBefore)).sort((a, b) => (a.checkFalseSinceAt ?? 0) - (b.checkFalseSinceAt ?? 0) || a.id - b.id).slice(0, Math.max(1, limit));
15248
+ return getPendingSmartNotes(db, projectPath).filter((note) => !retinaHandoff || note.compileStatus !== "compiled").map(toSmartNote).filter((note) => note.checkStatus === "compiled" && note.compiledCheck !== null && note.policyVersion === SMART_NOTE_CHECK_POLICY_VERSION && note.checkFalseSinceAt !== null && note.checkFalseSinceAt <= staleBefore && (note.checkLastLivenessAt === null || note.checkLastLivenessAt <= livenessBefore)).sort((a, b) => (a.checkFalseSinceAt ?? 0) - (b.checkFalseSinceAt ?? 0) || a.id - b.id).slice(0, Math.max(1, limit));
15081
15249
  }
15082
15250
  function storeCompiledSmartNoteCheck(db, args) {
15083
15251
  db.prepare(`UPDATE notes
@@ -15173,7 +15341,7 @@ var MAX_FAILURES_BEFORE_REAUTHOR = 3;
15173
15341
  async function runDueCompiledSmartNoteChecks(args) {
15174
15342
  const startedAt = Date.now();
15175
15343
  const now = args.now ?? startedAt;
15176
- const due = getDueCompiledSmartNoteChecks(args.db, args.projectIdentity, now, args.maxChecks ?? DEFAULT_MAX_CHECKS);
15344
+ const due = getDueCompiledSmartNoteChecks(args.db, args.projectIdentity, now, args.maxChecks ?? DEFAULT_MAX_CHECKS, args.retinaHandoff);
15177
15345
  let ran = 0;
15178
15346
  let surfaced = 0;
15179
15347
  let failed = 0;
@@ -15303,7 +15471,8 @@ async function evaluateSmartNotes(args) {
15303
15471
  const projectRoot = args.sessionDirectory ?? args.projectIdentity;
15304
15472
  const moduleBridge = getModuleNoteEvaluationBridge(args.projectIdentity);
15305
15473
  await moduleBridge?.sync();
15306
- const pendingAtStart = getPendingSmartNotes(args.db, args.projectIdentity).length;
15474
+ const pendingNotes = () => getPendingSmartNotes(args.db, args.projectIdentity).filter((note) => !args.retinaHandoff || note.compileStatus !== "compiled");
15475
+ const pendingAtStart = pendingNotes().length;
15307
15476
  if (pendingAtStart === 0) {
15308
15477
  log("[dreamer] smart notes: no pending notes");
15309
15478
  return { surfaced: 0, pending: 0, ran: false };
@@ -15322,12 +15491,12 @@ async function evaluateSmartNotes(args) {
15322
15491
  leaseAbortController.abort(new Error("Dream lease lost during smart notes"));
15323
15492
  log("[dreamer] smart notes: lease lost — aborting");
15324
15493
  args.onLeaseLost?.("smart notes");
15325
- });
15494
+ }, args.leaseAcquisition);
15326
15495
  let surfaced = 0;
15327
15496
  let didWork = false;
15328
15497
  try {
15329
15498
  if (moduleBridge) {
15330
- const candidates2 = getPendingSmartNotes(args.db, args.projectIdentity).slice(0, MAX_COMPILE_PER_RUN);
15499
+ const candidates2 = pendingNotes().slice(0, MAX_COMPILE_PER_RUN);
15331
15500
  for (const note of candidates2) {
15332
15501
  if (Date.now() >= args.deadline)
15333
15502
  break;
@@ -15348,7 +15517,7 @@ async function evaluateSmartNotes(args) {
15348
15517
  surfaced += 1;
15349
15518
  }
15350
15519
  await moduleBridge.sync();
15351
- const pending2 = getPendingSmartNotes(args.db, args.projectIdentity).length;
15520
+ const pending2 = pendingNotes().length;
15352
15521
  return { surfaced, pending: pending2, ran: didWork };
15353
15522
  }
15354
15523
  const dueRun = await runDueCompiledSmartNoteChecks({
@@ -15358,11 +15527,12 @@ async function evaluateSmartNotes(args) {
15358
15527
  maxChecks: 10,
15359
15528
  sweepBudgetMs: 1e4,
15360
15529
  leaseHeld,
15361
- signal: leaseAbortController.signal
15530
+ signal: leaseAbortController.signal,
15531
+ retinaHandoff: args.retinaHandoff
15362
15532
  });
15363
15533
  surfaced += dueRun.surfaced;
15364
15534
  didWork ||= dueRun.ran > 0;
15365
- const candidates = getSmartNotesNeedingCompilation(args.db, args.projectIdentity, Date.now(), MAX_COMPILE_PER_RUN);
15535
+ const candidates = getSmartNotesNeedingCompilation(args.db, args.projectIdentity, Date.now(), MAX_COMPILE_PER_RUN, args.retinaHandoff);
15366
15536
  for (const note of candidates) {
15367
15537
  if (Date.now() >= args.deadline)
15368
15538
  break;
@@ -15372,7 +15542,7 @@ async function evaluateSmartNotes(args) {
15372
15542
  if (compiled)
15373
15543
  surfaced += 1;
15374
15544
  }
15375
- const stale = getStaleCompiledSmartNotes(args.db, args.projectIdentity, Date.now(), MAX_FALLBACK_PER_RUN);
15545
+ const stale = getStaleCompiledSmartNotes(args.db, args.projectIdentity, Date.now(), MAX_FALLBACK_PER_RUN, args.retinaHandoff);
15376
15546
  for (const note of stale) {
15377
15547
  if (Date.now() >= args.deadline)
15378
15548
  break;
@@ -15382,7 +15552,7 @@ async function evaluateSmartNotes(args) {
15382
15552
  if (met)
15383
15553
  surfaced += 1;
15384
15554
  }
15385
- const fallbackNotes = getPendingSmartNotes(args.db, args.projectIdentity).filter((note) => note.checkStatus === "fallback").slice(0, MAX_FALLBACK_PER_RUN);
15555
+ const fallbackNotes = pendingNotes().filter((note) => note.checkStatus === "fallback").slice(0, MAX_FALLBACK_PER_RUN);
15386
15556
  for (const note of fallbackNotes) {
15387
15557
  if (Date.now() >= args.deadline)
15388
15558
  break;
@@ -15762,7 +15932,7 @@ function enforceMaintainDocsProtectedRegions(args) {
15762
15932
  }
15763
15933
 
15764
15934
  // src/features/magic-context/dreamer/map-memories.ts
15765
- import { createHash as createHash5 } from "node:crypto";
15935
+ import { createHash as createHash6 } from "node:crypto";
15766
15936
 
15767
15937
  // src/features/magic-context/dreamer/map-memories-prompt.ts
15768
15938
  import { existsSync as existsSync8, statSync as statSync2 } from "node:fs";
@@ -15879,7 +16049,7 @@ async function mapMemories(args) {
15879
16049
  }
15880
16050
  result.remaining = inputs.length;
15881
16051
  const abortController = new AbortController;
15882
- const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => abortController.abort());
16052
+ const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => abortController.abort(), args.leaseAcquisition);
15883
16053
  try {
15884
16054
  for (let i = 0;i < batches.length; i += 1) {
15885
16055
  const remainingMs = Math.max(0, args.deadline - Date.now());
@@ -16023,7 +16193,7 @@ async function applyBatchMappings(args, batch, manifestText) {
16023
16193
  memory_project: args.projectIdentity,
16024
16194
  context_store_uuid: args.moduleRoute.moduleContextStoreUuid,
16025
16195
  authority_generation: args.moduleRoute.moduleAuthorityGeneration,
16026
- command_id: `${args.moduleRoute.moduleCommandId}:${createHash5("sha256").update(rows.map((row) => row.memory_id).join(",")).digest("hex").slice(0, 16)}`,
16196
+ command_id: `${args.moduleRoute.moduleCommandId}:${createHash6("sha256").update(rows.map((row) => row.memory_id).join(",")).digest("hex").slice(0, 16)}`,
16027
16197
  rows
16028
16198
  }
16029
16199
  }
@@ -16248,7 +16418,7 @@ async function promotePrimers(args) {
16248
16418
  const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => {
16249
16419
  leaseLost = true;
16250
16420
  log("[dreamer] primers: lease lost during promote-primers — aborting");
16251
- });
16421
+ }, args.leaseAcquisition);
16252
16422
  try {
16253
16423
  assertLeaseHeld("prune start");
16254
16424
  result.pruned = pruneExpiredPrimerCandidatesForProject(args.db, args.projectIdentity, Date.now(), PRIMER_CANDIDATE_TTL_MS);
@@ -16480,7 +16650,7 @@ async function refreshPrimers(args) {
16480
16650
  if (primers.length === 0)
16481
16651
  return result;
16482
16652
  const abortController = new AbortController;
16483
- const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => abortController.abort());
16653
+ const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => abortController.abort(), args.leaseAcquisition);
16484
16654
  try {
16485
16655
  for (let i = 0;i < primers.length; i += 1) {
16486
16656
  const primer = primers[i];
@@ -16967,68 +17137,6 @@ function evaluateTaskGate(task, ctx) {
16967
17137
  // src/features/magic-context/dreamer/verify.ts
16968
17138
  import { createHash as createHash7 } from "node:crypto";
16969
17139
 
16970
- // src/features/magic-context/dreamer/provider-output-failure.ts
16971
- import { createHash as createHash6 } from "node:crypto";
16972
- var MAX_NEAR_ZERO_OUTPUT_TOKENS = 32;
16973
-
16974
- class DreamerProviderOutputFailureError extends Error {
16975
- fingerprint;
16976
- outputTokens;
16977
- reasoningTokens;
16978
- transient = true;
16979
- constructor(fingerprint, outputTokens, reasoningTokens, responseText) {
16980
- const preview = responseText.trim().replace(/\s+/g, " ").slice(0, 160);
16981
- super(`verify provider-outage completion (output_tokens=${outputTokens}, reasoning_tokens=${reasoningTokens}): ${JSON.stringify(preview)}`);
16982
- this.fingerprint = fingerprint;
16983
- this.outputTokens = outputTokens;
16984
- this.reasoningTokens = reasoningTokens;
16985
- this.name = "DreamerProviderOutputFailureError";
16986
- }
16987
- }
16988
- function finiteTokenCount(value) {
16989
- return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : null;
16990
- }
16991
- function completionShape(value) {
16992
- if (!isRecord(value))
16993
- return null;
16994
- const info = isRecord(value.info) ? value.info : value;
16995
- if (info.role !== "assistant")
16996
- return null;
16997
- const time = isRecord(info.time) ? info.time : null;
16998
- const tokens = isRecord(info.tokens) ? info.tokens : null;
16999
- return {
17000
- createdAt: typeof time?.created === "number" ? time.created : 0,
17001
- finish: typeof info.finish === "string" ? info.finish : typeof info.finish_reason === "string" ? info.finish_reason : typeof info.finishReason === "string" ? info.finishReason : null,
17002
- error: info.error,
17003
- outputTokens: finiteTokenCount(tokens?.output),
17004
- reasoningTokens: finiteTokenCount(tokens?.reasoning)
17005
- };
17006
- }
17007
- function latestAssistantCompletion(messages) {
17008
- if (!Array.isArray(messages))
17009
- return null;
17010
- let latest = null;
17011
- for (const message of messages) {
17012
- const completion = completionShape(message);
17013
- if (completion && (!latest || completion.createdAt >= latest.createdAt))
17014
- latest = completion;
17015
- }
17016
- return latest;
17017
- }
17018
- function providerOutputFailureFromInvalidManifest(messages, responseText) {
17019
- const completion = latestAssistantCompletion(messages);
17020
- if (completion?.finish?.toLowerCase() !== "stop")
17021
- return null;
17022
- if (completion.error != null || completion.outputTokens === null || completion.outputTokens > MAX_NEAR_ZERO_OUTPUT_TOKENS || completion.reasoningTokens !== 0) {
17023
- return null;
17024
- }
17025
- const normalized = responseText.trim().replace(/\s+/g, " ").toLowerCase();
17026
- if (!normalized)
17027
- return null;
17028
- const fingerprint = createHash6("sha256").update(normalized).digest("hex").slice(0, 16);
17029
- return new DreamerProviderOutputFailureError(fingerprint, completion.outputTokens, completion.reasoningTokens, responseText);
17030
- }
17031
-
17032
17140
  // src/features/magic-context/dreamer/verify-gate.ts
17033
17141
  import path4 from "node:path";
17034
17142
  function minOf(values) {
@@ -17273,7 +17381,7 @@ async function runVerify(args) {
17273
17381
  batches.push(gate.inScope.slice(i, i + VERIFY_BATCH_SIZE));
17274
17382
  }
17275
17383
  const abortController = new AbortController;
17276
- const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => abortController.abort());
17384
+ const heartbeat = startLeaseHeartbeat(args.db, args.holderId, args.leaseKey, () => abortController.abort(), args.leaseAcquisition);
17277
17385
  let consecutiveProviderFailures = 0;
17278
17386
  let priorProviderFailureFingerprint = null;
17279
17387
  let lastProviderFailure = null;
@@ -17609,6 +17717,9 @@ function createDreamTaskExecutor(deps) {
17609
17717
  return async (config, ctx) => {
17610
17718
  const { db, projectIdentity, holderId, leaseKey } = ctx;
17611
17719
  const startedAt = Date.now();
17720
+ const leaseAcquisition = ctx.leaseAcquisition ?? acquireLeaseWithAcquisition(db, holderId, leaseKey) ?? (() => {
17721
+ throw new Error("Dream lease unavailable during executor setup");
17722
+ })();
17612
17723
  const deadline = startedAt + config.timeoutMinutes * 60 * 1000;
17613
17724
  const backlogAtStart = getDreamTaskBacklog(db, projectIdentity, config.task);
17614
17725
  const reportProgress = (processed) => {
@@ -17626,7 +17737,7 @@ function createDreamTaskExecutor(deps) {
17626
17737
  };
17627
17738
  const parent = await resolveParentSessionId();
17628
17739
  let moduleRoute;
17629
- if (config.task === "map-memories" || config.task === "compress-cues" || config.task === "verify" || config.task === "verify-broad" || config.task === "retrospective") {
17740
+ if (config.task === "map-memories" || config.task === "compress-cues" || config.task === "classify-memories" || config.task === "verify" || config.task === "verify-broad" || config.task === "retrospective") {
17630
17741
  try {
17631
17742
  moduleRoute = await resolveDreamerModuleRoute({
17632
17743
  db,
@@ -17640,6 +17751,9 @@ function createDreamTaskExecutor(deps) {
17640
17751
  throw new DreamerModuleFailureError("authority.status", error);
17641
17752
  }
17642
17753
  }
17754
+ if (!leaseOwnershipMatches(db, holderId, leaseAcquisition.generation, leaseKey)) {
17755
+ throw new Error("Dream lease lost during executor setup");
17756
+ }
17643
17757
  const recordRun = (status, error, extra) => {
17644
17758
  try {
17645
17759
  insertDreamRun(db, {
@@ -17712,6 +17826,7 @@ function createDreamTaskExecutor(deps) {
17712
17826
  holderId,
17713
17827
  leaseKey,
17714
17828
  deadline,
17829
+ leaseAcquisition,
17715
17830
  model: config.model ?? deps.mural.model ?? deps.dreamerModel,
17716
17831
  fallbackModels: config.fallbackModels,
17717
17832
  moduleRoute,
@@ -17735,6 +17850,7 @@ function createDreamTaskExecutor(deps) {
17735
17850
  holderId,
17736
17851
  leaseKey,
17737
17852
  deadline,
17853
+ leaseAcquisition,
17738
17854
  promotionThreshold: config.promotionThreshold ?? 3,
17739
17855
  model: config.model,
17740
17856
  fallbackModels: config.fallbackModels,
@@ -17754,6 +17870,7 @@ function createDreamTaskExecutor(deps) {
17754
17870
  holderId,
17755
17871
  leaseKey,
17756
17872
  deadline,
17873
+ leaseAcquisition,
17757
17874
  model: config.model,
17758
17875
  fallbackModels: config.fallbackModels,
17759
17876
  moduleRoute,
@@ -17779,6 +17896,7 @@ function createDreamTaskExecutor(deps) {
17779
17896
  holderId,
17780
17897
  leaseKey,
17781
17898
  deadline,
17899
+ leaseAcquisition,
17782
17900
  forceBroad: config.task === "verify-broad",
17783
17901
  model: config.model,
17784
17902
  fallbackModels: config.fallbackModels,
@@ -17812,40 +17930,15 @@ function createDreamTaskExecutor(deps) {
17812
17930
  }
17813
17931
  if (config.task === "classify-memories") {
17814
17932
  let moduleArgs;
17815
- const moduleTransport = deps.transformMode === "ts" ? undefined : deps.moduleClient;
17816
- if (moduleTransport?.authorityStatus) {
17817
- const contextStoreUuid = getContextStoreUuid(db);
17818
- if (!contextStoreUuid) {
17819
- throw new Error("Rust classify requires a context store identity");
17820
- }
17821
- let authority;
17822
- try {
17823
- authority = await moduleTransport.authorityStatus({
17824
- context_store_uuid: contextStoreUuid,
17825
- project: projectIdentity,
17826
- projectRoot: deps.sessionDirectory,
17827
- domain: "memories"
17828
- });
17829
- } catch (error) {
17830
- throw new ClassifyModuleFailureError("authority.status", error);
17831
- }
17832
- if (authority.authority?.state === "MODULE") {
17833
- const generation = authority.authority.generation;
17834
- if (typeof generation !== "number") {
17835
- throw new ClassifyModuleFailureError("authority.status", new Error("response omitted generation"));
17836
- }
17837
- const moduleClient = {
17838
- call: (callArgs) => moduleTransport.call(callArgs)
17839
- };
17840
- moduleArgs = {
17841
- moduleClient,
17842
- moduleSessionId: projectIdentity,
17843
- moduleProjectRoot: deps.sessionDirectory,
17844
- moduleContextStoreUuid: contextStoreUuid,
17845
- moduleAuthorityGeneration: generation,
17846
- moduleCommandId: `${startedAt}:${holderId}`
17847
- };
17848
- }
17933
+ if (moduleRoute) {
17934
+ moduleArgs = {
17935
+ moduleClient: moduleRoute.moduleClient,
17936
+ moduleSessionId: moduleRoute.moduleSessionId,
17937
+ moduleProjectRoot: moduleRoute.moduleProjectRoot,
17938
+ moduleContextStoreUuid: moduleRoute.moduleContextStoreUuid,
17939
+ moduleAuthorityGeneration: moduleRoute.moduleAuthorityGeneration,
17940
+ moduleCommandId: moduleRoute.moduleCommandId
17941
+ };
17849
17942
  }
17850
17943
  const result = await runClassify({
17851
17944
  db,
@@ -17856,6 +17949,7 @@ function createDreamTaskExecutor(deps) {
17856
17949
  holderId,
17857
17950
  leaseKey,
17858
17951
  deadline,
17952
+ leaseAcquisition,
17859
17953
  model: config.model,
17860
17954
  fallbackModels: config.fallbackModels,
17861
17955
  ...moduleArgs,
@@ -17879,6 +17973,7 @@ function createDreamTaskExecutor(deps) {
17879
17973
  holderId,
17880
17974
  leaseKey,
17881
17975
  deadline,
17976
+ leaseAcquisition,
17882
17977
  promotionThreshold: config.promotionThreshold ?? 2,
17883
17978
  ensureProjectRegistered: deps.ensureProjectRegistered
17884
17979
  });
@@ -17896,6 +17991,7 @@ function createDreamTaskExecutor(deps) {
17896
17991
  holderId,
17897
17992
  leaseKey,
17898
17993
  deadline,
17994
+ leaseAcquisition,
17899
17995
  model: config.model,
17900
17996
  fallbackModels: config.fallbackModels,
17901
17997
  language: config.language ?? deps.language,
@@ -17916,8 +18012,10 @@ function createDreamTaskExecutor(deps) {
17916
18012
  holderId,
17917
18013
  leaseKey,
17918
18014
  deadline,
18015
+ leaseAcquisition,
17919
18016
  model: config.model,
17920
- fallbackModels: config.fallbackModels
18017
+ fallbackModels: config.fallbackModels,
18018
+ retinaHandoff: deps.retinaHandoff
17921
18019
  });
17922
18020
  recordRun("completed", null, {
17923
18021
  smartNotesSurfaced: result.surfaced,
@@ -18060,7 +18158,7 @@ async function runRetrospectiveTask(config, ctx, helpers) {
18060
18158
  const heartbeat = startLeaseHeartbeat(db, holderId, leaseKey, () => {
18061
18159
  leaseLost = true;
18062
18160
  abortController.abort();
18063
- });
18161
+ }, ctx.leaseAcquisition);
18064
18162
  let childSessionId = null;
18065
18163
  try {
18066
18164
  const createResponse = await createChildSessionWithFence({
@@ -18250,7 +18348,7 @@ async function runAgenticTask(config, ctx, helpers) {
18250
18348
  const heartbeat = startLeaseHeartbeat(db, holderId, leaseKey, () => {
18251
18349
  leaseLost = true;
18252
18350
  abortController.abort();
18253
- });
18351
+ }, ctx.leaseAcquisition);
18254
18352
  let childSessionId = null;
18255
18353
  try {
18256
18354
  const createResponse = await createChildSessionWithFence({
@@ -18433,15 +18531,15 @@ async function runDomainGroup(deps, group, cb) {
18433
18531
  const { db, projectIdentity, executor } = deps;
18434
18532
  const leaseKey = leaseKeyFor(group[0].config.task, projectIdentity);
18435
18533
  const holderId = crypto.randomUUID();
18436
- let acquired = acquireLease(db, holderId, leaseKey);
18437
- if (!acquired && cb?.leaseWaitMs) {
18534
+ let acquisition = acquireLeaseWithAcquisition(db, holderId, leaseKey);
18535
+ if (!acquisition && cb?.leaseWaitMs) {
18438
18536
  const deadline = Date.now() + cb.leaseWaitMs;
18439
- while (!acquired && Date.now() < deadline) {
18537
+ while (!acquisition && Date.now() < deadline) {
18440
18538
  await new Promise((resolve3) => setTimeout(resolve3, LEASE_WAIT_POLL_MS));
18441
- acquired = acquireLease(db, holderId, leaseKey);
18539
+ acquisition = acquireLeaseWithAcquisition(db, holderId, leaseKey);
18442
18540
  }
18443
18541
  }
18444
- if (!acquired) {
18542
+ if (!acquisition) {
18445
18543
  log(`[dreamer] domain lease busy (${leaseKey}) — deferring ${group.length} task(s)`);
18446
18544
  for (const due of group)
18447
18545
  cb?.onBusy?.(due.config.task);
@@ -18449,7 +18547,7 @@ async function runDomainGroup(deps, group, cb) {
18449
18547
  }
18450
18548
  try {
18451
18549
  for (const due of [...group].sort((a, b) => compareTaskOrder(a.config.task, b.config.task))) {
18452
- if (!peekLeaseHolderAndExpiry(db, holderId, leaseKey)) {
18550
+ if (!leaseOwnershipMatches(db, holderId, acquisition.generation, leaseKey)) {
18453
18551
  log(`[dreamer] domain lease lost (${leaseKey}) — stopping remaining task(s)`);
18454
18552
  break;
18455
18553
  }
@@ -18468,7 +18566,13 @@ async function runDomainGroup(deps, group, cb) {
18468
18566
  }
18469
18567
  let outcome;
18470
18568
  try {
18471
- outcome = await executor(due.config, { db, projectIdentity, holderId, leaseKey });
18569
+ outcome = await executor(due.config, {
18570
+ db,
18571
+ projectIdentity,
18572
+ holderId,
18573
+ leaseKey,
18574
+ leaseAcquisition: acquisition
18575
+ });
18472
18576
  } catch (error) {
18473
18577
  outcome = { status: "failed", transient: true, error: String(error) };
18474
18578
  }
@@ -19133,6 +19237,7 @@ async function sweepProject(reg, origin, db, gitCommitEnabled) {
19133
19237
  dreamerModel: dreamerConfig.model,
19134
19238
  mural: reg.mural,
19135
19239
  memoryInjectionBudgetTokens: reg.memoryInjectionBudgetTokens,
19240
+ retinaHandoff: reg.retinaHandoff,
19136
19241
  transformMode: reg.transformMode,
19137
19242
  moduleClient: reg.moduleClient,
19138
19243
  onProgress: (progress, completedTask) => reg.onDreamerProgress?.(progress, completedTask)
@@ -19176,7 +19281,8 @@ async function runCompiledSmartNoteSweep(reg, db) {
19176
19281
  const result = await runDueCompiledSmartNoteChecks({
19177
19282
  db,
19178
19283
  projectIdentity: reg.projectIdentity,
19179
- projectRoot: reg.directory
19284
+ projectRoot: reg.directory,
19285
+ retinaHandoff: reg.retinaHandoff
19180
19286
  });
19181
19287
  if (result.ran > 0) {
19182
19288
  log(`[dreamer] compiled smart-note sweep ${reg.projectIdentity}: ran=${result.ran} surfaced=${result.surfaced} logic_failed=${result.failed} network_failed=${result.networkFailed}`);
@@ -20991,14 +21097,15 @@ function createMagicContextCommandHandler(deps) {
20991
21097
  const isSessionUpgradeCommand = (command) => command === "ctx-session-upgrade";
20992
21098
  const isEmbedCommand = (command) => command === "ctx-embed";
20993
21099
  const rustMode = deps.transformMode === "rust" && deps.rustModeModuleClient;
20994
- const callRust = async (method, body) => {
21100
+ const callRust = async (method, body, timeoutMs) => {
20995
21101
  if (!rustMode)
20996
21102
  throw new Error("Rust module client is unavailable");
20997
21103
  return moduleResponseValue(await rustMode.call({
20998
21104
  sessionId: body.session_id,
20999
21105
  projectRoot: deps.projectRoot ?? process.cwd(),
21000
21106
  method,
21001
- body
21107
+ body,
21108
+ ...timeoutMs === undefined ? {} : { timeoutMs }
21002
21109
  }));
21003
21110
  };
21004
21111
  return {
@@ -21143,7 +21250,7 @@ Starting wrapup…`, {});
21143
21250
  session_id: sessionId,
21144
21251
  keep,
21145
21252
  command_id: rustCommandId("wrapup")
21146
- });
21253
+ }, MAX_WRAPUP_REQUEST_BUDGET_MS);
21147
21254
  result = formatRustOperationMessage("wrapup", value);
21148
21255
  } catch (error) {
21149
21256
  result = `## Magic Wrapup — Failed
@@ -21542,6 +21649,13 @@ var sessionLocks = new Map;
21542
21649
  var incrementalTimers = new Map;
21543
21650
  var pendingIncrementalKeys = new Set;
21544
21651
  var completedIncrementalKeys = new Set;
21652
+ function clearCompletedIncrementalKeys(sessionId) {
21653
+ const prefix = `${sessionId}\x00`;
21654
+ for (const key of completedIncrementalKeys) {
21655
+ if (key.startsWith(prefix))
21656
+ completedIncrementalKeys.delete(key);
21657
+ }
21658
+ }
21545
21659
  function defer(fn) {
21546
21660
  const immediate = globalThis.setImmediate;
21547
21661
  if (typeof immediate === "function") {
@@ -21656,14 +21770,12 @@ function scheduleIncrementalIndex(db, sessionId, messageId, messageSource) {
21656
21770
  function scheduleClearAndReindex(db, sessionId, readMessages) {
21657
21771
  reconciledSessions.delete(sessionId);
21658
21772
  reconciliationScheduledSessions.delete(sessionId);
21659
- const prefix = `${sessionId}\x00`;
21660
- for (const key of completedIncrementalKeys) {
21661
- if (key.startsWith(prefix))
21662
- completedIncrementalKeys.delete(key);
21663
- }
21773
+ clearCompletedIncrementalKeys(sessionId);
21664
21774
  scheduleAfterBootQuiet(() => {
21665
21775
  defer(() => {
21666
21776
  runWithSessionLock(sessionId, () => {
21777
+ reconciledSessions.delete(sessionId);
21778
+ clearCompletedIncrementalKeys(sessionId);
21667
21779
  clearIndexedMessages(db, sessionId);
21668
21780
  }).then(() => reconcileSessionIndex(db, sessionId, readMessages)).catch((error) => {
21669
21781
  reconciledSessions.delete(sessionId);
@@ -22693,16 +22805,8 @@ function reconcileCompactionMode(args) {
22693
22805
  notice: COMPACTION_ON_WRAPUP_SUGGESTION
22694
22806
  };
22695
22807
  }
22696
- if (stored === "off_notice_pending") {
22697
- const markerCleanup2 = cleanupOffMarkers(sessionId);
22698
- return {
22699
- ...NO_TRANSITION,
22700
- recordToWrite: markerCleanup2.verified ? "off" : "off_cleanup_pending",
22701
- notice: COMPACTION_OFF_FLIP_NOTICE,
22702
- markerCleanup: markerCleanup2
22703
- };
22704
- }
22705
- if (!args.compactionOff) {
22808
+ const completingOffNotice = stored === "off_notice_pending";
22809
+ if (!args.compactionOff && !completingOffNotice) {
22706
22810
  if (stored === null || resolveCompactionModeRecord(stored) === "on") {
22707
22811
  return stored === null ? { ...NO_TRANSITION, recordToWrite: "on" } : NO_TRANSITION;
22708
22812
  }
@@ -22738,6 +22842,9 @@ function reconcileCompactionMode(args) {
22738
22842
  markerCleanup: markerCleanup2
22739
22843
  };
22740
22844
  }
22845
+ if (!completingOffNotice) {
22846
+ setCompactionModeRecord(db, sessionId, "off_notice_pending");
22847
+ }
22741
22848
  let clearedSomething = false;
22742
22849
  const markerCleanup = cleanupOffMarkers(sessionId);
22743
22850
  if (markerCleanup.removedRows > 0)
@@ -22775,10 +22882,8 @@ function reconcileCompactionMode(args) {
22775
22882
  loggedUnverifiedMarkerCleanupRetry = true;
22776
22883
  sessionLog(sessionId, "compaction-off transition could not verify complete marker cleanup; durable cleanup retry will run on the next pass");
22777
22884
  }
22778
- const notice = clearedSomething ? COMPACTION_OFF_FLIP_NOTICE : null;
22779
- if (notice) {
22780
- setCompactionModeRecord(db, sessionId, "off_notice_pending");
22781
- } else if (!markerCleanup.verified) {
22885
+ const notice = clearedSomething || completingOffNotice ? COMPACTION_OFF_FLIP_NOTICE : null;
22886
+ if (!notice && !markerCleanup.verified) {
22782
22887
  setCompactionModeRecord(db, sessionId, "off_cleanup_pending");
22783
22888
  }
22784
22889
  return {
@@ -23607,6 +23712,22 @@ function partIsAnthropicThinking(part) {
23607
23712
  const type = part.type;
23608
23713
  return type === "thinking" || type === "reasoning" || type === "redacted_thinking";
23609
23714
  }
23715
+ function partEndsAnthropicAssistantRun(part) {
23716
+ if (!part || typeof part !== "object")
23717
+ return false;
23718
+ const value = part;
23719
+ if (value.type !== "tool" || value.providerExecuted === true || !value.state || typeof value.state !== "object") {
23720
+ return false;
23721
+ }
23722
+ const status = value.state.status;
23723
+ return status === "completed" || status === "error";
23724
+ }
23725
+ function partIsOpenCodeStepMetadata(part) {
23726
+ if (!part || typeof part !== "object")
23727
+ return false;
23728
+ const type = part.type;
23729
+ return type === "step-start" || type === "step-finish";
23730
+ }
23610
23731
  function validateAnthropicReasoningRuns(messages) {
23611
23732
  let index = 0;
23612
23733
  while (index < messages.length) {
@@ -23622,7 +23743,10 @@ function validateAnthropicReasoningRuns(messages) {
23622
23743
  thinkingBlocks += 1;
23623
23744
  if (thinkingBlocks > 1 || sawOtherContent)
23624
23745
  return false;
23625
- } else {
23746
+ } else if (partEndsAnthropicAssistantRun(part)) {
23747
+ thinkingBlocks = 0;
23748
+ sawOtherContent = false;
23749
+ } else if (!partIsOpenCodeStepMetadata(part)) {
23626
23750
  sawOtherContent = true;
23627
23751
  }
23628
23752
  }
@@ -24270,23 +24394,68 @@ function encodeOpenCodeMessagesToCk(messages) {
24270
24394
 
24271
24395
  // src/hooks/magic-context/module-state-sync.ts
24272
24396
  async function mirrorModuleCompartments(args) {
24273
- const row = args.db.prepare("SELECT COALESCE(MAX(sequence), -1) AS max_sequence FROM compartments WHERE session_id = ?").get(args.sessionId);
24274
- const afterSequence = row?.max_sequence ?? -1;
24275
- const published = await args.reader.getCompartmentsAfter(args.sessionId, afterSequence);
24276
- if (!Number.isFinite(published.max_sequence) || published.max_sequence <= afterSequence) {
24277
- return afterSequence;
24278
- }
24279
- const insert = args.db.prepare("INSERT INTO compartments (session_id, sequence, start_message, end_message, start_message_id, end_message_id, title, content, p1, p2, p3, p4, importance, episode_type, legacy, created_at, harness) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(session_id, sequence) DO NOTHING");
24280
- const now = Date.now();
24281
- args.db.transaction(() => {
24397
+ const authoritative = [];
24398
+ let afterSequence = -1;
24399
+ let maxSequence = null;
24400
+ for (;; ) {
24401
+ const published = await args.reader.getCompartmentsAfter(args.sessionId, afterSequence);
24402
+ if (!Number.isSafeInteger(published.max_sequence) || published.max_sequence < -1 || maxSequence !== null && published.max_sequence !== maxSequence) {
24403
+ throw new Error("module compartment mirror changed while its authoritative set was read");
24404
+ }
24405
+ maxSequence ??= published.max_sequence;
24406
+ let pageAdvanced = false;
24282
24407
  for (const compartment of published.compartments) {
24283
- if (!Number.isFinite(compartment.sequence) || compartment.sequence <= afterSequence || typeof compartment.start_message_id !== "string" || typeof compartment.end_message_id !== "string" || typeof compartment.title !== "string" || typeof compartment.content !== "string") {
24284
- continue;
24408
+ if (!Number.isSafeInteger(compartment.sequence) || compartment.sequence <= afterSequence || compartment.sequence > maxSequence || !Number.isSafeInteger(compartment.start_message) || !Number.isSafeInteger(compartment.end_message) || typeof compartment.start_message_id !== "string" || typeof compartment.end_message_id !== "string" || typeof compartment.title !== "string" || typeof compartment.content !== "string") {
24409
+ throw new Error("module compartment mirror returned an invalid authoritative row");
24285
24410
  }
24286
- insert.run(args.sessionId, compartment.sequence, compartment.start_message, compartment.end_message, compartment.start_message_id, compartment.end_message_id, compartment.title, compartment.content, compartment.p1 ?? null, compartment.p2 ?? null, compartment.p3 ?? null, compartment.p4 ?? null, compartment.importance ?? 50, compartment.episode_type ?? null, compartment.legacy ?? (compartment.p1 ? 0 : 1), compartment.created_at ?? now, getHarness());
24411
+ authoritative.push(compartment);
24412
+ afterSequence = compartment.sequence;
24413
+ pageAdvanced = true;
24414
+ }
24415
+ if (afterSequence >= maxSequence)
24416
+ break;
24417
+ if (!pageAdvanced) {
24418
+ throw new Error("module compartment mirror returned an incomplete authoritative set");
24419
+ }
24420
+ }
24421
+ const local = args.db.prepare("SELECT sequence, end_message FROM compartments WHERE session_id = ? ORDER BY sequence ASC").all(args.sessionId);
24422
+ let firstDifference = 0;
24423
+ while (firstDifference < local.length && firstDifference < authoritative.length && local[firstDifference]?.sequence === authoritative[firstDifference]?.sequence && local[firstDifference]?.end_message === authoritative[firstDifference]?.end_message) {
24424
+ firstDifference += 1;
24425
+ }
24426
+ const localDifference = local[firstDifference]?.sequence;
24427
+ const authoritativeDifference = authoritative[firstDifference]?.sequence;
24428
+ const divergentSequence = localDifference === undefined ? authoritativeDifference : authoritativeDifference === undefined ? localDifference : Math.min(localDifference, authoritativeDifference);
24429
+ const upsert = args.db.prepare(`INSERT INTO compartments
24430
+ (session_id, sequence, start_message, end_message, start_message_id, end_message_id,
24431
+ title, content, p1, p2, p3, p4, importance, episode_type, legacy, created_at, harness)
24432
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
24433
+ ON CONFLICT(session_id, sequence) DO UPDATE SET
24434
+ start_message = excluded.start_message,
24435
+ end_message = excluded.end_message,
24436
+ start_message_id = excluded.start_message_id,
24437
+ end_message_id = excluded.end_message_id,
24438
+ title = excluded.title,
24439
+ content = excluded.content,
24440
+ p1 = excluded.p1,
24441
+ p2 = excluded.p2,
24442
+ p3 = excluded.p3,
24443
+ p4 = excluded.p4,
24444
+ importance = excluded.importance,
24445
+ episode_type = excluded.episode_type,
24446
+ legacy = excluded.legacy,
24447
+ created_at = excluded.created_at,
24448
+ harness = excluded.harness`);
24449
+ const now = Date.now();
24450
+ args.db.transaction(() => {
24451
+ if (divergentSequence !== undefined) {
24452
+ args.db.prepare("DELETE FROM compartments WHERE session_id = ? AND sequence >= ?").run(args.sessionId, divergentSequence);
24453
+ }
24454
+ for (const compartment of authoritative) {
24455
+ upsert.run(args.sessionId, compartment.sequence, compartment.start_message, compartment.end_message, compartment.start_message_id, compartment.end_message_id, compartment.title, compartment.content, compartment.p1 ?? null, compartment.p2 ?? null, compartment.p3 ?? null, compartment.p4 ?? null, compartment.importance ?? 50, compartment.episode_type ?? null, compartment.legacy ?? (compartment.p1 ? 0 : 1), compartment.created_at ?? now, getHarness());
24287
24456
  }
24288
24457
  })();
24289
- return published.max_sequence;
24458
+ return maxSequence;
24290
24459
  }
24291
24460
  function stableHash(value) {
24292
24461
  return createHmac("sha256", "magic-context-shadow-watermark").update(value).digest("hex");
@@ -24906,7 +25075,7 @@ async function buildModuleStateSyncPayload(args) {
24906
25075
  workspace,
24907
25076
  nowMs: args.pass.nowMs
24908
25077
  }) : [];
24909
- const userProfile = includeUserProfile && profileChanged ? getActiveUserMemories(args.pass.db).map((memory) => memory.content) : [];
25078
+ const userProfile = includeUserProfile ? getActiveUserMemories(args.pass.db).map((memory) => memory.content) : [];
24910
25079
  const memoryMutations = memoryMutationsChanged && args.pass.projectPath ? getMemoryMutationsForRenderByProjects(args.pass.db, workspace.expandedIdentities, acked.memory_mutation_id, renderedMemoryIds).map((row) => ({
24911
25080
  id: row.id,
24912
25081
  project_path: row.projectPath,
@@ -25051,62 +25220,87 @@ function readAuthoritySeqMismatch(error) {
25051
25220
  async function syncModuleState(args) {
25052
25221
  let force = args.force;
25053
25222
  const adoption = args.options?.authoritySeqAdoption ?? { used: false };
25054
- let stateSyncDeltas = args.options?.stateSyncDeltas;
25055
- if (stateSyncDeltas === undefined && args.client.stateSyncCapabilities) {
25056
- try {
25057
- stateSyncDeltas = (await args.client.stateSyncCapabilities({
25058
- sessionId: args.pass.sessionId,
25059
- projectRoot: args.projectRoot
25060
- })).state_sync_deltas === true;
25061
- } catch {
25062
- stateSyncDeltas = false;
25063
- }
25064
- }
25065
- for (;; ) {
25066
- const payload = await buildModuleStateSyncPayload({
25067
- state: args.state,
25068
- pass: args.pass,
25069
- force,
25070
- options: { ...args.options, stateSyncDeltas }
25071
- });
25072
- if (payload === null)
25073
- return { status: "no_change" };
25074
- if (payload === "m0_mutation" || payload === "mismatch" || payload === "unresolved" || payload === "seed_budget") {
25075
- throw new Error(`module state sync ${payload}`);
25076
- }
25077
- try {
25078
- const batches = payload.wireBatches ?? [payload];
25079
- for (const batch of batches) {
25080
- const response = await args.client.call({
25223
+ const resolveStateSyncDeltas = async (afterGenerationChange = false) => {
25224
+ let capability = afterGenerationChange ? undefined : args.options?.stateSyncDeltas;
25225
+ capability ??= args.client.getCachedStateSyncCapabilities?.()?.state_sync_deltas;
25226
+ if (capability === undefined && args.client.stateSyncCapabilities) {
25227
+ try {
25228
+ capability = (await args.client.stateSyncCapabilities({
25081
25229
  sessionId: args.pass.sessionId,
25082
- projectRoot: args.projectRoot,
25083
- method: "state_sync",
25084
- body: {
25085
- method: batch.method,
25086
- ...batch.params
25230
+ projectRoot: args.projectRoot
25231
+ })).state_sync_deltas;
25232
+ } catch {
25233
+ capability = false;
25234
+ }
25235
+ }
25236
+ return capability === true;
25237
+ };
25238
+ let stateSyncDeltas = await resolveStateSyncDeltas();
25239
+ syncLoop:
25240
+ for (;; ) {
25241
+ const payload = await buildModuleStateSyncPayload({
25242
+ state: args.state,
25243
+ pass: args.pass,
25244
+ force,
25245
+ options: { ...args.options, stateSyncDeltas }
25246
+ });
25247
+ if (payload === null)
25248
+ return { status: "no_change" };
25249
+ if (payload === "m0_mutation" || payload === "mismatch" || payload === "unresolved" || payload === "seed_budget") {
25250
+ throw new Error(`module state sync ${payload}`);
25251
+ }
25252
+ try {
25253
+ const batches = payload.wireBatches ?? [payload];
25254
+ for (const batch of batches) {
25255
+ const response = await args.client.call({
25256
+ sessionId: args.pass.sessionId,
25257
+ projectRoot: args.projectRoot,
25258
+ method: "state_sync",
25259
+ body: {
25260
+ method: batch.method,
25261
+ ...batch.params
25262
+ },
25263
+ generationSensitive: stateSyncDeltas
25264
+ });
25265
+ if (isModuleTransportGenerationChangedResult(response)) {
25266
+ stateSyncDeltas = await resolveStateSyncDeltas(true);
25267
+ continue syncLoop;
25268
+ }
25269
+ if (args.options?.authority === true && responseMemoriesSkipped(response) && !args.state.authorityMemorySyncSkipLogged) {
25270
+ args.state.authorityMemorySyncSkipLogged = true;
25271
+ sessionLog(args.pass.sessionId, "authority state sync skipped module-owned memory sections");
25087
25272
  }
25088
- });
25089
- if (args.options?.authority === true && responseMemoriesSkipped(response) && !args.state.authorityMemorySyncSkipLogged) {
25090
- args.state.authorityMemorySyncSkipLogged = true;
25091
- sessionLog(args.pass.sessionId, "authority state sync skipped module-owned memory sections");
25092
25273
  }
25274
+ } catch (error) {
25275
+ if (isHistorianCompartmentSyncBusy(error)) {
25276
+ return { status: "retry_busy" };
25277
+ }
25278
+ const durableSeq = args.options?.authority ? readAuthoritySeqMismatch(error) : null;
25279
+ if (durableSeq === null || adoption.used)
25280
+ throw error;
25281
+ adoption.used = true;
25282
+ args.state.lastAckedSeq = durableSeq;
25283
+ args.state.lastAckedWatermarks = null;
25284
+ force = true;
25285
+ continue;
25093
25286
  }
25094
- } catch (error) {
25095
- if (isHistorianCompartmentSyncBusy(error)) {
25096
- return { status: "retry_busy" };
25097
- }
25098
- const durableSeq = args.options?.authority ? readAuthoritySeqMismatch(error) : null;
25099
- if (durableSeq === null || adoption.used)
25100
- throw error;
25101
- adoption.used = true;
25102
- args.state.lastAckedSeq = durableSeq;
25103
- args.state.lastAckedWatermarks = null;
25104
- force = true;
25105
- continue;
25287
+ args.state.lastAckedWatermarks = payload.watermarks;
25288
+ args.state.lastAckedSeq += 1;
25289
+ return { status: "acked", watermarks: payload.watermarks };
25106
25290
  }
25107
- args.state.lastAckedWatermarks = payload.watermarks;
25108
- args.state.lastAckedSeq += 1;
25109
- return { status: "acked", watermarks: payload.watermarks };
25291
+ }
25292
+
25293
+ // src/hooks/magic-context/raw-fallback-context-limit.ts
25294
+ class RawFallbackContextLimitError extends Error {
25295
+ estimatedTokens;
25296
+ contextLimitTokens;
25297
+ code = "RAW_FALLBACK_CONTEXT_LIMIT";
25298
+ recoverable = true;
25299
+ constructor(estimatedTokens, contextLimitTokens, options) {
25300
+ super(`Magic Context could not safely serve the raw prompt: the best local estimate is ${estimatedTokens.toLocaleString()} tokens, above the known ${contextLimitTokens.toLocaleString()}-token context limit. Retry the turn so the module can reconnect.`, options);
25301
+ this.estimatedTokens = estimatedTokens;
25302
+ this.contextLimitTokens = contextLimitTokens;
25303
+ this.name = "RawFallbackContextLimitError";
25110
25304
  }
25111
25305
  }
25112
25306
 
@@ -27590,7 +27784,7 @@ var REASONING_IGNORED_PART_TYPES = new Set([
27590
27784
  "compaction"
27591
27785
  ]);
27592
27786
  var REASONING_PART_TYPES = new Set(["reasoning", "thinking", "redacted_thinking"]);
27593
- function stripReasoningFromMergedAssistants(messages, providerID) {
27787
+ function stripReasoningFromMergedAssistants(messages, providerID, options) {
27594
27788
  if (providerID !== "anthropic")
27595
27789
  return 0;
27596
27790
  let stripped = 0;
@@ -27606,6 +27800,10 @@ function stripReasoningFromMergedAssistants(messages, providerID) {
27606
27800
  const firstInRun = prevRole !== "assistant";
27607
27801
  if (firstInRun)
27608
27802
  keptReasoningInRun = false;
27803
+ if (message === options?.mutationExemptMessage) {
27804
+ prevRole = role;
27805
+ continue;
27806
+ }
27609
27807
  let keepIndex = -1;
27610
27808
  if (firstInRun && !keptReasoningInRun) {
27611
27809
  for (let i = 0;i < message.parts.length; i++) {
@@ -28700,11 +28898,21 @@ function finalizeMessageRepresentation(messages, resolvedProviderID, options) {
28700
28898
  clearedParts = stripClearedReasoning(targetedMessages);
28701
28899
  }
28702
28900
  }
28703
- const mergedReasoningParts = stripReasoningFromMergedAssistants(messages, resolvedProviderID);
28901
+ const mergedReasoningParts = stripReasoningFromMergedAssistants(messages, resolvedProviderID, {
28902
+ mutationExemptMessage: options?.reasoningMutationExemptMessage
28903
+ });
28704
28904
  return { clearedParts, mergedReasoningParts };
28705
28905
  }
28706
28906
  async function runPostTransformPhase(args) {
28707
28907
  const compactionOff = args.compactionOff === true;
28908
+ let reasoningMutationExemptMessage;
28909
+ for (let index = args.messages.length - 1;index >= 0; index -= 1) {
28910
+ const message = args.messages[index];
28911
+ if (message.info.role !== "assistant")
28912
+ continue;
28913
+ reasoningMutationExemptMessage = message;
28914
+ break;
28915
+ }
28708
28916
  const pendingMaterializationAtPassStart = args.pendingMaterializationSessions.has(args.sessionId);
28709
28917
  const deferredMaterializationAtPassStart = args.deferredMaterializationSessions.has(args.sessionId);
28710
28918
  const isExplicitFlush = pendingMaterializationAtPassStart;
@@ -28723,6 +28931,10 @@ async function runPostTransformPhase(args) {
28723
28931
  state: args.sessionMeta,
28724
28932
  projectPath: args.m0M1.projectPath,
28725
28933
  projectDirectory: args.m0M1.projectDirectory,
28934
+ injectDocs: args.m0M1.injectDocs,
28935
+ muralEnabled: args.m0M1.muralEnabled,
28936
+ memoryInjectionBudgetTokens: args.m0M1.memoryInjectionBudgetTokens,
28937
+ historyBudgetTokens: args.m0M1.historyBudgetTokens,
28726
28938
  hardSignals: args.m0M1.hardSignals
28727
28939
  }).value : false;
28728
28940
  const bypassCompartmentGate = forceMaterialization || m0HardFoldThisPass;
@@ -29251,7 +29463,8 @@ async function runPostTransformPhase(args) {
29251
29463
  const tFinalRepresentation = performance.now();
29252
29464
  const finalRepresentation = finalizeMessageRepresentation(args.messages, args.resolvedProviderID, {
29253
29465
  prependedMessageCount,
29254
- reasoningMutatedMessages
29466
+ reasoningMutatedMessages,
29467
+ reasoningMutationExemptMessage
29255
29468
  });
29256
29469
  sessionLog(args.sessionId, `final representation: clearedParts=${finalRepresentation.clearedParts} mergedReasoningParts=${finalRepresentation.mergedReasoningParts}`);
29257
29470
  logTransformTiming(args.sessionId, "finalizeMessageRepresentation", tFinalRepresentation, `clearedParts=${finalRepresentation.clearedParts} mergedReasoningParts=${finalRepresentation.mergedReasoningParts}`);
@@ -29293,6 +29506,15 @@ var RUST_PARK_RETRY_INTERVAL = 5;
29293
29506
  var RUST_EMERGENCY_WALL_PCT = 95;
29294
29507
  var RUST_PARK_PROBE_PRESSURE_BYPASS_PCT = 90;
29295
29508
  var RUST_SEND_TIMEOUT_MS = 15000;
29509
+ var RAW_FALLBACK_BYTES_PER_CONTEXT_TOKEN = 4;
29510
+ function rawFallbackSerializedBytes(messages) {
29511
+ try {
29512
+ const serialized = JSON.stringify(messages);
29513
+ return typeof serialized === "string" ? Buffer.byteLength(serialized) : null;
29514
+ } catch {
29515
+ return null;
29516
+ }
29517
+ }
29296
29518
  function isRecord3(value) {
29297
29519
  return value !== null && typeof value === "object";
29298
29520
  }
@@ -29321,34 +29543,26 @@ function updateFnv1a32(hash, value) {
29321
29543
  }
29322
29544
  return next;
29323
29545
  }
29324
- var SNAPSHOT_ARRAY = Symbol("array");
29325
- var SNAPSHOT_OBJECT = Symbol("object");
29326
- var SNAPSHOT_KEY = Symbol("key");
29327
- var SNAPSHOT_STRING = Symbol("string");
29328
- var SNAPSHOT_NUMBER = Symbol("number");
29329
- var SNAPSHOT_BOOLEAN = Symbol("boolean");
29330
- var SNAPSHOT_NULL = Symbol("null");
29331
- var SNAPSHOT_UNDEFINED = Symbol("undefined");
29332
29546
  function isSnapshotObjectChild(value) {
29333
29547
  return value !== undefined && typeof value !== "function" && typeof value !== "symbol";
29334
29548
  }
29335
29549
  function visitMessageContentFields(value, visitor) {
29336
29550
  if (value === null)
29337
- return visitor.field(SNAPSHOT_NULL);
29551
+ return visitor.field(LKG_SNAPSHOT_NULL);
29338
29552
  if (typeof value === "string") {
29339
- return visitor.field(SNAPSHOT_STRING) && visitor.field(value);
29553
+ return visitor.field(LKG_SNAPSHOT_STRING) && visitor.field(value);
29340
29554
  }
29341
29555
  if (typeof value === "number") {
29342
- return visitor.field(SNAPSHOT_NUMBER) && visitor.field(value);
29556
+ return visitor.field(LKG_SNAPSHOT_NUMBER) && visitor.field(value);
29343
29557
  }
29344
29558
  if (typeof value === "boolean") {
29345
- return visitor.field(SNAPSHOT_BOOLEAN) && visitor.field(value);
29559
+ return visitor.field(LKG_SNAPSHOT_BOOLEAN) && visitor.field(value);
29346
29560
  }
29347
29561
  if (value === undefined || typeof value === "function" || typeof value === "symbol") {
29348
- return visitor.field(SNAPSHOT_UNDEFINED);
29562
+ return visitor.field(LKG_SNAPSHOT_UNDEFINED);
29349
29563
  }
29350
29564
  if (Array.isArray(value)) {
29351
- if (!visitor.field(SNAPSHOT_ARRAY) || !visitor.field(value.length))
29565
+ if (!visitor.field(LKG_SNAPSHOT_ARRAY) || !visitor.field(value.length))
29352
29566
  return false;
29353
29567
  for (const item of value) {
29354
29568
  if (!visitMessageContentFields(item, visitor))
@@ -29357,7 +29571,7 @@ function visitMessageContentFields(value, visitor) {
29357
29571
  return true;
29358
29572
  }
29359
29573
  if (typeof value === "object") {
29360
- if (!visitor.field(SNAPSHOT_OBJECT))
29574
+ if (!visitor.field(LKG_SNAPSHOT_OBJECT))
29361
29575
  return false;
29362
29576
  const objectToken = visitor.beginObject();
29363
29577
  if (objectToken === undefined)
@@ -29370,13 +29584,13 @@ function visitMessageContentFields(value, visitor) {
29370
29584
  if (!isSnapshotObjectChild(child))
29371
29585
  continue;
29372
29586
  entryCount += 1;
29373
- if (!visitor.field(SNAPSHOT_KEY) || !visitor.field(key) || !visitMessageContentFields(child, visitor)) {
29587
+ if (!visitor.field(LKG_SNAPSHOT_KEY) || !visitor.field(key) || !visitMessageContentFields(child, visitor)) {
29374
29588
  return false;
29375
29589
  }
29376
29590
  }
29377
29591
  return visitor.endObject(objectToken, entryCount);
29378
29592
  }
29379
- return visitor.field(SNAPSHOT_UNDEFINED);
29593
+ return visitor.field(LKG_SNAPSHOT_UNDEFINED);
29380
29594
  }
29381
29595
  function messageContentFields(message) {
29382
29596
  const fields = [];
@@ -29533,6 +29747,19 @@ function responseValue(response) {
29533
29747
  return response;
29534
29748
  throw new Error("module transform returned a non-object response");
29535
29749
  }
29750
+ function mirrorRustRenderedMemoryIds(args) {
29751
+ if (!("rendered_memory_ids" in args.response))
29752
+ return;
29753
+ const rawIds = args.response.rendered_memory_ids;
29754
+ if (!Array.isArray(rawIds) || rawIds.some((id) => typeof id !== "number" || !Number.isSafeInteger(id) || id <= 0)) {
29755
+ throw new Error("module transform returned an invalid rendered-memory manifest");
29756
+ }
29757
+ const serialized = JSON.stringify(rawIds);
29758
+ args.db.prepare(`UPDATE session_meta
29759
+ SET memory_block_ids = ?, memory_block_count = ?
29760
+ WHERE session_id = ?
29761
+ AND (COALESCE(memory_block_ids, '') <> ? OR COALESCE(memory_block_count, -1) <> ?)`).run(serialized, rawIds.length, args.sessionId, serialized, rawIds.length);
29762
+ }
29536
29763
  function noteDeliveryPassIds(response) {
29537
29764
  if (!Array.isArray(response.note_deliveries))
29538
29765
  return [];
@@ -29587,7 +29814,10 @@ function ensureState(states, sessionId) {
29587
29814
  memoryAuthorityProject: null,
29588
29815
  memoryAuthorityRoot: null,
29589
29816
  memoryAuthorityReady: false,
29590
- authorityMemorySyncSkipLogged: false
29817
+ authorityMemorySyncSkipLogged: false,
29818
+ lkgCaptureSequence: 0,
29819
+ lkgLastCapturedRowVersion: 0,
29820
+ lkgSyncCaptureRequired: false
29591
29821
  };
29592
29822
  states.set(sessionId, state);
29593
29823
  }
@@ -29878,8 +30108,10 @@ function buildTransformBody(args) {
29878
30108
  model_key: args.modelKey,
29879
30109
  provider_id: args.providerId,
29880
30110
  tool_present: args.passInputs.tool_present === true,
30111
+ ...typeof args.passInputs.todo_tool_present === "boolean" ? { todo_tool_present: args.passInputs.todo_tool_present } : {},
29881
30112
  prompt_surface_preset: args.passInputs.prompt_surface_preset ?? "full",
29882
30113
  prompt_surface_model_key: args.passInputs.prompt_surface_model_key,
30114
+ prompt_surface_config_identity: args.passInputs.prompt_surface_config_identity,
29883
30115
  prompt_surface_tool_descriptions: args.passInputs.prompt_surface_tool_descriptions ?? {},
29884
30116
  effective_execute_threshold: args.passInputs.effective_execute_threshold,
29885
30117
  history_budget_tokens: args.passInputs.history_budget_tokens,
@@ -29901,6 +30133,8 @@ function buildTransformBody(args) {
29901
30133
  function createRustModeTransform(deps, options) {
29902
30134
  const states = new Map;
29903
30135
  const wireCaches = new Map;
30136
+ const scheduleLkgCapture = options.scheduleLkgCapture ?? ((capture) => setImmediate(capture));
30137
+ const rawFallbackEstimator = options.rawFallbackEstimatorForTests ?? estimateFinalWireInputTokens;
29904
30138
  const timeoutMs = Math.max(1, options.moduleTimeoutMs ?? RUST_SEND_TIMEOUT_MS);
29905
30139
  const logStage = (sessionId, stage, startedAt, timings, extra) => {
29906
30140
  const elapsed = Math.max(0, performance.now() - startedAt);
@@ -30019,28 +30253,50 @@ function createRustModeTransform(deps, options) {
30019
30253
  sessionLog(sessionId, "lkg_replay_served");
30020
30254
  return true;
30021
30255
  };
30022
- const captureRustResponse = (sessionId, input, response) => {
30023
- const ids = input.map((message) => message.info.id);
30024
- if (ids.some((id) => typeof id !== "string") || new Set(ids).size !== ids.length || ids.length === 0) {
30025
- return false;
30256
+ const prepareRustCapture = (state, sessionId, input, inputSnapshots, response, responseRowVersion) => {
30257
+ state.lkgCaptureSequence += 1;
30258
+ const inputIds = input.map((message) => message.info.id);
30259
+ if (inputIds.some((id) => typeof id !== "string") || new Set(inputIds).size !== inputIds.length || inputIds.length === 0 || inputSnapshots.length !== inputIds.length) {
30260
+ return null;
30026
30261
  }
30027
- const inputContentDigests = input.map((message) => lkgContentDigest(message));
30028
- if (inputContentDigests.some((digest) => digest === null))
30029
- return false;
30030
30262
  const native = response.native_messages;
30031
30263
  const jsonPrefix = typeof native === "string" ? native : JSON.stringify(native);
30032
30264
  if (typeof jsonPrefix !== "string")
30033
- return false;
30265
+ return null;
30034
30266
  const keys = resolveLkgModelKeys(input);
30035
- return captureSlot(sessionId, {
30267
+ return {
30268
+ sessionId,
30269
+ inputIds,
30270
+ inputSnapshots,
30036
30271
  jsonPrefix,
30037
- inputIdSeq: ids,
30038
- inputContentDigests,
30039
- lastInputMessageId: ids[ids.length - 1],
30040
30272
  modelKey: keys.modelKey,
30041
30273
  providerKey: keys.providerKey,
30042
- capturedAt: Date.now()
30274
+ capturedAt: Date.now(),
30275
+ rowVersion: responseRowVersion,
30276
+ captureSequence: state.lkgCaptureSequence
30277
+ };
30278
+ };
30279
+ const commitRustCapture = (state, plan) => {
30280
+ if (states.get(plan.sessionId) !== state || plan.captureSequence !== state.lkgCaptureSequence || plan.rowVersion < state.lkgLastCapturedRowVersion) {
30281
+ return "superseded";
30282
+ }
30283
+ const inputContentDigests = plan.inputSnapshots.map((snapshot) => lkgContentDigestFromFields(snapshot.fields));
30284
+ const captured = captureSlot(plan.sessionId, {
30285
+ jsonPrefix: plan.jsonPrefix,
30286
+ inputIdSeq: plan.inputIds,
30287
+ inputContentDigests,
30288
+ lastInputMessageId: plan.inputIds[plan.inputIds.length - 1],
30289
+ modelKey: plan.modelKey,
30290
+ providerKey: plan.providerKey,
30291
+ capturedAt: plan.capturedAt,
30292
+ rowVersion: plan.rowVersion,
30293
+ captureSequence: plan.captureSequence
30043
30294
  });
30295
+ if (!captured)
30296
+ throw new Error("LKG slot rejected the prepared snapshot");
30297
+ state.lkgLastCapturedRowVersion = plan.rowVersion;
30298
+ state.lkgSyncCaptureRequired = false;
30299
+ return "captured";
30044
30300
  };
30045
30301
  const run = async (sessionId, messages, output, sessionMeta) => {
30046
30302
  const passStartedAt = performance.now();
@@ -30098,6 +30354,29 @@ function createRustModeTransform(deps, options) {
30098
30354
  const hasProviderProof = overflowState.detectedContextLimit > 0 && detectedLimitMatchesModel || isProviderOverflowReconfirmed(sessionId);
30099
30355
  emergencyFailClosed ||= overflowState.needsEmergencyRecovery && overflowState.emergencyRecoveryOrigin === "provider_overflow" && hasProviderProof;
30100
30356
  }
30357
+ const serveRawFallback = (cause) => {
30358
+ const contextLimit = resolvedContextLimit ?? (overflowState && overflowState.detectedContextLimit > 0 ? overflowState.detectedContextLimit : undefined);
30359
+ if (contextLimit !== undefined) {
30360
+ let estimate;
30361
+ try {
30362
+ estimate = rawFallbackEstimator({
30363
+ messages,
30364
+ systemPromptTokens: sessionMeta.systemPromptTokens,
30365
+ providerID: model?.providerID,
30366
+ modelID: model?.modelID,
30367
+ agentName: deps.getNotificationParams?.(sessionId)?.agent
30368
+ });
30369
+ } catch {}
30370
+ const rawBytes = rawFallbackSerializedBytes(messages);
30371
+ const proxyTokens = rawBytes === null ? contextLimit + 1 : Math.ceil(rawBytes / RAW_FALLBACK_BYTES_PER_CONTEXT_TOKEN);
30372
+ const refusalTokens = Math.max(estimate?.tokens ?? 0, proxyTokens);
30373
+ if (refusalTokens > contextLimit) {
30374
+ sessionLog(sessionId, `raw_fallback_over_context_limit estimated=${estimate?.tokens ?? "unavailable"} ` + `proxy_bytes=${rawBytes ?? "unavailable"} proxy_tokens=${proxyTokens} limit=${contextLimit}`);
30375
+ throw new RawFallbackContextLimitError(refusalTokens, contextLimit, { cause });
30376
+ }
30377
+ }
30378
+ replaceMessagesInPlace(output, messages);
30379
+ };
30101
30380
  const finishPass = (applied, served = true) => {
30102
30381
  const elapsedAt = applied && appliedAt !== undefined ? appliedAt : performance.now();
30103
30382
  const elapsedMs = Math.max(0, elapsedAt - passStartedAt);
@@ -30128,11 +30407,19 @@ function createRustModeTransform(deps, options) {
30128
30407
  servedFrom = typeof response.served_from === "string" ? response.served_from : "unknown";
30129
30408
  materializeReason = typeof response.materialize_reason === "string" && response.materialize_reason.length > 0 ? response.materialize_reason : "none";
30130
30409
  const timings2 = isRecord3(response.timings) ? response.timings : undefined;
30131
- const total = timings2?.total;
30132
- moduleElapsedMs = typeof total === "number" && Number.isFinite(total) ? total : 0;
30410
+ const applyOnceTotal = timings2?.total;
30411
+ const handlerTotal = timings2?.handler_total;
30412
+ moduleElapsedMs = typeof handlerTotal === "number" && Number.isFinite(handlerTotal) ? handlerTotal : typeof applyOnceTotal === "number" && Number.isFinite(applyOnceTotal) ? applyOnceTotal : 0;
30133
30413
  rowVersion = typeof response.row_version === "number" && Number.isSafeInteger(response.row_version) ? response.row_version : 0;
30414
+ if (timings2 && (typeof timings2.handler_total === "number" || typeof timings2.native_cache_reused_messages === "number" || typeof timings2.native_cache_encoded_messages === "number")) {
30415
+ const stage = (name) => {
30416
+ const value = timings2[name];
30417
+ return typeof value === "number" && Number.isFinite(value) ? value.toFixed(1) : "n/a";
30418
+ };
30419
+ sessionLog(sessionId, `rust module stages: handler=${stage("handler_total")} apply_once=${stage("total")} ` + `request_to_handler=${stage("request_observed_to_handler")} ` + `projection=${stage("projection")} selection=${stage("selection")} ` + `build_output=${stage("build_output")} store_commit=${stage("store_commit")} ` + `post_attach=${stage("post_attach")} response_encode=${stage("response_encode")} ` + `native_cache_reused=${stage("native_cache_reused_messages")} ` + `native_cache_encoded=${stage("native_cache_encoded_messages")}`);
30420
+ }
30134
30421
  if (timings2 && moduleElapsedMs >= 1000) {
30135
- const detail = Object.entries(timings2).filter(([key, value]) => key !== "total" && typeof value === "number").map(([key, value]) => `${key}:${value.toFixed(1)}`).join(" ");
30422
+ const detail = Object.entries(timings2).filter(([key, value]) => key !== "total" && key !== "handler_total" && typeof value === "number").map(([key, value]) => `${key}:${value.toFixed(1)}`).join(" ");
30136
30423
  if (detail)
30137
30424
  sessionLog(sessionId, `rust module stages (slow pass): ${detail}`);
30138
30425
  }
@@ -30146,7 +30433,12 @@ function createRustModeTransform(deps, options) {
30146
30433
  servedFrom = "lkg";
30147
30434
  } else {
30148
30435
  servedFrom = "raw";
30149
- replaceMessagesInPlace(output, messages);
30436
+ try {
30437
+ serveRawFallback();
30438
+ } catch (error) {
30439
+ finishPass(false, false);
30440
+ throw error;
30441
+ }
30150
30442
  }
30151
30443
  finishPass(false);
30152
30444
  return;
@@ -30154,7 +30446,9 @@ function createRustModeTransform(deps, options) {
30154
30446
  }
30155
30447
  const reduceAvailability = resolveCtxReduceAvailability(sessionId);
30156
30448
  resolveTodowriteAvailabilityFromMessages(sessionId, messages);
30449
+ const todoAvailability = resolveTodowriteAvailability(sessionId);
30157
30450
  const toolPresent = reduceAvailability.frozen && reduceAvailability.callable;
30451
+ const todoToolPresent = todoAvailability.frozen ? todoAvailability.callable : undefined;
30158
30452
  try {
30159
30453
  if (preflightError)
30160
30454
  throw preflightError;
@@ -30188,8 +30482,10 @@ function createRustModeTransform(deps, options) {
30188
30482
  system_prompt_hash: sessionMeta.systemPromptHash ?? "",
30189
30483
  upgrade_state: readUpgradeState(deps.db, sessionId),
30190
30484
  tool_present: toolPresent,
30485
+ todo_tool_present: todoToolPresent,
30191
30486
  prompt_surface_preset: promptSurface.preset,
30192
30487
  prompt_surface_model_key: modelKey,
30488
+ prompt_surface_config_identity: promptSurfaceConfigIdentity(deps.promptSurface),
30193
30489
  prompt_surface_tool_descriptions: deps.promptSurface?.tool_descriptions ?? {},
30194
30490
  protected_tags: deps.protectedTags ?? DEFAULT_PROTECTED_TAGS,
30195
30491
  temporal_awareness: deps.experimentalTemporalAwareness === true,
@@ -30306,10 +30602,12 @@ function createRustModeTransform(deps, options) {
30306
30602
  };
30307
30603
  }
30308
30604
  }
30605
+ const getCachedStateSyncCapabilities = options.moduleClient.getCachedStateSyncCapabilities;
30309
30606
  const stateSyncCapabilities = options.moduleClient.stateSyncCapabilities;
30310
30607
  const stateSyncResult = await syncModuleState({
30311
30608
  client: {
30312
30609
  call: callModule,
30610
+ getCachedStateSyncCapabilities: getCachedStateSyncCapabilities ? () => getCachedStateSyncCapabilities.call(options.moduleClient) : undefined,
30313
30611
  stateSyncCapabilities: stateSyncCapabilities ? (capabilityArgs) => stateSyncCapabilities.call(options.moduleClient, capabilityArgs) : undefined
30314
30612
  },
30315
30613
  state,
@@ -30434,6 +30732,7 @@ function createRustModeTransform(deps, options) {
30434
30732
  throw new Error("rust module returned no transform response");
30435
30733
  captureResponseTelemetry(response);
30436
30734
  if (isNeedFullSync(response)) {
30735
+ options.moduleClient.invalidateStateSyncCapabilities?.();
30437
30736
  state.forceFullWire = true;
30438
30737
  if (wireDelta) {
30439
30738
  const retryOrdinalStartedAt = performance.now();
@@ -30587,13 +30886,46 @@ function createRustModeTransform(deps, options) {
30587
30886
  }
30588
30887
  logStage(sessionId, "apply", applyStartedAt, timings);
30589
30888
  const lkgSnapshotStartedAt = performance.now();
30590
- if (cacheBustingPass || !getSlot(sessionId)) {
30591
- const captured = captureRustResponse(sessionId, messages, response);
30592
- if (cacheBustingPass && !captured) {
30593
- dropSlot(sessionId, "lkg_refresh_declined");
30889
+ if (cacheBustingPass) {
30890
+ dropSlot(sessionId, "lkg_cache_bust_pending_capture");
30891
+ }
30892
+ const capturePlan = prepareRustCapture(state, sessionId, messages, pendingWireCache.rawContentSnapshots, response, rowVersion);
30893
+ let captureMode = "async";
30894
+ const captureFailed = (mode, error) => {
30895
+ if (states.get(sessionId) !== state || capturePlan && capturePlan.captureSequence !== state.lkgCaptureSequence) {
30896
+ return;
30897
+ }
30898
+ dropSlot(sessionId, `lkg_${mode}_capture_failed`);
30899
+ state.lkgSyncCaptureRequired = true;
30900
+ sessionLog(sessionId, `LKG ${mode.toUpperCase()} CAPTURE FAILED; forcing synchronous capture on the next applied pass:`, error);
30901
+ };
30902
+ if (!capturePlan) {
30903
+ captureMode = "declined";
30904
+ captureFailed("async", new Error("LKG snapshot preparation was rejected"));
30905
+ } else if (state.lkgSyncCaptureRequired) {
30906
+ captureMode = "sync_recovery";
30907
+ try {
30908
+ commitRustCapture(state, capturePlan);
30909
+ } catch (error) {
30910
+ captureFailed("sync", error);
30911
+ }
30912
+ } else {
30913
+ try {
30914
+ scheduleLkgCapture(() => {
30915
+ const asyncStartedAt = performance.now();
30916
+ try {
30917
+ const result = commitRustCapture(state, capturePlan);
30918
+ logTransformTiming(sessionId, "rust.lkg_snapshot_async", asyncStartedAt, `result=${result} row_version=${capturePlan.rowVersion}`);
30919
+ } catch (error) {
30920
+ captureFailed("async", error);
30921
+ }
30922
+ });
30923
+ } catch (error) {
30924
+ captureMode = "schedule_failed";
30925
+ captureFailed("async", error);
30594
30926
  }
30595
30927
  }
30596
- logStage(sessionId, "lkgSnapshot", lkgSnapshotStartedAt, timings, cacheBustingPass ? "captured=true" : "captured=false");
30928
+ logStage(sessionId, "lkgSnapshot", lkgSnapshotStartedAt, timings, `mode=${captureMode} row_version=${rowVersion}`);
30597
30929
  const applyReplaceStartedAt = performance.now();
30598
30930
  replaceMessagesInPlace(output, appliedMessages);
30599
30931
  logStage(sessionId, "apply", applyReplaceStartedAt, timings);
@@ -30606,6 +30938,11 @@ function createRustModeTransform(deps, options) {
30606
30938
  }
30607
30939
  throw error;
30608
30940
  }
30941
+ try {
30942
+ mirrorRustRenderedMemoryIds({ db: deps.db, sessionId, response });
30943
+ } catch (error) {
30944
+ sessionLog(sessionId, "rust rendered-memory mirror write failed (ignored):", error);
30945
+ }
30609
30946
  if (deliveryPassIds.length > 0) {
30610
30947
  try {
30611
30948
  await sendNoteDeliveryDisposition("transform.ack");
@@ -30700,13 +31037,19 @@ function createRustModeTransform(deps, options) {
30700
31037
  throw new EmergencyFailClosedError("Rust Magic Context was unavailable at a provider-proven context limit", { cause: error });
30701
31038
  }
30702
31039
  const replayed = replayLastGood(sessionId, messages, output, sessionMeta.systemPromptTokens);
30703
- if (!replayed)
30704
- replaceMessagesInPlace(output, messages);
30705
31040
  servedFrom = replayed ? "lkg" : "raw";
30706
31041
  if (decision.toLowerCase() !== "need_full_sync")
30707
31042
  decision = "error";
30708
31043
  materializeReason = "none";
30709
31044
  markFailure(sessionId, state, error);
31045
+ if (!replayed) {
31046
+ try {
31047
+ serveRawFallback(error);
31048
+ } catch (rawFallbackError) {
31049
+ finishPass(false, false);
31050
+ throw rawFallbackError;
31051
+ }
31052
+ }
30710
31053
  finishPass(false);
30711
31054
  return;
30712
31055
  }
@@ -31156,16 +31499,6 @@ function createTransform(deps) {
31156
31499
  sessionLog(sessionId, "transform skipped (internal magic-context child session)");
31157
31500
  return;
31158
31501
  }
31159
- if (deps.transformMode === "rust") {
31160
- if (!rustModeTransform) {
31161
- sessionLog(sessionId, "rust transform unavailable; using raw passthrough");
31162
- return;
31163
- }
31164
- await rustModeTransform.run(sessionId, messages, output, sessionMeta);
31165
- return;
31166
- }
31167
- const reducedMode = sessionMeta.isSubagent;
31168
- const fullFeatureMode = !reducedMode;
31169
31502
  const compactionOff = deps.compactionOff === true;
31170
31503
  try {
31171
31504
  const transition = reconcileCompactionMode({
@@ -31207,6 +31540,18 @@ function createTransform(deps) {
31207
31540
  passOutcome.record("compaction-mode-transition-failure");
31208
31541
  sessionLog(sessionId, "compaction mode transition failed (retrying next pass):", error);
31209
31542
  }
31543
+ if (deps.transformMode === "rust") {
31544
+ if (compactionOff)
31545
+ return;
31546
+ if (!rustModeTransform) {
31547
+ sessionLog(sessionId, "rust transform unavailable; using raw passthrough");
31548
+ return;
31549
+ }
31550
+ await rustModeTransform.run(sessionId, messages, output, sessionMeta);
31551
+ return;
31552
+ }
31553
+ const reducedMode = sessionMeta.isSubagent;
31554
+ const fullFeatureMode = !reducedMode;
31210
31555
  const ctxReduceAvailability = resolveCtxReduceAvailabilityFromMessages(sessionId, messages);
31211
31556
  const ctxReduceCallable = ctxReduceAvailability.callable;
31212
31557
  const todowriteAvailability = resolveTodowriteAvailabilityFromMessages(sessionId, messages);
@@ -33284,37 +33629,49 @@ function createSystemPromptHashHandler(deps) {
33284
33629
  }
33285
33630
  const isCacheBusting = deps.systemPromptRefreshSessions.has(sessionId);
33286
33631
  const DATE_PATTERN = /Today's date: .+/;
33632
+ const DATE_PATTERN_ALL = /Today's date: .+/g;
33633
+ const liveSystemContent = output.system.join(`
33634
+ `);
33635
+ if (liveSystemContent.length === 0)
33636
+ return;
33637
+ const previousHash = sessionMetaEarly?.systemPromptHash ?? "";
33638
+ const hasPersistedHash = previousHash !== "" && previousHash !== "0";
33639
+ const dateElementIndexes = [];
33640
+ let currentDate;
33287
33641
  for (let i = 0;i < output.system.length; i++) {
33288
33642
  const match = output.system[i].match(DATE_PATTERN);
33289
33643
  if (!match)
33290
33644
  continue;
33291
- const currentDate = match[0];
33292
- const stickyDate = stickyDateBySession.get(sessionId);
33293
- if (!stickyDate) {
33645
+ dateElementIndexes.push(i);
33646
+ currentDate ??= match[0];
33647
+ }
33648
+ const stickyDate = stickyDateBySession.get(sessionId);
33649
+ const stableCandidate = currentDate && stickyDate && currentDate !== stickyDate ? liveSystemContent.replace(DATE_PATTERN_ALL, stickyDate) : liveSystemContent;
33650
+ const stableCandidateHash = createHash14("md5").update(promptSurfaceHashMaterial(stableCandidate, promptSurface.preset)).digest("hex");
33651
+ const contentOrPresetChanged = hasPersistedHash && stableCandidateHash !== previousHash;
33652
+ const dateMayAdvance = isCacheBusting || contentOrPresetChanged;
33653
+ if (currentDate && !stickyDate) {
33654
+ stickyDateBySession.set(sessionId, currentDate);
33655
+ } else if (currentDate && stickyDate && currentDate !== stickyDate) {
33656
+ if (dateMayAdvance) {
33294
33657
  stickyDateBySession.set(sessionId, currentDate);
33295
- } else if (currentDate !== stickyDate) {
33296
- if (isCacheBusting) {
33297
- stickyDateBySession.set(sessionId, currentDate);
33298
- sessionLog(sessionId, `system prompt date updated: ${stickyDate} → ${currentDate} (cache-busting pass)`);
33299
- } else {
33300
- output.system[i] = output.system[i].replace(DATE_PATTERN, stickyDate);
33301
- sessionLog(sessionId, `system prompt date frozen: real=${currentDate}, using=${stickyDate} (defer pass)`);
33658
+ sessionLog(sessionId, `system prompt date updated: ${stickyDate} → ${currentDate} (cache-busting pass)`);
33659
+ } else if (dateElementIndexes.length > 0) {
33660
+ for (const index of dateElementIndexes) {
33661
+ output.system[index] = output.system[index].replace(DATE_PATTERN_ALL, stickyDate);
33302
33662
  }
33663
+ sessionLog(sessionId, `system prompt date frozen: real=${currentDate}, using=${stickyDate} (defer pass)`);
33303
33664
  }
33304
- break;
33305
33665
  }
33306
33666
  const systemContent = output.system.join(`
33307
33667
  `);
33308
- if (systemContent.length === 0)
33309
- return;
33310
- if (!availability.frozen)
33668
+ if (!availability.frozen || !modelKey)
33311
33669
  return;
33312
33670
  const currentHash = createHash14("md5").update(promptSurfaceHashMaterial(systemContent, promptSurface.preset)).digest("hex");
33313
33671
  if (!sessionMetaEarly) {
33314
33672
  return;
33315
33673
  }
33316
33674
  const sessionMeta = sessionMetaEarly;
33317
- const previousHash = sessionMeta.systemPromptHash;
33318
33675
  if (previousHash !== "" && previousHash !== "0" && previousHash !== currentHash) {
33319
33676
  sessionLog(sessionId, `system prompt hash changed: ${previousHash} → ${currentHash} (len=${systemContent.length}), triggering flush`);
33320
33677
  deps.historyRefreshSessions.add(sessionId);
@@ -33487,6 +33844,37 @@ function notifyMagicContextDisabled(client, reason) {
33487
33844
  log("[magic-context] failed to show disabled toast:", error);
33488
33845
  });
33489
33846
  }
33847
+ function moduleNoteRowId(response, depth = 0) {
33848
+ if (depth > 4 || response === null || response === undefined)
33849
+ return null;
33850
+ if (typeof response === "string") {
33851
+ const match = response.match(/\b(?:smart\s+)?note\s+#(\d+)/i);
33852
+ return match ? Number(match[1]) : null;
33853
+ }
33854
+ if (Array.isArray(response)) {
33855
+ for (const item of response) {
33856
+ const id = moduleNoteRowId(item, depth + 1);
33857
+ if (id !== null)
33858
+ return id;
33859
+ }
33860
+ return null;
33861
+ }
33862
+ if (typeof response !== "object")
33863
+ return null;
33864
+ const record = response;
33865
+ return moduleNoteRowId(record.result, depth + 1) ?? moduleNoteRowId(record.content, depth + 1) ?? moduleNoteRowId(record.text, depth + 1);
33866
+ }
33867
+ function moduleNoteResponseIsError(response, depth = 0) {
33868
+ if (depth > 4 || response === null || typeof response !== "object")
33869
+ return false;
33870
+ if (Array.isArray(response)) {
33871
+ return response.some((item) => moduleNoteResponseIsError(item, depth + 1));
33872
+ }
33873
+ const record = response;
33874
+ if (record.isError === true || record.ok === false || record.error !== undefined)
33875
+ return true;
33876
+ return moduleNoteResponseIsError(record.result, depth + 1);
33877
+ }
33490
33878
  function createMagicContextHook(deps) {
33491
33879
  const contextUsageMap = new Map;
33492
33880
  let db;
@@ -33761,6 +34149,7 @@ function createMagicContextHook(deps) {
33761
34149
  autoEmbedAttemptedBySession.add(sessionId);
33762
34150
  const directory = sessionDirectoryBySession.get(sessionId) ?? deps.directory;
33763
34151
  (async () => {
34152
+ let completedDrainWithWork = false;
33764
34153
  try {
33765
34154
  await new Promise((resolve3) => setTimeout(resolve3, 0));
33766
34155
  await ensureProjectRegisteredFromOpenCodeDirectory(directory, db);
@@ -33782,6 +34171,8 @@ function createMagicContextHook(deps) {
33782
34171
  });
33783
34172
  }
33784
34173
  const summary = await executeEmbedHistory(sessionId);
34174
+ const completedCoverage = getEmbeddingCoverageStatus(db, sessionProjectIdentity, sessionId);
34175
+ completedDrainWithWork = completedCoverage.session.total - completedCoverage.session.embedded <= 0;
33785
34176
  if (!isTuiConnected(sessionId)) {
33786
34177
  await sendIgnoredMessage(deps.client, sessionId, summary, {
33787
34178
  ...notifyParams
@@ -33789,6 +34180,9 @@ function createMagicContextHook(deps) {
33789
34180
  }
33790
34181
  } catch (error) {
33791
34182
  log("[magic-context] auto-embed drain failed:", error);
34183
+ } finally {
34184
+ if (!completedDrainWithWork)
34185
+ autoEmbedAttemptedBySession.delete(sessionId);
33792
34186
  }
33793
34187
  })();
33794
34188
  };
@@ -33878,6 +34272,10 @@ function createMagicContextHook(deps) {
33878
34272
  action,
33879
34273
  content,
33880
34274
  surfaceCondition,
34275
+ compiledProvider,
34276
+ compiledConfig,
34277
+ compiledAt,
34278
+ compileStatus,
33881
34279
  filter,
33882
34280
  limit,
33883
34281
  offset,
@@ -33903,6 +34301,22 @@ function createMagicContextHook(deps) {
33903
34301
  }
33904
34302
  });
33905
34303
  await syncModuleNotes();
34304
+ if (compileStatus && !moduleNoteResponseIsError(response)) {
34305
+ const moduleRowId = action === "write" ? moduleNoteRowId(response) : noteId ?? null;
34306
+ if (moduleRowId === null || !applyMirroredNoteCompileFields({
34307
+ db,
34308
+ moduleProject: memoryProject,
34309
+ moduleRowId,
34310
+ fields: {
34311
+ compiledProvider: compiledProvider ?? null,
34312
+ compiledConfig: compiledConfig ?? null,
34313
+ compiledAt: compiledAt ?? null,
34314
+ compileStatus
34315
+ }
34316
+ })) {
34317
+ throw new Error("Rust note was written but its host compilation metadata could not be mirrored");
34318
+ }
34319
+ }
33906
34320
  return response;
33907
34321
  },
33908
34322
  memory: async ({
@@ -34130,6 +34544,7 @@ function createMagicContextHook(deps) {
34130
34544
  }),
34131
34545
  userMemoryCollectionEnabled: userMemoryCollectionEnabled(dreaming),
34132
34546
  language: deps.config.language,
34547
+ retinaHandoff: deps.config.smart_notes?.retina_handoff === true,
34133
34548
  transformMode: deps.config.transform_mode,
34134
34549
  moduleClient: rustModeModuleClient,
34135
34550
  onProgress: (progress, completedTask) => {
@@ -34215,6 +34630,7 @@ function createMagicContextHook(deps) {
34215
34630
  language: deps.config.language,
34216
34631
  mural: deps.config.mural,
34217
34632
  memoryInjectionBudgetTokens: deps.config.memory?.injection_budget_tokens,
34633
+ retinaHandoff: deps.config.smart_notes?.retina_handoff === true,
34218
34634
  transformMode: deps.config.transform_mode,
34219
34635
  moduleClient: rustModeModuleClient,
34220
34636
  onProgress: (progress, completedTask) => {
@@ -34443,6 +34859,8 @@ function createMessagesTransformHandler(args) {
34443
34859
  await magicContext?.["experimental.chat.messages.transform"]?.(input, output);
34444
34860
  return output.messages;
34445
34861
  } catch (error) {
34862
+ if (error instanceof RawFallbackContextLimitError)
34863
+ throw error;
34446
34864
  if (error instanceof EmergencyFailClosedError || isFailClosedBlockingError(error)) {
34447
34865
  if (!args.compactionOff)
34448
34866
  throw error;
@@ -35182,7 +35600,7 @@ function registerRpcHandlers(rpcServer, args) {
35182
35600
  }
35183
35601
  });
35184
35602
  const buildManagedCtx = async (db) => {
35185
- const { deriveHistorianChunkTokens: deriveHistorianChunkTokens2, resolveHistorianContextLimit: resolveHistorianContextLimit2 } = await import("./derive-budgets-9crp0cvd.js");
35603
+ const { deriveHistorianChunkTokens: deriveHistorianChunkTokens2, resolveHistorianContextLimit: resolveHistorianContextLimit2 } = await import("./derive-budgets-88mxk2w1.js");
35186
35604
  const { resolveFallbackChain: resolveFallbackChain2 } = await import("./resolve-fallbacks-5n5tvge1.js");
35187
35605
  const { userMemoryCollectionEnabled: userMemoryCollectionEnabled2 } = await import("./task-config-gbp7r23g.js");
35188
35606
  const DEFAULT_HISTORIAN_TIMEOUT_MS2 = 600000;
@@ -35209,8 +35627,8 @@ function registerRpcHandlers(rpcServer, args) {
35209
35627
  const db = getDb();
35210
35628
  if (!db)
35211
35629
  return { ok: false, error: "db unavailable" };
35212
- const { runManagedRecomp: runManagedRecomp2 } = await import("./recomp-orchestrator-29f4rqax.js");
35213
- const { sendIgnoredMessage: sendIgnoredMessage2 } = await import("./send-session-notification-sr5g06hz.js");
35630
+ const { runManagedRecomp: runManagedRecomp2 } = await import("./recomp-orchestrator-a0g9b52q.js");
35631
+ const { sendIgnoredMessage: sendIgnoredMessage2 } = await import("./send-session-notification-bgtf4853.js");
35214
35632
  log(`[rpc] recomp requested for session ${sessionId}`);
35215
35633
  const ctx = await buildManagedCtx(db);
35216
35634
  runManagedRecomp2(ctx, sessionId).then((message) => {
@@ -35225,8 +35643,8 @@ function registerRpcHandlers(rpcServer, args) {
35225
35643
  const db = getDb();
35226
35644
  if (!db)
35227
35645
  return { ok: false, error: "db unavailable" };
35228
- const { runManagedUpgrade: runManagedUpgrade2 } = await import("./recomp-orchestrator-29f4rqax.js");
35229
- const { sendIgnoredMessage: sendIgnoredMessage2 } = await import("./send-session-notification-sr5g06hz.js");
35646
+ const { runManagedUpgrade: runManagedUpgrade2 } = await import("./recomp-orchestrator-a0g9b52q.js");
35647
+ const { sendIgnoredMessage: sendIgnoredMessage2 } = await import("./send-session-notification-bgtf4853.js");
35230
35648
  log(`[rpc] session-upgrade requested for session ${sessionId}`);
35231
35649
  const ctx = await buildManagedCtx(db);
35232
35650
  runManagedUpgrade2(ctx, sessionId).then((message) => {
@@ -35242,7 +35660,7 @@ function registerRpcHandlers(rpcServer, args) {
35242
35660
  if (!db)
35243
35661
  return { ok: false, error: "db unavailable" };
35244
35662
  try {
35245
- const { updateSessionMeta: updateSessionMeta2 } = await import("./storage-meta-session-ev8b55a9.js");
35663
+ const { updateSessionMeta: updateSessionMeta2 } = await import("./storage-meta-session-df9tstzr.js");
35246
35664
  updateSessionMeta2(db, sessionId, { upgradeRemindedAt: Date.now() });
35247
35665
  return { ok: true };
35248
35666
  } catch (error) {
@@ -36198,6 +36616,496 @@ Smart notes: pass surface_condition and the note stays hidden until a background
36198
36616
  Example: ctx_note(action="write", content="Re-run the perf benchmark once the boundary rework ships", surface_condition="When the latest release tag is >= v0.23.0")`;
36199
36617
  // src/tools/ctx-note/tools.ts
36200
36618
  import { tool as tool3 } from "@opencode-ai/plugin";
36619
+
36620
+ // src/features/magic-context/smart-notes/condition-compiler.ts
36621
+ import { existsSync as existsSync11 } from "node:fs";
36622
+ import { isAbsolute as isAbsolute4 } from "node:path";
36623
+
36624
+ // ../retina-local-fs/src/path-fence.ts
36625
+ import { lstat as lstat2, readlink, realpath as realpath2 } from "node:fs/promises";
36626
+ import { homedir as homedir4 } from "node:os";
36627
+ import { basename, dirname as dirname4, isAbsolute as isAbsolute3, join as join6, relative, resolve as resolve3, sep } from "node:path";
36628
+
36629
+ // ../retina-local-fs/src/errors.ts
36630
+ class ProviderError extends Error {
36631
+ code;
36632
+ constructor(code, message) {
36633
+ super(message);
36634
+ this.code = code;
36635
+ this.name = "ProviderError";
36636
+ }
36637
+ }
36638
+
36639
+ // ../retina-local-fs/src/path-fence.ts
36640
+ async function resolveAndFenceProviderPath(configuredPath, options) {
36641
+ const { home, dataDirectory } = await resolveFenceRoots(options);
36642
+ const expanded = configuredPath.startsWith("~/") ? join6(home, configuredPath.slice(2)) : configuredPath === "~" ? home : configuredPath;
36643
+ const absolute = isAbsolute3(expanded) ? resolve3(expanded) : resolve3(options.cwd ?? process.cwd(), expanded);
36644
+ const canonical = await canonicalPath(absolute, options.allowMissing);
36645
+ if (isFencedPath(canonical, home, dataDirectory)) {
36646
+ throw new ProviderError("fenced_path", `Refusing fenced path: ${canonical}`);
36647
+ }
36648
+ return canonical;
36649
+ }
36650
+ async function resolveFenceRoots(options) {
36651
+ const configuredHomePath = resolve3(options.homeDirectory ?? process.env.HOME ?? homedir4());
36652
+ let home;
36653
+ try {
36654
+ home = await realpath2(configuredHomePath);
36655
+ } catch (error) {
36656
+ throw fsError(configuredHomePath, error);
36657
+ }
36658
+ const configuredDataDirectory = resolve3(options.dataDirectory ?? process.env.XDG_DATA_HOME ?? join6(home, ".local", "share"));
36659
+ const dataDirectory = await canonicalPath(configuredDataDirectory, true);
36660
+ return { home, dataDirectory };
36661
+ }
36662
+ async function canonicalPath(path6, allowMissing) {
36663
+ try {
36664
+ return await realpath2(path6);
36665
+ } catch (error) {
36666
+ if (!allowMissing || !isMissingError(error)) {
36667
+ throw fsError(path6, error);
36668
+ }
36669
+ const suffix = [];
36670
+ let candidate = path6;
36671
+ while (true) {
36672
+ try {
36673
+ const metadata = await lstat2(candidate);
36674
+ if (metadata.isSymbolicLink()) {
36675
+ const target = await readlink(candidate);
36676
+ const resolvedTarget = resolve3(dirname4(candidate), target);
36677
+ return canonicalPath(join6(resolvedTarget, ...suffix), true);
36678
+ }
36679
+ } catch (candidateError) {
36680
+ if (!isMissingError(candidateError)) {
36681
+ throw fsError(path6, candidateError);
36682
+ }
36683
+ }
36684
+ const parent = dirname4(candidate);
36685
+ if (parent === candidate) {
36686
+ throw fsError(path6, error);
36687
+ }
36688
+ suffix.unshift(basename(candidate));
36689
+ candidate = parent;
36690
+ try {
36691
+ return join6(await realpath2(candidate), ...suffix);
36692
+ } catch (parentError) {
36693
+ if (!isMissingError(parentError)) {
36694
+ throw fsError(path6, parentError);
36695
+ }
36696
+ }
36697
+ }
36698
+ }
36699
+ }
36700
+ function isFencedPath(canonicalPath2, homeDirectory, dataDirectory = process.env.XDG_DATA_HOME ?? join6(resolve3(homeDirectory), ".local", "share")) {
36701
+ const cortexkitRoot = join6(resolve3(dataDirectory), "cortexkit");
36702
+ const relativeToCortexkit = relative(cortexkitRoot, canonicalPath2);
36703
+ const insideCortexkit = relativeToCortexkit !== "" && relativeToCortexkit !== ".." && !relativeToCortexkit.startsWith(`..${sep}`) && !isAbsolute3(relativeToCortexkit);
36704
+ const parts = insideCortexkit ? relativeToCortexkit.split(sep) : [];
36705
+ const pathParts = canonicalPath2.split(sep).filter(Boolean);
36706
+ const name = basename(canonicalPath2);
36707
+ const catalogDirectoryCarveIn = pathParts.includes("catalog");
36708
+ const moduleBinCarveIn = parts.length >= 2 && parts[1] === "bin";
36709
+ const catalogJsonCarveIn = name.endsWith(".json") && name.includes("catalog");
36710
+ const rootWithoutCarveIns = insideCortexkit && (parts[0] === "run" || parts[0] === "magic-context");
36711
+ if (!rootWithoutCarveIns && (catalogDirectoryCarveIn || moduleBinCarveIn || catalogJsonCarveIn)) {
36712
+ return false;
36713
+ }
36714
+ const inFencedRoot = insideCortexkit && ["plexus", "claustrum", "staging", "run", "magic-context"].includes(parts[0] ?? "");
36715
+ const fencedBasename = name.includes("binding-key") || name.endsWith(".handle");
36716
+ const plexusStore = insideCortexkit && parts[0] === "plexus" && name.startsWith("store.db");
36717
+ return inFencedRoot || fencedBasename || plexusStore;
36718
+ }
36719
+ function fsError(path6, error) {
36720
+ const message = error instanceof Error ? error.message : String(error);
36721
+ return new ProviderError("unreadable_path", `Could not read ${path6}: ${message}`);
36722
+ }
36723
+ function isMissingError(error) {
36724
+ return error !== null && typeof error === "object" && "code" in error && (error.code === "ENOENT" || error.code === "ENOTDIR");
36725
+ }
36726
+
36727
+ // ../retina-local-fs/src/provider.ts
36728
+ import { execFile as execFile3 } from "node:child_process";
36729
+ import { promisify as promisify3 } from "node:util";
36730
+ var execFileAsync3 = promisify3(execFile3);
36731
+ function parseSemver(value) {
36732
+ const match = /^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/.exec(value);
36733
+ if (!match) {
36734
+ throw new ProviderError("invalid_config", `Invalid semantic version: ${value}`);
36735
+ }
36736
+ return {
36737
+ major: Number(match[1]),
36738
+ minor: Number(match[2]),
36739
+ patch: Number(match[3]),
36740
+ prerelease: match[4] ? match[4].split(".").map((part) => /^\d+$/.test(part) ? Number(part) : part) : []
36741
+ };
36742
+ }
36743
+ function validateProviderConfig(input) {
36744
+ try {
36745
+ return { success: true, config: parseConfig(input) };
36746
+ } catch (error) {
36747
+ return {
36748
+ success: false,
36749
+ reason: error instanceof Error ? error.message : String(error)
36750
+ };
36751
+ }
36752
+ }
36753
+ function parseConfig(value) {
36754
+ const config = requireObject(value, "config");
36755
+ if ("any" in config) {
36756
+ requireOnlyKeys(config, ["any"], "compound config");
36757
+ if (!Array.isArray(config.any) || config.any.length < 1 || config.any.length > 4) {
36758
+ invalid("config.any must contain between 1 and 4 predicates");
36759
+ }
36760
+ return { any: config.any.map(parseAtomicPredicate) };
36761
+ }
36762
+ return parseAtomicPredicate(config);
36763
+ }
36764
+ function parseAtomicPredicate(value) {
36765
+ const predicate = requireObject(value, "predicate");
36766
+ if (typeof predicate.kind !== "string") {
36767
+ invalid("predicate.kind must be a string");
36768
+ }
36769
+ switch (predicate.kind) {
36770
+ case "file_contains":
36771
+ requireOnlyKeys(predicate, ["kind", "path", "needle", "absent", "resolved_path_exists"], predicate.kind);
36772
+ return {
36773
+ kind: predicate.kind,
36774
+ path: requireString(predicate.path, "path"),
36775
+ needle: requireString(predicate.needle, "needle", true),
36776
+ ...optionalBoolean(predicate.absent, "absent") === undefined ? {} : { absent: predicate.absent },
36777
+ ...predicateAudit(predicate)
36778
+ };
36779
+ case "path_exists":
36780
+ requireOnlyKeys(predicate, ["kind", "path", "gone", "resolved_path_exists"], predicate.kind);
36781
+ return {
36782
+ kind: predicate.kind,
36783
+ path: requireString(predicate.path, "path"),
36784
+ ...optionalBoolean(predicate.gone, "gone") === undefined ? {} : { gone: predicate.gone },
36785
+ ...predicateAudit(predicate)
36786
+ };
36787
+ case "mtime_after":
36788
+ requireOnlyKeys(predicate, ["kind", "path", "since_ms", "resolved_path_exists"], predicate.kind);
36789
+ return {
36790
+ kind: predicate.kind,
36791
+ path: requireString(predicate.path, "path"),
36792
+ since_ms: requireFiniteNumber(predicate.since_ms, "since_ms"),
36793
+ ...predicateAudit(predicate)
36794
+ };
36795
+ case "git_commit_after":
36796
+ requireOnlyKeys(predicate, ["kind", "repo_path", "ref", "sha", "resolved_path_exists"], predicate.kind);
36797
+ return {
36798
+ kind: predicate.kind,
36799
+ repo_path: requireString(predicate.repo_path, "repo_path"),
36800
+ sha: requireString(predicate.sha, "sha"),
36801
+ ...predicate.ref === undefined ? {} : { ref: requireString(predicate.ref, "ref") },
36802
+ ...predicateAudit(predicate)
36803
+ };
36804
+ case "git_tag_matching": {
36805
+ requireOnlyKeys(predicate, ["kind", "repo_path", "pattern", "above", "resolved_path_exists"], predicate.kind);
36806
+ const above = predicate.above === undefined ? undefined : requireString(predicate.above, "above");
36807
+ if (above !== undefined) {
36808
+ parseSemver(above);
36809
+ }
36810
+ return {
36811
+ kind: predicate.kind,
36812
+ repo_path: requireString(predicate.repo_path, "repo_path"),
36813
+ pattern: requireString(predicate.pattern, "pattern"),
36814
+ ...above === undefined ? {} : { above },
36815
+ ...predicateAudit(predicate)
36816
+ };
36817
+ }
36818
+ default:
36819
+ invalid(`Unsupported predicate kind: ${predicate.kind}`);
36820
+ }
36821
+ }
36822
+ function requireObject(value, field) {
36823
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
36824
+ invalid(`${field} must be an object`);
36825
+ }
36826
+ return value;
36827
+ }
36828
+ function requireOnlyKeys(value, allowed, field) {
36829
+ const unknown = Object.keys(value).filter((key) => !allowed.includes(key));
36830
+ if (unknown.length > 0) {
36831
+ invalid(`${field} contains unknown field(s): ${unknown.join(", ")}`);
36832
+ }
36833
+ }
36834
+ function requireString(value, field, allowEmpty = false) {
36835
+ if (typeof value !== "string" || !allowEmpty && value.length === 0) {
36836
+ invalid(`${field} must be ${allowEmpty ? "a string" : "a non-empty string"}`);
36837
+ }
36838
+ return value;
36839
+ }
36840
+ function predicateAudit(predicate) {
36841
+ const exists = optionalBoolean(predicate.resolved_path_exists, "resolved_path_exists");
36842
+ return exists === undefined ? {} : { resolved_path_exists: exists };
36843
+ }
36844
+ function optionalBoolean(value, field) {
36845
+ if (value !== undefined && typeof value !== "boolean") {
36846
+ invalid(`${field} must be a boolean`);
36847
+ }
36848
+ return value;
36849
+ }
36850
+ function requireFiniteNumber(value, field) {
36851
+ if (typeof value !== "number" || !Number.isFinite(value)) {
36852
+ invalid(`${field} must be a finite number`);
36853
+ }
36854
+ return value;
36855
+ }
36856
+ function invalid(message) {
36857
+ throw new ProviderError("invalid_config", message);
36858
+ }
36859
+
36860
+ // src/features/magic-context/smart-notes/condition-compiler.ts
36861
+ var RETINA_LOCAL_FS_PROVIDER = "local-fs";
36862
+ var VALUE = String.raw`(?:"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|\S+)`;
36863
+ async function compileSurfaceCondition(surfaceCondition, options) {
36864
+ const plainReason = unsafeGrammarReason(surfaceCondition);
36865
+ if (plainReason)
36866
+ return { status: "plain", reason: plainReason };
36867
+ const parsed = parseCondition(surfaceCondition, options.projectPath);
36868
+ if (parsed === null)
36869
+ return { status: "plain" };
36870
+ const now = (options.now ?? Date.now)();
36871
+ const resolvePath = options.resolvePath ?? (async (path6) => {
36872
+ const resolved = await resolveAndFenceProviderPath(path6, {
36873
+ allowMissing: true,
36874
+ homeDirectory: options.homeDirectory,
36875
+ cwd: options.projectPath
36876
+ });
36877
+ return { path: resolved, exists: existsSync11(resolved) };
36878
+ });
36879
+ let predicates;
36880
+ try {
36881
+ predicates = [];
36882
+ for (const predicate of parsed) {
36883
+ predicates.push(await resolvePredicate(predicate, resolvePath, now));
36884
+ }
36885
+ } catch (error) {
36886
+ const code = error !== null && typeof error === "object" && "code" in error ? error.code : undefined;
36887
+ return {
36888
+ status: "refused",
36889
+ reason: code === "fenced_path" ? "fenced path" : "path resolution failed"
36890
+ };
36891
+ }
36892
+ const candidate = predicates.length === 1 ? predicates[0] : { any: predicates };
36893
+ const validation = validateProviderConfig(candidate);
36894
+ if (!validation.success) {
36895
+ return {
36896
+ status: "refused",
36897
+ reason: `provider schema: ${singleLine(validation.reason)}`.slice(0, 180)
36898
+ };
36899
+ }
36900
+ return {
36901
+ status: "compiled",
36902
+ provider: RETINA_LOCAL_FS_PROVIDER,
36903
+ config: validation.config,
36904
+ compiledAt: now
36905
+ };
36906
+ }
36907
+ function conditionCompileStorageFields(result) {
36908
+ if (result.status === "compiled") {
36909
+ return {
36910
+ compiledProvider: result.provider,
36911
+ compiledConfig: JSON.stringify(result.config),
36912
+ compiledAt: result.compiledAt,
36913
+ compileStatus: result.status
36914
+ };
36915
+ }
36916
+ return {
36917
+ compiledProvider: null,
36918
+ compiledConfig: null,
36919
+ compiledAt: null,
36920
+ compileStatus: result.status
36921
+ };
36922
+ }
36923
+ function conditionCompileReplySuffix(result) {
36924
+ if (result.status === "compiled") {
36925
+ return `
36926
+ - Retina provider: ${result.provider}`;
36927
+ }
36928
+ if (result.status === "refused") {
36929
+ return `
36930
+ - Retina compile refused: ${result.reason}`;
36931
+ }
36932
+ return "";
36933
+ }
36934
+ function parseCondition(surfaceCondition, projectPath) {
36935
+ const trimmed = surfaceCondition.trim();
36936
+ const either = trimmed.match(/^either\s+(.+)$/i);
36937
+ if (!either) {
36938
+ const predicate = parseAtomicCondition(trimmed, projectPath);
36939
+ return predicate ? [predicate] : null;
36940
+ }
36941
+ const clauses = splitOrClauses(either[1]);
36942
+ if (clauses.length < 2)
36943
+ return null;
36944
+ const predicates = clauses.map((clause) => parseAtomicCondition(clause, projectPath));
36945
+ return predicates.every((predicate) => predicate !== null) ? predicates : null;
36946
+ }
36947
+ function parseAtomicCondition(text, projectPath) {
36948
+ const fileContains = text.match(new RegExp(`^(?:when\\s+)?file\\s+(${VALUE})\\s+(no longer contains|contains)\\s+(${VALUE})$`, "i"));
36949
+ if (fileContains) {
36950
+ const path6 = unquote(fileContains[1]);
36951
+ const needle = unquote(fileContains[3].trim());
36952
+ if (path6 === null || needle === null)
36953
+ return null;
36954
+ return {
36955
+ kind: "file_contains",
36956
+ path: path6,
36957
+ needle,
36958
+ ...fileContains[2].toLowerCase() === "no longer contains" ? { absent: true } : {}
36959
+ };
36960
+ }
36961
+ const commit = text.match(new RegExp(`^(?:when\\s+)?(?:repo(?:sitory)?\\s+)?(${VALUE})\\s+has\\s+a\\s+commit\\s+(?:after|newer than)\\s+([0-9a-f]{7,64})$`, "i"));
36962
+ if (commit) {
36963
+ const repoPath = unquote(commit[1]);
36964
+ if (repoPath === null)
36965
+ return null;
36966
+ return {
36967
+ kind: "git_commit_after",
36968
+ repo_path: repoPath,
36969
+ sha: commit[2]
36970
+ };
36971
+ }
36972
+ const tag = text.match(new RegExp(`^(?:when\\s+)?a\\s+tag\\s+(?:(?:matching\\s+(${VALUE})(?:\\s+above\\s+semver\\s+(${VALUE}))?)|(?:above\\s+semver\\s+(${VALUE})))\\s+appears(?:\\s+in\\s+(?:repo(?:sitory)?\\s+)?(${VALUE}))?$`, "i"));
36973
+ if (tag) {
36974
+ const pattern = tag[1] ? unquote(tag[1]) : "*";
36975
+ const above = unquote(tag[2] ?? tag[3] ?? "");
36976
+ const repoPath = tag[4] ? unquote(tag[4]) : projectPath;
36977
+ if (pattern === null || above === null || repoPath === null)
36978
+ return null;
36979
+ return {
36980
+ kind: "git_tag_matching",
36981
+ repo_path: repoPath,
36982
+ pattern,
36983
+ ...above.length > 0 ? { above } : {}
36984
+ };
36985
+ }
36986
+ const mtime = text.match(new RegExp(`^(?:when\\s+)?(?:file\\s+)?(${VALUE})\\s+(changes|is rebuilt|mtime moves)$`, "i"));
36987
+ if (mtime) {
36988
+ const path6 = unquote(mtime[1]);
36989
+ if (path6 === null)
36990
+ return null;
36991
+ return {
36992
+ kind: "mtime_after",
36993
+ path: path6
36994
+ };
36995
+ }
36996
+ const pathExists = text.match(new RegExp(`^(?:when\\s+)?(?:path\\s+)?(${VALUE})\\s+(exists|is gone)$`, "i"));
36997
+ if (pathExists) {
36998
+ const path6 = unquote(pathExists[1]);
36999
+ if (path6 === null)
37000
+ return null;
37001
+ return {
37002
+ kind: "path_exists",
37003
+ path: path6,
37004
+ ...pathExists[2].toLowerCase() === "is gone" ? { gone: true } : {}
37005
+ };
37006
+ }
37007
+ return null;
37008
+ }
37009
+ async function resolvePredicate(predicate, resolvePath, now) {
37010
+ const configuredPath = "repo_path" in predicate ? predicate.repo_path : predicate.path;
37011
+ const resolved = await resolvePath(configuredPath);
37012
+ const sourceIsResolvable = isAbsolute4(configuredPath) || configuredPath === "~" || configuredPath.startsWith("~/");
37013
+ const audit = sourceIsResolvable && resolved.exists ? {} : { resolved_path_exists: false };
37014
+ switch (predicate.kind) {
37015
+ case "file_contains":
37016
+ return { ...predicate, path: resolved.path, ...audit };
37017
+ case "path_exists":
37018
+ return { ...predicate, path: resolved.path, ...audit };
37019
+ case "mtime_after":
37020
+ return { kind: predicate.kind, path: resolved.path, since_ms: now, ...audit };
37021
+ case "git_commit_after":
37022
+ return { ...predicate, repo_path: resolved.path, ...audit };
37023
+ case "git_tag_matching":
37024
+ return { ...predicate, repo_path: resolved.path, ...audit };
37025
+ }
37026
+ }
37027
+ function splitOrClauses(text) {
37028
+ const clauses = [];
37029
+ let start = 0;
37030
+ let quote = null;
37031
+ let escaped = false;
37032
+ for (let index = 0;index < text.length; index += 1) {
37033
+ const character = text[index];
37034
+ if (escaped) {
37035
+ escaped = false;
37036
+ continue;
37037
+ }
37038
+ if (quote && character === "\\") {
37039
+ escaped = true;
37040
+ continue;
37041
+ }
37042
+ if (character === '"' || character === "'") {
37043
+ quote = quote === character ? null : quote === null ? character : quote;
37044
+ continue;
37045
+ }
37046
+ if (quote !== null)
37047
+ continue;
37048
+ const separator = text.slice(index).match(/^\s+or\s+/i);
37049
+ if (!separator)
37050
+ continue;
37051
+ clauses.push(text.slice(start, index).trim());
37052
+ index += separator[0].length - 1;
37053
+ start = index + 1;
37054
+ }
37055
+ clauses.push(text.slice(start).trim());
37056
+ return clauses.filter(Boolean);
37057
+ }
37058
+ function unsafeGrammarReason(value) {
37059
+ let quote = null;
37060
+ let escaped = false;
37061
+ for (const character of value) {
37062
+ if (escaped) {
37063
+ escaped = false;
37064
+ continue;
37065
+ }
37066
+ if (quote && character === "\\") {
37067
+ escaped = true;
37068
+ continue;
37069
+ }
37070
+ if (character === '"' || character === "'") {
37071
+ quote = quote === character ? null : quote === null ? character : quote;
37072
+ }
37073
+ }
37074
+ if (quote !== null)
37075
+ return "unbalanced quote; leaving condition dreamer-evaluated";
37076
+ if (/\bcontains\s+no(?:\s|$)/i.test(value)) {
37077
+ return "ambiguous negation after contains; leaving condition dreamer-evaluated";
37078
+ }
37079
+ const temporalSuffix = new RegExp(`\\bcontains\\s+${VALUE}\\s+(?:since|until|after|before|when|while|for|as\\s+of)\\b`, "i");
37080
+ if (temporalSuffix.test(value)) {
37081
+ return "temporal suffix after contains; leaving condition dreamer-evaluated";
37082
+ }
37083
+ return null;
37084
+ }
37085
+ function unquote(value) {
37086
+ const quote = value[0];
37087
+ const final = value.at(-1);
37088
+ const startsQuoted = quote === '"' || quote === "'";
37089
+ const endsQuoted = final === '"' || final === "'";
37090
+ if (!startsQuoted && !endsQuoted)
37091
+ return value;
37092
+ if (!startsQuoted || final !== quote || value.length < 2)
37093
+ return null;
37094
+ if (quote === '"') {
37095
+ try {
37096
+ const parsed = JSON.parse(value);
37097
+ return typeof parsed === "string" ? parsed : null;
37098
+ } catch {
37099
+ return null;
37100
+ }
37101
+ }
37102
+ return value.slice(1, -1).replace(/\\'/g, "'").replace(/\\\\/g, "\\");
37103
+ }
37104
+ function singleLine(value) {
37105
+ return value.replace(/\s+/g, " ").trim();
37106
+ }
37107
+
37108
+ // src/tools/ctx-note/tools.ts
36201
37109
  function captureAnchorOrdinal(db, sessionId) {
36202
37110
  try {
36203
37111
  const ordinal = getLastIndexedOrdinal(db, sessionId);
@@ -36377,8 +37285,15 @@ function createCtxNoteTool(deps) {
36377
37285
  if (!rustNote || !projectIdentity) {
36378
37286
  return "Error: Rust notes authority is active, but this module transport does not support ctx_note.";
36379
37287
  }
36380
- if (action === "write" && args.surface_condition?.trim() && deps.rustToolBackends?.noteEvaluationAvailable?.(projectIdentity) !== true) {
36381
- return "Error: Smart-note evaluation is unavailable for this Rust-authority project; the note was not written.";
37288
+ const surfaceCondition = args.surface_condition?.trim();
37289
+ let compilation;
37290
+ if ((action === "write" || action === "update") && surfaceCondition) {
37291
+ if (deps.rustToolBackends?.noteEvaluationAvailable?.(projectIdentity) !== true) {
37292
+ return "Error: Smart-note evaluation is unavailable for this Rust-authority project; the note was not written.";
37293
+ }
37294
+ compilation = await compileSurfaceCondition(surfaceCondition, {
37295
+ projectPath: toolContext.directory
37296
+ });
36382
37297
  }
36383
37298
  const commandId = toolCallIdFromContext(toolContext);
36384
37299
  const request2 = {
@@ -36389,7 +37304,8 @@ function createCtxNoteTool(deps) {
36389
37304
  memoryProject: projectIdentity,
36390
37305
  action,
36391
37306
  content: args.content,
36392
- surfaceCondition: args.surface_condition,
37307
+ surfaceCondition,
37308
+ ...compilation ? conditionCompileStorageFields(compilation) : {},
36393
37309
  filter: args.filter,
36394
37310
  limit: args.limit,
36395
37311
  offset: args.offset,
@@ -36397,9 +37313,13 @@ function createCtxNoteTool(deps) {
36397
37313
  };
36398
37314
  try {
36399
37315
  const text = moduleNoteText(await rustNote(request2));
36400
- if (text !== null)
36401
- return text;
36402
- return "Error: Rust module returned an invalid ctx_note response.";
37316
+ if (text === null) {
37317
+ return "Error: Rust module returned an invalid ctx_note response.";
37318
+ }
37319
+ if (compilation && !text.startsWith("Error:")) {
37320
+ return text + conditionCompileReplySuffix(compilation);
37321
+ }
37322
+ return text;
36403
37323
  } catch (error) {
36404
37324
  if (isRustAuthorityDrainingError(error)) {
36405
37325
  return "Error: Rust notes authority is not ready; TypeScript fallback is disabled.";
@@ -36423,16 +37343,21 @@ function createCtxNoteTool(deps) {
36423
37343
  if (!projectIdentity) {
36424
37344
  return "Error: Could not resolve project identity for smart note.";
36425
37345
  }
37346
+ const surfaceCondition = args.surface_condition.trim();
37347
+ const compilation = await compileSurfaceCondition(surfaceCondition, {
37348
+ projectPath: toolContext.directory
37349
+ });
36426
37350
  const note2 = addNote(deps.db, "smart", {
36427
37351
  content,
36428
37352
  projectPath: projectIdentity,
36429
37353
  sessionId,
36430
- surfaceCondition: args.surface_condition.trim(),
36431
- anchorOrdinal
37354
+ surfaceCondition,
37355
+ anchorOrdinal,
37356
+ ...conditionCompileStorageFields(compilation)
36432
37357
  });
36433
37358
  return `Created smart note #${note2.id}. Dreamer will evaluate the condition during nightly runs:
36434
37359
  - Content: ${content}
36435
- - Condition: ${args.surface_condition.trim()}`;
37360
+ - Condition: ${surfaceCondition}${conditionCompileReplySuffix(compilation)}`;
36436
37361
  }
36437
37362
  const note = addNote(deps.db, "session", { sessionId, content, anchorOrdinal });
36438
37363
  return `Saved session note #${note.id}.`;
@@ -36459,8 +37384,15 @@ function createCtxNoteTool(deps) {
36459
37384
  const updates = {};
36460
37385
  if (args.content?.trim())
36461
37386
  updates.content = args.content.trim();
36462
- if (args.surface_condition?.trim())
36463
- updates.surfaceCondition = args.surface_condition.trim();
37387
+ let compilation;
37388
+ if (args.surface_condition?.trim()) {
37389
+ const surfaceCondition = args.surface_condition.trim();
37390
+ updates.surfaceCondition = surfaceCondition;
37391
+ compilation = await compileSurfaceCondition(surfaceCondition, {
37392
+ projectPath: toolContext.directory
37393
+ });
37394
+ Object.assign(updates, conditionCompileStorageFields(compilation));
37395
+ }
36464
37396
  if (!updates.content && !updates.surfaceCondition) {
36465
37397
  return "Error: Provide 'content' and/or 'surface_condition' to update.";
36466
37398
  }
@@ -36481,7 +37413,7 @@ function createCtxNoteTool(deps) {
36481
37413
  parts.push(`Condition: ${updates.surfaceCondition}`);
36482
37414
  return `Updated note #${noteId}:
36483
37415
  ${parts.join(`
36484
- `)}`;
37416
+ `)}${compilation ? conditionCompileReplySuffix(compilation) : ""}`;
36485
37417
  }
36486
37418
  const limit = typeof args.limit === "number" && args.limit > 0 ? Math.floor(args.limit) : DEFAULT_READ_LIMIT;
36487
37419
  const offset = typeof args.offset === "number" && args.offset > 0 ? Math.floor(args.offset) : 0;
@@ -37050,7 +37982,7 @@ import {
37050
37982
  unlinkSync,
37051
37983
  writeFileSync as writeFileSync4
37052
37984
  } from "node:fs";
37053
- import { dirname as dirname4 } from "node:path";
37985
+ import { dirname as dirname5 } from "node:path";
37054
37986
  var MAX_BODY_BYTES = 1048576;
37055
37987
  var WS_AUTH_TIMEOUT_MS = 5000;
37056
37988
  var WS_CLOSE_UNAUTHORIZED = 4401;
@@ -37124,7 +38056,7 @@ class MagicContextRpcServer {
37124
38056
  this.port = server.port ?? 0;
37125
38057
  try {
37126
38058
  this.warnIfOtherLiveInstance();
37127
- const dir = dirname4(this.portFilePath);
38059
+ const dir = dirname5(this.portFilePath);
37128
38060
  const enforcePrivatePermissions = shouldEnforcePrivateStoragePermissions();
37129
38061
  if (enforcePrivatePermissions) {
37130
38062
  mkdirSync2(dir, { recursive: true, mode: 448 });
@@ -37357,7 +38289,7 @@ var server = async (ctx) => {
37357
38289
  `);
37358
38290
  setTimeout(async () => {
37359
38291
  try {
37360
- const { sendIgnoredMessage: sendIgnoredMessage2 } = await import("./send-session-notification-sr5g06hz.js");
38292
+ const { sendIgnoredMessage: sendIgnoredMessage2 } = await import("./send-session-notification-bgtf4853.js");
37361
38293
  const clientWithSessions = ctx.client;
37362
38294
  const sessions = await Promise.resolve(clientWithSessions.session?.list?.()).catch(() => null);
37363
38295
  const sessionList = Array.isArray(sessions) ? sessions : sessions?.data;
@@ -37501,6 +38433,7 @@ var server = async (ctx) => {
37501
38433
  memoryEnabled: pluginConfig.memory?.enabled === true,
37502
38434
  memoryInjectionBudgetTokens: pluginConfig.memory?.injection_budget_tokens,
37503
38435
  mural: pluginConfig.mural,
38436
+ retinaHandoff: pluginConfig.smart_notes.retina_handoff,
37504
38437
  gitCommitIndexing: pluginConfig.memory.git_commit_indexing?.enabled ? {
37505
38438
  enabled: true,
37506
38439
  since_days: pluginConfig.memory.git_commit_indexing.since_days,
@@ -37538,7 +38471,7 @@ var server = async (ctx) => {
37538
38471
  {
37539
38472
  const fence = getSchemaFenceRejection();
37540
38473
  if (fence) {
37541
- import("./conflict-warning-hook-p2pmhvn7.js").then(({ sendSchemaFenceWarning }) => sendSchemaFenceWarning(ctx.client, ctx.directory, fence));
38474
+ import("./conflict-warning-hook-mt0ttc4x.js").then(({ sendSchemaFenceWarning }) => sendSchemaFenceWarning(ctx.client, ctx.directory, fence));
37542
38475
  }
37543
38476
  }
37544
38477
  if (conflictResult?.hasConflict) {
@@ -37556,10 +38489,10 @@ var server = async (ctx) => {
37556
38489
  ANNOUNCEMENT_FEATURES: ANNOUNCEMENT_FEATURES2,
37557
38490
  ANNOUNCEMENT_FOOTER: ANNOUNCEMENT_FOOTER2,
37558
38491
  markAnnouncementSeen: markAnnouncementSeen2
37559
- } = await import("./announcement-gms2nhya.js");
38492
+ } = await import("./announcement-6c1g4es4.js");
37560
38493
  if (shouldShowAnnouncement2()) {
37561
38494
  setTimeout(() => {
37562
- import("./conflict-warning-hook-p2pmhvn7.js").then(({ sendStartupAnnouncement }) => sendStartupAnnouncement(ctx.client, ctx.directory, ANNOUNCEMENT_VERSION2, ANNOUNCEMENT_FEATURES2, ANNOUNCEMENT_FOOTER2, markAnnouncementSeen2)).catch(() => {});
38495
+ import("./conflict-warning-hook-mt0ttc4x.js").then(({ sendStartupAnnouncement }) => sendStartupAnnouncement(ctx.client, ctx.directory, ANNOUNCEMENT_VERSION2, ANNOUNCEMENT_FEATURES2, ANNOUNCEMENT_FOOTER2, markAnnouncementSeen2)).catch(() => {});
37563
38496
  }, 8000);
37564
38497
  }
37565
38498
  } catch {}
@@ -37611,6 +38544,7 @@ var server = async (ctx) => {
37611
38544
  await magicContextRuntime.magicContext?.["command.execute.before"]?.(input, output);
37612
38545
  },
37613
38546
  "chat.message": async (input, _output) => {
38547
+ await preloadTokenizer();
37614
38548
  const typed = input;
37615
38549
  const provId = typed.model?.providerID;
37616
38550
  const modId = typed.model?.modelID;
@@ -37686,14 +38620,17 @@ var server = async (ctx) => {
37686
38620
  historianDisallowed: pluginConfig.historian?.disallowed_tools ?? []
37687
38621
  });
37688
38622
  const agentConfig = { ...config.agent ?? {} };
38623
+ const agentConfigRecord = agentConfig;
38624
+ const internalAgentIds = registrations.map((registration) => registration.id);
37689
38625
  for (const reg of registrations) {
37690
38626
  if (typeof reg.prompt !== "string" || reg.prompt.length === 0) {
37691
38627
  log(`[magic-context] skipping hidden agent '${reg.id}' — prompt unavailable at config time (dir=${ctx.directory}); will re-register on a later complete pass`);
37692
38628
  continue;
37693
38629
  }
37694
- agentConfig[reg.id] = buildHiddenAgentConfig(reg.prompt, reg.allowedTools, reg.maxSteps, reg.overrides, reg.id, reg.lockPermissions === true, reg.description);
38630
+ agentConfigRecord[reg.id] = buildHiddenAgentConfig(reg.prompt, reg.allowedTools, reg.maxSteps, reg.overrides, reg.id, reg.lockPermissions === true, reg.description);
37695
38631
  }
37696
- config.agent = agentConfig;
38632
+ const callerAgentConfig = denyTaskRoutingToCallerAgents(agentConfigRecord, internalAgentIds);
38633
+ config.agent = callerAgentConfig;
37697
38634
  } catch (error) {
37698
38635
  const e = error;
37699
38636
  log(`[magic-context] config hook failed (commands/agents NOT registered; transform still active): ${e?.message ?? error}`, e?.stack ? { stackHead: e.stack.split(`