@cortexkit/opencode-magic-context 0.37.0 → 0.38.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 (150) hide show
  1. package/README.md +2 -0
  2. package/dist/{announcement-6c1g4es4.js → announcement-5eg4t64s.js} +6 -6
  3. package/dist/config/schema/magic-context.d.ts +1 -1
  4. package/dist/{conflict-warning-hook-an4fxhwf.js → conflict-warning-hook-f406ggbw.js} +5 -5
  5. package/dist/{derive-budgets-0f8xpyw2.js → derive-budgets-xk8cy5e6.js} +5 -5
  6. package/dist/{emscripten-module-ap8t3st0.js → emscripten-module-49k43zfy.js} +1 -1
  7. package/dist/{emscripten-module-682pfzaa.js → emscripten-module-ex4v0x4z.js} +1 -1
  8. package/dist/{emscripten-module-r5h7aghp.js → emscripten-module-jfs3d1dq.js} +1 -1
  9. package/dist/{emscripten-module-bkktz927.js → emscripten-module-ss4g4spn.js} +1 -1
  10. package/dist/features/magic-context/dreamer/classify-prompt.d.ts +5 -1
  11. package/dist/features/magic-context/dreamer/classify-prompt.d.ts.map +1 -1
  12. package/dist/features/magic-context/dreamer/classify.d.ts.map +1 -1
  13. package/dist/features/magic-context/dreamer/manifest-parser.d.ts +8 -0
  14. package/dist/features/magic-context/dreamer/manifest-parser.d.ts.map +1 -1
  15. package/dist/features/magic-context/dreamer/map-memories-prompt.d.ts +7 -1
  16. package/dist/features/magic-context/dreamer/map-memories-prompt.d.ts.map +1 -1
  17. package/dist/features/magic-context/dreamer/map-memories.d.ts +18 -0
  18. package/dist/features/magic-context/dreamer/map-memories.d.ts.map +1 -1
  19. package/dist/features/magic-context/dreamer/retrospective-orphan-sweep.d.ts +17 -6
  20. package/dist/features/magic-context/dreamer/retrospective-orphan-sweep.d.ts.map +1 -1
  21. package/dist/features/magic-context/dreamer/storage-dream-runs.d.ts +5 -0
  22. package/dist/features/magic-context/dreamer/storage-dream-runs.d.ts.map +1 -1
  23. package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
  24. package/dist/features/magic-context/dreamer/verify-prompt.d.ts +5 -1
  25. package/dist/features/magic-context/dreamer/verify-prompt.d.ts.map +1 -1
  26. package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
  27. package/dist/features/magic-context/fail-closed-block.d.ts +6 -1
  28. package/dist/features/magic-context/fail-closed-block.d.ts.map +1 -1
  29. package/dist/features/magic-context/memory/storage-memory.d.ts.map +1 -1
  30. package/dist/features/magic-context/memory/types.d.ts +16 -0
  31. package/dist/features/magic-context/memory/types.d.ts.map +1 -1
  32. package/dist/features/magic-context/message-index.d.ts +3 -2
  33. package/dist/features/magic-context/message-index.d.ts.map +1 -1
  34. package/dist/features/magic-context/migrations.d.ts.map +1 -1
  35. package/dist/features/magic-context/reclaim-protection.d.ts +13 -0
  36. package/dist/features/magic-context/reclaim-protection.d.ts.map +1 -0
  37. package/dist/features/magic-context/storage-db.d.ts +7 -2
  38. package/dist/features/magic-context/storage-db.d.ts.map +1 -1
  39. package/dist/features/magic-context/storage-embedding-measurements.d.ts +1 -1
  40. package/dist/features/magic-context/storage-embedding-measurements.d.ts.map +1 -1
  41. package/dist/features/magic-context/storage-meta-persisted.d.ts +7 -6
  42. package/dist/features/magic-context/storage-meta-persisted.d.ts.map +1 -1
  43. package/dist/features/magic-context/storage-meta-session.d.ts.map +1 -1
  44. package/dist/features/magic-context/storage-session-tables.d.ts +18 -0
  45. package/dist/features/magic-context/storage-session-tables.d.ts.map +1 -0
  46. package/dist/features/magic-context/storage-tags.d.ts +13 -5
  47. package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
  48. package/dist/features/magic-context/transform-decision-log.d.ts +22 -0
  49. package/dist/features/magic-context/transform-decision-log.d.ts.map +1 -1
  50. package/dist/{ffi-d8pnn3mn.js → ffi-bbm9vkfa.js} +1 -1
  51. package/dist/{ffi-04jzypzk.js → ffi-kb5r0x1j.js} +1 -1
  52. package/dist/{ffi-t8b862vx.js → ffi-qnrt0y78.js} +1 -1
  53. package/dist/{ffi-9wvt2wwz.js → ffi-yx2hpf4p.js} +1 -1
  54. package/dist/hooks/auto-update-checker/checker.d.ts +8 -1
  55. package/dist/hooks/auto-update-checker/checker.d.ts.map +1 -1
  56. package/dist/hooks/auto-update-checker/index.d.ts.map +1 -1
  57. package/dist/hooks/magic-context/channel2-cycle.d.ts +16 -0
  58. package/dist/hooks/magic-context/channel2-cycle.d.ts.map +1 -0
  59. package/dist/hooks/magic-context/channel2-delivery.d.ts +3 -9
  60. package/dist/hooks/magic-context/channel2-delivery.d.ts.map +1 -1
  61. package/dist/hooks/magic-context/command-handler.d.ts +2 -0
  62. package/dist/hooks/magic-context/command-handler.d.ts.map +1 -1
  63. package/dist/hooks/magic-context/ctx-reduce-nudge.d.ts +33 -103
  64. package/dist/hooks/magic-context/ctx-reduce-nudge.d.ts.map +1 -1
  65. package/dist/hooks/magic-context/emergency-drop.d.ts.map +1 -1
  66. package/dist/hooks/magic-context/empty-task-output.d.ts +16 -0
  67. package/dist/hooks/magic-context/empty-task-output.d.ts.map +1 -0
  68. package/dist/hooks/magic-context/event-handler.d.ts.map +1 -1
  69. package/dist/hooks/magic-context/execute-status.d.ts +2 -1
  70. package/dist/hooks/magic-context/execute-status.d.ts.map +1 -1
  71. package/dist/hooks/magic-context/fold-execution-gate.d.ts +2 -0
  72. package/dist/hooks/magic-context/fold-execution-gate.d.ts.map +1 -0
  73. package/dist/hooks/magic-context/hook-handlers.d.ts.map +1 -1
  74. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  75. package/dist/hooks/magic-context/inject-compartments.d.ts +6 -0
  76. package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
  77. package/dist/hooks/magic-context/live-session-state.d.ts +3 -0
  78. package/dist/hooks/magic-context/live-session-state.d.ts.map +1 -1
  79. package/dist/hooks/magic-context/rust-mode-transform.d.ts +4 -2
  80. package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
  81. package/dist/hooks/magic-context/strip-content.d.ts +10 -8
  82. package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
  83. package/dist/hooks/magic-context/supersession-reclaim.d.ts.map +1 -1
  84. package/dist/hooks/magic-context/system-prompt-hash.d.ts.map +1 -1
  85. package/dist/hooks/magic-context/tail-hygiene-walk.d.ts +78 -0
  86. package/dist/hooks/magic-context/tail-hygiene-walk.d.ts.map +1 -0
  87. package/dist/hooks/magic-context/tool-reclaim.d.ts.map +1 -1
  88. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +7 -0
  89. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  90. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  91. package/dist/{index-cae89eas.js → index-1h9t9xb5.js} +2 -2
  92. package/dist/{index-wckvcay0.js → index-1yh8g550.js} +8 -6
  93. package/dist/index-22mw8km4.js +558 -0
  94. package/dist/{index-cgyfn1s2.js → index-2wchnyk6.js} +4 -2
  95. package/dist/{index-0ze9p983.js → index-5znjkjws.js} +9996 -7043
  96. package/dist/{index-4cz5nfxf.js → index-btj2qhmc.js} +5 -5
  97. package/dist/{index-q0t189ay.js → index-mg1yx1ph.js} +28 -36
  98. package/dist/{index-ayd60xnw.js → index-rgdqj8nj.js} +3 -3
  99. package/dist/{index-ygcng9t8.js → index-rpgg35ms.js} +50 -50
  100. package/dist/index.d.ts.map +1 -1
  101. package/dist/index.js +776 -846
  102. package/dist/{module-ES6BEMUI-atfbtnbp.js → module-ES6BEMUI-1yjdz59c.js} +4 -4
  103. package/dist/{module-asyncify-2EFITU5U-7xckhw8w.js → module-asyncify-2EFITU5U-fdkx4fhy.js} +1 -1
  104. package/dist/plugin/dream-timer.d.ts +5 -0
  105. package/dist/plugin/dream-timer.d.ts.map +1 -1
  106. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  107. package/dist/plugin/messages-transform.d.ts.map +1 -1
  108. package/dist/plugin/rpc-handlers.d.ts +2 -0
  109. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  110. package/dist/{prompt-context-jpe2dstn.js → prompt-context-29qkb28f.js} +1 -1
  111. package/dist/{recomp-orchestrator-c3ff16k7.js → recomp-orchestrator-p030kxtc.js} +15 -15
  112. package/dist/{resolve-fallbacks-5n5tvge1.js → resolve-fallbacks-qf0ekmz9.js} +3 -3
  113. package/dist/{rpc-notifications-4d22ybn5.js → rpc-notifications-1ffm755w.js} +6 -6
  114. package/dist/{safe-notification-target-b693f9x3.js → safe-notification-target-tepzc2xa.js} +3 -3
  115. package/dist/{send-session-notification-dxske5zm.js → send-session-notification-6v5b72b4.js} +7 -7
  116. package/dist/shared/harness-provider-map.d.ts +6 -0
  117. package/dist/shared/harness-provider-map.d.ts.map +1 -1
  118. package/dist/shared/models-dev-cache.d.ts +2 -0
  119. package/dist/shared/models-dev-cache.d.ts.map +1 -1
  120. package/dist/shared/rpc-server.d.ts.map +1 -1
  121. package/dist/shared/rpc-types.d.ts +15 -0
  122. package/dist/shared/rpc-types.d.ts.map +1 -1
  123. package/dist/shared/rpc-utils.d.ts +9 -0
  124. package/dist/shared/rpc-utils.d.ts.map +1 -1
  125. package/dist/shared/tail-hygiene-status.d.ts +15 -0
  126. package/dist/shared/tail-hygiene-status.d.ts.map +1 -0
  127. package/dist/shared/window-geometry.d.ts +3 -2
  128. package/dist/shared/window-geometry.d.ts.map +1 -1
  129. package/dist/{storage-meta-session-mk4gsnke.js → storage-meta-session-2306t3j7.js} +8 -8
  130. package/dist/{task-config-gbp7r23g.js → task-config-at3adc59.js} +6 -6
  131. package/package.json +4 -2
  132. package/src/config/schema/magic-context.test.ts +1 -0
  133. package/src/config/schema/magic-context.ts +5 -5
  134. package/src/shared/harness-provider-map.test.ts +36 -0
  135. package/src/shared/harness-provider-map.ts +8 -0
  136. package/src/shared/models-dev-cache.test.ts +25 -0
  137. package/src/shared/models-dev-cache.ts +5 -4
  138. package/src/shared/rpc-server.ts +1 -0
  139. package/src/shared/rpc-types.ts +16 -0
  140. package/src/shared/rpc-utils.test.ts +25 -0
  141. package/src/shared/rpc-utils.ts +80 -0
  142. package/src/shared/tail-hygiene-status.ts +57 -0
  143. package/src/shared/window-geometry.test.ts +34 -1
  144. package/src/shared/window-geometry.ts +37 -40
  145. package/src/tui/index.tsx +12 -2
  146. package/src/tui/slots/sidebar-content.tsx +17 -5
  147. package/src/tui/tui-compiled-runtime-imports.test.ts +3 -0
  148. package/src/tui-compiled/index.tsx +312 -290
  149. package/src/tui-compiled/slots/sidebar-content.tsx +316 -287
  150. package/dist/index-crke4z5j.js +0 -3022
package/dist/index.js CHANGED
@@ -14,9 +14,12 @@ import {
14
14
  AdmissionClass,
15
15
  BoundedSessionMap,
16
16
  CATEGORY_PRIORITY,
17
+ CHANNEL1_FLOOR_TOKENS,
18
+ CHANNEL1_SENTINEL,
17
19
  COMPARTMENT_AGENT_SYSTEM_PROMPT,
18
20
  COMPARTMENT_LEASE_RENEWAL_MS,
19
21
  COMPARTMENT_STRUCTURAL_SYSTEM_PROMPT,
22
+ CTX_REDUCE_KEEP,
20
23
  DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE,
21
24
  DEFAULT_HISTORIAN_TIMEOUT_MS,
22
25
  DEFAULT_LOCAL_EMBEDDING_MODEL,
@@ -48,6 +51,7 @@ import {
48
51
  StaleRouteHandleError,
49
52
  SubcClient,
50
53
  SynapseEmbeddingProvider,
54
+ ToolMutationBatch,
51
55
  USER_MEMORY_CANDIDATE_TTL_MS,
52
56
  V2_MEMORY_CATEGORIES,
53
57
  acquireCompartmentLease,
@@ -65,25 +69,34 @@ import {
65
69
  applyMirroredNoteCompileFields,
66
70
  applyStrippedPlaceholderDelta,
67
71
  archiveMemory,
72
+ assertTailHygieneContentUnchanged,
68
73
  backfillTagTokenCounts,
69
74
  beginBootQuietPeriod,
70
75
  bootQuietRemainingMs,
76
+ buildChannel1Reminder,
77
+ buildChannel2Reminder,
78
+ buildFileSourceContent,
79
+ buildInMemoryTailRawMessages,
71
80
  buildPrimaryLanguageDirective,
81
+ buildSyntheticTodoPart,
72
82
  buildWorkspaceMemorySqlFilter,
73
83
  bumpProjectMemoryEpoch,
74
84
  bumpProjectUserProfileVersion,
85
+ byteSize,
75
86
  captureSlot,
76
87
  casChannel2NudgeClaim,
77
88
  casChannel2NudgeState,
78
89
  checkCompactionMarkerConsistency,
79
90
  checksumAuthoritySeedRows,
80
91
  claimChannel2NudgeState,
92
+ cleanUserText,
81
93
  clearDeferredExecutePendingIfMatches,
82
94
  clearDetectedContextLimit,
83
95
  clearEmergencyDropSample,
84
96
  clearEmergencyRecovery,
85
97
  clearHistorianFailureState,
86
98
  clearHookInitFailure,
99
+ clearIndexedMessages,
87
100
  clearInjectionCache,
88
101
  clearMemoryVerifications,
89
102
  clearNoteNudgeTriggerAndCooldown,
@@ -95,6 +108,7 @@ import {
95
108
  clearRecompStaging,
96
109
  computeCueContentHash,
97
110
  computeNormalizedHash,
111
+ computeSyntheticCallId,
98
112
  computeWorkspaceEpochFingerprint,
99
113
  connectionFileExists,
100
114
  contentSha256,
@@ -108,6 +122,9 @@ import {
108
122
  createPrimer,
109
123
  createPromptSurfaceGuidanceEpochCache,
110
124
  createPromptSurfaceRuntime,
125
+ createToolDropTarget,
126
+ decideChannel1,
127
+ deleteIndexedMessage,
111
128
  deleteTagsByMessageId,
112
129
  deleteUserMemoryCandidates,
113
130
  deriveTagLoadFloor,
@@ -117,6 +134,7 @@ import {
117
134
  drainAuthority,
118
135
  drainCommitBacklogForProject,
119
136
  dropSlot,
137
+ effectiveTailHygiene,
120
138
  embedBatchForProject,
121
139
  embedItemsForProject,
122
140
  embedSessionCompartmentChunks,
@@ -129,14 +147,22 @@ import {
129
147
  ensureContextStoreUuid,
130
148
  ensureMemoryEmbeddings,
131
149
  escalationBands,
150
+ estimateEmergencyDropReclaimTokens,
151
+ estimateImageTokensFromDataUrl,
152
+ estimateTokens,
153
+ estimateTrueRawMessageTokens,
154
+ evaluateChannel2,
132
155
  expandWorkspaceIdentitySetWithAliases,
133
156
  exports_external,
157
+ extractInMemoryMessageViews,
134
158
  extractLatestAssistantText,
135
159
  extractM0Block,
160
+ extractTexts,
161
+ extractToolCallObservation,
162
+ extractToolCallSummaries,
136
163
  formatDate,
137
164
  getActiveCompartmentRun,
138
165
  getActivePrimers,
139
- getActiveTagTokenAggregate,
140
166
  getActiveTagTokenTotalsByMessage,
141
167
  getActiveTagsBySession,
142
168
  getActiveToolTagsForAgeReclaim,
@@ -157,9 +183,11 @@ import {
157
183
  getEmergencyInputSample,
158
184
  getEmergencyRecoveryArmedAt,
159
185
  getHistorianFailureState,
186
+ getIndexedMessageCorpusSize,
160
187
  getLastCompartmentEndMessage,
161
188
  getLastCompartmentEndMessageId,
162
189
  getLastHookInitFailure,
190
+ getLastIndexedOrdinal,
163
191
  getLastNudgeLevel,
164
192
  getLastNudgeUndropped,
165
193
  getLatestIndexedCommitTimeMs,
@@ -178,6 +206,8 @@ import {
178
206
  getMemoryMutationsForRenderByProjects,
179
207
  getMemoryVerifications,
180
208
  getMergedReasoningStrippedIds,
209
+ getMessageIndexReconciliationStartOrdinal,
210
+ getMessageIndexSourceIdentity,
181
211
  getMigrationOnOpenRefusal,
182
212
  getMirrorCursor,
183
213
  getModuleNoteEvaluationBridge,
@@ -206,6 +236,7 @@ import {
206
236
  getProjectEmbeddings,
207
237
  getProjectState,
208
238
  getRawHistoryEligibility,
239
+ getRawSessionStoredMessageCount,
209
240
  getReadySmartNotes,
210
241
  getSchemaFenceRejection,
211
242
  getSessionNotes,
@@ -218,6 +249,7 @@ import {
218
249
  getTagNumberByMessageId,
219
250
  getTagsByNumbers,
220
251
  getTagsBySession,
252
+ getTailHygieneTags,
221
253
  getToolTagNumberByOwner,
222
254
  getTrailingBlankDecisions,
223
255
  getTriggerTagTokenUpperBound,
@@ -227,11 +259,14 @@ import {
227
259
  getVisibleMemoryIds,
228
260
  getWrapupInProgressState,
229
261
  hasLengthCappedOutput,
262
+ hasMeaningfulUserText,
230
263
  hasMemoryClassifiedAtColumn,
231
264
  hasMemoryShareableColumn,
232
265
  hasMuralCueColumns,
233
266
  hasRunnableCompartmentWindow,
234
267
  incrementalLkgContentDigests,
268
+ indexMessagesAfterOrdinal,
269
+ indexSingleMessage,
235
270
  injectM0M1,
236
271
  injectTemporalMarkers,
237
272
  insertMemory,
@@ -241,14 +276,25 @@ import {
241
276
  insertUserMemoryCandidates,
242
277
  invalidateMemory,
243
278
  invalidateProject,
279
+ invalidateTrueRawTokenCache,
244
280
  isConsumerReconnectTransient,
245
281
  isDatabasePersisted,
282
+ isEditTool,
246
283
  isEmbeddingEnabled,
247
284
  isEmergencyRecoveryArmed,
248
285
  isFailClosedBlockingError,
286
+ isFilePart,
249
287
  isLinkedGitWorktree,
288
+ isMessageIndexReconciledThrough,
289
+ isMessageIndexSourceCurrent,
250
290
  isPidAlive,
251
291
  isProviderOverflowReconfirmed,
292
+ isRawCompactionSummaryInfo,
293
+ isRecord,
294
+ isSyntheticTodoPart,
295
+ isTextPart,
296
+ isThinkingPart,
297
+ isToolPartWithOutput,
252
298
  lkgContentDigest,
253
299
  loadCompartmentChunkEmbeddingsForSearch,
254
300
  loadPersistedUsage,
@@ -269,6 +315,8 @@ import {
269
315
  nextOccurrence,
270
316
  normalizeSDKResponse,
271
317
  normalizeStoredProjectPath,
318
+ normalizeText,
319
+ normalizeTodoStateJson,
272
320
  normalizeVerificationFiles,
273
321
  noteEntry,
274
322
  onNoteTrigger,
@@ -277,12 +325,18 @@ import {
277
325
  parkGitSweepNonIndexable,
278
326
  parseCron,
279
327
  parseRpcPortFile,
328
+ partHasCompletedResult,
280
329
  peekDeferredExecutePending,
281
330
  peekNoteNudgeText,
282
331
  peekProjectEmbeddings,
283
332
  pickNearestPriorOwner,
333
+ planEmergencyDrop,
334
+ preloadTokenizer,
284
335
  prepareAuthority,
285
336
  prepareCompartmentInjection,
337
+ prependTag,
338
+ primeInMemoryTailRawMessageCache,
339
+ primeTailRawMessageCache,
286
340
  primerOccurrenceKey,
287
341
  primerOccurrenceUtcDay,
288
342
  promptSurfaceConfigIdentity,
@@ -298,6 +352,12 @@ import {
298
352
  readGitFileChangeTimesSince,
299
353
  readGitHead,
300
354
  readNewMemoriesForM1Union,
355
+ readRawSessionMessageById,
356
+ readRawSessionMessageOrdinalById,
357
+ readRawSessionMessageOrdinalPage,
358
+ readRawSessionMessagePartsById,
359
+ readRawSessionMessages,
360
+ readSessionChunk,
301
361
  reconcileAuthorityProject,
302
362
  recordChildInvocation,
303
363
  recordDetectedContextLimit,
@@ -310,6 +370,7 @@ import {
310
370
  recordOverflowDetected,
311
371
  recordSessionProjectIdentity,
312
372
  recordToolDefinition,
373
+ refreshTailHygieneBaseline,
313
374
  registerActiveCompartmentRun,
314
375
  registerModuleNoteEvaluationBridge,
315
376
  registerProjectEmbedding,
@@ -355,6 +416,7 @@ import {
355
416
  runManagedRecomp,
356
417
  runManagedUpgrade,
357
418
  runSqliteOptimize,
419
+ sameTailHygieneStructuralSignature,
358
420
  sanitizeFtsQuery,
359
421
  saveCommitEmbedding,
360
422
  saveEmbeddingIfHashMatches,
@@ -376,6 +438,7 @@ import {
376
438
  setPersistedReasoningWatermark,
377
439
  setPersistedTodoPermissionDenied,
378
440
  setPersistedTodoSyntheticAnchor,
441
+ setRawMessageProvider,
379
442
  setRecompStarting,
380
443
  setRecompTerminal,
381
444
  setSessionWorkMetrics,
@@ -387,10 +450,16 @@ import {
387
450
  startCompartmentAgent,
388
451
  storedPathBelongsToIdentity,
389
452
  storedPathBelongsToWorkspace,
453
+ stripPersistedAssistantText,
454
+ stripTagPrefix,
390
455
  supersededMemory,
456
+ sweepOrphanedOpenCodeMessageIndexes,
391
457
  sweepStaleEmbeddingIdentitiesForProject,
392
458
  tagTokenCountIsNull,
459
+ tailHygieneStructuralSignature,
393
460
  takeDubiousOwnershipProjectIdentityWarning,
461
+ textMentionsRecentCommit,
462
+ toolOutputTokens,
394
463
  trimMemoriesToBudgetV2,
395
464
  updateCavemanDepth,
396
465
  updateMemoryRetrievalCount,
@@ -406,8 +475,9 @@ import {
406
475
  updateWrapupInProgress,
407
476
  upsertCommits,
408
477
  verificationFileExists,
409
- withContentLanguageDirective
410
- } from "./index-0ze9p983.js";
478
+ withContentLanguageDirective,
479
+ withRawSessionMessageCache
480
+ } from "./index-5znjkjws.js";
411
481
  import {
412
482
  deriveHistorianChunkTokens,
413
483
  deriveTriggerBudget,
@@ -422,7 +492,7 @@ import {
422
492
  setStoragePrivatePermissionEnforcement,
423
493
  setWindowOverlayPath,
424
494
  shouldEnforcePrivateStoragePermissions
425
- } from "./index-q0t189ay.js";
495
+ } from "./index-mg1yx1ph.js";
426
496
  import {
427
497
  modelBodyField,
428
498
  resolveFallbackChain
@@ -434,69 +504,19 @@ import {
434
504
  getErrorMessage,
435
505
  sendIgnoredMessage,
436
506
  sendUserPrompt
437
- } from "./index-4cz5nfxf.js";
507
+ } from "./index-btj2qhmc.js";
438
508
  import {
439
- ToolMutationBatch,
440
509
  advanceToolReclaimWatermark,
441
- buildFileSourceContent,
442
- buildInMemoryTailRawMessages,
443
- byteSize,
444
- cleanUserText,
445
- clearIndexedMessages,
446
510
  clearSession,
447
- createToolDropTarget,
448
- deleteIndexedMessage,
449
- estimateTokens,
450
- estimateTrueRawMessageTokens,
451
- extractInMemoryMessageViews,
452
- extractTexts,
453
- extractToolCallObservation,
454
- extractToolCallSummaries,
455
- getIndexedMessageCorpusSize,
456
- getLastIndexedOrdinal,
457
- getMessageIndexReconciliationStartOrdinal,
458
- getMessageIndexSourceIdentity,
459
511
  getOrCreateSessionMeta,
460
- getRawSessionStoredMessageCount,
461
- hasMeaningfulUserText,
462
- indexMessagesAfterOrdinal,
463
- indexSingleMessage,
464
- invalidateTrueRawTokenCache,
465
- isEditTool,
466
- isFilePart,
467
- isMessageIndexReconciledThrough,
468
- isMessageIndexSourceCurrent,
469
- isRawCompactionSummaryInfo,
470
- isRecord,
471
- isTextPart,
472
- isThinkingPart,
473
- isToolPartWithOutput,
474
512
  markSessionCleanupPending,
475
- normalizeText,
476
- partHasCompletedResult,
477
- preloadTokenizer,
478
- prependTag,
479
- primeInMemoryTailRawMessageCache,
480
- primeTailRawMessageCache,
481
- readRawSessionMessageById,
482
- readRawSessionMessageOrdinalById,
483
- readRawSessionMessageOrdinalPage,
484
- readRawSessionMessagePartsById,
485
- readRawSessionMessages,
486
- readSessionChunk,
487
513
  retryPendingSessionCleanups,
488
- setRawMessageProvider,
489
- stripPersistedAssistantText,
490
- stripTagPrefix,
491
- sweepOrphanedOpenCodeMessageIndexes,
492
- textMentionsRecentCommit,
493
- updateSessionMeta,
494
- withRawSessionMessageCache
495
- } from "./index-crke4z5j.js";
514
+ updateSessionMeta
515
+ } from "./index-22mw8km4.js";
496
516
  import {
497
517
  modelRefLookupOrder,
498
518
  piModelRefToCanonical
499
- } from "./index-cgyfn1s2.js";
519
+ } from "./index-2wchnyk6.js";
500
520
  import {
501
521
  Database,
502
522
  closeQuietly,
@@ -511,7 +531,7 @@ import {
511
531
  detectConflicts,
512
532
  resolveCompactionForBoot,
513
533
  sendConflictWarning
514
- } from "./index-cae89eas.js";
534
+ } from "./index-1h9t9xb5.js";
515
535
  import {
516
536
  detectConfigFile,
517
537
  isPrototypePollutionKey,
@@ -553,10 +573,10 @@ import {
553
573
  __commonJS,
554
574
  __require,
555
575
  __toESM
556
- } from "./index-wckvcay0.js";
576
+ } from "./index-1yh8g550.js";
557
577
 
558
578
  // ../../node_modules/.bun/esprima@4.0.1/node_modules/esprima/dist/esprima.js
559
- var require_esprima = __commonJS((exports, module) => {
579
+ var require_esprima = __commonJS(function(exports, module) {
560
580
  (function webpackUniversalModuleDefinition(root, factory) {
561
581
  if (typeof exports === "object" && typeof module === "object")
562
582
  module.exports = factory();
@@ -6696,7 +6716,7 @@ var require_esprima = __commonJS((exports, module) => {
6696
6716
  });
6697
6717
 
6698
6718
  // ../../node_modules/.bun/array-timsort@1.0.3/node_modules/array-timsort/src/index.js
6699
- var require_src = __commonJS((exports, module) => {
6719
+ var require_src = __commonJS(function(exports, module) {
6700
6720
  var DEFAULT_MIN_MERGE = 32;
6701
6721
  var DEFAULT_MIN_GALLOPING = 7;
6702
6722
  var DEFAULT_TMP_STORAGE_LENGTH = 256;
@@ -7339,7 +7359,7 @@ var require_src = __commonJS((exports, module) => {
7339
7359
  });
7340
7360
 
7341
7361
  // ../../node_modules/.bun/comment-json@5.0.0/node_modules/comment-json/src/common.js
7342
- var require_common = __commonJS((exports, module) => {
7362
+ var require_common = __commonJS(function(exports, module) {
7343
7363
  var PREFIX_BEFORE = "before";
7344
7364
  var PREFIX_AFTER_PROP = "after-prop";
7345
7365
  var PREFIX_AFTER_COLON = "after-colon";
@@ -7625,7 +7645,7 @@ var require_common = __commonJS((exports, module) => {
7625
7645
  });
7626
7646
 
7627
7647
  // ../../node_modules/.bun/comment-json@5.0.0/node_modules/comment-json/src/array.js
7628
- var require_array = __commonJS((exports, module) => {
7648
+ var require_array = __commonJS(function(exports, module) {
7629
7649
  var { sort } = require_src();
7630
7650
  var {
7631
7651
  PROP_SYMBOL_PREFIXES,
@@ -7783,7 +7803,7 @@ var require_array = __commonJS((exports, module) => {
7783
7803
  });
7784
7804
 
7785
7805
  // ../../node_modules/.bun/comment-json@5.0.0/node_modules/comment-json/src/parse.js
7786
- var require_parse = __commonJS((exports, module) => {
7806
+ var require_parse = __commonJS(function(exports, module) {
7787
7807
  var esprima = require_esprima();
7788
7808
  var {
7789
7809
  CommentArray
@@ -8149,7 +8169,7 @@ var require_parse = __commonJS((exports, module) => {
8149
8169
  });
8150
8170
 
8151
8171
  // ../../node_modules/.bun/comment-json@5.0.0/node_modules/comment-json/src/stringify.js
8152
- var require_stringify = __commonJS((exports, module) => {
8172
+ var require_stringify = __commonJS(function(exports, module) {
8153
8173
  var {
8154
8174
  PREFIX_BEFORE_ALL,
8155
8175
  PREFIX_BEFORE,
@@ -8357,7 +8377,7 @@ var require_stringify = __commonJS((exports, module) => {
8357
8377
  });
8358
8378
 
8359
8379
  // ../../node_modules/.bun/comment-json@5.0.0/node_modules/comment-json/src/index.js
8360
- var require_src2 = __commonJS((exports, module) => {
8380
+ var require_src2 = __commonJS(function(exports, module) {
8361
8381
  var { parse, tokenize } = require_parse();
8362
8382
  var stringify = require_stringify();
8363
8383
  var { CommentArray } = require_array();
@@ -11051,8 +11071,8 @@ function getCurrentRuntimePackageJsonPath(currentModuleUrl = import.meta.url) {
11051
11071
  return null;
11052
11072
  }
11053
11073
  }
11054
- function findPluginEntry(directory) {
11055
- const winner = getWinningConfig(directory, "server");
11074
+ function findPluginEntry(directory, surface = "server") {
11075
+ const winner = getWinningConfig(directory, surface);
11056
11076
  if (!winner)
11057
11077
  return null;
11058
11078
  const entry = winner.entries.find((value) => value === PACKAGE_NAME || value.startsWith(`${PACKAGE_NAME}@`));
@@ -11066,13 +11086,21 @@ function findPluginEntry(directory) {
11066
11086
  configPath: winner.path
11067
11087
  };
11068
11088
  }
11089
+ function hasExplicitNonExactPluginVersion(spec) {
11090
+ if (!spec.startsWith(`${PACKAGE_NAME}@`))
11091
+ return false;
11092
+ return !isValidSemver(spec.slice(PACKAGE_NAME.length + 1));
11093
+ }
11094
+ function isExactOrBarePluginSpec(spec) {
11095
+ return spec === PACKAGE_NAME || spec.startsWith(`${PACKAGE_NAME}@`) && !hasExplicitNonExactPluginVersion(spec);
11096
+ }
11069
11097
  function configUpdateContent(content, version) {
11070
11098
  const parsed = parseJsonConfig(content);
11071
11099
  if (!parsed)
11072
11100
  return null;
11073
11101
  const entries = getPluginEntries(parsed);
11074
11102
  const current = entries.find((entry) => entry === PACKAGE_NAME || entry.startsWith(`${PACKAGE_NAME}@`));
11075
- if (!current)
11103
+ if (!current || !isExactOrBarePluginSpec(current))
11076
11104
  return null;
11077
11105
  const escaped = current.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
11078
11106
  const entryRegex = new RegExp(`(["'])${escaped}\\1`);
@@ -11390,6 +11418,12 @@ async function runBackgroundUpdateCheck(ctx, options) {
11390
11418
  log("[auto-update-checker] Plugin not found in config");
11391
11419
  return;
11392
11420
  }
11421
+ if (hasExplicitNonExactPluginVersion(pluginInfo.entry)) {
11422
+ if (pluginInfo.entry === `${PACKAGE_NAME}@latest`) {
11423
+ log("[auto-update-checker] Explicit @latest leaves the active package unpinned; OpenCode may delete it mid-session.");
11424
+ }
11425
+ return;
11426
+ }
11393
11427
  const cachedVersion = getCachedVersion(pluginInfo.entry);
11394
11428
  const currentVersion = cachedVersion ?? pluginInfo.pinnedVersion;
11395
11429
  if (!currentVersion) {
@@ -11445,6 +11479,7 @@ function createLiveSessionState() {
11445
11479
  liveModelBySession: new Map,
11446
11480
  variantBySession: new Map,
11447
11481
  agentBySession: new Map,
11482
+ channel1StateBySession: new Map,
11448
11483
  historyRefreshSessions: new Set,
11449
11484
  deferredHistoryRefreshSessions: new Set,
11450
11485
  systemPromptRefreshSessions: new Set,
@@ -12218,6 +12253,7 @@ function releaseLease(db, holderId, leaseKey = DREAMING_LEASE_KEY) {
12218
12253
  }
12219
12254
 
12220
12255
  // src/features/magic-context/dreamer/retrospective-orphan-sweep.ts
12256
+ var HISTORIAN_CHILD_TITLE = "magic-context-compartment";
12221
12257
  var RETROSPECTIVE_CHILD_TITLE = "magic-context-dream-retrospective";
12222
12258
  var USER_MEMORIES_CHILD_TITLE = "magic-context-dream-user-memories";
12223
12259
  var CURATE_CHILD_TITLE = "magic-context-dream-curate";
@@ -12243,16 +12279,34 @@ var PRIVACY_SENSITIVE_CHILD_TITLE_MATCHES = {
12243
12279
  ],
12244
12280
  prefixes: [SMART_NOTE_COMPILE_CHILD_TITLE_PREFIX, SMART_NOTE_CONFIRM_CHILD_TITLE_PREFIX]
12245
12281
  };
12282
+ var HISTORIAN_CHILD_TITLE_MATCHES = {
12283
+ exact: [HISTORIAN_CHILD_TITLE],
12284
+ prefixes: []
12285
+ };
12286
+ var INTERNAL_CHILD_TITLE_MATCHES = {
12287
+ exact: [HISTORIAN_CHILD_TITLE, ...PRIVACY_SENSITIVE_CHILD_TITLE_MATCHES.exact],
12288
+ prefixes: PRIVACY_SENSITIVE_CHILD_TITLE_MATCHES.prefixes
12289
+ };
12246
12290
  function retrospectiveOrphanStaleMs(taskTimeoutMinutes) {
12247
12291
  const timeoutCandidates = Array.isArray(taskTimeoutMinutes) ? taskTimeoutMinutes : [taskTimeoutMinutes];
12248
12292
  const maxTimeoutMinutes = Math.max(...timeoutCandidates.map((minutes) => Math.max(1, minutes ?? 20)), 20);
12249
12293
  const timeoutMs = maxTimeoutMinutes * 60000;
12250
12294
  return Math.max(60 * 60000, timeoutMs * 3);
12251
12295
  }
12296
+ var HISTORIAN_OUTER_ATTEMPTS = 3;
12297
+ var HISTORIAN_MODEL_SUGGESTION_ATTEMPTS = 2;
12298
+ var HISTORIAN_MAX_RETRY_BACKOFF_MS = 11000;
12299
+ var HISTORIAN_DETACHED_WRITER_GRACE_MS = 15 * 60000;
12300
+ function historianOrphanStaleMs(timeoutMs, fallbackModelCount) {
12301
+ const timeout = Math.max(60000, timeoutMs);
12302
+ const fallbackCount = Math.max(0, Math.floor(fallbackModelCount));
12303
+ const fullAttemptBudget = timeout * HISTORIAN_OUTER_ATTEMPTS * HISTORIAN_MODEL_SUGGESTION_ATTEMPTS * (fallbackCount + 1);
12304
+ return Math.max(60 * 60000, fullAttemptBudget + HISTORIAN_MAX_RETRY_BACKOFF_MS + HISTORIAN_DETACHED_WRITER_GRACE_MS);
12305
+ }
12252
12306
  async function sweepOrphanedRetrospectiveChildren(args) {
12253
12307
  const { opencodeDb, client, sessionDirectory, staleMs } = args;
12254
- const titleMatches = args.titleMatches ?? PRIVACY_SENSITIVE_CHILD_TITLE_MATCHES;
12255
- if (!opencodeDb)
12308
+ const titleMatches = args.titleMatches ?? INTERNAL_CHILD_TITLE_MATCHES;
12309
+ if (!opencodeDb || args.keepSubagents === true)
12256
12310
  return 0;
12257
12311
  const now = args.now ?? Date.now();
12258
12312
  const cutoff = now - staleMs;
@@ -12275,7 +12329,7 @@ async function sweepOrphanedRetrospectiveChildren(args) {
12275
12329
  ORDER BY time_created ASC
12276
12330
  LIMIT 200`).all(...titleParams, sessionDirectory, cutoff);
12277
12331
  } catch (error) {
12278
- log(`[dreamer] retrospective orphan sweep: read skipped (${String(error)})`);
12332
+ log(`[magic-context] internal child orphan sweep: read skipped (${String(error)})`);
12279
12333
  return 0;
12280
12334
  }
12281
12335
  if (rows.length === 0)
@@ -12290,7 +12344,7 @@ async function sweepOrphanedRetrospectiveChildren(args) {
12290
12344
  }
12291
12345
  }
12292
12346
  if (deleted > 0) {
12293
- log(`[dreamer] swept ${deleted} crash-orphaned privacy-sensitive child session(s)`);
12347
+ log(`[magic-context] swept ${deleted} stale internal child session(s)`);
12294
12348
  }
12295
12349
  return deleted;
12296
12350
  }
@@ -12723,6 +12777,34 @@ function assertManifestCoversExactly(ids, expectedIds, rootName) {
12723
12777
  throw new Error(`${rootName} manifest missing id ${id}`);
12724
12778
  }
12725
12779
  }
12780
+ var OPEN_TAG_RE = /<([A-Za-z][\w:-]*)\b/;
12781
+ function describeUnrecognizedManifestShape(text, expectedRoot, expectedEntry) {
12782
+ const expected = `expected <${expectedRoot}> with <${expectedEntry}> entries`;
12783
+ const trimmed = text.trim();
12784
+ if (trimmed.startsWith("[") || trimmed.startsWith("{")) {
12785
+ return `JSON ${trimmed.startsWith("[") ? "array" : "object"} unrecognized; ${expected}`;
12786
+ }
12787
+ const firstTag = OPEN_TAG_RE.exec(trimmed)?.[1];
12788
+ if (firstTag && firstTag.toLowerCase() !== expectedRoot.toLowerCase()) {
12789
+ return `root <${firstTag}> unrecognized; ${expected}`;
12790
+ }
12791
+ const escapedRoot = expectedRoot.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
12792
+ const bodyMatch = new RegExp(`<${escapedRoot}\\b[^>]*>([\\s\\S]*?)<\\/${escapedRoot}>`, "i").exec(text);
12793
+ const body = (bodyMatch?.[1] ?? "").trim();
12794
+ if (body.startsWith("[") || body.startsWith("{")) {
12795
+ return `JSON ${body.startsWith("[") ? "array" : "object"} unrecognized; ${expected}`;
12796
+ }
12797
+ const innerTag = OPEN_TAG_RE.exec(body)?.[1];
12798
+ if (innerTag && innerTag.toLowerCase() !== expectedEntry.toLowerCase()) {
12799
+ return `root <${innerTag}> unrecognized; ${expected}`;
12800
+ }
12801
+ return `parsed zero entries; ${expected}`;
12802
+ }
12803
+ function assertParsedManifestNonEmpty(parsedCount, expectedCount, text, expectedRoot, expectedEntry) {
12804
+ if (expectedCount > 0 && parsedCount === 0) {
12805
+ throw new Error(describeUnrecognizedManifestShape(text, expectedRoot, expectedEntry));
12806
+ }
12807
+ }
12726
12808
 
12727
12809
  // src/features/magic-context/dreamer/module-apply.ts
12728
12810
  class DreamerModuleBusyError extends Error {
@@ -13754,9 +13836,19 @@ ${renderAnchors(args.anchors ?? [])}### Memory pool to classify
13754
13836
  ${renderPool2(args.memories)}`;
13755
13837
  }
13756
13838
  var SCOPES = new Set(["project", "ecosystem", "universe"]);
13839
+ function classifyBody(text) {
13840
+ try {
13841
+ return extractCompleteManifestBody(text, "classify");
13842
+ } catch (error) {
13843
+ const described = describeUnrecognizedManifestShape(text, "classify", "memory");
13844
+ if (!described.startsWith("parsed zero entries"))
13845
+ throw new Error(described);
13846
+ throw error;
13847
+ }
13848
+ }
13757
13849
  function parseClassifyManifest(text) {
13758
13850
  const out = [];
13759
- const body = extractCompleteManifestBody(text, "classify");
13851
+ const body = classifyBody(text);
13760
13852
  for (const m of body.matchAll(/<memory\b([^>]*)\/?>/g)) {
13761
13853
  const attrs = m[1];
13762
13854
  const idMatch = attrs.match(/\bid\s*=\s*"(\d+)"/);
@@ -13789,9 +13881,18 @@ function parseClassifyManifest(text) {
13789
13881
  }
13790
13882
  out.push(entry);
13791
13883
  }
13884
+ if (out.length === 0 && body.trim().length > 0) {
13885
+ throw new Error(describeUnrecognizedManifestShape(text, "classify", "memory"));
13886
+ }
13792
13887
  assertNoDuplicateManifestIds(out.map((entry) => entry.id), "classify");
13793
13888
  return out;
13794
13889
  }
13890
+ function validateClassifyManifest(text, expectedIds) {
13891
+ const parsed = parseClassifyManifest(text);
13892
+ assertParsedManifestNonEmpty(parsed.length, expectedIds.size, text, "classify", "memory");
13893
+ assertManifestCoversExactly(parsed.map((entry) => entry.id), expectedIds, "classify");
13894
+ return parsed;
13895
+ }
13795
13896
 
13796
13897
  // src/features/magic-context/dreamer/classify.ts
13797
13898
  var MIN_POOL_TO_CLASSIFY = 10;
@@ -13990,7 +14091,7 @@ async function classifyOneChunk(args, chunk, anchors, sliceMs, signal) {
13990
14091
  if (!text)
13991
14092
  throw new Error("classify returned no output");
13992
14093
  try {
13993
- parseClassifyManifest(text);
14094
+ validateClassifyManifest(text, new Set(chunk.map((candidate) => candidate.id)));
13994
14095
  } catch (error) {
13995
14096
  const providerFailure = providerOutputFailureFromInvalidManifest(messages, text);
13996
14097
  if (providerFailure)
@@ -14058,8 +14159,7 @@ async function runClassifyThroughModule(args, chunk, anchors, signal) {
14058
14159
  if (result.truncated === true) {
14059
14160
  throw new Error("classify returned length-capped output");
14060
14161
  }
14061
- const parsed = parseClassifyManifest(manifestText);
14062
- assertManifestCoversExactly(parsed.map((entry) => entry.id), new Set(chunk.map((candidate) => candidate.id)), "classify");
14162
+ const parsed = validateClassifyManifest(manifestText, new Set(chunk.map((candidate) => candidate.id)));
14063
14163
  const rows = parsed.map((entry) => {
14064
14164
  const candidate = chunk.find((item) => item.id === entry.id);
14065
14165
  if (!candidate)
@@ -14739,8 +14839,8 @@ var asyncModulePromise = null;
14739
14839
  function getAsyncModule() {
14740
14840
  asyncModulePromise ??= (async () => {
14741
14841
  const [{ default: singlefileAsyncifyVariant }, { newQuickJSAsyncWASMModuleFromVariant }] = await Promise.all([
14742
- import("./index-ayd60xnw.js").then((m)=>__toESM(m.default,1)),
14743
- import("./index-ygcng9t8.js")
14842
+ import("./index-rgdqj8nj.js").then((m)=>__toESM(m.default,1)),
14843
+ import("./index-rpgg35ms.js")
14744
14844
  ]);
14745
14845
  return newQuickJSAsyncWASMModuleFromVariant(singlefileAsyncifyVariant);
14746
14846
  })();
@@ -16088,11 +16188,33 @@ For each memory below, find the repo file(s) it makes a claim about, or mark it
16088
16188
  ${list}
16089
16189
  </memories>`;
16090
16190
  }
16191
+ var MEMORY_ELEMENT_PATTERN = "<memory\\b([^>]*)(?:\\/>|>([\\s\\S]*?)<\\/memory>)";
16192
+ var NESTED_FILE_PATTERN = "<file\\b([^>]*)\\/?>";
16193
+ function extractNestedFilePaths(inner) {
16194
+ const files = [];
16195
+ for (const match of inner.matchAll(new RegExp(NESTED_FILE_PATTERN, "gi"))) {
16196
+ const pathMatch = match[1].match(/\bpath\s*=\s*"([^"]+)"/);
16197
+ if (pathMatch)
16198
+ files.push(pathMatch[1].trim());
16199
+ }
16200
+ return files.filter(Boolean);
16201
+ }
16202
+ function mappingsBody(text) {
16203
+ try {
16204
+ return extractCompleteManifestBody(text, "mappings");
16205
+ } catch (error) {
16206
+ const described = describeUnrecognizedManifestShape(text, "mappings", "memory");
16207
+ if (!described.startsWith("parsed zero entries"))
16208
+ throw new Error(described);
16209
+ throw error;
16210
+ }
16211
+ }
16091
16212
  function parseMapMemoriesManifest(text) {
16092
16213
  const out = [];
16093
- const body = extractCompleteManifestBody(text, "mappings");
16094
- for (const m of body.matchAll(/<memory\b([^>]*)\/?>/g)) {
16214
+ const body = mappingsBody(text);
16215
+ for (const m of body.matchAll(new RegExp(MEMORY_ELEMENT_PATTERN, "gi"))) {
16095
16216
  const attrs = m[1];
16217
+ const inner = m[2];
16096
16218
  const idMatch = attrs.match(/\bid\s*=\s*"(\d+)"/);
16097
16219
  if (!idMatch)
16098
16220
  throw new Error("mappings manifest entry missing numeric id");
@@ -16101,24 +16223,67 @@ function parseMapMemoriesManifest(text) {
16101
16223
  throw new Error("mappings manifest entry missing numeric id");
16102
16224
  const independent = /\bindependent\s*=\s*"(?:true|1)"/i.test(attrs);
16103
16225
  const filesMatch = attrs.match(/\bfiles\s*=\s*"([^"]*)"/);
16104
- const files = filesMatch ? filesMatch[1].split(",").map((f) => f.trim()).filter(Boolean) : [];
16105
- out.push({ id, files, independent: independent || files.length === 0 });
16226
+ const attrFiles = filesMatch ? filesMatch[1].split(",").map((f) => f.trim()).filter(Boolean) : [];
16227
+ const nestedFiles = inner ? extractNestedFilePaths(inner) : [];
16228
+ const files = attrFiles.length > 0 ? attrFiles : nestedFiles;
16229
+ if (!independent && files.length === 0) {
16230
+ throw new Error(`mappings manifest entry ${id} has neither files nor independent="true"`);
16231
+ }
16232
+ out.push({
16233
+ id,
16234
+ files: independent && files.length === 0 ? [] : files,
16235
+ independent: independent && files.length === 0
16236
+ });
16237
+ }
16238
+ if (out.length === 0 && body.trim().length > 0) {
16239
+ throw new Error(describeUnrecognizedManifestShape(text, "mappings", "memory"));
16106
16240
  }
16107
16241
  assertNoDuplicateManifestIds(out.map((entry) => entry.id), "mappings");
16108
16242
  return out;
16109
16243
  }
16244
+ function validateMapMemoriesManifest(text, expectedIds) {
16245
+ const parsed = parseMapMemoriesManifest(text);
16246
+ assertParsedManifestNonEmpty(parsed.length, expectedIds.size, text, "mappings", "memory");
16247
+ assertManifestCoversExactly(parsed.map((entry) => entry.id), expectedIds, "mappings");
16248
+ return parsed;
16249
+ }
16110
16250
 
16111
16251
  // src/features/magic-context/dreamer/map-memories.ts
16112
16252
  var MAP_BATCH_SIZE = 80;
16113
- function loadUnmappedInputs(db, projectIdentity, repoDir) {
16253
+ var MAX_INDEPENDENT_REQUEUE_PER_RUN = MAP_BATCH_SIZE;
16254
+ function shouldRequeueIndependentMapping(state, content, repoDir) {
16255
+ if (!state.hasSentinel || state.files.length > 0)
16256
+ return false;
16257
+ return extractMemoryCandidatePaths(content, repoDir).length > 0;
16258
+ }
16259
+ function toMapInput(memory, repoDir) {
16260
+ return {
16261
+ id: memory.id,
16262
+ category: memory.category,
16263
+ content: memory.content,
16264
+ candidates: extractMemoryCandidatePaths(memory.content, repoDir)
16265
+ };
16266
+ }
16267
+ function selectMapMemoryInputs(db, projectIdentity, repoDir) {
16114
16268
  const active = getMemoriesByProject(db, projectIdentity);
16115
- const unmapped = new Set(getUnmappedMemoryIds(db, active.map((m) => m.id)));
16116
- return active.filter((m) => unmapped.has(m.id)).map((m) => ({
16117
- id: m.id,
16118
- category: m.category,
16119
- content: m.content,
16120
- candidates: extractMemoryCandidatePaths(m.content, repoDir)
16121
- }));
16269
+ const activeIds = active.map((m) => m.id);
16270
+ const unmapped = new Set(getUnmappedMemoryIds(db, activeIds));
16271
+ const verifications = getMemoryVerifications(db, activeIds);
16272
+ const unmappedInputs = active.filter((m) => unmapped.has(m.id)).map((m) => toMapInput(m, repoDir));
16273
+ const requeue = [];
16274
+ for (const memory of active) {
16275
+ if (unmapped.has(memory.id))
16276
+ continue;
16277
+ const state = verifications.get(memory.id);
16278
+ if (!state)
16279
+ continue;
16280
+ if (!shouldRequeueIndependentMapping(state, memory.content, repoDir))
16281
+ continue;
16282
+ requeue.push(toMapInput(memory, repoDir));
16283
+ if (requeue.length >= MAX_INDEPENDENT_REQUEUE_PER_RUN)
16284
+ break;
16285
+ }
16286
+ return [...unmappedInputs, ...requeue];
16122
16287
  }
16123
16288
  async function mapMemories(args) {
16124
16289
  const result = {
@@ -16128,7 +16293,7 @@ async function mapMemories(args) {
16128
16293
  remaining: 0,
16129
16294
  complete: true
16130
16295
  };
16131
- const inputs = loadUnmappedInputs(args.db, args.projectIdentity, args.sessionDirectory);
16296
+ const inputs = selectMapMemoryInputs(args.db, args.projectIdentity, args.sessionDirectory);
16132
16297
  if (inputs.length === 0)
16133
16298
  return result;
16134
16299
  const batches = [];
@@ -16207,7 +16372,7 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
16207
16372
  const text = extractLatestAssistantText(messages);
16208
16373
  if (!text)
16209
16374
  throw new Error("map-memories returned no output");
16210
- parseMapMemoriesManifest(text);
16375
+ validateMapMemoriesManifest(text, new Set(batch.map((memory) => memory.id)));
16211
16376
  return text;
16212
16377
  }
16213
16378
  });
@@ -16241,10 +16406,13 @@ async function applyBatchMappings(args, batch, manifestText) {
16241
16406
  return { mapped: 0, independent: 0 };
16242
16407
  const planned = [];
16243
16408
  for (const p of parsed) {
16244
- if (p.independent || p.files.length === 0) {
16409
+ if (p.independent) {
16245
16410
  planned.push({ id: p.id, files: [], independent: true });
16246
16411
  continue;
16247
16412
  }
16413
+ if (p.files.length === 0) {
16414
+ throw new Error(`mapping entry ${p.id} has no files and no independent sentinel`);
16415
+ }
16248
16416
  const normalized = await normalizeVerificationFiles({
16249
16417
  cwd: args.sessionDirectory,
16250
16418
  files: p.files
@@ -17389,9 +17557,22 @@ function attrOf(s, name) {
17389
17557
  function filesOf(s) {
17390
17558
  return (attrOf(s, "files") ?? "").split(",").map((f) => f.trim()).filter(Boolean);
17391
17559
  }
17560
+ function verifyIds(parsed) {
17561
+ return [...parsed.verified, ...parsed.updated, ...parsed.archived].map((entry) => entry.id);
17562
+ }
17563
+ function verifyBody(text) {
17564
+ try {
17565
+ return extractCompleteManifestBody(text, "verify");
17566
+ } catch (error) {
17567
+ const described = describeUnrecognizedManifestShape(text, "verify", "verified");
17568
+ if (!described.startsWith("parsed zero entries"))
17569
+ throw new Error(described);
17570
+ throw error;
17571
+ }
17572
+ }
17392
17573
  function parseVerifyManifest(text) {
17393
17574
  const out = { verified: [], updated: [], archived: [] };
17394
- const body = extractCompleteManifestBody(text, "verify");
17575
+ const body = verifyBody(text);
17395
17576
  for (const m of body.matchAll(/<verified\b([^>]*)\/?>/g)) {
17396
17577
  const id = Number.parseInt(attrOf(m[1], "id") ?? "", 10);
17397
17578
  if (!Number.isInteger(id))
@@ -17410,9 +17591,19 @@ function parseVerifyManifest(text) {
17410
17591
  throw new Error("verify manifest entry missing numeric id");
17411
17592
  out.archived.push({ id, reason: attrOf(m[1], "reason") ?? "" });
17412
17593
  }
17413
- assertNoDuplicateManifestIds([...out.verified, ...out.updated, ...out.archived].map((entry) => entry.id), "verify");
17594
+ if (verifyIds(out).length === 0 && body.trim().length > 0) {
17595
+ throw new Error(describeUnrecognizedManifestShape(text, "verify", "verified"));
17596
+ }
17597
+ assertNoDuplicateManifestIds(verifyIds(out), "verify");
17414
17598
  return out;
17415
17599
  }
17600
+ function validateVerifyManifest(text, expectedIds) {
17601
+ const parsed = parseVerifyManifest(text);
17602
+ const ids = verifyIds(parsed);
17603
+ assertParsedManifestNonEmpty(ids.length, expectedIds.size, text, "verify", "verified");
17604
+ assertManifestCoversExactly(ids, expectedIds, "verify");
17605
+ return parsed;
17606
+ }
17416
17607
 
17417
17608
  // src/features/magic-context/dreamer/verify.ts
17418
17609
  var VERIFY_BATCH_SIZE = 50;
@@ -17564,7 +17755,7 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
17564
17755
  if (!text)
17565
17756
  throw new Error("verify returned no output");
17566
17757
  try {
17567
- parseVerifyManifest(text);
17758
+ validateVerifyManifest(text, new Set(batch.map((memory) => memory.id)));
17568
17759
  } catch (error) {
17569
17760
  const providerFailure = providerOutputFailureFromInvalidManifest(messages, text);
17570
17761
  if (providerFailure)
@@ -17784,6 +17975,18 @@ function loadActiveMemoryPromptMemories(db, projectIdentity) {
17784
17975
  const verificationById = getMemoryVerifications(db, memories.map((memory) => memory.id));
17785
17976
  return memories.map((memory) => toCuratePromptMemory(memory, verificationById));
17786
17977
  }
17978
+ var TEXTUAL_CURATE_TOOL_CALL_PATTERNS = [
17979
+ /\[\s*historical tool call\s*\][\s\S]*?(?:^|\n)\s*name\s*:\s*ctx_memory\b[\s\S]*?(?:^|\n)\s*arguments\s*:/im,
17980
+ /(?:^|\n)\s*name\s*:\s*ctx_memory\b[\s\S]*?(?:^|\n)\s*arguments\s*:/im,
17981
+ /(?:^|\n)\s*(?:```[^\n]*\n\s*)?ctx_memory\s*\(\s*action\s*=/im,
17982
+ /["']name["']\s*:\s*["']ctx_memory["'][\s\S]*?["']arguments["']\s*:/i
17983
+ ];
17984
+ function validateCurateAssistantText(text) {
17985
+ if (TEXTUAL_CURATE_TOOL_CALL_PATTERNS.some((pattern) => pattern.test(text))) {
17986
+ throw new Error("Curate returned an unresolved textual ctx_memory tool call.");
17987
+ }
17988
+ return text;
17989
+ }
17787
17990
  function createDreamTaskExecutor(deps) {
17788
17991
  let parentSessionIdPromise;
17789
17992
  const resolveParentSessionId = () => {
@@ -17854,7 +18057,8 @@ function createDreamTaskExecutor(deps) {
17854
18057
  name: config.task,
17855
18058
  durationMs: Date.now() - startedAt,
17856
18059
  resultChars: 0,
17857
- ...error ? { error } : {},
18060
+ ...status === "failed" && error ? { error } : {},
18061
+ ...extra?.progress ? { progress: extra.progress } : {},
17858
18062
  backlog: (() => {
17859
18063
  const end = extra?.backlogAfter ?? getDreamTaskBacklog(db, projectIdentity, config.task);
17860
18064
  const processed = processedDreamTaskItems(backlogAtStart.pending, end.pending);
@@ -17997,11 +18201,12 @@ function createDreamTaskExecutor(deps) {
17997
18201
  const backlogAfter = config.task === "verify-broad" ? { pending: result.remaining, total: backlogAtStart.total } : undefined;
17998
18202
  if (!result.complete) {
17999
18203
  if (broadProgress && processed > 0) {
18000
- recordRun("completed", broadProgress, {
18204
+ recordRun("completed", null, {
18205
+ progress: broadProgress,
18001
18206
  memoryChanges: computeMemoryDelta(memoryBefore),
18002
18207
  backlogAfter
18003
18208
  });
18004
- return { status: "completed", error: broadProgress };
18209
+ return { status: "completed" };
18005
18210
  }
18006
18211
  const error = incompleteMessage(result.remaining);
18007
18212
  recordRun("failed", error, {
@@ -18010,11 +18215,12 @@ function createDreamTaskExecutor(deps) {
18010
18215
  });
18011
18216
  return { status: "failed", transient: true, error };
18012
18217
  }
18013
- recordRun("completed", broadProgress, {
18218
+ recordRun("completed", null, {
18219
+ progress: broadProgress,
18014
18220
  memoryChanges: computeMemoryDelta(memoryBefore),
18015
18221
  backlogAfter
18016
18222
  });
18017
- return broadProgress ? { status: "completed", error: broadProgress } : { status: "completed" };
18223
+ return { status: "completed" };
18018
18224
  }
18019
18225
  if (config.task === "classify-memories") {
18020
18226
  let moduleArgs;
@@ -18481,7 +18687,7 @@ async function runAgenticTask(config, ctx, helpers) {
18481
18687
  const text = extractLatestAssistantText(messages);
18482
18688
  if (!text)
18483
18689
  throw new Error("Dreamer returned no assistant output.");
18484
- return text;
18690
+ return task === "curate" ? validateCurateAssistantText(text) : text;
18485
18691
  }
18486
18692
  });
18487
18693
  if (leaseLost)
@@ -19260,7 +19466,7 @@ function scheduleInitialProjectRun(reg, db) {
19260
19466
  startupTimers.set(reg.directory, timer);
19261
19467
  }
19262
19468
  async function runProjectMaintenance(reg, origin, db) {
19263
- const projectMaintenanceEnabled = Boolean(reg.dreamerConfig && reg.dreamerConfig.disable !== true) || reg.memoryEnabled === true || reg.gitCommitIndexing?.enabled === true;
19469
+ const projectMaintenanceEnabled = Boolean(reg.dreamerConfig && reg.dreamerConfig.disable !== true) || reg.memoryEnabled === true || reg.gitCommitIndexing?.enabled === true || reg.historianChildSweep !== undefined;
19264
19470
  if (!projectMaintenanceEnabled)
19265
19471
  return;
19266
19472
  await reg.ensureRegistered(reg.directory, db);
@@ -19297,6 +19503,7 @@ async function sweepProject(reg, origin, db, gitCommitEnabled) {
19297
19503
  if (gcDeleted > 0) {
19298
19504
  log(`[magic-context] GC'd ${gcDeleted} stale embedding row(s) for ${reg.projectIdentity} ` + `(memory=${gc.memoryRowsDeleted} commit=${gc.commitRowsDeleted} chunk=${gc.chunkRowsDeleted})`);
19299
19505
  }
19506
+ await sweepOrphanedHistorianChildren(reg);
19300
19507
  const dreamerConfig = reg.dreamerConfig;
19301
19508
  const dreamingEnabled = Boolean(dreamerConfig && dreamerConfig.disable !== true);
19302
19509
  if (commitIndexingEnabled && reg.gitCommitIndexing) {
@@ -19360,6 +19567,27 @@ async function sweepProject(reg, origin, db, gitCommitEnabled) {
19360
19567
  log(`[dreamer] timer-triggered task scheduling failed for ${reg.projectIdentity}:`, error);
19361
19568
  }
19362
19569
  }
19570
+ async function sweepOrphanedHistorianChildren(reg) {
19571
+ const config = reg.historianChildSweep;
19572
+ if (!config || config.keepSubagents)
19573
+ return;
19574
+ const ocDb = openOpenCodeDb();
19575
+ if (!ocDb)
19576
+ return;
19577
+ try {
19578
+ await sweepOrphanedRetrospectiveChildren({
19579
+ opencodeDb: ocDb,
19580
+ client: reg.client,
19581
+ sessionDirectory: reg.directory,
19582
+ staleMs: historianOrphanStaleMs(config.timeoutMs, config.fallbackModelCount),
19583
+ titleMatches: HISTORIAN_CHILD_TITLE_MATCHES
19584
+ });
19585
+ } catch (error) {
19586
+ log(`[magic-context] historian child orphan sweep failed for ${reg.projectIdentity}:`, error);
19587
+ } finally {
19588
+ closeQuietly(ocDb);
19589
+ }
19590
+ }
19363
19591
  async function runCompiledSmartNoteSweep(reg, db) {
19364
19592
  const leaseKey = leaseKeyFor("evaluate-smart-notes", reg.projectIdentity);
19365
19593
  const holderId = crypto.randomUUID();
@@ -20358,6 +20586,44 @@ function createTagger() {
20358
20586
  // src/hooks/magic-context/command-handler.ts
20359
20587
  import { randomUUID as randomUUID2 } from "node:crypto";
20360
20588
 
20589
+ // src/shared/tail-hygiene-status.ts
20590
+ function finiteNumber(value, fallback = 0) {
20591
+ return typeof value === "number" && Number.isFinite(value) ? value : fallback;
20592
+ }
20593
+ function resolveTailHygieneStatus(tsBaseline, rustBaseline) {
20594
+ if (rustBaseline !== undefined && rustBaseline !== null) {
20595
+ const t2 = Math.max(0, finiteNumber(rustBaseline.t));
20596
+ const u2 = Math.min(t2, Math.max(0, finiteNumber(rustBaseline.u)));
20597
+ return {
20598
+ u: u2,
20599
+ t: t2,
20600
+ severity: Math.min(1, Math.max(0, finiteNumber(rustBaseline.severity, u2 / Math.max(t2, 1)))),
20601
+ evaluable: rustBaseline.evaluable === true,
20602
+ generationInvalidated: rustBaseline.generation_invalidated === true,
20603
+ baselineGeneration: Math.max(0, finiteNumber(rustBaseline.baseline_generation)),
20604
+ computedAt: Math.max(0, finiteNumber(rustBaseline.computed_at_ms))
20605
+ };
20606
+ }
20607
+ if (tsBaseline === undefined)
20608
+ return;
20609
+ const t = Math.max(0, tsBaseline.baselineT + tsBaseline.turnDeltaT);
20610
+ const u = Math.min(t, Math.max(0, tsBaseline.baselineU + tsBaseline.turnDeltaU));
20611
+ return {
20612
+ u,
20613
+ t,
20614
+ severity: Math.min(1, Math.max(0, u / Math.max(t, 1))),
20615
+ evaluable: tsBaseline.evaluable && !tsBaseline.generationInvalidated,
20616
+ generationInvalidated: tsBaseline.generationInvalidated,
20617
+ baselineGeneration: Math.max(0, tsBaseline.baselineGeneration),
20618
+ computedAt: Math.max(0, tsBaseline.computedAt)
20619
+ };
20620
+ }
20621
+ function formatTailHygiene(status) {
20622
+ const percentage = (status.severity * 100).toFixed(1);
20623
+ const state = status.evaluable ? "" : " · held until baseline refresh";
20624
+ return `${percentage}% · ${status.u.toLocaleString()} / ${status.t.toLocaleString()} tok${state}`;
20625
+ }
20626
+
20361
20627
  // src/hooks/magic-context/execute-flush.ts
20362
20628
  function executeFlush(db, sessionId) {
20363
20629
  try {
@@ -20798,7 +21064,7 @@ function formatExecuteThreshold(detail, contextLimit) {
20798
21064
  }
20799
21065
  return `${percentage}%${clampNote}`;
20800
21066
  }
20801
- function executeStatus(db, sessionId, protectedTags, executeThresholdPercentageConfig = DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE, liveModelKey, historyBudgetPercentage, commitClusterTrigger, executeThresholdTokens, contextLimit, dreamer, windowGeometry) {
21067
+ function executeStatus(db, sessionId, protectedTags, executeThresholdPercentageConfig = DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE, liveModelKey, historyBudgetPercentage, commitClusterTrigger, executeThresholdTokens, contextLimit, dreamer, windowGeometry, tailHygiene) {
20802
21068
  const thresholdDetail = resolveExecuteThresholdDetail(executeThresholdPercentageConfig, liveModelKey, DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE, {
20803
21069
  tokensConfig: executeThresholdTokens,
20804
21070
  contextLimit,
@@ -20843,7 +21109,7 @@ function executeStatus(db, sessionId, protectedTags, executeThresholdPercentageC
20843
21109
  "### Cache TTL",
20844
21110
  `- Configured: ${meta.cacheTtl}`,
20845
21111
  `- Last response: ${meta.lastResponseTime > 0 ? `${Math.round(elapsed / 1000)}s ago` : "never"}`,
20846
- `- Remaining: ${cacheExpired ? "expired" : ttlMs === Number.POSITIVE_INFINITY ? "never expires (always-warm lane)" : `${Math.round(remainingMs / 1000)}s`}`,
21112
+ `- Remaining: ${cacheExpired ? "expired" : ttlMs === Number.POSITIVE_INFINITY ? "never (MC never assumes expiry — external cache-keep)" : `${Math.round(remainingMs / 1000)}s`}`,
20847
21113
  `- Queue will auto-execute: ${cacheExpired ? "yes (cache expired)" : ttlMs === Number.POSITIVE_INFINITY ? `when context >= ${executeThresholdPercentage}%` : `when TTL expires or context >= ${executeThresholdPercentage}%`}`,
20848
21114
  "",
20849
21115
  "### Execute Threshold",
@@ -20853,6 +21119,9 @@ function executeStatus(db, sessionId, protectedTags, executeThresholdPercentageC
20853
21119
  `**Protected tags:** ${protectedTags}`,
20854
21120
  `**Subagent session:** ${meta.isSubagent}`
20855
21121
  ];
21122
+ if (tailHygiene !== undefined) {
21123
+ lines.push("", "### Tail Hygiene", `- Reclaimable / eligible: ${formatTailHygiene(tailHygiene)}`, "- Reasoning is excluded from both terms.");
21124
+ }
20856
21125
  if (dreamer?.backlog && Object.keys(dreamer.backlog).length > 0) {
20857
21126
  lines.push("", "### Dreamer", ...dreamer.progress ? [
20858
21127
  `- Running: ${dreamer.progress.task} — ${dreamer.progress.processed}/${dreamer.progress.total} processed`
@@ -21329,10 +21598,12 @@ Embedding status is unavailable.`;
21329
21598
  const liveContextLimit = deps.getContextLimit?.(sessionId);
21330
21599
  const modelSlash = liveModelKey?.indexOf("/") ?? -1;
21331
21600
  const windowGeometry = liveModelKey && modelSlash > 0 ? resolveContextWindowGeometry(liveModelKey.slice(0, modelSlash), liveModelKey.slice(modelSlash + 1), { db: deps.db, sessionID: sessionId }) : undefined;
21601
+ const rustTailHygiene = rustStatus?.tail_hygiene;
21602
+ const tailHygiene = resolveTailHygieneStatus(deps.getTailHygiene?.(sessionId), rustTailHygiene && typeof rustTailHygiene === "object" ? rustTailHygiene : undefined);
21332
21603
  const statusOutput = executeStatus(deps.db, sessionId, deps.protectedTags, deps.executeThresholdPercentage, liveModelKey, deps.historyBudgetPercentage, deps.commitClusterTrigger, deps.executeThresholdTokens, liveContextLimit, deps.dreamer ? {
21333
21604
  backlog: readDreamTaskBacklogsSafely(deps.db, deps.dreamer.projectPath, CANONICAL_DREAM_TASKS),
21334
21605
  progress: deps.getDreamerProgress?.() ?? null
21335
- } : undefined, windowGeometry);
21606
+ } : undefined, windowGeometry, tailHygiene);
21336
21607
  const moduleStatus = rustStatus ? `
21337
21608
 
21338
21609
  ${formatRustStatusText(rustStatus)}` : "";
@@ -21985,6 +22256,10 @@ function writeRustTransformDecision(args) {
21985
22256
  decision: mapped.decision,
21986
22257
  materialized: mapped.materialized,
21987
22258
  materializeReason: args.materializeReason,
22259
+ systemHashPrev: null,
22260
+ systemHashNew: null,
22261
+ m0ModelKeyPrev: null,
22262
+ m0ModelKeyNew: null,
21988
22263
  emergency: false,
21989
22264
  droppedTokens: 0,
21990
22265
  droppedCount: 0,
@@ -22076,10 +22351,16 @@ function writeTransformDecisionRow(dbPath, row) {
22076
22351
  function writeTransformDecisionRowOnDatabase(db, row, configureBusyTimeout) {
22077
22352
  if (configureBusyTimeout)
22078
22353
  db.exec("PRAGMA busy_timeout=0");
22354
+ const systemHashPrev = row.materialized ? row.systemHashPrev : null;
22355
+ const systemHashNew = row.materialized ? row.systemHashNew : null;
22356
+ const m0ModelKeyPrev = row.materialized ? row.m0ModelKeyPrev : null;
22357
+ const m0ModelKeyNew = row.materialized ? row.m0ModelKeyNew : null;
22079
22358
  db.prepare(`INSERT OR REPLACE INTO transform_decisions (
22080
22359
  session_id, harness, message_id, ts_ms, decision, materialized,
22081
- materialize_reason, emergency, dropped_tokens, dropped_count, input_tokens
22082
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(row.sessionId, row.harness, row.messageId, row.tsMs, row.decision, row.materialized ? 1 : 0, row.materializeReason, row.emergency ? 1 : 0, Math.max(0, Math.floor(row.droppedTokens)), Math.max(0, Math.floor(row.droppedCount)), Math.max(0, Math.floor(row.inputTokens)));
22360
+ materialize_reason, system_hash_prev, system_hash_new,
22361
+ m0_model_key_prev, m0_model_key_new, emergency, dropped_tokens,
22362
+ dropped_count, input_tokens
22363
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(row.sessionId, row.harness, row.messageId, row.tsMs, row.decision, row.materialized ? 1 : 0, row.materializeReason, systemHashPrev, systemHashNew, m0ModelKeyPrev, m0ModelKeyNew, row.emergency ? 1 : 0, Math.max(0, Math.floor(row.droppedTokens)), Math.max(0, Math.floor(row.droppedCount)), Math.max(0, Math.floor(row.inputTokens)));
22083
22364
  db.prepare(`DELETE FROM transform_decisions
22084
22365
  WHERE session_id = ? AND harness = ?
22085
22366
  AND rowid NOT IN (
@@ -22363,185 +22644,6 @@ function captureWindowReport(input) {
22363
22644
 
22364
22645
  // src/hooks/magic-context/channel2-delivery.ts
22365
22646
  import { randomUUID as randomUUID3 } from "node:crypto";
22366
-
22367
- // src/hooks/magic-context/ctx-reduce-nudge.ts
22368
- var CHANNEL1_SENTINEL = "<system-reminder>";
22369
- var TOKENS_PER_BYTE = 0.25;
22370
- var CHANNEL1_FLOOR_TOKENS = 1e4;
22371
- var CHANNEL1_REFIRE_FLOOR_TOKENS = 1e4;
22372
- function channel1RefireTokens(workingWindowTokens) {
22373
- const scaled = Math.round(0.05 * Math.max(0, workingWindowTokens));
22374
- return Math.max(CHANNEL1_REFIRE_FLOOR_TOKENS, scaled);
22375
- }
22376
- var S_GENTLE = 0.2;
22377
- var S_FIRM = 0.4;
22378
- var S_URGENT = 0.65;
22379
- var CHANNEL1_PRESSURE_FLOOR = 0.8;
22380
- var LEVEL_RANK = { gentle: 1, firm: 2, urgent: 3 };
22381
- var DROP_SENTINELS = ["[dropped", "[truncated"];
22382
- function isDroppedToolOutput(output) {
22383
- const head = output.slice(0, 16);
22384
- return DROP_SENTINELS.some((s) => head.startsWith(s));
22385
- }
22386
- function isToolPartWithStringOutput(part) {
22387
- if (part === null || typeof part !== "object")
22388
- return false;
22389
- const p = part;
22390
- if (p.type !== "tool" && p.type !== "tool-invocation")
22391
- return false;
22392
- const state = p.state;
22393
- return typeof state?.output === "string";
22394
- }
22395
- function toolOutputTokens(output) {
22396
- return Math.round(byteSize(output) * TOKENS_PER_BYTE);
22397
- }
22398
- function stringTokens(value) {
22399
- return Math.round(byteSize(value) * TOKENS_PER_BYTE);
22400
- }
22401
- function unknownJsonTokens(value) {
22402
- if (value === undefined || value === null)
22403
- return 0;
22404
- try {
22405
- return stringTokens(JSON.stringify(value));
22406
- } catch {
22407
- return 0;
22408
- }
22409
- }
22410
- function textFromPart(part) {
22411
- if (part === null || typeof part !== "object")
22412
- return "";
22413
- const p = part;
22414
- if (typeof p.text === "string")
22415
- return p.text;
22416
- if (typeof p.content === "string")
22417
- return p.content;
22418
- if (typeof p.thinking === "string")
22419
- return p.thinking;
22420
- return "";
22421
- }
22422
- function computeTailTokenEstimate(messages) {
22423
- let toolOutputTokensTotal = 0;
22424
- let toolCallTokensTotal = 0;
22425
- let conversationTokens = 0;
22426
- for (const message of messages) {
22427
- for (const part of message.parts) {
22428
- if (isToolPartWithStringOutput(part)) {
22429
- const outputTokens = isDroppedToolOutput(part.state.output) ? 0 : toolOutputTokens(part.state.output);
22430
- const inputTokens = unknownJsonTokens(part.state?.input);
22431
- toolOutputTokensTotal += outputTokens;
22432
- toolCallTokensTotal += outputTokens + inputTokens;
22433
- continue;
22434
- }
22435
- conversationTokens += stringTokens(textFromPart(part));
22436
- }
22437
- }
22438
- return {
22439
- tailToolTokens: toolOutputTokensTotal,
22440
- liveTailTokens: conversationTokens + toolCallTokensTotal
22441
- };
22442
- }
22443
- function decideChannel1(input) {
22444
- const { undroppedTokens, workingWindowTokens, hasRecentReduce } = input;
22445
- const pressure = Math.min(1, Math.max(0, input.pressure));
22446
- const resetCycle = hasRecentReduce || undroppedTokens < input.lastNudgeUndropped;
22447
- const lastNudge = resetCycle ? 0 : input.lastNudgeUndropped;
22448
- const lastLevel = resetCycle ? "" : input.lastNudgeLevel;
22449
- const quiet = () => ({
22450
- fire: false,
22451
- level: "gentle",
22452
- undroppedTokens,
22453
- nextLastNudge: lastNudge,
22454
- nextLastNudgeLevel: lastLevel
22455
- });
22456
- if (hasRecentReduce)
22457
- return quiet();
22458
- if (undroppedTokens < CHANNEL1_FLOOR_TOKENS)
22459
- return quiet();
22460
- if (pressure < CHANNEL1_PRESSURE_FLOOR)
22461
- return quiet();
22462
- const denom = Math.max(input.estimatedInputTokens, 1);
22463
- const severity = Math.min(1, undroppedTokens / denom);
22464
- if (severity < S_GENTLE)
22465
- return quiet();
22466
- let level;
22467
- if (severity >= S_URGENT)
22468
- level = "urgent";
22469
- else if (severity >= S_FIRM)
22470
- level = "firm";
22471
- else
22472
- level = "gentle";
22473
- if (lastLevel === "") {
22474
- if (undroppedTokens < lastNudge + channel1RefireTokens(workingWindowTokens)) {
22475
- return quiet();
22476
- }
22477
- } else if (LEVEL_RANK[level] <= LEVEL_RANK[lastLevel]) {
22478
- return quiet();
22479
- }
22480
- return {
22481
- fire: true,
22482
- level,
22483
- undroppedTokens,
22484
- nextLastNudge: undroppedTokens,
22485
- nextLastNudgeLevel: level
22486
- };
22487
- }
22488
- function computePressure(input) {
22489
- const { lastInputTokens, turnToolTokens, contextLimit, executeThresholdPercentage } = input;
22490
- if (contextLimit <= 0 || executeThresholdPercentage <= 0)
22491
- return 0;
22492
- const estimatedInput = lastInputTokens + turnToolTokens;
22493
- const usagePercentage = estimatedInput / contextLimit * 100;
22494
- return usagePercentage / executeThresholdPercentage;
22495
- }
22496
- function approxThousands(tokens) {
22497
- return `${Math.round(tokens / 1000)}k`;
22498
- }
22499
- function formatOldestReclaimableHint(hint) {
22500
- if (!hint || hint.length === 0)
22501
- return "";
22502
- const rendered = hint.slice(0, 4).map((tag) => `§${tag.tagNumber}§ ${tag.toolName ?? "tool"}`).join(" · ");
22503
- return rendered.length > 0 ? `
22504
- oldest reclaimable: ${rendered}.` : "";
22505
- }
22506
- var CHANNEL2_USABLE_FRACTION = 1 / 3;
22507
- var CHANNEL2_MIN_RECLAIMABLE = 1e4;
22508
- function shouldTriggerChannel2(input) {
22509
- if (input.reclaimableTokens < CHANNEL2_MIN_RECLAIMABLE)
22510
- return false;
22511
- if (input.usableTokens <= 0)
22512
- return true;
22513
- return input.reclaimableTokens >= input.usableTokens * CHANNEL2_USABLE_FRACTION;
22514
- }
22515
- function buildChannel2Reminder(undroppedTokens, hint) {
22516
- const amount = approxThousands(undroppedTokens);
22517
- const hintText = formatOldestReclaimableHint(hint);
22518
- return `<system-reminder>
22519
- ` + `Routine context housekeeping is near: a large span of this session will be comparted soon, ` + `and ~${amount} tokens of tool output remain unreduced. Drop spent outputs with ctx_reduce ` + `first so the archived span is the part that matters.${hintText}
22520
- ` + `</system-reminder>`;
22521
- }
22522
- function buildChannel1Reminder(level, undroppedTokens, hint) {
22523
- const amount = approxThousands(undroppedTokens);
22524
- const hintText = formatOldestReclaimableHint(hint);
22525
- let body;
22526
- switch (level) {
22527
- case "gentle":
22528
- body = `You have ~${amount} tokens of tool output you have not reduced. ` + `When you are done with earlier outputs, dropping them with ctx_reduce keeps context lean.`;
22529
- break;
22530
- case "firm":
22531
- body = `~${amount} tokens of unreduced tool output has built up. ` + `At your next natural stopping point, consider dropping what you have already processed with ctx_reduce.`;
22532
- break;
22533
- case "urgent":
22534
- body = `~${amount} tokens of unreduced tool output remain, and a large span of this session will be comparted before long. ` + `Consider dropping spent outputs with ctx_reduce so the archived span is the part that matters.`;
22535
- break;
22536
- }
22537
- return `
22538
-
22539
- <system-reminder>
22540
- ${body}${hintText}
22541
- </system-reminder>`;
22542
- }
22543
-
22544
- // src/hooks/magic-context/channel2-delivery.ts
22545
22647
  function subagentRunIsActive(deps, sessionId) {
22546
22648
  try {
22547
22649
  const meta = getOrCreateSessionMeta(deps.db, sessionId);
@@ -22584,19 +22686,18 @@ async function maybeDeliverChannel2(sessionId, deps) {
22584
22686
  clearPendingChannel2Intent(deps.db, sessionId);
22585
22687
  return false;
22586
22688
  }
22587
- if (deps.directiveText === undefined && (deps.reclaimableTokens === undefined || deps.usableTokens === undefined)) {
22689
+ const evaluation = evaluateChannel2(deps.baseline);
22690
+ if (deps.directiveText === undefined && !evaluation.evaluable) {
22588
22691
  return false;
22589
22692
  }
22590
- if (deps.directiveText === undefined && !shouldTriggerChannel2({
22591
- reclaimableTokens: deps.reclaimableTokens,
22592
- usableTokens: deps.usableTokens
22593
- })) {
22693
+ if (deps.directiveText === undefined && !evaluation.shouldTrigger) {
22594
22694
  try {
22595
22695
  casChannel2NudgeState(deps.db, sessionId, "pending", "");
22596
- sessionLog(sessionId, `channel2 intent cleared pre-delivery (reclaimable ${deps.reclaimableTokens}, usable ${deps.usableTokens} — trigger no longer holds; re-armable)`);
22696
+ sessionLog(sessionId, `channel2 intent cleared pre-delivery (U ${evaluation.reclaimableTokens}, T ${evaluation.tailTokens} — trigger no longer holds; re-armable)`);
22597
22697
  } catch {}
22598
22698
  return false;
22599
22699
  }
22700
+ const effectiveU = evaluation.reclaimableTokens;
22600
22701
  const client = deps.client;
22601
22702
  if (!client)
22602
22703
  return false;
@@ -22610,7 +22711,7 @@ async function maybeDeliverChannel2(sessionId, deps) {
22610
22711
  }
22611
22712
  try {
22612
22713
  const promptContext = await resolvePromptContext(client, sessionId);
22613
- const reminder = deps.directiveText ?? buildChannel2Reminder(deps.reclaimableTokens, deps.oldestReclaimableToolTags);
22714
+ const reminder = deps.directiveText ?? buildChannel2Reminder(effectiveU, deps.oldestReclaimableToolTags);
22614
22715
  const body = {
22615
22716
  noReply: false,
22616
22717
  parts: [{ type: "text", text: reminder, synthetic: true }]
@@ -23296,156 +23397,6 @@ class EmergencyFailClosedError extends Error {
23296
23397
  }
23297
23398
  }
23298
23399
 
23299
- // src/hooks/magic-context/image-token-estimate.ts
23300
- var IMAGE_TOKEN_DIVISOR = 750;
23301
- var IMAGE_FALLBACK_TOKENS = 1200;
23302
- var IMAGE_TOKEN_CAP = 4500;
23303
- function estimateImageTokensFromDataUrl(url) {
23304
- const comma = url.indexOf(",");
23305
- if (comma < 0)
23306
- return IMAGE_FALLBACK_TOKENS;
23307
- const header = url.slice(0, comma);
23308
- const payload = url.slice(comma + 1);
23309
- const sliceLen = Math.min(512, payload.length);
23310
- const preview = payload.slice(0, sliceLen);
23311
- let bytes;
23312
- try {
23313
- bytes = base64Decode(preview);
23314
- } catch {
23315
- return IMAGE_FALLBACK_TOKENS;
23316
- }
23317
- if (header.includes("image/png")) {
23318
- const dims = parsePngDimensions(bytes);
23319
- if (dims)
23320
- return clampImageTokens(Math.ceil(dims.w * dims.h / IMAGE_TOKEN_DIVISOR));
23321
- } else if (header.includes("image/jpeg") || header.includes("image/jpg")) {
23322
- const dims = parseJpegDimensions(bytes);
23323
- if (dims)
23324
- return clampImageTokens(Math.ceil(dims.w * dims.h / IMAGE_TOKEN_DIVISOR));
23325
- } else if (header.includes("image/webp")) {
23326
- const dims = parseWebpDimensions(bytes);
23327
- if (dims)
23328
- return clampImageTokens(Math.ceil(dims.w * dims.h / IMAGE_TOKEN_DIVISOR));
23329
- } else if (header.includes("image/gif")) {
23330
- const dims = parseGifDimensions(bytes);
23331
- if (dims)
23332
- return clampImageTokens(Math.ceil(dims.w * dims.h / IMAGE_TOKEN_DIVISOR));
23333
- }
23334
- return IMAGE_FALLBACK_TOKENS;
23335
- }
23336
- function clampImageTokens(n) {
23337
- if (n < 1)
23338
- return 1;
23339
- if (n > IMAGE_TOKEN_CAP)
23340
- return IMAGE_TOKEN_CAP;
23341
- return n;
23342
- }
23343
- function base64Decode(b64) {
23344
- const pad = b64.length % 4;
23345
- const padded = pad === 0 ? b64 : b64 + "=".repeat(4 - pad);
23346
- const binary = atob(padded);
23347
- const out = new Uint8Array(binary.length);
23348
- for (let i = 0;i < binary.length; i++)
23349
- out[i] = binary.charCodeAt(i);
23350
- return out;
23351
- }
23352
- function parsePngDimensions(b) {
23353
- if (b.length < 24)
23354
- return null;
23355
- if (b[0] !== 137 || b[1] !== 80 || b[2] !== 78 || b[3] !== 71 || b[4] !== 13 || b[5] !== 10 || b[6] !== 26 || b[7] !== 10)
23356
- return null;
23357
- const w = readUint32BE(b, 16);
23358
- const h = readUint32BE(b, 20);
23359
- if (!w || !h)
23360
- return null;
23361
- return { w, h };
23362
- }
23363
- function parseJpegDimensions(b) {
23364
- if (b.length < 4 || b[0] !== 255 || b[1] !== 216)
23365
- return null;
23366
- let i = 2;
23367
- while (i < b.length - 8) {
23368
- if (b[i] !== 255) {
23369
- i++;
23370
- continue;
23371
- }
23372
- const marker = b[i + 1];
23373
- if (marker === undefined)
23374
- break;
23375
- if (isSofMarker(marker)) {
23376
- const h = b[i + 5] << 8 | b[i + 6];
23377
- const w = b[i + 7] << 8 | b[i + 8];
23378
- if (w && h)
23379
- return { w, h };
23380
- return null;
23381
- }
23382
- if (marker === 216 || marker === 217 || marker === 1) {
23383
- i += 2;
23384
- continue;
23385
- }
23386
- const segLen = b[i + 2] << 8 | b[i + 3];
23387
- if (segLen < 2)
23388
- return null;
23389
- i += 2 + segLen;
23390
- }
23391
- return null;
23392
- }
23393
- function isSofMarker(m) {
23394
- if (m >= 192 && m <= 195)
23395
- return true;
23396
- if (m >= 197 && m <= 199)
23397
- return true;
23398
- if (m >= 201 && m <= 203)
23399
- return true;
23400
- if (m >= 205 && m <= 207)
23401
- return true;
23402
- return false;
23403
- }
23404
- function parseWebpDimensions(b) {
23405
- if (b.length < 30)
23406
- return null;
23407
- if (b[0] !== 82 || b[1] !== 73 || b[2] !== 70 || b[3] !== 70)
23408
- return null;
23409
- if (b[8] !== 87 || b[9] !== 69 || b[10] !== 66 || b[11] !== 80)
23410
- return null;
23411
- const variant = String.fromCharCode(b[12], b[13], b[14], b[15]);
23412
- if (variant === "VP8 ") {
23413
- const w = (b[26] | b[27] << 8) & 16383;
23414
- const h = (b[28] | b[29] << 8) & 16383;
23415
- if (w && h)
23416
- return { w, h };
23417
- } else if (variant === "VP8L") {
23418
- const b0 = b[21];
23419
- const b1 = b[22];
23420
- const b2 = b[23];
23421
- const b3 = b[24];
23422
- const w = 1 + ((b0 | b1 << 8) & 16383);
23423
- const h = 1 + ((b1 >> 6 | b2 << 2 | b3 << 10) & 16383);
23424
- if (w && h)
23425
- return { w, h };
23426
- } else if (variant === "VP8X") {
23427
- const w = 1 + (b[24] | b[25] << 8 | b[26] << 16);
23428
- const h = 1 + (b[27] | b[28] << 8 | b[29] << 16);
23429
- if (w && h)
23430
- return { w, h };
23431
- }
23432
- return null;
23433
- }
23434
- function parseGifDimensions(b) {
23435
- if (b.length < 10)
23436
- return null;
23437
- if (b[0] !== 71 || b[1] !== 73 || b[2] !== 70)
23438
- return null;
23439
- const w = b[6] | b[7] << 8;
23440
- const h = b[8] | b[9] << 8;
23441
- if (!w || !h)
23442
- return null;
23443
- return { w, h };
23444
- }
23445
- function readUint32BE(b, offset) {
23446
- return (b[offset] << 24 | b[offset + 1] << 16 | b[offset + 2] << 8 | b[offset + 3]) >>> 0;
23447
- }
23448
-
23449
23400
  // src/hooks/magic-context/tokenizer-calibration.ts
23450
23401
  var CALIBRATION_TABLE = [
23451
23402
  { prefix: "anthropic/claude-opus-4-8", systemRatio: 1.51, toolsRatio: 1.57 },
@@ -24294,7 +24245,7 @@ function createPassOutcome() {
24294
24245
  }
24295
24246
 
24296
24247
  // src/hooks/magic-context/rust-mode-transform.ts
24297
- import { createHash as createHash13 } from "node:crypto";
24248
+ import { createHash as createHash12 } from "node:crypto";
24298
24249
 
24299
24250
  // src/hooks/magic-context/module-state-sync.ts
24300
24251
  import { createHmac, randomUUID as randomUUID5 } from "node:crypto";
@@ -25764,121 +25715,6 @@ class RawFallbackContextLimitError extends Error {
25764
25715
  }
25765
25716
  }
25766
25717
 
25767
- // src/hooks/magic-context/todo-view.ts
25768
- import { createHash as createHash11 } from "node:crypto";
25769
- var TODO_STATUS_PENDING = "pending";
25770
- var TODO_STATUS_IN_PROGRESS = "in_progress";
25771
- var TODO_STATUS_COMPLETED = "completed";
25772
- var TODO_STATUS_CANCELLED = "cancelled";
25773
- var TODO_PRIORITY_HIGH = "high";
25774
- var TODO_PRIORITY_MEDIUM = "medium";
25775
- var TODO_PRIORITY_LOW = "low";
25776
- var TODO_STATUSES = [
25777
- TODO_STATUS_PENDING,
25778
- TODO_STATUS_IN_PROGRESS,
25779
- TODO_STATUS_COMPLETED,
25780
- TODO_STATUS_CANCELLED
25781
- ];
25782
- var TODO_PRIORITIES = [
25783
- TODO_PRIORITY_HIGH,
25784
- TODO_PRIORITY_MEDIUM,
25785
- TODO_PRIORITY_LOW
25786
- ];
25787
- var TODO_STATUS_SET = new Set(TODO_STATUSES);
25788
- var TODO_PRIORITY_SET = new Set(TODO_PRIORITIES);
25789
- var TERMINAL_STATUSES = new Set([
25790
- TODO_STATUS_COMPLETED,
25791
- TODO_STATUS_CANCELLED
25792
- ]);
25793
- var TITLE_DONE_STATUSES = new Set([TODO_STATUS_COMPLETED]);
25794
- var SYNTHETIC_CALL_ID_PREFIX = "mc_synthetic_todo_";
25795
- function normalizeTodoStateJson(todos) {
25796
- if (!Array.isArray(todos))
25797
- return null;
25798
- const normalized = [];
25799
- for (const todo of todos) {
25800
- if (!isTodoItem(todo))
25801
- return null;
25802
- normalized.push({
25803
- content: todo.content,
25804
- status: todo.status,
25805
- priority: todo.priority ?? TODO_PRIORITY_MEDIUM
25806
- });
25807
- }
25808
- return JSON.stringify(normalized);
25809
- }
25810
- function buildSyntheticTodoPart(stateJson) {
25811
- const todos = parseTodoState(stateJson);
25812
- if (todos === null || todos.length === 0)
25813
- return null;
25814
- if (todos.every((t) => TERMINAL_STATUSES.has(t.status)))
25815
- return null;
25816
- const callID = computeSyntheticCallId(stateJson);
25817
- const activeCount = todos.filter((t) => !TITLE_DONE_STATUSES.has(t.status)).length;
25818
- const output = JSON.stringify(todos, null, 2);
25819
- const ts = 0;
25820
- return {
25821
- type: "tool",
25822
- callID,
25823
- tool: "todowrite",
25824
- state: {
25825
- status: "completed",
25826
- input: { todos },
25827
- output,
25828
- title: `${activeCount} todos`,
25829
- metadata: { todos, truncated: false },
25830
- time: { start: ts, end: ts }
25831
- },
25832
- syntheticTodoMarker: true
25833
- };
25834
- }
25835
- function computeSyntheticCallId(stateJson) {
25836
- const hash = createHash11("sha256").update(stateJson).digest("hex").slice(0, 16);
25837
- return `${SYNTHETIC_CALL_ID_PREFIX}${hash}`;
25838
- }
25839
- function isSyntheticTodoPart(part) {
25840
- if (part === null || typeof part !== "object")
25841
- return false;
25842
- const p = part;
25843
- if (p.syntheticTodoMarker === true)
25844
- return true;
25845
- return p.type === "tool" && p.tool === "todowrite" && typeof p.callID === "string" && p.callID.startsWith(SYNTHETIC_CALL_ID_PREFIX);
25846
- }
25847
- function parseTodoState(stateJson) {
25848
- if (stateJson.length === 0)
25849
- return null;
25850
- try {
25851
- const parsed = JSON.parse(stateJson);
25852
- if (!Array.isArray(parsed))
25853
- return null;
25854
- const result = [];
25855
- for (const item of parsed) {
25856
- if (!isTodoItem(item))
25857
- return null;
25858
- result.push({
25859
- content: item.content,
25860
- status: item.status,
25861
- priority: item.priority ?? TODO_PRIORITY_MEDIUM
25862
- });
25863
- }
25864
- return result;
25865
- } catch {
25866
- return null;
25867
- }
25868
- }
25869
- function isTodoStatus(value) {
25870
- return typeof value === "string" && TODO_STATUS_SET.has(value);
25871
- }
25872
- function isTodoPriority(value) {
25873
- return typeof value === "string" && TODO_PRIORITY_SET.has(value);
25874
- }
25875
- function isTodoItem(value) {
25876
- if (value === null || typeof value !== "object")
25877
- return false;
25878
- const todo = value;
25879
- return typeof todo.content === "string" && isTodoStatus(todo.status) && (todo.priority === undefined || isTodoPriority(todo.priority));
25880
- }
25881
-
25882
25718
  // src/hooks/magic-context/transform-context-state.ts
25883
25719
  function loadPersistedUsageWatermark(db, sessionId) {
25884
25720
  const result = db.prepare("SELECT last_response_time FROM session_meta WHERE session_id = ?").get(sessionId);
@@ -25982,7 +25818,7 @@ function containsProbeVerbatim(text, probes) {
25982
25818
  }
25983
25819
 
25984
25820
  // src/features/magic-context/search-measurement.ts
25985
- import { createHash as createHash12 } from "node:crypto";
25821
+ import { createHash as createHash11 } from "node:crypto";
25986
25822
  function resultId(result) {
25987
25823
  switch (result.source) {
25988
25824
  case "memory":
@@ -26069,7 +25905,7 @@ async function recordShadowMeasurement(args) {
26069
25905
  }
26070
25906
  }
26071
25907
  function sha256(value) {
26072
- return createHash12("sha256").update(value).digest("hex");
25908
+ return createHash11("sha256").update(value).digest("hex");
26073
25909
  }
26074
25910
 
26075
25911
  // src/features/magic-context/search.ts
@@ -27458,6 +27294,21 @@ ${hintText}`;
27458
27294
  }
27459
27295
  function clearAutoSearchForSession(_sessionId) {}
27460
27296
 
27297
+ // src/hooks/magic-context/channel2-cycle.ts
27298
+ function rearmChannel2AfterCoverageAdvancingHardFold(input) {
27299
+ if (input.compactionOff || !input.foldExecuted || input.previousCoverage === null || input.currentCoverage === null || input.currentCoverage <= input.previousCoverage) {
27300
+ return false;
27301
+ }
27302
+ return casChannel2NudgeState(input.db, input.sessionId, "delivered", "");
27303
+ }
27304
+ function rearmChannel2AfterMeasuredCollapse(input) {
27305
+ if (!input.baseline.evaluable || input.baseline.generationInvalidated)
27306
+ return false;
27307
+ if (effectiveTailHygiene(input.baseline).u >= CHANNEL1_FLOOR_TOKENS)
27308
+ return false;
27309
+ return casChannel2NudgeState(input.db, input.sessionId, "delivered", "");
27310
+ }
27311
+
27461
27312
  // src/hooks/magic-context/drop-stale-reduce-calls.ts
27462
27313
  var STALE_TOOL_NAMES = new Set(["ctx_reduce"]);
27463
27314
  function isReduceToolPart(part) {
@@ -27535,126 +27386,9 @@ function dropStaleReduceCalls(messages, frozenIds, options = {}) {
27535
27386
  return { didDrop, newlyStrippedIds };
27536
27387
  }
27537
27388
 
27538
- // src/hooks/magic-context/emergency-drop.ts
27539
- var TARGET_FRACTION = 0.3;
27540
- var TIER_RECENCY_RESERVE = 0.2;
27541
- var EMERGENCY_REARM_MIN_TOKENS = 2000;
27542
- var T1_TOOLS = new Set(["read", "todowrite", "task", "aft_outline", "aft_zoom"]);
27543
- var T2_TOOLS = new Set(["edit", "write", "apply_patch", "grep", "glob", "aft_search"]);
27544
- function normalizeToolName(toolName) {
27545
- if (!toolName)
27546
- return "";
27547
- let name = toolName.toLowerCase();
27548
- if (name.startsWith("mcp_"))
27549
- name = name.slice(4);
27550
- return name;
27551
- }
27552
- function resolveToolTier(toolName) {
27553
- const name = normalizeToolName(toolName);
27554
- if (T1_TOOLS.has(name))
27555
- return 1;
27556
- if (T2_TOOLS.has(name))
27557
- return 2;
27558
- return 3;
27559
- }
27560
- function tagReclaimBytes(tag) {
27561
- return tag.byteSize + tag.inputByteSize + tag.reasoningByteSize;
27562
- }
27563
- function estimateEmergencyDropReclaimTokens(tag) {
27564
- return Math.round(tagReclaimBytes(tag) * TOKENS_PER_BYTE);
27565
- }
27566
- function planEmergencyDrop(input) {
27567
- const {
27568
- tags,
27569
- floorTags,
27570
- maxTag,
27571
- protectedTags,
27572
- currentTotalInputTokens,
27573
- ceilingTokens,
27574
- priorInputSample,
27575
- hasPriorDrop
27576
- } = input;
27577
- const noop = (reason) => ({
27578
- shouldDrop: false,
27579
- tagNumbers: [],
27580
- reclaimTokens: 0,
27581
- reason
27582
- });
27583
- if (!Number.isFinite(ceilingTokens) || ceilingTokens <= 0) {
27584
- return noop("unknown-ceiling");
27585
- }
27586
- if (!Number.isFinite(currentTotalInputTokens) || currentTotalInputTokens <= 0) {
27587
- return noop("unknown-usage");
27588
- }
27589
- if (hasPriorDrop && currentTotalInputTokens === priorInputSample) {
27590
- return noop("same-input-sample (awaiting fresh usage after prior drop)");
27591
- }
27592
- let tailTokens = 0;
27593
- for (const tag of floorTags) {
27594
- if (tag.status !== "active")
27595
- continue;
27596
- tailTokens += estimateEmergencyDropReclaimTokens(tag);
27597
- }
27598
- const fixedFloor = Math.max(currentTotalInputTokens - tailTokens, 0);
27599
- const workingSpan = Math.max(ceilingTokens - fixedFloor, 0);
27600
- const target = fixedFloor + TARGET_FRACTION * workingSpan;
27601
- const reclaimTokens = Math.round(currentTotalInputTokens - target);
27602
- if (reclaimTokens <= EMERGENCY_REARM_MIN_TOKENS) {
27603
- return noop(`reclaim<=min (${reclaimTokens} <= ${EMERGENCY_REARM_MIN_TOKENS})`);
27604
- }
27605
- const protectedCutoff = maxTag - protectedTags;
27606
- const tierActive = { 1: [], 2: [] };
27607
- for (const tag of tags) {
27608
- if (tag.status !== "active" || tag.type !== "tool")
27609
- continue;
27610
- const tier = resolveToolTier(tag.toolName);
27611
- if (tier === 1 || tier === 2)
27612
- tierActive[tier].push(tag.tagNumber);
27613
- }
27614
- const reserved = new Set;
27615
- for (const tier of [1, 2]) {
27616
- const nums = tierActive[tier];
27617
- if (nums.length === 0)
27618
- continue;
27619
- nums.sort((a, b) => b - a);
27620
- const reserveCount = Math.ceil(TIER_RECENCY_RESERVE * nums.length);
27621
- for (let i = 0;i < reserveCount && i < nums.length; i++) {
27622
- reserved.add(nums[i]);
27623
- }
27624
- }
27625
- const byTier = { 1: [], 2: [], 3: [] };
27626
- for (const tag of tags) {
27627
- if (tag.status !== "active" || tag.type !== "tool")
27628
- continue;
27629
- if (tag.tagNumber > protectedCutoff)
27630
- continue;
27631
- const tier = resolveToolTier(tag.toolName);
27632
- if ((tier === 1 || tier === 2) && reserved.has(tag.tagNumber))
27633
- continue;
27634
- byTier[tier].push(tag);
27635
- }
27636
- const selected = [];
27637
- let reclaimed = 0;
27638
- outer:
27639
- for (const tier of [3, 2, 1]) {
27640
- const group = byTier[tier];
27641
- group.sort((a, b) => a.tagNumber - b.tagNumber);
27642
- for (const tag of group) {
27643
- selected.push(tag.tagNumber);
27644
- reclaimed += estimateEmergencyDropReclaimTokens(tag);
27645
- if (reclaimed >= reclaimTokens)
27646
- break outer;
27647
- }
27648
- }
27649
- if (selected.length === 0) {
27650
- return noop("no-candidates");
27651
- }
27652
- return {
27653
- shouldDrop: true,
27654
- tagNumbers: selected,
27655
- reclaimTokens,
27656
- reason: `tiered drop: ${selected.length} tags, reclaim≈${reclaimed}/${reclaimTokens} tokens (floor≈${fixedFloor}, ceiling=${Math.round(ceilingTokens)})`
27657
- };
27389
+ // src/hooks/magic-context/fold-execution-gate.ts
27390
+ function foldExecutesThisPass(foldDue, materialized) {
27391
+ return foldDue && materialized;
27658
27392
  }
27659
27393
 
27660
27394
  // src/hooks/magic-context/system-injection-stripper.ts
@@ -28305,6 +28039,7 @@ function planMergedAssistantReasoningStrip(messages, mutationExemptMessage) {
28305
28039
  }
28306
28040
  return plan;
28307
28041
  }
28042
+ var MAX_FROZEN_TRAILING_BLANKS = 1e4;
28308
28043
  var CANONICAL_BLANK_PART = { type: "text", text: "" };
28309
28044
  function isSentinelInvisibleTextPart(part) {
28310
28045
  return isRecord(part) && part.type === "text" && typeof part.text === "string" && part.text.trim() === "";
@@ -28312,18 +28047,37 @@ function isSentinelInvisibleTextPart(part) {
28312
28047
  function isCanonicalBlankPart(part) {
28313
28048
  return isRecord(part) && Object.keys(part).length === 2 && part.type === "text" && part.text === "";
28314
28049
  }
28315
- function findTrailingBlankDecisionCandidates(messages, frozenDecisions) {
28050
+ function trailingBlankKeepCount(decision) {
28051
+ if (decision === "keep")
28052
+ return 1;
28053
+ if (!decision.startsWith("keep:"))
28054
+ return;
28055
+ const countText = decision.slice("keep:".length);
28056
+ if (!/^[1-9]\d*$/.test(countText))
28057
+ return;
28058
+ const count = Number(countText);
28059
+ return Number.isSafeInteger(count) && count > 0 && count <= MAX_FROZEN_TRAILING_BLANKS ? count : undefined;
28060
+ }
28061
+ function findTrailingBlankDecisionCandidates(messages, frozenDecisions, options) {
28316
28062
  const decisions = [];
28317
28063
  for (const message of messages) {
28318
28064
  const id = message.info.id;
28319
- if (message.info.role !== "assistant" || typeof id !== "string" || id.length === 0 || frozenDecisions.has(id)) {
28065
+ if (message.info.role !== "assistant" || typeof id !== "string" || id.length === 0) {
28320
28066
  continue;
28321
28067
  }
28322
- const last = message.parts.at(-1);
28323
- decisions.push([
28324
- id,
28325
- message.parts.length === 0 || isSentinelInvisibleTextPart(last) ? "keep" : "strip"
28326
- ]);
28068
+ let trailingCount = 0;
28069
+ while (trailingCount < message.parts.length && isSentinelInvisibleTextPart(message.parts[message.parts.length - trailingCount - 1])) {
28070
+ trailingCount += 1;
28071
+ }
28072
+ if (trailingCount > MAX_FROZEN_TRAILING_BLANKS && trailingCount < message.parts.length) {
28073
+ continue;
28074
+ }
28075
+ const decision = message.parts.length === 0 || trailingCount === message.parts.length ? "keep" : trailingCount === 0 ? "strip" : trailingCount === 1 ? "keep" : `keep:${trailingCount}`;
28076
+ const frozen = frozenDecisions.get(id);
28077
+ if (frozen !== undefined && (id !== options?.refreshMessageId || frozen === decision)) {
28078
+ continue;
28079
+ }
28080
+ decisions.push([id, decision]);
28327
28081
  }
28328
28082
  return decisions;
28329
28083
  }
@@ -28341,24 +28095,26 @@ function applyFrozenTrailingBlankDecisions(messages, newestAssistantId, frozenDe
28341
28095
  while (lastMeaningfulIndex >= 0 && isSentinelInvisibleTextPart(message.parts[lastMeaningfulIndex])) {
28342
28096
  lastMeaningfulIndex -= 1;
28343
28097
  }
28344
- const replaceParts = (start, deleteCount, insertBlank) => {
28098
+ const replaceParts = (start, deleteCount, insertBlankCount) => {
28345
28099
  message = { ...message, parts: [...message.parts] };
28346
28100
  messages[messageIndex] = message;
28347
- message.parts.splice(start, deleteCount, ...insertBlank ? [{ ...CANONICAL_BLANK_PART }] : []);
28101
+ message.parts.splice(start, deleteCount, ...Array.from({ length: insertBlankCount }, () => ({ ...CANONICAL_BLANK_PART })));
28348
28102
  };
28349
28103
  if (lastMeaningfulIndex < 0) {
28350
28104
  if (message.parts.length !== 1 || !isCanonicalBlankPart(message.parts[0])) {
28351
28105
  mutations += Math.max(1, message.parts.length);
28352
- replaceParts(0, message.parts.length, true);
28106
+ replaceParts(0, message.parts.length, 1);
28353
28107
  }
28354
28108
  continue;
28355
28109
  }
28356
28110
  const trailingCount = message.parts.length - lastMeaningfulIndex - 1;
28357
- if (decision === "keep") {
28111
+ const keepCount = trailingBlankKeepCount(decision);
28112
+ if (keepCount !== undefined) {
28358
28113
  const blankIndex = lastMeaningfulIndex + 1;
28359
- if (trailingCount !== 1 || !isCanonicalBlankPart(message.parts[blankIndex])) {
28360
- mutations += Math.max(1, trailingCount);
28361
- replaceParts(blankIndex, trailingCount, true);
28114
+ const suffixIsCanonical = trailingCount === keepCount && message.parts.slice(blankIndex).every(isCanonicalBlankPart);
28115
+ if (!suffixIsCanonical) {
28116
+ mutations += Math.max(1, trailingCount, keepCount);
28117
+ replaceParts(blankIndex, trailingCount, keepCount);
28362
28118
  }
28363
28119
  continue;
28364
28120
  }
@@ -28369,12 +28125,12 @@ function applyFrozenTrailingBlankDecisions(messages, newestAssistantId, frozenDe
28369
28125
  const blankIndex = lastMeaningfulIndex + 1;
28370
28126
  if (trailingCount !== 1 || !isCanonicalBlankPart(message.parts[blankIndex])) {
28371
28127
  mutations += Math.max(1, trailingCount);
28372
- replaceParts(blankIndex, trailingCount, true);
28128
+ replaceParts(blankIndex, trailingCount, 1);
28373
28129
  }
28374
28130
  continue;
28375
28131
  }
28376
28132
  mutations += trailingCount;
28377
- replaceParts(lastMeaningfulIndex + 1, trailingCount, false);
28133
+ replaceParts(lastMeaningfulIndex + 1, trailingCount, 0);
28378
28134
  }
28379
28135
  return mutations;
28380
28136
  }
@@ -28451,7 +28207,6 @@ function stripProcessedImages(messages, frozenIds, options) {
28451
28207
 
28452
28208
  // src/hooks/magic-context/supersession-reclaim.ts
28453
28209
  var TODOWRITE_KEEP = 1;
28454
- var CTX_REDUCE_KEEP = 5;
28455
28210
  var ZERO_VALUE_META_TOOLS = new Set(["bash_status", "bash_kill"]);
28456
28211
  var CTX_NOTE_ZERO_VALUE_ACTIONS = new Set(["read", "dismiss"]);
28457
28212
  function buildSupersessionReclaimOps(input) {
@@ -29509,7 +29264,7 @@ async function runPostTransformPhase(args) {
29509
29264
  const deferredMaterialize = args.canConsumeDeferredLate && deferredMaterializationWasPending;
29510
29265
  const materializationRequested = isExplicitFlush || deferredMaterialize;
29511
29266
  const m0M1EnabledForFold = args.m0M1 !== undefined && (!!args.m0M1.projectPath || !!args.m0M1.projectDirectory) && (args.fullFeatureMode || compactionOff);
29512
- const m0HardFoldThisPass = m0M1EnabledForFold && args.m0M1 ? mustMaterialize({
29267
+ const foldDueDecision = m0M1EnabledForFold && args.m0M1 ? mustMaterialize({
29513
29268
  db: args.db,
29514
29269
  sessionId: args.sessionId,
29515
29270
  state: args.sessionMeta,
@@ -29520,13 +29275,59 @@ async function runPostTransformPhase(args) {
29520
29275
  memoryInjectionBudgetTokens: args.m0M1.memoryInjectionBudgetTokens,
29521
29276
  historyBudgetTokens: args.m0M1.historyBudgetTokens,
29522
29277
  hardSignals: args.m0M1.hardSignals
29523
- }).value : false;
29524
- const bypassCompartmentGate = forceMaterialization || m0HardFoldThisPass;
29525
- const shouldReadPendingOps = !compactionOff && (materializationRequested || args.schedulerDecision === "execute" || forceMaterialization || m0HardFoldThisPass || compartmentRunning);
29278
+ }) : { value: false, reason: null };
29279
+ let foldExecutedThisPass = false;
29280
+ let m0RematerializedThisPass = false;
29281
+ const m0CoverageBeforeFold = args.sessionMeta.cachedM0Bytes === null ? -1 : args.sessionMeta.cachedM0MaxCompartmentSeq;
29282
+ let m0MaterializeReason = null;
29283
+ let m0ComparisonDecision = null;
29284
+ if (foldDueDecision.value && args.m0M1) {
29285
+ try {
29286
+ const foldResult = injectM0M1({
29287
+ db: args.db,
29288
+ sessionId: args.sessionId,
29289
+ state: args.sessionMeta,
29290
+ projectPath: args.m0M1.projectPath,
29291
+ projectDirectory: args.m0M1.projectDirectory,
29292
+ injectDocs: args.m0M1.injectDocs,
29293
+ memoryInjectionBudgetTokens: args.m0M1.memoryInjectionBudgetTokens,
29294
+ historyBudgetTokens: args.m0M1.historyBudgetTokens,
29295
+ temporalAwareness: args.m0M1.temporalAwareness,
29296
+ isCacheBustingPass: true,
29297
+ hardSignals: args.m0M1.hardSignals,
29298
+ muralEnabled: args.m0M1.muralEnabled,
29299
+ compactionOff
29300
+ });
29301
+ foldExecutedThisPass = foldExecutesThisPass(foldDueDecision.value, foldResult.m0RematerializedThisPass);
29302
+ m0RematerializedThisPass = foldResult.m0RematerializedThisPass;
29303
+ m0MaterializeReason = foldResult.decision.reason;
29304
+ if (foldResult.m0RematerializedThisPass) {
29305
+ m0ComparisonDecision = foldResult.decision;
29306
+ }
29307
+ try {
29308
+ rearmChannel2AfterCoverageAdvancingHardFold({
29309
+ db: args.db,
29310
+ sessionId: args.sessionId,
29311
+ foldExecuted: foldExecutedThisPass,
29312
+ compactionOff,
29313
+ previousCoverage: m0CoverageBeforeFold,
29314
+ currentCoverage: args.sessionMeta.cachedM0MaxCompartmentSeq
29315
+ });
29316
+ } catch (error) {
29317
+ sessionLog(args.sessionId, "channel2 fold-cycle reset failed (ignored):", error);
29318
+ }
29319
+ } catch (error) {
29320
+ args.passOutcome?.record("m0-m1-fold-preexecution-degradation");
29321
+ sessionLog(args.sessionId, "transform: m[0] HARD fold pre-execution failed:", getErrorMessage(error));
29322
+ }
29323
+ sessionLog(args.sessionId, `m[0] HARD fold decision: reason=${foldDueDecision.reason ?? "unknown"} executed=${foldExecutedThisPass}`);
29324
+ }
29325
+ const bypassCompartmentGate = forceMaterialization || foldExecutedThisPass;
29326
+ const shouldReadPendingOps = !compactionOff && (materializationRequested || args.schedulerDecision === "execute" || forceMaterialization || foldExecutedThisPass || compartmentRunning);
29526
29327
  const pendingOps = shouldReadPendingOps ? getPendingOps(args.db, args.sessionId) : [];
29527
29328
  const hasPendingUserOps = pendingOps.length > 0;
29528
- const shouldApplyPendingOps = !compactionOff && (args.schedulerDecision === "execute" || materializationRequested || forceMaterialization || m0HardFoldThisPass) && (!compartmentRunning || bypassCompartmentGate);
29529
- const shouldRunHeuristics = !compactionOff && (!compartmentRunning || bypassCompartmentGate) && (materializationRequested || forceMaterialization || m0HardFoldThisPass || emergencyDropEligible || args.schedulerDecision === "execute" && (!alreadyRanThisTurn || !args.fullFeatureMode));
29329
+ const shouldApplyPendingOps = !compactionOff && (args.schedulerDecision === "execute" || materializationRequested || forceMaterialization || foldExecutedThisPass) && (!compartmentRunning || bypassCompartmentGate);
29330
+ const shouldRunHeuristics = !compactionOff && (!compartmentRunning || bypassCompartmentGate) && (materializationRequested || forceMaterialization || foldExecutedThisPass || emergencyDropEligible || args.schedulerDecision === "execute" && (!alreadyRanThisTurn || !args.fullFeatureMode));
29530
29331
  const isCacheBustingPass = shouldApplyPendingOps || shouldRunHeuristics;
29531
29332
  if (isCacheBustingPass && args.client && args.ctxReduceAvailability.callable && !hasLoggedCtxReducePermissionDeny(args.sessionId)) {
29532
29333
  try {
@@ -29542,7 +29343,7 @@ async function runPostTransformPhase(args) {
29542
29343
  const canUseEmptySentinels = modelAcceptsEmptyContent(args.resolvedProviderID);
29543
29344
  if (shouldRunHeuristics) {
29544
29345
  const subagentRerun = !args.fullFeatureMode && alreadyRanThisTurn && args.schedulerDecision === "execute" && !isExplicitFlush && !forceMaterialization;
29545
- const reason = isExplicitFlush ? "explicit_flush" : deferredMaterialize ? "deferred_materialization" : forceMaterialization ? `force_materialization (${args.contextUsage.percentage.toFixed(1)}% >= ${args.forceMaterializationPercentage}%)` : m0HardFoldThisPass && args.schedulerDecision !== "execute" ? `m0_hard_fold (drain folded into known m[0] bust, scheduler=${args.schedulerDecision})` : subagentRerun ? `scheduler_execute_subagent_rerun (pendingOps=${pendingOps.length}, scheduler=${args.schedulerDecision})` : `scheduler_execute (pendingOps=${pendingOps.length}, scheduler=${args.schedulerDecision})`;
29346
+ const reason = isExplicitFlush ? "explicit_flush" : deferredMaterialize ? "deferred_materialization" : forceMaterialization ? `force_materialization (${args.contextUsage.percentage.toFixed(1)}% >= ${args.forceMaterializationPercentage}%)` : foldExecutedThisPass && args.schedulerDecision !== "execute" ? `m0_hard_fold (drain folded into executed m[0] bust, scheduler=${args.schedulerDecision})` : subagentRerun ? `scheduler_execute_subagent_rerun (pendingOps=${pendingOps.length}, scheduler=${args.schedulerDecision})` : `scheduler_execute (pendingOps=${pendingOps.length}, scheduler=${args.schedulerDecision})`;
29546
29347
  sessionLog(args.sessionId, `heuristics WILL RUN — reason=${reason}, context=${args.contextUsage.percentage.toFixed(1)}%, turn=${args.currentTurnId}`);
29547
29348
  }
29548
29349
  if (alreadyRanThisTurn && args.schedulerDecision === "execute" && !materializationRequested && args.fullFeatureMode) {
@@ -29566,8 +29367,6 @@ async function runPostTransformPhase(args) {
29566
29367
  const droppedTokens = 0;
29567
29368
  let emergencyReclaimedTokens = 0;
29568
29369
  let emergency = false;
29569
- let m0RematerializedThisPass = false;
29570
- let m0MaterializeReason = null;
29571
29370
  let m0M1InjectedThisPass = false;
29572
29371
  let prependedMessageCount = 0;
29573
29372
  const reasoningMutatedMessages = new Set;
@@ -29583,7 +29382,7 @@ async function runPostTransformPhase(args) {
29583
29382
  let autoReclaimDidMutateThisPass = false;
29584
29383
  try {
29585
29384
  if (shouldApplyPendingOps) {
29586
- const applyReason = isExplicitFlush ? "explicit_flush" : deferredMaterialize ? "deferred_materialization" : `scheduler_execute (scheduler=${args.schedulerDecision})`;
29385
+ const applyReason = isExplicitFlush ? "explicit_flush" : deferredMaterialize ? "deferred_materialization" : foldExecutedThisPass && args.schedulerDecision !== "execute" ? `m0_hard_fold (drain folded into executed m[0] bust, scheduler=${args.schedulerDecision})` : `scheduler_execute (scheduler=${args.schedulerDecision})`;
29587
29386
  sessionLog(args.sessionId, `pending ops WILL APPLY — reason=${applyReason}, pendingOps=${pendingOps.length}, context=${args.contextUsage.percentage.toFixed(1)}%`);
29588
29387
  const tApply = performance.now();
29589
29388
  pendingOpsDidMutate = applyPendingOperations(args.sessionId, args.db, args.targets, args.protectedTags, undefined, pendingOps);
@@ -29800,6 +29599,9 @@ async function runPostTransformPhase(args) {
29800
29599
  prependedMessageCount += result.prependedMessageCount;
29801
29600
  m0RematerializedThisPass ||= result.m0RematerializedThisPass;
29802
29601
  m0MaterializeReason = result.decision.reason ?? m0MaterializeReason;
29602
+ if (result.m0RematerializedThisPass) {
29603
+ m0ComparisonDecision = result.decision;
29604
+ }
29803
29605
  sessionLog(args.sessionId, `transform: injected m[0]/m[1] (rematerialized=${result.m0RematerializedThisPass}, reason=${result.decision.reason ?? "cache_hit"})`);
29804
29606
  }
29805
29607
  } catch (error) {
@@ -30081,6 +29883,7 @@ async function runPostTransformPhase(args) {
30081
29883
  sessionLog(args.sessionId, "transform failed loading trailing blank decisions:", error);
30082
29884
  }
30083
29885
  }
29886
+ const newestAssistantId = typeof reasoningMutationExemptMessage?.info.id === "string" ? reasoningMutationExemptMessage.info.id : undefined;
30084
29887
  const tFinalRepresentation = performance.now();
30085
29888
  const finalRepresentation = finalizeMessageRepresentation(args.messages, args.resolvedProviderID, {
30086
29889
  prependedMessageCount,
@@ -30091,11 +29894,14 @@ async function runPostTransformPhase(args) {
30091
29894
  skipMergedReasoningStrip: compactionOff,
30092
29895
  skipTrailingWhitespaceStrip: compactionOff
30093
29896
  });
30094
- if (canUseEmptySentinels && !compactionOff && isCacheBustingPass) {
30095
- const candidates = findTrailingBlankDecisionCandidates(args.messages, trailingBlankDecisions);
29897
+ if (canUseEmptySentinels && !compactionOff) {
29898
+ const detectedCandidates = findTrailingBlankDecisionCandidates(args.messages, trailingBlankDecisions, { refreshMessageId: newestAssistantId });
29899
+ const candidates = isCacheBustingPass ? detectedCandidates : detectedCandidates.filter(([id]) => id === newestAssistantId);
30096
29900
  if (candidates.length > 0) {
30097
29901
  try {
30098
- const persisted = addTrailingBlankDecisions(args.db, args.sessionId, candidates);
29902
+ const persisted = addTrailingBlankDecisions(args.db, args.sessionId, candidates, {
29903
+ overwriteMessageId: newestAssistantId
29904
+ });
30099
29905
  if (persisted) {
30100
29906
  const committed = getTrailingBlankDecisions(args.db, args.sessionId);
30101
29907
  const newlyFrozen = new Map;
@@ -30106,8 +29912,9 @@ async function runPostTransformPhase(args) {
30106
29912
  trailingBlankDecisions.set(id, decision);
30107
29913
  newlyFrozen.set(id, decision);
30108
29914
  }
30109
- applyFrozenTrailingBlankDecisions(args.messages, typeof reasoningMutationExemptMessage?.info.id === "string" ? reasoningMutationExemptMessage.info.id : undefined, newlyFrozen);
30110
- bustedThisPass = true;
29915
+ applyFrozenTrailingBlankDecisions(args.messages, newestAssistantId, newlyFrozen);
29916
+ if (isCacheBustingPass)
29917
+ bustedThisPass = true;
30111
29918
  } else {
30112
29919
  args.passOutcome?.record("trailing-blank-decision-persistence-failure");
30113
29920
  sessionLog(args.sessionId, "trailing blank decision: persistence failed; leaving newly observed assistants intact");
@@ -30120,12 +29927,80 @@ async function runPostTransformPhase(args) {
30120
29927
  }
30121
29928
  sessionLog(args.sessionId, `final representation: clearedParts=${finalRepresentation.clearedParts} mergedReasoningParts=${finalRepresentation.mergedReasoningParts}`);
30122
29929
  logTransformTiming(args.sessionId, "finalizeMessageRepresentation", tFinalRepresentation, `clearedParts=${finalRepresentation.clearedParts} mergedReasoningParts=${finalRepresentation.mergedReasoningParts}`);
29930
+ let assertedBaseline;
29931
+ if (args.channel1StateBySession) {
29932
+ if (args.ctxReduceAvailability.callable && !compactionOff) {
29933
+ try {
29934
+ const tags = getTailHygieneTags(args.db, args.sessionId);
29935
+ const previous = args.channel1StateBySession.get(args.sessionId);
29936
+ const baseline = refreshTailHygieneBaseline({
29937
+ messages: args.messages,
29938
+ tags,
29939
+ protectedTags: args.protectedTags,
29940
+ cacheBusting: bustedThisPass,
29941
+ previous
29942
+ });
29943
+ const structuralSignature = tailHygieneStructuralSignature(args.messages);
29944
+ args.channel1StateBySession.set(args.sessionId, {
29945
+ ...baseline,
29946
+ reducedSinceRefresh: baseline.baselineGeneration !== previous?.baselineGeneration ? false : previous?.reducedSinceRefresh ?? false,
29947
+ oldestReclaimableToolTags: getOldestActiveUnprotectedToolTags(args.db, args.sessionId, args.protectedTags)
29948
+ });
29949
+ try {
29950
+ rearmChannel2AfterMeasuredCollapse({
29951
+ db: args.db,
29952
+ sessionId: args.sessionId,
29953
+ baseline
29954
+ });
29955
+ } catch (error) {
29956
+ sessionLog(args.sessionId, "channel2 U-collapse reset failed (ignored):", error);
29957
+ }
29958
+ assertedBaseline = {
29959
+ tags,
29960
+ protectedTags: args.protectedTags,
29961
+ contentSignature: baseline.contentSignature,
29962
+ structuralSignature
29963
+ };
29964
+ } catch (error) {
29965
+ const stale = args.channel1StateBySession.get(args.sessionId);
29966
+ if (stale) {
29967
+ stale.evaluable = false;
29968
+ stale.generationInvalidated = true;
29969
+ }
29970
+ sessionLog(args.sessionId, "tail hygiene baseline refresh failed (held):", error);
29971
+ }
29972
+ } else {
29973
+ args.channel1StateBySession.delete(args.sessionId);
29974
+ }
29975
+ }
29976
+ if (assertedBaseline) {
29977
+ try {
29978
+ const servedSignature = tailHygieneStructuralSignature(args.messages);
29979
+ if (!sameTailHygieneStructuralSignature(assertedBaseline.structuralSignature, servedSignature)) {
29980
+ sessionLog(args.sessionId, `ERROR [tail-hygiene-last-writer-mismatch]: served messages changed after tail-hygiene baseline refresh (expected messages=${assertedBaseline.structuralSignature.messageCount}, parts=[${assertedBaseline.structuralSignature.partCounts.join(",")}], bytes=${assertedBaseline.structuralSignature.totalBytes}; actual messages=${servedSignature.messageCount}, parts=[${servedSignature.partCounts.join(",")}], bytes=${servedSignature.totalBytes})`);
29981
+ }
29982
+ } catch (error) {
29983
+ sessionLog(args.sessionId, "ERROR [tail-hygiene-last-writer-check-failed]: structural production guard failed open:", error);
29984
+ }
29985
+ if (true) {
29986
+ assertTailHygieneContentUnchanged({
29987
+ messages: args.messages,
29988
+ tags: assertedBaseline.tags,
29989
+ protectedTags: assertedBaseline.protectedTags,
29990
+ expectedSignature: assertedBaseline.contentSignature
29991
+ });
29992
+ }
29993
+ }
30123
29994
  return {
30124
29995
  explicitMaterializedSuccessfully,
30125
29996
  deferredMaterializedSuccessfully,
30126
29997
  materialized,
30127
29998
  historianFoldMaterializedThisPass: historyWasConsumedThisPass,
30128
29999
  materializeReason,
30000
+ systemHashPrev: m0RematerializedThisPass ? m0ComparisonDecision?.systemHashPrev ?? null : null,
30001
+ systemHashNew: m0RematerializedThisPass ? m0ComparisonDecision?.systemHashNew ?? null : null,
30002
+ m0ModelKeyPrev: m0RematerializedThisPass ? m0ComparisonDecision?.m0ModelKeyPrev ?? null : null,
30003
+ m0ModelKeyNew: m0RematerializedThisPass ? m0ComparisonDecision?.m0ModelKeyNew ?? null : null,
30129
30004
  droppedTokens,
30130
30005
  emergencyReclaimedTokens,
30131
30006
  droppedCount,
@@ -30341,10 +30216,10 @@ function messageCacheSignature(message) {
30341
30216
  const parts = Array.isArray(message.parts) ? message.parts : [];
30342
30217
  const serializedParts = JSON.stringify(parts) ?? "null";
30343
30218
  const serializedMessage = JSON.stringify(message) ?? "null";
30344
- return `${messageIdOf(message) ?? ""}:${parts.length}:${Buffer.byteLength(serializedParts)}:${createHash13("sha256").update(serializedMessage).digest("hex")}`;
30219
+ return `${messageIdOf(message) ?? ""}:${parts.length}:${Buffer.byteLength(serializedParts)}:${createHash12("sha256").update(serializedMessage).digest("hex")}`;
30345
30220
  }
30346
30221
  function advanceWireFingerprint(previous, encoded) {
30347
- return createHash13("sha256").update(previous).update("\\0").update(JSON.stringify(encoded) ?? "null").digest("hex");
30222
+ return createHash12("sha256").update(previous).update("\\0").update(JSON.stringify(encoded) ?? "null").digest("hex");
30348
30223
  }
30349
30224
  function buildWireFingerprint(encoded) {
30350
30225
  let fingerprint = "rust-wire-v1";
@@ -30603,7 +30478,7 @@ function canonicalizeForChecksum(value) {
30603
30478
  return Object.fromEntries(Object.keys(value).sort().map((key) => [key, canonicalizeForChecksum(value[key])]));
30604
30479
  }
30605
30480
  function checksumSeedRows(rows) {
30606
- return createHash13("sha256").update(JSON.stringify(rows.map(canonicalizeForChecksum))).digest("hex");
30481
+ return createHash12("sha256").update(JSON.stringify(rows.map(canonicalizeForChecksum))).digest("hex");
30607
30482
  }
30608
30483
  function authoritySeedRows(db, projectPath, domain) {
30609
30484
  const snapshots = domain === "memories" ? db.prepare("SELECT * FROM memories WHERE project_path = ? ORDER BY id ASC").all(projectPath) : db.prepare(`SELECT n.*
@@ -30773,7 +30648,14 @@ function mirrorRustSyntheticTodoAnchor(args) {
30773
30648
  clearPersistedTodoSyntheticAnchor(args.db, args.sessionId);
30774
30649
  }
30775
30650
  }
30776
- function applyNativeMessagesVerbatim(output, response) {
30651
+ function hasNativeResponseContent(response) {
30652
+ if (typeof response.native_messages === "string" || Array.isArray(response.native_messages)) {
30653
+ return true;
30654
+ }
30655
+ const delta = response.native_messages_delta;
30656
+ return isRecord3(delta) && Array.isArray(delta.messages);
30657
+ }
30658
+ function applyNativeMessagesVerbatim(output, response, previous) {
30777
30659
  const nativeMessages = response.native_messages;
30778
30660
  if (typeof nativeMessages === "string") {
30779
30661
  const parsed = JSON.parse(nativeMessages);
@@ -30781,10 +30663,21 @@ function applyNativeMessagesVerbatim(output, response) {
30781
30663
  throw new Error("rust transform native_messages string was not an array");
30782
30664
  return replaceMessagesInPlace(output, parsed);
30783
30665
  }
30784
- if (!Array.isArray(nativeMessages)) {
30666
+ if (Array.isArray(nativeMessages)) {
30667
+ return replaceMessagesInPlace(output, nativeMessages);
30668
+ }
30669
+ const delta = response.native_messages_delta;
30670
+ if (!isRecord3(delta) || !Array.isArray(delta.messages)) {
30785
30671
  throw new Error("rust transform response omitted native_messages");
30786
30672
  }
30787
- return replaceMessagesInPlace(output, nativeMessages);
30673
+ const replaceFrom = delta.replace_from;
30674
+ if (!previous || delta.after !== previous.fingerprint || typeof replaceFrom !== "number" || !Number.isSafeInteger(replaceFrom) || replaceFrom < 0 || replaceFrom > previous.messages.length) {
30675
+ throw new Error("rust transform native_messages_delta did not match the acknowledged output");
30676
+ }
30677
+ return replaceMessagesInPlace(output, [
30678
+ ...previous.messages.slice(0, replaceFrom),
30679
+ ...delta.messages
30680
+ ]);
30788
30681
  }
30789
30682
  function muralInputForWire(mural) {
30790
30683
  if (!mural?.enabled || !mural.supportsVision || typeof mural.dataUrl !== "string" || mural.dataUrl.length === 0) {
@@ -30988,14 +30881,13 @@ function createRustModeTransform(deps, options) {
30988
30881
  sessionLog(sessionId, "lkg_replay_served");
30989
30882
  return true;
30990
30883
  };
30991
- const prepareRustCapture = (state, sessionId, input, inputSnapshots, response, responseRowVersion) => {
30884
+ const prepareRustCapture = (state, sessionId, input, inputSnapshots, nativeMessages, responseRowVersion) => {
30992
30885
  state.lkgCaptureSequence += 1;
30993
30886
  const inputIds = input.map((message) => message.info.id);
30994
30887
  if (inputIds.some((id) => typeof id !== "string") || new Set(inputIds).size !== inputIds.length || inputIds.length === 0 || inputSnapshots.length !== inputIds.length) {
30995
30888
  return null;
30996
30889
  }
30997
- const native = response.native_messages;
30998
- const jsonPrefix = typeof native === "string" ? native : JSON.stringify(native);
30890
+ const jsonPrefix = JSON.stringify(nativeMessages);
30999
30891
  if (typeof jsonPrefix !== "string")
31000
30892
  return null;
31001
30893
  const keys = resolveLkgModelKeys(input);
@@ -31166,7 +31058,7 @@ function createRustModeTransform(deps, options) {
31166
31058
  const value = timings2[name];
31167
31059
  return typeof value === "number" && Number.isFinite(value) ? value.toFixed(1) : "n/a";
31168
31060
  };
31169
- 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")}`);
31061
+ sessionLog(sessionId, `rust module stages: handler=${stage("handler_total")} apply_once=${stage("total")} ` + `request_to_handler=${stage("request_observed_to_handler")} delta_expand=${stage("delta_expand")} ` + `projection_cache_lookup=${stage("projection_cache_lookup")} projection=${stage("projection")} ` + `selection=${stage("selection")} build_output=${stage("build_output")} ` + `store_commit=${stage("store_commit")} trigger=${stage("trigger_ms")} ` + `trigger_boundary=${stage("trigger_boundary_build")} trigger_eval=${stage("trigger_eval")} ` + `projection_cache_store=${stage("projection_cache_store")} native_attach=${stage("native_attach")} ` + `retained_size=${stage("retained_size")} snapshot_store=${stage("snapshot_store")} ` + `post_attach=${stage("post_attach")} response_encode=${stage("response_encode")} ` + `response_meta_encode=${stage("response_meta_encode")} response_splice=${stage("response_splice")} ` + `native_cache_reused=${stage("native_cache_reused_messages")} ` + `native_cache_encoded=${stage("native_cache_encoded_messages")}`);
31170
31062
  }
31171
31063
  if (timings2 && moduleElapsedMs >= 1000) {
31172
31064
  const detail = Object.entries(timings2).filter(([key, value]) => key !== "total" && key !== "handler_total" && typeof value === "number").map(([key, value]) => `${key}:${value.toFixed(1)}`).join(" ");
@@ -31542,8 +31434,14 @@ function createRustModeTransform(deps, options) {
31542
31434
  let response = await sendTransformSeriesWithSingleRestart(body);
31543
31435
  let servedFinalWireEstimate;
31544
31436
  captureResponseTelemetry(response);
31545
- if (isNeedFullSync(response)) {
31546
- options.moduleClient.invalidateStateSyncCapabilities?.();
31437
+ const needFullSync = isNeedFullSync(response);
31438
+ const nativeContentOmitted = !hasNativeResponseContent(response);
31439
+ if (needFullSync || nativeContentOmitted) {
31440
+ if (needFullSync) {
31441
+ options.moduleClient.invalidateStateSyncCapabilities?.();
31442
+ } else {
31443
+ sessionLog(sessionId, "native_delta_fallback_reason=adapter_response_omitted_native_content retry=full");
31444
+ }
31547
31445
  state.forceFullWire = true;
31548
31446
  if (wireDelta) {
31549
31447
  const retryOrdinalStartedAt = performance.now();
@@ -31629,6 +31527,9 @@ function createRustModeTransform(deps, options) {
31629
31527
  if (isNeedFullSync(response)) {
31630
31528
  throw new Error("rust module still requires full sync after a full-array send");
31631
31529
  }
31530
+ if (!hasNativeResponseContent(response)) {
31531
+ throw new Error("rust module omitted native content after a full-array retry");
31532
+ }
31632
31533
  }
31633
31534
  const deliveryPassIds = noteDeliveryPassIds(response);
31634
31535
  const sendNoteDeliveryDisposition = async (method) => {
@@ -31652,7 +31553,11 @@ function createRustModeTransform(deps, options) {
31652
31553
  let appliedMessages;
31653
31554
  const applyStartedAt = performance.now();
31654
31555
  try {
31655
- appliedMessages = applyNativeMessagesVerbatim({ messages: [] }, response);
31556
+ appliedMessages = applyNativeMessagesVerbatim({ messages: [] }, response, previousWireCache?.nativeOutput ? {
31557
+ messages: previousWireCache.nativeOutput,
31558
+ fingerprint: previousWireCache.fingerprint
31559
+ } : undefined);
31560
+ pendingWireCache.nativeOutput = appliedMessages;
31656
31561
  runRustModePostprocess({
31657
31562
  db: deps.db,
31658
31563
  sessionId,
@@ -31689,7 +31594,7 @@ function createRustModeTransform(deps, options) {
31689
31594
  if (cacheBustingPass) {
31690
31595
  dropSlot(sessionId, "lkg_cache_bust_pending_capture");
31691
31596
  }
31692
- const capturePlan = prepareRustCapture(state, sessionId, messages, pendingWireCache.rawContentSnapshots, response, rowVersion);
31597
+ const capturePlan = prepareRustCapture(state, sessionId, messages, pendingWireCache.rawContentSnapshots, appliedMessages, rowVersion);
31693
31598
  let captureMode = "async";
31694
31599
  const captureFailed = (mode, error) => {
31695
31600
  if (states.get(sessionId) !== state || capturePlan && capturePlan.captureSequence !== state.lkgCaptureSequence) {
@@ -31801,35 +31706,39 @@ function createRustModeTransform(deps, options) {
31801
31706
  }
31802
31707
  wireCaches.set(sessionId, pendingWireCache);
31803
31708
  appliedAt = performance.now();
31804
- if (options.moduleClient.mirrorPull) {
31805
- const mirrorPullStartedAt = performance.now();
31806
- try {
31807
- await pullMemoryMirrorOnce({
31808
- db: deps.db,
31809
- module: options.moduleClient
31810
- });
31811
- } catch (error) {
31812
- sessionLog(sessionId, "rust memory mirror-back failed (ignored):", error);
31813
- } finally {
31814
- logStage(sessionId, "mirrorPull", mirrorPullStartedAt, timings);
31815
- }
31816
- }
31817
31709
  const getCompartmentsAfter = options.moduleClient.getCompartmentsAfter;
31818
- if (getCompartmentsAfter) {
31819
- const compartmentMirrorStartedAt = performance.now();
31820
- try {
31821
- await mirrorModuleCompartments({
31822
- db: deps.db,
31823
- sessionId,
31824
- reader: {
31825
- getCompartmentsAfter: (mirroredSessionId, afterSequence) => getCompartmentsAfter.call(options.moduleClient, mirroredSessionId, afterSequence)
31710
+ if (options.moduleClient.mirrorPull || getCompartmentsAfter) {
31711
+ (async () => {
31712
+ if (options.moduleClient.mirrorPull) {
31713
+ const mirrorPullStartedAt = performance.now();
31714
+ try {
31715
+ await pullMemoryMirrorOnce({
31716
+ db: deps.db,
31717
+ module: options.moduleClient
31718
+ });
31719
+ } catch (error) {
31720
+ sessionLog(sessionId, "rust memory mirror-back failed (ignored):", error);
31721
+ } finally {
31722
+ logStage(sessionId, "mirrorPull", mirrorPullStartedAt, timings);
31826
31723
  }
31827
- });
31828
- } catch (error) {
31829
- sessionLog(sessionId, "rust compartment mirror-back failed (ignored):", error);
31830
- } finally {
31831
- logStage(sessionId, "compartmentMirror", compartmentMirrorStartedAt, timings);
31832
- }
31724
+ }
31725
+ if (getCompartmentsAfter) {
31726
+ const compartmentMirrorStartedAt = performance.now();
31727
+ try {
31728
+ await mirrorModuleCompartments({
31729
+ db: deps.db,
31730
+ sessionId,
31731
+ reader: {
31732
+ getCompartmentsAfter: (mirroredSessionId, afterSequence) => getCompartmentsAfter.call(options.moduleClient, mirroredSessionId, afterSequence)
31733
+ }
31734
+ });
31735
+ } catch (error) {
31736
+ sessionLog(sessionId, "rust compartment mirror-back failed (ignored):", error);
31737
+ } finally {
31738
+ logStage(sessionId, "compartmentMirror", compartmentMirrorStartedAt, timings);
31739
+ }
31740
+ }
31741
+ })();
31833
31742
  }
31834
31743
  finishPass(true);
31835
31744
  } catch (error) {
@@ -32888,6 +32797,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
32888
32797
  messageTagNumbers,
32889
32798
  tagger: deps.tagger,
32890
32799
  ctxReduceAvailability,
32800
+ channel1StateBySession: deps.channel1StateBySession,
32891
32801
  todowriteAvailability,
32892
32802
  client: deps.client,
32893
32803
  activeAgent,
@@ -33029,6 +32939,10 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
33029
32939
  decision: schedulerDecision,
33030
32940
  materialized: postTransformResult.materialized,
33031
32941
  materializeReason: normalizeMaterializeReason("opencode", postTransformResult.materializeReason, postTransformResult.materialized),
32942
+ systemHashPrev: postTransformResult.systemHashPrev,
32943
+ systemHashNew: postTransformResult.systemHashNew,
32944
+ m0ModelKeyPrev: postTransformResult.m0ModelKeyPrev,
32945
+ m0ModelKeyNew: postTransformResult.m0ModelKeyNew,
33032
32946
  emergency: postTransformResult.emergency,
33033
32947
  droppedTokens: postTransformResult.droppedTokens,
33034
32948
  droppedCount: postTransformResult.droppedCount,
@@ -33080,59 +32994,22 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
33080
32994
  sessionLog(sessionId, "conversation_tokens UPDATE failed:", error);
33081
32995
  }
33082
32996
  }
33083
- if (ctxReduceCallable && !compactionOff && deps.channel1StateBySession) {
33084
- try {
33085
- const resolvedExecuteThresholdPct = resolveExecuteThreshold(deps.executeThresholdPercentage ?? 65, deps.getModelKey?.(sessionId), 65, {
33086
- tokensConfig: deps.executeThresholdTokens,
33087
- contextLimit: resolvedContextLimit ?? 0
33088
- });
33089
- let tailToolTokens;
33090
- let liveTailTokens;
32997
+ const channelBaseline = deps.channel1StateBySession?.get(sessionId);
32998
+ if (ctxReduceCallable && !compactionOff && channelBaseline) {
32999
+ const measuredU = Math.min(Math.max(0, channelBaseline.baselineT + channelBaseline.turnDeltaT), Math.max(0, channelBaseline.baselineU + channelBaseline.turnDeltaU));
33000
+ resetLastNudgeCycleIfTailShrank(db, sessionId, measuredU);
33001
+ if (channelBaseline.evaluable && !channelBaseline.generationInvalidated && !channelBaseline.reducedSinceRefresh) {
33002
+ const channel2Evaluation = evaluateChannel2(channelBaseline);
33091
33003
  try {
33092
- const agg = getActiveTagTokenAggregate(db, sessionId, deps.protectedTags);
33093
- tailToolTokens = agg.toolOutput;
33094
- liveTailTokens = agg.conversation + agg.toolCall;
33095
- } catch {
33096
- const estimate = computeTailTokenEstimate(messages);
33097
- tailToolTokens = estimate.tailToolTokens;
33098
- liveTailTokens = estimate.liveTailTokens;
33099
- }
33100
- const executeThresholdTokens = Math.round((resolvedContextLimit ?? 0) * resolvedExecuteThresholdPct / 100);
33101
- const usableTokens = Math.max(0, executeThresholdTokens - contextUsage.inputTokens + liveTailTokens);
33102
- resetLastNudgeCycleIfTailShrank(db, sessionId, tailToolTokens);
33103
- const oldestReclaimableToolTags = getOldestActiveUnprotectedToolTags(db, sessionId, deps.protectedTags);
33104
- deps.channel1StateBySession.set(sessionId, {
33105
- tailToolTokens,
33106
- historyBudgetTokens: historyBudgetTokens ?? 0,
33107
- contextLimit: resolvedContextLimit ?? 0,
33108
- executeThresholdPercentage: resolvedExecuteThresholdPct,
33109
- lastInputTokens: contextUsage.inputTokens,
33110
- turnToolTokens: 0,
33111
- usableTokens,
33112
- reducedSinceRefresh: false,
33113
- oldestReclaimableToolTags
33114
- });
33115
- const channel2MetricsKnown = resolvedContextLimit !== undefined && resolvedContextLimit > 0 && resolvedExecuteThresholdPct > 0;
33116
- if (channel2MetricsKnown) {
33117
- const channel2ShouldTrigger = shouldTriggerChannel2({
33118
- reclaimableTokens: tailToolTokens,
33119
- usableTokens
33120
- });
33121
- try {
33122
- if (channel2ShouldTrigger) {
33123
- casChannel2NudgeState(db, sessionId, "", "pending");
33124
- } else {
33125
- casChannel2NudgeState(db, sessionId, "pending", "");
33126
- }
33127
- } catch (error) {
33128
- sessionLog(sessionId, "channel2 trigger CAS failed (ignored):", error);
33004
+ if (channel2Evaluation.shouldTrigger) {
33005
+ casChannel2NudgeState(db, sessionId, "", "pending");
33006
+ } else {
33007
+ casChannel2NudgeState(db, sessionId, "pending", "");
33129
33008
  }
33009
+ } catch (error) {
33010
+ sessionLog(sessionId, "channel2 trigger CAS failed (ignored):", error);
33130
33011
  }
33131
- } catch (error) {
33132
- sessionLog(sessionId, "channel1 baseline snapshot failed (ignored):", error);
33133
33012
  }
33134
- } else {
33135
- deps.channel1StateBySession?.delete(sessionId);
33136
33013
  }
33137
33014
  const elapsed = (performance.now() - startTime).toFixed(1);
33138
33015
  sessionLog(sessionId, `transform completed in ${elapsed}ms (${messages.length} messages, ${targets.size} targets, watermark: ${watermark})`);
@@ -33190,8 +33067,7 @@ async function deliverChannel2IfPending(deps, sessionId) {
33190
33067
  db: deps.db,
33191
33068
  client: deps.client,
33192
33069
  directiveText: deps.channel2DirectiveTextBySession?.get(sessionId),
33193
- reclaimableTokens: baseline ? baseline.tailToolTokens + baseline.turnToolTokens : undefined,
33194
- usableTokens: baseline?.usableTokens,
33070
+ baseline,
33195
33071
  oldestReclaimableToolTags: baseline?.oldestReclaimableToolTags
33196
33072
  });
33197
33073
  if (delivered || getChannel2NudgeState(deps.db, sessionId) !== "pending") {
@@ -34000,6 +33876,23 @@ function clearSidebarSnapshotCache(sessionId) {
34000
33876
  cache.delete(sessionId);
34001
33877
  }
34002
33878
 
33879
+ // src/hooks/magic-context/empty-task-output.ts
33880
+ var EMPTY_TASK_OUTPUT_SENTINEL = "<magic-context-empty-task-output>";
33881
+ var EMPTY_COMPLETED_TASK_RESULT = /^<task\b[^>]*\bstate="completed"[^>]*>[\s\S]*<task_result>\s*<\/task_result>\s*<\/task>\s*$/;
33882
+ function annotateEmptyTaskOutput(tool, output) {
33883
+ if (tool !== "task" || !isRecord(output))
33884
+ return;
33885
+ if (typeof output.output !== "string")
33886
+ return;
33887
+ if (output.output.includes(EMPTY_TASK_OUTPUT_SENTINEL))
33888
+ return;
33889
+ if (!EMPTY_COMPLETED_TASK_RESULT.test(output.output))
33890
+ return;
33891
+ Reflect.set(output, "output", `${output.output}
33892
+ ${EMPTY_TASK_OUTPUT_SENTINEL}
33893
+ The subagent completed without a final text response. Context-fill truncation may have omitted its final output, or its provider may have emitted reasoning only; inspect the child session and retry with a low-reasoning model or variant.`);
33894
+ }
33895
+
34003
33896
  // src/hooks/magic-context/hook-handlers.ts
34004
33897
  function getLiveNotificationParams(sessionId, liveModelBySession, variantBySession, agentBySession, toastDurationMs) {
34005
33898
  const model = liveModelBySession.get(sessionId);
@@ -34133,26 +34026,19 @@ function maybeInjectChannel1Nudge(args, sessionId, tool, output) {
34133
34026
  return;
34134
34027
  if (out.output.includes(CHANNEL1_SENTINEL))
34135
34028
  return;
34136
- const thisTurnTokens = toolOutputTokens(out.output);
34137
- state.turnToolTokens += thisTurnTokens;
34029
+ state.turnDeltaT += toolOutputTokens(out.output);
34138
34030
  if (state.reducedSinceRefresh)
34139
34031
  return;
34140
- const undroppedTokens = state.tailToolTokens + state.turnToolTokens;
34141
- const pressure = computePressure({
34142
- lastInputTokens: state.lastInputTokens,
34143
- turnToolTokens: state.turnToolTokens,
34144
- contextLimit: state.contextLimit,
34145
- executeThresholdPercentage: state.executeThresholdPercentage
34146
- });
34147
- const workingWindowTokens = Math.round(state.contextLimit * state.executeThresholdPercentage / 100);
34148
34032
  const decision = decideChannel1({
34149
- undroppedTokens,
34150
- pressure,
34151
- estimatedInputTokens: state.lastInputTokens + state.turnToolTokens,
34152
- workingWindowTokens,
34033
+ baselineU: state.baselineU,
34034
+ baselineT: state.baselineT,
34035
+ turnDeltaU: state.turnDeltaU,
34036
+ turnDeltaT: state.turnDeltaT,
34153
34037
  lastNudgeUndropped: getLastNudgeUndropped(args.db, sessionId),
34154
34038
  lastNudgeLevel: getLastNudgeLevel(args.db, sessionId),
34155
- hasRecentReduce: false
34039
+ hasRecentReduce: false,
34040
+ evaluable: state.evaluable,
34041
+ generationInvalidated: state.generationInvalidated
34156
34042
  });
34157
34043
  setLastNudgeUndropped(args.db, sessionId, decision.nextLastNudge);
34158
34044
  setLastNudgeLevel(args.db, sessionId, decision.nextLastNudgeLevel);
@@ -34168,10 +34054,14 @@ function createToolExecuteAfterHook(args) {
34168
34054
  return;
34169
34055
  }
34170
34056
  await flushIgnoredMessages(typedInput.sessionID);
34057
+ annotateEmptyTaskOutput(typedInput.tool, output);
34171
34058
  if (typedInput.tool === "ctx_reduce") {
34172
34059
  const state = args.channel1StateBySession.get(typedInput.sessionID);
34173
- if (state)
34060
+ if (state) {
34174
34061
  state.reducedSinceRefresh = true;
34062
+ state.evaluable = false;
34063
+ state.generationInvalidated = true;
34064
+ }
34175
34065
  try {
34176
34066
  resetLastNudgeCycle(args.db, typedInput.sessionID);
34177
34067
  } catch (error) {
@@ -34237,7 +34127,7 @@ function createToolExecuteAfterHook(args) {
34237
34127
  }
34238
34128
 
34239
34129
  // src/hooks/magic-context/system-prompt-hash.ts
34240
- import { createHash as createHash14 } from "node:crypto";
34130
+ import { createHash as createHash13 } from "node:crypto";
34241
34131
 
34242
34132
  // src/agents/magic-context-prompt.ts
34243
34133
  var LONG_TERM_PARTNER_FRAME = `### You are the user's long-term partner on this project — not a one-off hire
@@ -34396,6 +34286,9 @@ Prefer many small targeted operations over one large blanket operation, and keep
34396
34286
 
34397
34287
  // src/hooks/magic-context/system-prompt-hash.ts
34398
34288
  var MAGIC_CONTEXT_MARKER = "## Magic Context";
34289
+ var SYSTEM_PROMPT_GUIDANCE_SEPARATOR = `
34290
+
34291
+ `;
34399
34292
  function clearSystemPromptHashSession(sessionId, handleMaps) {
34400
34293
  handleMaps.stickyDateBySession.delete(sessionId);
34401
34294
  handleMaps.cachedDocsBySession.delete(sessionId);
@@ -34457,7 +34350,7 @@ function createSystemPromptHashHandler(deps) {
34457
34350
  `);
34458
34351
  if (fullPrompt.length > 0 && !fullPrompt.includes(MAGIC_CONTEXT_MARKER) && !skipGuidanceForDisabledSubagent) {
34459
34352
  const guidance = buildMagicContextSection(null, deps.protectedTags, effectiveCtxReduceEnabled, deps.dreamerEnabled, deps.experimentalTemporalAwareness, deps.experimentalCavemanTextCompression, subagentReduceMode, deps.language, deps.memoryEnabled !== false, promptSurface.preset, promptSurface.primaryOverride);
34460
- output.system.push(guidance);
34353
+ output.system[0] = `${output.system[0]}${SYSTEM_PROMPT_GUIDANCE_SEPARATOR}${guidance}`;
34461
34354
  sessionLog(sessionId, `injected generic guidance into system prompt (ctxReduce=${effectiveCtxReduceEnabled}, subagent=${isSubagentSession2}, subagentReduceMode=${subagentReduceMode})`);
34462
34355
  }
34463
34356
  const isCacheBusting = deps.systemPromptRefreshSessions.has(sessionId);
@@ -34480,7 +34373,7 @@ function createSystemPromptHashHandler(deps) {
34480
34373
  }
34481
34374
  const stickyDate = stickyDateBySession.get(sessionId);
34482
34375
  const stableCandidate = currentDate && stickyDate && currentDate !== stickyDate ? liveSystemContent.replace(DATE_PATTERN_ALL, stickyDate) : liveSystemContent;
34483
- const stableCandidateHash = createHash14("md5").update(promptSurfaceHashMaterial(stableCandidate, promptSurface.preset)).digest("hex");
34376
+ const stableCandidateHash = createHash13("md5").update(promptSurfaceHashMaterial(stableCandidate, promptSurface.preset)).digest("hex");
34484
34377
  const contentOrPresetChanged = hasPersistedHash && stableCandidateHash !== previousHash;
34485
34378
  const dateMayAdvance = isCacheBusting || contentOrPresetChanged;
34486
34379
  if (currentDate && !stickyDate) {
@@ -34500,7 +34393,7 @@ function createSystemPromptHashHandler(deps) {
34500
34393
  `);
34501
34394
  if (!availability.frozen || !modelKey)
34502
34395
  return;
34503
- const currentHash = createHash14("md5").update(promptSurfaceHashMaterial(systemContent, promptSurface.preset)).digest("hex");
34396
+ const currentHash = createHash13("md5").update(promptSurfaceHashMaterial(systemContent, promptSurface.preset)).digest("hex");
34504
34397
  if (!sessionMetaEarly) {
34505
34398
  return;
34506
34399
  }
@@ -34719,7 +34612,7 @@ function createMagicContextHook(deps) {
34719
34612
  log("[magic-context] disabling feature because persistent storage is unavailable:", reason);
34720
34613
  notifyMagicContextDisabled(deps.client, reason);
34721
34614
  const migration = getMigrationOnOpenRefusal();
34722
- const blockingProcesses = migration?.serverPids.map((pid) => ({ harness: "OpenCode server", pid })) ?? [];
34615
+ const blockingProcesses = migration?.blockingProcesses ?? migration?.serverPids.map((pid) => ({ kind: "process", pid })) ?? [];
34723
34616
  const fence = getSchemaFenceRejection();
34724
34617
  recordHookInitFailure({
34725
34618
  type: "storage",
@@ -34795,7 +34688,7 @@ function createMagicContextHook(deps) {
34795
34688
  const internalChildSessions = deps.liveSessionState?.internalChildSessions ?? new Set;
34796
34689
  const recompProgressBySession = deps.liveSessionState?.recompProgressBySession ?? new Map;
34797
34690
  const dreamerProgressByProject = deps.liveSessionState?.dreamerProgressByProject ?? new Map;
34798
- const channel1StateBySession = new Map;
34691
+ const channel1StateBySession = deps.liveSessionState?.channel1StateBySession ?? new Map;
34799
34692
  const channel2DirectiveTextBySession = new Map;
34800
34693
  const resolveLiveModel = (sessionId) => {
34801
34694
  const cached = liveModelBySession.get(sessionId);
@@ -34826,6 +34719,7 @@ function createMagicContextHook(deps) {
34826
34719
  db,
34827
34720
  liveSessionState: {
34828
34721
  liveModelBySession,
34722
+ channel1StateBySession,
34829
34723
  variantBySession,
34830
34724
  agentBySession,
34831
34725
  historyRefreshSessions,
@@ -35423,6 +35317,7 @@ function createMagicContextHook(deps) {
35423
35317
  return model ? `${model.providerID}/${model.modelID}` : undefined;
35424
35318
  },
35425
35319
  getDreamerProgress: () => dreamerProgressByProject.get(projectPath) ?? null,
35320
+ getTailHygiene: (sessionId) => channel1StateBySession.get(sessionId),
35426
35321
  getContextLimit: (sessionId) => {
35427
35322
  const model = resolveLiveModel(sessionId);
35428
35323
  if (!model)
@@ -35657,8 +35552,27 @@ function replaceMessagesInPlace2(output, next) {
35657
35552
  if (output.messages !== next)
35658
35553
  output.messages.splice(0, output.messages.length, ...next);
35659
35554
  }
35555
+ function preserveUserTerminatedTail(messages, inputTail) {
35556
+ if (inputTail?.info.role !== "user" || messages.at(-1)?.info.role !== "assistant")
35557
+ return;
35558
+ let userIndex = messages.lastIndexOf(inputTail);
35559
+ if (userIndex < 0) {
35560
+ const inputId = inputTail.info.id;
35561
+ for (let index = messages.length - 1;index >= 0; index -= 1) {
35562
+ const message = messages[index];
35563
+ if (message.info.role === "user" && message.info.id === inputId) {
35564
+ userIndex = index;
35565
+ break;
35566
+ }
35567
+ }
35568
+ }
35569
+ const trailingUser = userIndex >= 0 ? messages[userIndex] : inputTail;
35570
+ if (userIndex >= 0)
35571
+ messages.splice(userIndex, 1);
35572
+ messages.push(trailingUser);
35573
+ }
35660
35574
  function createMessagesTransformHandler(args) {
35661
- return async (input, output) => {
35575
+ const run = async (input, output) => {
35662
35576
  const sessionId = resolveSessionId2(output);
35663
35577
  const agent = resolveAgentNameFromMessages(output.messages);
35664
35578
  const isInternalChild = typeof sessionId === "string" && sessionId.length > 0 && args.internalChildSessions?.has(sessionId) === true;
@@ -35779,6 +35693,14 @@ function createMessagesTransformHandler(args) {
35779
35693
  restoreCompactionOffInput();
35780
35694
  return output.messages;
35781
35695
  };
35696
+ return async (input, output) => {
35697
+ const inputTail = output.messages.at(-1);
35698
+ try {
35699
+ return await run(input, output);
35700
+ } finally {
35701
+ preserveUserTerminatedTail(output.messages, inputTail);
35702
+ }
35703
+ };
35782
35704
  }
35783
35705
  function resolveSessionId2(output) {
35784
35706
  for (const message of output.messages) {
@@ -36167,6 +36089,7 @@ function buildSidebarSnapshot(db, sessionId, directory, liveSessionState, inject
36167
36089
  }) : contextLimit;
36168
36090
  const nativeContextUsagePercentage = nativeContextLimit > 0 ? effectiveInputTokens / nativeContextLimit * 100 : undefined;
36169
36091
  const calibration = resolveModelCalibration(activeProviderID, activeModelID);
36092
+ const tailHygiene = resolveTailHygieneStatus(liveSessionState?.channel1StateBySession.get(sessionId), moduleStatus?.tail_hygiene);
36170
36093
  const calibrated = calibrateBuckets({
36171
36094
  inputTokens: effectiveInputTokens,
36172
36095
  systemLocal: systemPromptTokens,
@@ -36211,6 +36134,7 @@ function buildSidebarSnapshot(db, sessionId, directory, liveSessionState, inject
36211
36134
  conversationTokens: calibrated.conversationTokens,
36212
36135
  toolCallTokens: calibrated.toolCallTokens,
36213
36136
  toolDefinitionTokens: calibrated.toolDefinitionTokens,
36137
+ ...tailHygiene === undefined ? {} : { tailHygiene },
36214
36138
  executeThreshold,
36215
36139
  executeThresholdClamped,
36216
36140
  boundaryPresent: moduleStatus?.boundary_present,
@@ -36447,9 +36371,9 @@ function registerRpcHandlers(rpcServer, args) {
36447
36371
  }
36448
36372
  });
36449
36373
  const buildManagedCtx = async (db) => {
36450
- const { deriveHistorianChunkTokens: deriveHistorianChunkTokens2, resolveHistorianContextLimit: resolveHistorianContextLimit2 } = await import("./derive-budgets-0f8xpyw2.js");
36451
- const { resolveFallbackChain: resolveFallbackChain2 } = await import("./resolve-fallbacks-5n5tvge1.js");
36452
- const { userMemoryCollectionEnabled: userMemoryCollectionEnabled2 } = await import("./task-config-gbp7r23g.js");
36374
+ const { deriveHistorianChunkTokens: deriveHistorianChunkTokens2, resolveHistorianContextLimit: resolveHistorianContextLimit2 } = await import("./derive-budgets-xk8cy5e6.js");
36375
+ const { resolveFallbackChain: resolveFallbackChain2 } = await import("./resolve-fallbacks-qf0ekmz9.js");
36376
+ const { userMemoryCollectionEnabled: userMemoryCollectionEnabled2 } = await import("./task-config-at3adc59.js");
36453
36377
  const DEFAULT_HISTORIAN_TIMEOUT_MS2 = 600000;
36454
36378
  return {
36455
36379
  client: args.client,
@@ -36474,8 +36398,8 @@ function registerRpcHandlers(rpcServer, args) {
36474
36398
  const db = getDb();
36475
36399
  if (!db)
36476
36400
  return { ok: false, error: "db unavailable" };
36477
- const { runManagedRecomp: runManagedRecomp2 } = await import("./recomp-orchestrator-c3ff16k7.js");
36478
- const { sendIgnoredMessage: sendIgnoredMessage2 } = await import("./send-session-notification-dxske5zm.js");
36401
+ const { runManagedRecomp: runManagedRecomp2 } = await import("./recomp-orchestrator-p030kxtc.js");
36402
+ const { sendIgnoredMessage: sendIgnoredMessage2 } = await import("./send-session-notification-6v5b72b4.js");
36479
36403
  log(`[rpc] recomp requested for session ${sessionId}`);
36480
36404
  const ctx = await buildManagedCtx(db);
36481
36405
  runManagedRecomp2(ctx, sessionId).then((message) => {
@@ -36490,8 +36414,8 @@ function registerRpcHandlers(rpcServer, args) {
36490
36414
  const db = getDb();
36491
36415
  if (!db)
36492
36416
  return { ok: false, error: "db unavailable" };
36493
- const { runManagedUpgrade: runManagedUpgrade2 } = await import("./recomp-orchestrator-c3ff16k7.js");
36494
- const { sendIgnoredMessage: sendIgnoredMessage2 } = await import("./send-session-notification-dxske5zm.js");
36417
+ const { runManagedUpgrade: runManagedUpgrade2 } = await import("./recomp-orchestrator-p030kxtc.js");
36418
+ const { sendIgnoredMessage: sendIgnoredMessage2 } = await import("./send-session-notification-6v5b72b4.js");
36495
36419
  log(`[rpc] session-upgrade requested for session ${sessionId}`);
36496
36420
  const ctx = await buildManagedCtx(db);
36497
36421
  runManagedUpgrade2(ctx, sessionId).then((message) => {
@@ -36507,7 +36431,7 @@ function registerRpcHandlers(rpcServer, args) {
36507
36431
  if (!db)
36508
36432
  return { ok: false, error: "db unavailable" };
36509
36433
  try {
36510
- const { updateSessionMeta: updateSessionMeta2 } = await import("./storage-meta-session-mk4gsnke.js");
36434
+ const { updateSessionMeta: updateSessionMeta2 } = await import("./storage-meta-session-2306t3j7.js");
36511
36435
  updateSessionMeta2(db, sessionId, { upgradeRemindedAt: Date.now() });
36512
36436
  return { ok: true };
36513
36437
  } catch (error) {
@@ -38340,7 +38264,7 @@ Mark discardable once processed: large outputs you've summarized, repeated or re
38340
38264
  Keep: user messages, unresolved errors, raw evidence you haven't extracted yet, and outputs whose exact wording may matter later.
38341
38265
  Never blanket-mark large ranges (e.g. "1-50") — review what each tag holds first.`;
38342
38266
  // src/tools/ctx-reduce/tools.ts
38343
- import { createHash as createHash15 } from "node:crypto";
38267
+ import { createHash as createHash14 } from "node:crypto";
38344
38268
  import { tool as tool4 } from "@opencode-ai/plugin";
38345
38269
 
38346
38270
  // src/features/magic-context/range-parser.ts
@@ -38410,11 +38334,11 @@ function createCtxReduceTool(deps) {
38410
38334
  const stableId = `oc-${sessionId}-${callId}`;
38411
38335
  if (Buffer.byteLength(stableId) <= 128)
38412
38336
  return stableId;
38413
- return `oc-${createHash15("sha256").update(stableId).digest("hex")}`;
38337
+ return `oc-${createHash14("sha256").update(stableId).digest("hex")}`;
38414
38338
  }
38415
38339
  fallbackCommandSequence += 1;
38416
38340
  const monotonicId = `oc-${sessionId}-${fallbackCommandSequence}`;
38417
- return Buffer.byteLength(monotonicId) <= 128 ? monotonicId : `oc-${createHash15("sha256").update(monotonicId).digest("hex")}`;
38341
+ return Buffer.byteLength(monotonicId) <= 128 ? monotonicId : `oc-${createHash14("sha256").update(monotonicId).digest("hex")}`;
38418
38342
  };
38419
38343
  return tool4({
38420
38344
  description: CTX_REDUCE_DESCRIPTION,
@@ -38954,6 +38878,7 @@ class MagicContextRpcServer {
38954
38878
  port: this.port,
38955
38879
  pid: process.pid,
38956
38880
  started_at: this.startedAt,
38881
+ kind: "OpenCode server",
38957
38882
  token: this.token,
38958
38883
  instance_id: this.instanceId
38959
38884
  }), enforcePrivatePermissions ? { encoding: "utf-8", mode: 384 } : { encoding: "utf-8" });
@@ -39169,7 +39094,7 @@ var server = async (ctx) => {
39169
39094
  `);
39170
39095
  setTimeout(async () => {
39171
39096
  try {
39172
- const { sendIgnoredMessage: sendIgnoredMessage2 } = await import("./send-session-notification-dxske5zm.js");
39097
+ const { sendIgnoredMessage: sendIgnoredMessage2 } = await import("./send-session-notification-6v5b72b4.js");
39173
39098
  const clientWithSessions = ctx.client;
39174
39099
  const sessions = await Promise.resolve(clientWithSessions.session?.list?.()).catch(() => null);
39175
39100
  const sessionList = Array.isArray(sessions) ? sessions : sessions?.data;
@@ -39317,6 +39242,11 @@ var server = async (ctx) => {
39317
39242
  embeddingConfig: pluginConfig.embedding,
39318
39243
  memoryEnabled: pluginConfig.memory?.enabled === true,
39319
39244
  memoryInjectionBudgetTokens: pluginConfig.memory?.injection_budget_tokens,
39245
+ historianChildSweep: {
39246
+ timeoutMs: pluginConfig.historian_timeout_ms,
39247
+ fallbackModelCount: resolveFallbackChain(pluginConfig.historian?.fallback_models).length,
39248
+ keepSubagents: pluginConfig.keep_subagents === true
39249
+ },
39320
39250
  mural: pluginConfig.mural,
39321
39251
  retinaHandoff: pluginConfig.smart_notes.retina_handoff,
39322
39252
  gitCommitIndexing: pluginConfig.memory.git_commit_indexing?.enabled ? {
@@ -39356,7 +39286,7 @@ var server = async (ctx) => {
39356
39286
  {
39357
39287
  const fence = getSchemaFenceRejection();
39358
39288
  if (fence) {
39359
- import("./conflict-warning-hook-an4fxhwf.js").then(({ sendSchemaFenceWarning }) => sendSchemaFenceWarning(ctx.client, ctx.directory, fence));
39289
+ import("./conflict-warning-hook-f406ggbw.js").then(({ sendSchemaFenceWarning }) => sendSchemaFenceWarning(ctx.client, ctx.directory, fence));
39360
39290
  }
39361
39291
  }
39362
39292
  if (conflictResult?.hasConflict) {
@@ -39374,10 +39304,10 @@ var server = async (ctx) => {
39374
39304
  ANNOUNCEMENT_FEATURES: ANNOUNCEMENT_FEATURES2,
39375
39305
  ANNOUNCEMENT_FOOTER: ANNOUNCEMENT_FOOTER2,
39376
39306
  markAnnouncementSeen: markAnnouncementSeen2
39377
- } = await import("./announcement-6c1g4es4.js");
39307
+ } = await import("./announcement-5eg4t64s.js");
39378
39308
  if (shouldShowAnnouncement2()) {
39379
39309
  setTimeout(() => {
39380
- import("./conflict-warning-hook-an4fxhwf.js").then(({ sendStartupAnnouncement }) => sendStartupAnnouncement(ctx.client, ctx.directory, ANNOUNCEMENT_VERSION2, ANNOUNCEMENT_FEATURES2, ANNOUNCEMENT_FOOTER2, markAnnouncementSeen2)).catch(() => {});
39310
+ import("./conflict-warning-hook-f406ggbw.js").then(({ sendStartupAnnouncement }) => sendStartupAnnouncement(ctx.client, ctx.directory, ANNOUNCEMENT_VERSION2, ANNOUNCEMENT_FEATURES2, ANNOUNCEMENT_FOOTER2, markAnnouncementSeen2)).catch(() => {});
39381
39311
  }, 8000);
39382
39312
  }
39383
39313
  } catch {}