@retaw106/mmc-oc 1.2.2 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (227) hide show
  1. package/dist/cli.js +7095 -0
  2. package/dist/config/index.d.ts +0 -12
  3. package/dist/config/index.d.ts.map +1 -1
  4. package/dist/config/legacy-harness-blocks.d.ts +27 -0
  5. package/dist/config/legacy-harness-blocks.d.ts.map +1 -0
  6. package/dist/config/live-run-config.d.ts.map +1 -1
  7. package/dist/config/live-snapshot.d.ts +2 -1
  8. package/dist/config/live-snapshot.d.ts.map +1 -1
  9. package/dist/config/project-security.d.ts +4 -5
  10. package/dist/config/project-security.d.ts.map +1 -1
  11. package/dist/config/raw-loader.d.ts +7 -26
  12. package/dist/config/raw-loader.d.ts.map +1 -1
  13. package/dist/config/schema/magic-context.d.ts +164 -259
  14. package/dist/config/schema/magic-context.d.ts.map +1 -1
  15. package/dist/config/variable.d.ts +8 -0
  16. package/dist/config/variable.d.ts.map +1 -1
  17. package/dist/config-init.js +5595 -0
  18. package/dist/{context-a6px04s0.js → context-95zkksn3.js} +2471 -2438
  19. package/dist/{derive-budgets-fhk00zv8.js → derive-budgets-rjjz5f7y.js} +2 -2
  20. package/dist/features/magic-context/compaction-marker.d.ts.map +1 -1
  21. package/dist/features/magic-context/message-index.d.ts +2 -0
  22. package/dist/features/magic-context/message-index.d.ts.map +1 -1
  23. package/dist/features/magic-context/migration-v3-perf-schema.d.ts +8 -0
  24. package/dist/features/magic-context/migration-v3-perf-schema.d.ts.map +1 -0
  25. package/dist/features/magic-context/migration-v4-temporal-decisions.d.ts +12 -0
  26. package/dist/features/magic-context/migration-v4-temporal-decisions.d.ts.map +1 -0
  27. package/dist/features/magic-context/migrations.d.ts.map +1 -1
  28. package/dist/features/magic-context/overflow-detection.d.ts +6 -0
  29. package/dist/features/magic-context/overflow-detection.d.ts.map +1 -1
  30. package/dist/features/magic-context/reclaim-protection.d.ts +15 -10
  31. package/dist/features/magic-context/reclaim-protection.d.ts.map +1 -1
  32. package/dist/features/magic-context/session-cache-ttl.d.ts +4 -2
  33. package/dist/features/magic-context/session-cache-ttl.d.ts.map +1 -1
  34. package/dist/features/magic-context/storage-db.d.ts +1 -1
  35. package/dist/features/magic-context/storage-db.d.ts.map +1 -1
  36. package/dist/features/magic-context/storage-historian-runs.d.ts +2 -0
  37. package/dist/features/magic-context/storage-historian-runs.d.ts.map +1 -1
  38. package/dist/features/magic-context/storage-ops.d.ts +2 -0
  39. package/dist/features/magic-context/storage-ops.d.ts.map +1 -1
  40. package/dist/features/magic-context/storage-session-tables.d.ts.map +1 -1
  41. package/dist/features/magic-context/storage-tags.d.ts +15 -2
  42. package/dist/features/magic-context/storage-tags.d.ts.map +1 -1
  43. package/dist/features/magic-context/storage.d.ts +2 -2
  44. package/dist/features/magic-context/storage.d.ts.map +1 -1
  45. package/dist/features/magic-context/temporal-decisions.d.ts +10 -0
  46. package/dist/features/magic-context/temporal-decisions.d.ts.map +1 -0
  47. package/dist/features/magic-context/tool-definition-tokens.d.ts +3 -0
  48. package/dist/features/magic-context/tool-definition-tokens.d.ts.map +1 -1
  49. package/dist/hooks/magic-context/active-anthropic-turn.d.ts +8 -0
  50. package/dist/hooks/magic-context/active-anthropic-turn.d.ts.map +1 -0
  51. package/dist/hooks/magic-context/apply-operations.d.ts +15 -0
  52. package/dist/hooks/magic-context/apply-operations.d.ts.map +1 -1
  53. package/dist/hooks/magic-context/auto-search-deadline.d.ts +10 -3
  54. package/dist/hooks/magic-context/auto-search-deadline.d.ts.map +1 -1
  55. package/dist/hooks/magic-context/auto-search-runner.d.ts +1 -1
  56. package/dist/hooks/magic-context/auto-search-runner.d.ts.map +1 -1
  57. package/dist/hooks/magic-context/caveman-cleanup.d.ts.map +1 -1
  58. package/dist/hooks/magic-context/channel2-cycle.d.ts +2 -0
  59. package/dist/hooks/magic-context/channel2-cycle.d.ts.map +1 -1
  60. package/dist/hooks/magic-context/compaction-marker-manager.d.ts.map +1 -1
  61. package/dist/hooks/magic-context/compartment-render-epoch.d.ts +8 -0
  62. package/dist/hooks/magic-context/compartment-render-epoch.d.ts.map +1 -1
  63. package/dist/hooks/magic-context/compartment-runner-partial-recomp.d.ts.map +1 -1
  64. package/dist/hooks/magic-context/compartment-runner-recomp.d.ts.map +1 -1
  65. package/dist/hooks/magic-context/compartment-trigger.d.ts +3 -1
  66. package/dist/hooks/magic-context/compartment-trigger.d.ts.map +1 -1
  67. package/dist/hooks/magic-context/ctx-reduce-availability.d.ts +12 -0
  68. package/dist/hooks/magic-context/ctx-reduce-availability.d.ts.map +1 -1
  69. package/dist/hooks/magic-context/decision-calibration.d.ts +3 -0
  70. package/dist/hooks/magic-context/decision-calibration.d.ts.map +1 -1
  71. package/dist/hooks/magic-context/emergency-drop.d.ts +2 -0
  72. package/dist/hooks/magic-context/emergency-drop.d.ts.map +1 -1
  73. package/dist/hooks/magic-context/emergency-fail-closed.d.ts +21 -1
  74. package/dist/hooks/magic-context/emergency-fail-closed.d.ts.map +1 -1
  75. package/dist/hooks/magic-context/final-wire-token-estimate.d.ts +30 -1
  76. package/dist/hooks/magic-context/final-wire-token-estimate.d.ts.map +1 -1
  77. package/dist/hooks/magic-context/heuristic-cleanup.d.ts +2 -0
  78. package/dist/hooks/magic-context/heuristic-cleanup.d.ts.map +1 -1
  79. package/dist/hooks/magic-context/inject-compartments.d.ts +10 -8
  80. package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
  81. package/dist/hooks/magic-context/latest-assistant-turn.d.ts +25 -0
  82. package/dist/hooks/magic-context/latest-assistant-turn.d.ts.map +1 -0
  83. package/dist/hooks/magic-context/lkg-measured-request.d.ts +69 -0
  84. package/dist/hooks/magic-context/lkg-measured-request.d.ts.map +1 -0
  85. package/dist/hooks/magic-context/read-session-formatting.d.ts +3 -0
  86. package/dist/hooks/magic-context/read-session-formatting.d.ts.map +1 -1
  87. package/dist/hooks/magic-context/reasoning-budget-status.d.ts +15 -0
  88. package/dist/hooks/magic-context/reasoning-budget-status.d.ts.map +1 -0
  89. package/dist/hooks/magic-context/reasoning-budget.d.ts +40 -0
  90. package/dist/hooks/magic-context/reasoning-budget.d.ts.map +1 -0
  91. package/dist/hooks/magic-context/reasoning-removal.d.ts +6 -6
  92. package/dist/hooks/magic-context/reasoning-removal.d.ts.map +1 -1
  93. package/dist/hooks/magic-context/recomp-orchestrator.d.ts +2 -0
  94. package/dist/hooks/magic-context/recomp-orchestrator.d.ts.map +1 -1
  95. package/dist/hooks/magic-context/sentinel.d.ts +2 -0
  96. package/dist/hooks/magic-context/sentinel.d.ts.map +1 -1
  97. package/dist/hooks/magic-context/strip-content.d.ts +7 -3
  98. package/dist/hooks/magic-context/strip-content.d.ts.map +1 -1
  99. package/dist/hooks/magic-context/supersession-reclaim.d.ts +4 -0
  100. package/dist/hooks/magic-context/supersession-reclaim.d.ts.map +1 -1
  101. package/dist/hooks/magic-context/tag-messages.d.ts +13 -0
  102. package/dist/hooks/magic-context/tag-messages.d.ts.map +1 -1
  103. package/dist/hooks/magic-context/tail-hygiene-walk.d.ts +5 -0
  104. package/dist/hooks/magic-context/tail-hygiene-walk.d.ts.map +1 -1
  105. package/dist/hooks/magic-context/temporal-awareness.d.ts +6 -3
  106. package/dist/hooks/magic-context/temporal-awareness.d.ts.map +1 -1
  107. package/dist/hooks/magic-context/temporal-served-projection.d.ts +4 -0
  108. package/dist/hooks/magic-context/temporal-served-projection.d.ts.map +1 -0
  109. package/dist/hooks/magic-context/tool-reclaim.d.ts +2 -0
  110. package/dist/hooks/magic-context/tool-reclaim.d.ts.map +1 -1
  111. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +34 -12
  112. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  113. package/dist/hooks/magic-context/transform.d.ts +11 -5
  114. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  115. package/dist/hooks/magic-context/wrapup-orchestrator.d.ts.map +1 -1
  116. package/dist/{index-wgt4gamw.js → index-1mjhzqq7.js} +422 -31
  117. package/dist/index-33gprt9g.js +30 -0
  118. package/dist/{index-zx63j2e2.js → index-5cep2r9n.js} +3 -2
  119. package/dist/{index-by6h2pav.js → index-bdt9my9y.js} +374 -239
  120. package/dist/{index-3wagyrnj.js → index-x37vg474.js} +5 -1
  121. package/dist/{index-1vs6anwz.js → index-xt7y10x6.js} +2 -1
  122. package/dist/{index-me3zcj5t.js → index-z2g20msd.js} +4 -8
  123. package/dist/index.js +2 -2
  124. package/dist/{message-time-backfill-5ewk0axe.js → message-time-backfill-zfernxbw.js} +1 -1
  125. package/dist/{model-resolution-5haaxnpt.js → model-resolution-wazv26n0.js} +1 -1
  126. package/dist/plugin/rpc-handlers.d.ts +4 -0
  127. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  128. package/dist/{read-session-chunk-apjwrttc.js → read-session-chunk-hp464g13.js} +2 -2
  129. package/dist/{recomp-orchestrator-gyeevxaw.js → recomp-orchestrator-3qxeqwb9.js} +6 -6
  130. package/dist/shared/auto-search-lifecycle.d.ts +7 -0
  131. package/dist/shared/auto-search-lifecycle.d.ts.map +1 -0
  132. package/dist/shared/cache-ttl-display.d.ts +6 -4
  133. package/dist/shared/cache-ttl-display.d.ts.map +1 -1
  134. package/dist/shared/model-cache-ttl.d.ts +1 -1
  135. package/dist/shared/model-cache-ttl.d.ts.map +1 -1
  136. package/dist/shared/model-resolution.d.ts +5 -2
  137. package/dist/shared/model-resolution.d.ts.map +1 -1
  138. package/dist/shared/model-suggestion-retry.d.ts +2 -0
  139. package/dist/shared/model-suggestion-retry.d.ts.map +1 -1
  140. package/dist/shared/protected-tools-policy.d.ts +6 -0
  141. package/dist/shared/protected-tools-policy.d.ts.map +1 -0
  142. package/dist/shared/provider-output-failure.d.ts +19 -0
  143. package/dist/shared/provider-output-failure.d.ts.map +1 -0
  144. package/dist/shared/temporal-upgrade-fixture.d.ts +19 -0
  145. package/dist/shared/temporal-upgrade-fixture.d.ts.map +1 -0
  146. package/dist/shared/window-geometry.d.ts +4 -0
  147. package/dist/shared/window-geometry.d.ts.map +1 -1
  148. package/dist/shared/write-transaction-timing.d.ts +8 -1
  149. package/dist/shared/write-transaction-timing.d.ts.map +1 -1
  150. package/dist/tools/ctx-reduce/tools.d.ts +2 -0
  151. package/dist/tools/ctx-reduce/tools.d.ts.map +1 -1
  152. package/dist/v2/hidden-child-native.d.ts +7 -0
  153. package/dist/v2/hidden-child-native.d.ts.map +1 -1
  154. package/dist/v2/hidden-child-record.d.ts +13 -0
  155. package/dist/v2/hidden-child-record.d.ts.map +1 -1
  156. package/dist/v2/hidden-completion.d.ts.map +1 -1
  157. package/dist/v2/hooks/context.d.ts.map +1 -1
  158. package/dist/v2/hooks/hidden-child.d.ts +46 -2
  159. package/dist/v2/hooks/hidden-child.d.ts.map +1 -1
  160. package/dist/v2/hooks/payload.d.ts.map +1 -1
  161. package/dist/v2/hooks/store.d.ts.map +1 -1
  162. package/dist/v2/hooks/tools.d.ts.map +1 -1
  163. package/dist/v2/hooks/types.d.ts +8 -0
  164. package/dist/v2/hooks/types.d.ts.map +1 -1
  165. package/dist/v2/server.js +4540 -3889
  166. package/dist/v2/tool-result.d.ts +8 -0
  167. package/dist/v2/tool-result.d.ts.map +1 -0
  168. package/dist/web/api.d.ts +6 -0
  169. package/dist/web/api.d.ts.map +1 -1
  170. package/dist/web/context-store.d.ts +13 -0
  171. package/dist/web/context-store.d.ts.map +1 -1
  172. package/dist/web/display-path.d.ts +28 -0
  173. package/dist/web/display-path.d.ts.map +1 -0
  174. package/dist/web/entry-args.d.ts +33 -0
  175. package/dist/web/entry-args.d.ts.map +1 -0
  176. package/dist/web/host-pi.d.ts +2 -0
  177. package/dist/web/host-pi.d.ts.map +1 -1
  178. package/dist/web/main.d.ts +4 -6
  179. package/dist/web/main.d.ts.map +1 -1
  180. package/dist/web/main.js +772 -77
  181. package/dist/web/message-stats.d.ts +45 -0
  182. package/dist/web/message-stats.d.ts.map +1 -0
  183. package/dist/web/ui/index.html +1 -0
  184. package/dist/web/ui/panel.css +5 -0
  185. package/dist/web/ui/panel.js +220 -70
  186. package/dist/web/views.d.ts +23 -0
  187. package/dist/web/views.d.ts.map +1 -1
  188. package/dist/{wrapup-orchestrator-z9sqpqjf.js → wrapup-orchestrator-wgb2nd19.js} +7 -6
  189. package/package.json +7 -2
  190. package/src/config/index.test.ts +257 -126
  191. package/src/config/index.ts +45 -39
  192. package/src/config/legacy-harness-blocks.test.ts +78 -0
  193. package/src/config/legacy-harness-blocks.ts +71 -0
  194. package/src/config/live-run-config.test.ts +49 -5
  195. package/src/config/live-run-config.ts +1 -0
  196. package/src/config/live-snapshot.ts +5 -1
  197. package/src/config/profiles.ts +1 -1
  198. package/src/config/project-config-trust-boundary.test.ts +2 -2
  199. package/src/config/project-security.hostile-matrix.test.ts +51 -65
  200. package/src/config/project-security.test.ts +6 -1
  201. package/src/config/project-security.ts +13 -12
  202. package/src/config/protected-tokens.test.ts +1 -1
  203. package/src/config/raw-loader.test.ts +29 -352
  204. package/src/config/raw-loader.ts +17 -406
  205. package/src/config/removed-config-keys.test.ts +1 -1
  206. package/src/config/schema/magic-context.test.ts +60 -64
  207. package/src/config/schema/magic-context.ts +105 -137
  208. package/src/config/variable.ts +21 -12
  209. package/src/shared/auto-search-lifecycle.ts +27 -0
  210. package/src/shared/cache-ttl-display.test.ts +1 -1
  211. package/src/shared/cache-ttl-display.ts +17 -16
  212. package/src/shared/model-cache-ttl.test.ts +2 -2
  213. package/src/shared/model-cache-ttl.ts +8 -4
  214. package/src/shared/model-resolution.test.ts +22 -32
  215. package/src/shared/model-resolution.ts +13 -18
  216. package/src/shared/model-suggestion-retry.ts +63 -7
  217. package/src/shared/protected-tools-policy.ts +25 -0
  218. package/src/shared/provider-output-failure.ts +176 -0
  219. package/src/shared/status-detail-text.test.ts +1 -1
  220. package/src/shared/status-view.test.ts +1 -1
  221. package/src/shared/temporal-upgrade-fixture.ts +50 -0
  222. package/src/shared/window-geometry.ts +10 -0
  223. package/src/shared/write-transaction-timing.ts +25 -1
  224. package/dist/features/magic-context/window-report-ledger.d.ts +0 -70
  225. package/dist/features/magic-context/window-report-ledger.d.ts.map +0 -1
  226. package/dist/index-e1q8002h.js +0 -16
  227. package/src/config/misplaced-agent-model.test.ts +0 -55
@@ -24,6 +24,8 @@ import {
24
24
  } from "./index-fg34g6a5.js";
25
25
  import {
26
26
  toolTemplateError,
27
+ DEFAULT_PROTECTED_TOOLS,
28
+ mergeProtectedTools,
27
29
  isRecord,
28
30
  detectOverflow,
29
31
  removeSystemReminders,
@@ -34,6 +36,8 @@ import {
34
36
  stripTagPrefix,
35
37
  peelLeadingMcTagNotation,
36
38
  stableStringify,
39
+ installV3PerfSchema,
40
+ queuePendingDropForUnchangedTag,
37
41
  getAllStatusTagTokenTotalsFlat,
38
42
  updateTagStatus,
39
43
  foldShrunkPartTags,
@@ -66,7 +70,7 @@ import {
66
70
  getRawSessionTagKeysThrough2,
67
71
  getLegacyProtectedTailStartOrdinal2,
68
72
  readSessionChunk2
69
- } from "./index-wgt4gamw.js";
73
+ } from "./index-1mjhzqq7.js";
70
74
  import {
71
75
  piModelRefToCanonical,
72
76
  modelRefLookupOrder,
@@ -74,7 +78,7 @@ import {
74
78
  providerMass,
75
79
  calibrationForModelKey,
76
80
  historyLocalBudget
77
- } from "./index-3wagyrnj.js";
81
+ } from "./index-x37vg474.js";
78
82
  import {
79
83
  closeQuietly,
80
84
  isKnownAutocommit,
@@ -99,7 +103,7 @@ import {
99
103
  deriveTriggerBudget2,
100
104
  resolveHistorianProducerLimits2,
101
105
  producerSourceLocalBudget2
102
- } from "./index-zx63j2e2.js";
106
+ } from "./index-5cep2r9n.js";
103
107
  import {
104
108
  pushNotification2
105
109
  } from "./index-jdxxq8cz.js";
@@ -109,8 +113,9 @@ import {
109
113
  sendStatusNotification2
110
114
  } from "./index-5pg0acf7.js";
111
115
  import {
112
- logSlowWriteTransaction
113
- } from "./index-e1q8002h.js";
116
+ logSlowWriteTransaction,
117
+ WriteTransactionSteps
118
+ } from "./index-33gprt9g.js";
114
119
 
115
120
  // src/agents/memory-maintainer.ts
116
121
  var MEMORY_MAINTAINER_A_AGENT = "magic-context-maintainer-a";
@@ -7458,64 +7463,28 @@ var PromptSurfaceConfigSchema = object({
7458
7463
  message: "tool description values must not be empty or whitespace-only"
7459
7464
  })).optional().describe("USER-LEVEL ONLY top-level description overrides keyed by mmc_* tool ID; parameter schemas and descriptions are unchanged.")
7460
7465
  }).describe("Prompt-surface preset routing. Project config may select default/models, while guidance_override_path and tool_descriptions are user-level only.");
7461
- var PER_HARNESS_MIGRATION_INVENTORY = {
7462
- historian: {
7463
- retained: [
7464
- "temperature",
7465
- "top_p",
7466
- "prompt",
7467
- "tools",
7468
- "disable",
7469
- "description",
7470
- "mode",
7471
- "color",
7472
- "maxSteps",
7473
- "permission",
7474
- "maxTokens",
7475
- "two_pass",
7476
- "disallowed_tools"
7477
- ],
7478
- migrated_execution: ["model", "fallback_models", "variant", "thinking_level"]
7479
- }
7480
- };
7481
- var PER_HARNESS_MODEL_KEYS = ["opencode", "pi"];
7482
- var OcEntryObjectSchema = object({
7483
- model: string2().describe("OpenCode model ID (for example, provider/model)."),
7484
- variant: string2().optional().describe("OpenCode reasoning variant for this entry.")
7485
- }).strict();
7486
- var OcEntrySchema = union([string2(), OcEntryObjectSchema]);
7487
- var PiEntryObjectSchema = object({
7488
- model: string2().describe("Pi model ID (for example, provider/model)."),
7466
+ var HISTORIAN_MODEL_RESOLUTION_FIELDS = [
7467
+ "model",
7468
+ "fallback_models",
7469
+ "variant",
7470
+ "thinking_level"
7471
+ ];
7472
+ var LEGACY_HARNESS_BLOCK_KEYS = ["opencode", "pi"];
7473
+ var HistorianModelEntryObjectSchema = object({
7474
+ model: string2().describe("Model ID (for example, provider/model)."),
7475
+ variant: string2().optional().describe("OpenCode reasoning variant for this entry."),
7489
7476
  thinking_level: PiThinkingLevelSchema.describe("Pi thinking level for this entry.")
7490
7477
  }).strict();
7491
- var PiEntrySchema = union([string2(), PiEntryObjectSchema]);
7492
- var OpenCodeHarnessBlockSchema = object({
7493
- model: OcEntrySchema.optional().describe("Primary OpenCode model entry."),
7494
- fallback_models: array(OcEntrySchema).optional().describe("Ordered fallback OpenCode entries. New-shape configuration requires an array; legacy singleton values migrate to a one-element array."),
7495
- variant: string2().optional().describe("OpenCode reasoning variant for the primary entry when it declares none. Fallback entries declare variants per-entry.")
7496
- }).strict().describe("Strict OpenCode model-resolution block. It accepts no Pi vocabulary.");
7497
- var PiHarnessBlockSchema = object({
7498
- model: PiEntrySchema.optional().describe("Primary Pi model entry."),
7499
- fallback_models: array(PiEntrySchema).optional().describe("Ordered fallback Pi entries. New-shape configuration requires an array; legacy singleton values migrate to a one-element array."),
7500
- thinking_level: PiThinkingLevelSchema.describe("Pi thinking level for the primary entry when it declares none. Fallback entries declare thinking levels per-entry.")
7501
- }).strict().describe("Strict Pi model-resolution block. It accepts no OpenCode vocabulary.");
7502
- var ProfileOpenCodeModelBlockSchema = object({
7503
- model: OcEntrySchema.optional().describe("Primary OpenCode model entry."),
7504
- fallback_models: array(OcEntrySchema).optional().describe("Ordered fallback OpenCode model entries."),
7505
- variant: string2().optional().describe("OpenCode reasoning variant for the primary model entry.")
7506
- }).strict().describe("Strict profile-only OpenCode model-selection block.");
7507
- var ProfilePiModelBlockSchema = object({
7508
- model: PiEntrySchema.optional().describe("Primary Pi model entry."),
7509
- fallback_models: array(PiEntrySchema).optional().describe("Ordered fallback Pi model entries."),
7510
- thinking_level: PiThinkingLevelSchema.describe("Pi thinking level for the primary model entry.")
7511
- }).strict().describe("Strict profile-only Pi model-selection block.");
7478
+ var HistorianModelEntrySchema = union([string2(), HistorianModelEntryObjectSchema]);
7512
7479
  var ProfileHistorianSchema = object({
7513
- opencode: ProfileOpenCodeModelBlockSchema.optional(),
7514
- pi: ProfilePiModelBlockSchema.optional()
7515
- }).strict();
7480
+ model: HistorianModelEntrySchema.optional().describe("Primary historian model entry."),
7481
+ fallback_models: array(HistorianModelEntrySchema).optional().describe("Ordered fallback historian model entries."),
7482
+ variant: string2().optional().describe("OpenCode reasoning variant for the primary entry. Ignored by Pi."),
7483
+ thinking_level: PiThinkingLevelSchema.describe("Pi thinking level for the primary entry. Ignored by OpenCode.")
7484
+ }).strict().describe("Strict profile-only historian model-selection block.");
7516
7485
  var ConfigProfileSchema = object({
7517
7486
  historian: ProfileHistorianSchema.optional()
7518
- }).strict().describe("User-owned model-selection overlay. Only historian harness model blocks are allowed.");
7487
+ }).strict().describe("User-owned model-selection overlay. Only the flat historian model-resolution fields are allowed.");
7519
7488
  var ConfigProfilesSchema = record(string2().trim().min(1, "Profile names must not be empty or whitespace-only."), ConfigProfileSchema);
7520
7489
  var AgentMetadataSchema = AgentOverrideConfigSchema.pick({
7521
7490
  temperature: true,
@@ -7539,20 +7508,22 @@ var HistorianConfigSchema = AgentMetadataSchema.extend({
7539
7508
  }),
7540
7509
  literal(false)
7541
7510
  ])).optional().describe('Readable historian tool expansions, keyed by exact host tool name. Templates override built-in defaults; false disables an expansion. Supports ${input.path}, ${output.path}, bare ${output}, array [N], [*].field, .each("${field}"), .join("separator"), .count and final .truncate(N). Missing fields are empty; placeholders default to 300 characters, lists to 10 elements, expansions to 1000 characters. Valid in user and project config; affects historian/recomp and verbose ctx_expand only, never the wire or default ctx_expand transcript.'),
7542
- opencode: OpenCodeHarnessBlockSchema.optional(),
7543
- pi: PiHarnessBlockSchema.optional(),
7511
+ model: HistorianModelEntrySchema.optional().describe("Primary historian model entry. The active harness reads its own qualifier (OpenCode variant, Pi thinking_level); the other harness's qualifier is ignored."),
7512
+ fallback_models: array(HistorianModelEntrySchema).optional().describe("Ordered fallback historian model entries, tried in order."),
7513
+ variant: string2().optional().describe("OpenCode reasoning variant for the primary entry when it declares none. Ignored by Pi."),
7514
+ thinking_level: PiThinkingLevelSchema.describe("Pi thinking level for the primary entry when it declares none. Ignored by OpenCode."),
7544
7515
  two_pass: boolean2().default(false).describe("Run a second editor pass over historian output to clean low-signal U: lines and cross-compartment duplicates. Adds ~1 extra API call and ~1.3x cost per historian run. Useful for models without extended thinking support. (default: false)"),
7545
7516
  disallowed_tools: array(_enum(["*", "read", "aft_outline", "aft_zoom", "aft_search"])).default([]).describe(`OpenCode only. Tools to REMOVE from the historian's default allow-list [read, aft_outline, aft_zoom, aft_search]. Applies to both historian and historian-editor agents. Use ["*"] to strip all tool definitions from the model request — this prevents weak instruction-following models (e.g. mistral-small-latest) from entering tool-calling loops. Individual tool names remove just that tool. Note: a user-supplied historian.permission override can re-allow a tool that disallowed_tools removed — disallowed_tools sets the baseline, permission overrides take precedence. (default: [])`)
7546
- }).optional();
7517
+ }).strict().optional();
7547
7518
  var MagicContextConfigSchema = object({
7548
7519
  enabled: boolean2().default(true).describe("Enable magic context (default: true)"),
7549
7520
  allow_home_project: boolean2().default(false).describe("Allow Magic Context sessions launched from the exact canonical home directory. A non-git home uses its deterministic dir: identity; a home repository uses its git: identity. USER-LEVEL ONLY: project config is ignored. The home identity is excluded from registry seed exports, never resolves descendants by containment, and cannot join a workspace."),
7550
7521
  auto_update: boolean2().optional().describe("DEPRECATED no-op: the automatic update check was removed (the package is private-registry-only, so public npm checks always 404). The key is still accepted so existing configs keep parsing; upgrade via the host's own plugin update channel."),
7551
7522
  language: string2().trim().toLowerCase().refine((s) => isValidLanguageCode(s), 'language must be a 2-letter ISO 639-1 code (e.g. "tr", "es", "de")').optional().describe("Output language for Magic Context's generated content and guidance, as a " + '2-letter ISO 639-1 code (e.g. "tr", "es", "de", "ja", "pt"). When set, the ' + "historian and the agent-guidance block instruct the model to " + "write its PROSE in this language while keeping all structural tokens (XML tags, " + "the five memory category names, code identifiers, file paths) in English. " + "USER-LEVEL ONLY (ignored in project config for security). Unset = today's " + "behavior (model mirrors the conversation; English scaffolding). Changing it " + "triggers one cache re-materialization; existing compartments/memories keep their " + "original language until naturally rewritten."),
7552
7523
  profile: string2().trim().min(1).optional().describe("Select a named user-owned model profile. A valid project name overrides this user default; an empty string, null, or other non-string project value is ignored with a warning so the user selection still applies. Unknown names warn and use the base configuration."),
7553
- profiles: ConfigProfilesSchema.optional().describe("User-level named model profiles. A profile may contain only historian model, fallback_models, OpenCode variant, and Pi thinking_level fields. Project configs may select a name but cannot define profiles."),
7554
- historian: HistorianConfigSchema.describe("Historian metadata plus independent strict OpenCode and Pi execution blocks. Retained metadata stays at historian; model, fallback_models, variant, and thinking_level belong only in historian.opencode or historian.pi."),
7555
- cache_ttl: union([string2(), object({ default: string2() }).catchall(string2())]).default("5m").describe(`How long Magic Context assumes the provider's cached prefix stays valid. This is MC's own deferral gate — it does not change the provider's actual cache lifetime. String (e.g. "5m", "1h", "30s") or per-model object ({ default: "5m", "provider/model": "1h", "provider/*": "never" }); keys resolve most-specific first (exact provider/model, bare model ID, shorter dash-prefixes, then the provider/* wildcard). Explicit per-model entries win; otherwise GPT-5.6 and later (including gpt-6*, through any provider prefix) use a built-in 30m lifetime before the object default or 5m fallback. An unset or global "5m" opts into built-in defaults; any other global string is an explicit policy and wins. Policy is frozen per session, including across restarts; a model switch resolves against that frozen policy. /mmc-status shows the effective value and source. OpenAI documents at least 30 minutes since the latest write or reuse: https://developers.openai.com/api/docs/guides/prompt-caching (Cache lifetime and Summary of model differences). Set to "never" to mean MC never assumes expiry (for lanes kept warm externally by a cache-keep tool) — disables the idle-TTL heuristic so MC never initiates a rebuild based on elapsed time. Provider-side extended TTL is a separate request-level concern (cache_control: { ttl } in the request body).`),
7524
+ profiles: ConfigProfilesSchema.optional().describe("User-level named model profiles. A profile may contain only the flat historian model-resolution fields (model, fallback_models, OpenCode variant, Pi thinking_level). Project configs may select a name but cannot define profiles."),
7525
+ historian: HistorianConfigSchema.describe("Historian metadata plus the flat model-resolution fields (model, fallback_models, variant, thinking_level). The active harness reads its own qualifier; the removed historian.opencode / historian.pi blocks are no longer accepted."),
7526
+ cache_ttl: union([string2(), object({ default: string2() }).catchall(string2())]).default("5m").describe(`How long Magic Context assumes the provider's cached prefix stays valid. This is MC's own deferral gate — it does not change the provider's actual cache lifetime. String (e.g. "5m", "1h", "30s") or per-model object ({ default: "5m", "provider/model": "1h", "provider/*": "never" }); keys resolve most-specific first (exact provider/model, bare model ID, shorter dash-prefixes, then the provider/* wildcard). Explicit per-model entries win; otherwise GPT-5.6 and later (including gpt-6*, through any provider prefix) use a built-in 30m lifetime before the object default or 5m fallback. An unset or global "5m" opts into built-in defaults; any other global string is an explicit policy and wins. User and project settings, including an explicit "5m" or object default, apply on the next pass. Only built-in defaults are frozen per session (per model), including across restarts. /mmc-status shows the effective value and source. OpenAI documents at least 30 minutes since the latest write or reuse: https://developers.openai.com/api/docs/guides/prompt-caching (Cache lifetime and Summary of model differences). Set to "never" to mean MC never assumes expiry (for lanes kept warm externally by a cache-keep tool) — disables the idle-TTL heuristic so MC never initiates a rebuild based on elapsed time. Provider-side extended TTL is a separate request-level concern (cache_control: { ttl } in the request body).`),
7556
7527
  prompt_surface: PromptSurfaceConfigSchema.default({ default: "full" }).describe("Prompt-surface presets: default is full; models use bare model IDs, provider/model, or provider/* routing keys. Guidance and tool-description overrides are user-level only. OpenCode 1.x and Pi register tool descriptions once per process (they follow the default preset). OpenCode 2 rewrites the five mmc_* descriptions per request from the draft model."),
7557
7528
  output_reserve: union([
7558
7529
  number2().min(0),
@@ -7570,7 +7541,13 @@ var MagicContextConfigSchema = object({
7570
7541
  default: number2().min(5000).max(2000000).optional()
7571
7542
  }).catchall(number2().min(5000).max(2000000)).optional().describe("Absolute token thresholds per model. When matched, overrides execute_threshold_percentage for that model. Accepts `default` for all models or per-model keys. Values above 90% × context_limit are clamped with a warning log. Min 5_000, max 2_000_000."),
7572
7543
  protected_tokens: number2().int().min(PROTECTED_TOKENS_MIN).max(1e6).optional().describe("Positive integer token floor to protect from automatic reclaim (min: 4_000, max: 1_000_000). When omitted, the derived default is clamp(round(0.05 × usableSoft), min(16_000, round(0.08 × usableSoft)), 64_000)."),
7573
- clear_reasoning_age: number2().min(10).default(50).describe("Clear reasoning/thinking blocks older than N tags (default: 50)"),
7544
+ clear_reasoning_age: unknown().optional().describe("Deprecated and ignored. Use keep_reasoning_tokens instead.").meta({ deprecated: true }),
7545
+ keep_reasoning_tokens: union([
7546
+ number2().int().min(0).max(1e6),
7547
+ object({
7548
+ default: number2().int().min(0).max(1e6).optional()
7549
+ }).catchall(number2().int().min(0).max(1e6))
7550
+ ]).optional().describe("Reasoning tokens to keep on rebuilding passes. Number or per-model object; exact, shorter model keys, provider/*, then default. Omitted: fixed 10,000. 0 removes all eligible historical reasoning; newest and exempt steps always stay."),
7574
7551
  history_budget_percentage: number2().min(0.05).max(0.5).default(DEFAULT_HISTORY_BUDGET_PERCENTAGE).describe("Fraction of usable context (context_limit × execute_threshold) reserved for the session history block (default: 0.15)"),
7575
7552
  historian_timeout_ms: number2().min(60000).default(DEFAULT_HISTORIAN_TIMEOUT_MS).describe("Timeout for each historian prompt call in both TypeScript and Rust transform modes, in milliseconds (default: 600000)"),
7576
7553
  commit_cluster_trigger: object({
@@ -7603,7 +7580,8 @@ var MagicContextConfigSchema = object({
7603
7580
  overlay: boolean2().default(true).describe("Pi only: show the persistent todo overlay above the editor while tasks are active.")
7604
7581
  }).default({ enabled: false, overlay: true }).describe("Pi-only todowrite tool and overlay controls. Pi registers tools and widgets at extension boot, so changing this after /cd requires /reload or restart."),
7605
7582
  pi: PiConfigSchema.describe("Pi-only child-process extension controls. This setting is user-level only; project configuration cannot choose which extensions a user's subagent children load."),
7606
- smart_drops: boolean2().default(false).describe("Content-aware reclaim of provably-superseded tool output, layered on the existing execute-pass auto-drop. When on: superseded todowrite (keep newest 1), spent mmc_reduce (keep newest 3), and zero-value meta (bash_status, bash_kill, mmc_note read/dismiss) outputs are dropped; older edits to a file are compressed to a filePath-preserving marker while the newest edit per file stays full. Only acts on passes already busting the cache, so it never originates a cache bust. Honors the protected-tag reserve. Experimental: opt-in, default off until cache stability is proven; when off the wire is byte-identical to the positional-only reclaim. Requires a restart."),
7583
+ smart_drops: union([boolean2(), record(string2(), unknown())]).optional(),
7584
+ protected_tools: record(string2(), number2().int().nonnegative()).default({ ...DEFAULT_PROTECTED_TOOLS }).transform((map) => mergeProtectedTools(map)).describe("Keep each tool's newest N still-active results in every automatic drop lane (upstream issue 621). User and project maps merge over defaults {todowrite: 1, mmc_reduce: 3}; 0 turns protection off. Names are case-insensitive and ignore leading mcp_ (upstream's ctx_reduce maps to mmc_reduce). Holds even at 95% pressure, with no byte cap: large protected outputs can reach refusal sooner. Queued drops, from the agent or historian publication, are held until newer calls displace the result and a later cache-rebuilding pass applies them. The historian's summary is unaffected; the raw result leaves at the next fold. Frozen strips are unaffected. Changes and rotation never originate a bust; dropped results are never restored."),
7607
7585
  caveman_text_compression: object({
7608
7586
  enabled: boolean2().default(false).describe("Apply deterministic caveman-style text compression to old conversation text. Active for primary sessions when enabled; never for subagents. Compresses user/assistant text in oldest-first tiers: ultra (oldest 20%), full, lite, untouched (newest 40%)."),
7609
7587
  min_chars: number2().min(100).max(1e4).default(500).describe("Text parts shorter than this (characters) stay untouched. Min 100, max 10000. Default: 500.")
@@ -7669,13 +7647,12 @@ var MagicContextConfigSchema = object({
7669
7647
  }).describe("Automatic memory-maintenance run controls (dreamer replacement). USER-LEVEL ONLY: the whole group is stripped from project-tier config so a cloned repository cannot raise budgets, relax cooldowns, or loosen the anomaly guard.")
7670
7648
  });
7671
7649
  var LIVE_RELOAD_CONFIG_PATHS = [
7650
+ "cache_ttl",
7672
7651
  "toast_duration_ms",
7673
- "historian.opencode.model",
7674
- "historian.opencode.fallback_models",
7675
- "historian.opencode.variant",
7676
- "historian.pi.model",
7677
- "historian.pi.fallback_models",
7678
- "historian.pi.thinking_level",
7652
+ "historian.model",
7653
+ "historian.fallback_models",
7654
+ "historian.variant",
7655
+ "historian.thinking_level",
7679
7656
  "historian.two_pass",
7680
7657
  "historian.expand_tools",
7681
7658
  "historian.maxTokens",
@@ -9828,9 +9805,6 @@ function resolveEpochFloorForPass(db, sessionId, inputs) {
9828
9805
  return preSnapshotResult(firstObservedMemo, resolvedInputs);
9829
9806
  }
9830
9807
 
9831
- // src/hooks/magic-context/lkg-slot.ts
9832
- import { createHash as createHash4 } from "node:crypto";
9833
-
9834
9808
  // src/shared/bounded-session-map.ts
9835
9809
  class BoundedSessionMap {
9836
9810
  maxEntries;
@@ -9877,6 +9851,7 @@ class BoundedSessionMap {
9877
9851
  }
9878
9852
 
9879
9853
  // src/hooks/magic-context/lkg-slot.ts
9854
+ import { createHash as createHash4 } from "node:crypto";
9880
9855
  var LKG_TOTAL_BYTES = 64 * 1024 * 1024;
9881
9856
  var LKG_SINGLE_SLOT_BYTES = 24 * 1024 * 1024;
9882
9857
  var LKG_METADATA_BYTES = 256;
@@ -10401,6 +10376,29 @@ function layoutLkgPrefix(jsonPrefix) {
10401
10376
  const chunkHashes = chunks.map(hashLkgChunk);
10402
10377
  return { chunks, chunkHashes, chars: jsonPrefix.length, hash: hashLkgChunkList(chunkHashes) };
10403
10378
  }
10379
+ function assembleLkgPrefix(expected, rows) {
10380
+ const { chars, chunks, hash } = expected;
10381
+ if (typeof chars !== "number" || !Number.isSafeInteger(chars) || typeof chunks !== "number" || !Number.isSafeInteger(chunks) || typeof hash !== "string" || rows.length !== chunks) {
10382
+ return;
10383
+ }
10384
+ const bodies = [];
10385
+ let length = 0;
10386
+ for (let index = 0;index < rows.length; index += 1) {
10387
+ const row = rows[index];
10388
+ if (row?.chunk !== index || typeof row.body !== "string")
10389
+ return;
10390
+ bodies.push(row.body);
10391
+ length += row.body.length;
10392
+ }
10393
+ if (length !== chars)
10394
+ return;
10395
+ const chunkHashes = bodies.map(hashLkgChunk);
10396
+ if (chunkHashes.some((chunkHash, index) => rows[index]?.hash !== chunkHash))
10397
+ return;
10398
+ if (hashLkgChunkList(chunkHashes) !== hash)
10399
+ return;
10400
+ return { jsonPrefix: bodies.join(""), chunkHashes, hash };
10401
+ }
10404
10402
 
10405
10403
  // src/features/magic-context/migration-v2-write-split.ts
10406
10404
  var LKG_SLOT_CHUNKS_DDL = `
@@ -10559,6 +10557,113 @@ function splitReplayDecisions(db) {
10559
10557
  db.exec("DROP TABLE temp.v2_replay_documents");
10560
10558
  }
10561
10559
 
10560
+ // src/features/magic-context/temporal-decisions.ts
10561
+ var PREFIX = "temporal-message-v1:";
10562
+ function decodeTemporalDecision(entry) {
10563
+ if (!entry.startsWith(PREFIX))
10564
+ return null;
10565
+ try {
10566
+ const pair = JSON.parse(entry.slice(PREFIX.length));
10567
+ if (Array.isArray(pair) && pair.length === 2 && typeof pair[0] === "string" && pair[0] && typeof pair[1] === "string")
10568
+ return [pair[0], pair[1]];
10569
+ } catch {}
10570
+ return null;
10571
+ }
10572
+ function readRows(db, sessionId, messageIds) {
10573
+ if (!messageIds)
10574
+ return db.prepare("SELECT message_id,marker FROM temporal_decisions WHERE session_id=?").all(sessionId);
10575
+ const ids = [...messageIds];
10576
+ const result = [];
10577
+ for (let offset = 0;offset < ids.length; offset += 400) {
10578
+ const chunk = ids.slice(offset, offset + 400);
10579
+ result.push(...db.prepare(`SELECT message_id,marker FROM temporal_decisions WHERE session_id=? AND message_id IN (${chunk.map(() => "?").join(",")})`).all(sessionId, ...chunk));
10580
+ }
10581
+ return result;
10582
+ }
10583
+ function getTemporalDecisions(db, sessionId, messageIds) {
10584
+ return new Map(readRows(db, sessionId, messageIds).flatMap((row) => row.marker === null ? [] : [[row.message_id, row.marker]]));
10585
+ }
10586
+ function observeTemporalDecisions(db, sessionId, candidates, previouslyServed, messageIds) {
10587
+ const ids = new Set([...candidates.keys(), ...messageIds ?? []]);
10588
+ const rows = readRows(db, sessionId, ids);
10589
+ const known = new Set(rows.map((row) => row.message_id));
10590
+ const missing = [...candidates].filter(([id]) => !known.has(id));
10591
+ if (!missing.length)
10592
+ return new Map(rows.flatMap((row) => row.marker === null ? [] : [[row.message_id, row.marker]]));
10593
+ const transient = new Map;
10594
+ db.transaction(() => {
10595
+ const insert = db.prepare("INSERT OR IGNORE INTO temporal_decisions(session_id,message_id,marker) VALUES (?,?,?)");
10596
+ const servedTag = db.prepare("SELECT 1 FROM tags WHERE session_id=? AND message_id=? UNION ALL SELECT 1 FROM tags WHERE session_id=? AND message_id>=? AND message_id<? LIMIT 1");
10597
+ let served;
10598
+ for (const [id, candidate] of missing) {
10599
+ const historical = servedTag.get(sessionId, id, sessionId, `${id}:p`, `${id}:q`);
10600
+ if (historical) {
10601
+ served ??= previouslyServed?.(missing.map(([missingId]) => missingId)) ?? new Map;
10602
+ const previous = served.get(id);
10603
+ if (previous === undefined) {
10604
+ transient.set(id, candidate);
10605
+ continue;
10606
+ }
10607
+ insert.run(sessionId, id, previous === "" && candidate !== "" ? null : previous);
10608
+ } else {
10609
+ insert.run(sessionId, id, null);
10610
+ }
10611
+ }
10612
+ }).immediate();
10613
+ return new Map([...transient, ...getTemporalDecisions(db, sessionId, ids)]);
10614
+ }
10615
+ function freezeTemporalDecisions(db, sessionId, candidates) {
10616
+ if (candidates.size === 0)
10617
+ return new Map;
10618
+ return db.transaction(() => {
10619
+ const insert = db.prepare("INSERT INTO temporal_decisions(session_id,message_id,marker) VALUES (?,?,?) ON CONFLICT(session_id,message_id) DO UPDATE SET marker=excluded.marker WHERE temporal_decisions.marker IS NULL");
10620
+ for (const [id, marker] of candidates) {
10621
+ insert.run(sessionId, id, marker);
10622
+ }
10623
+ return getTemporalDecisions(db, sessionId, candidates.keys());
10624
+ }).immediate();
10625
+ }
10626
+
10627
+ // src/features/magic-context/migration-v4-temporal-decisions.ts
10628
+ var TEMPORAL_DECISIONS_DDL = `CREATE TABLE IF NOT EXISTS temporal_decisions (
10629
+ session_id TEXT NOT NULL,
10630
+ message_id TEXT NOT NULL,
10631
+ marker TEXT,
10632
+ PRIMARY KEY (session_id, message_id)
10633
+ ) WITHOUT ROWID`;
10634
+ function installV4TemporalDecisions(db) {
10635
+ const schema = new Map(db.prepare("SELECT name FROM sqlite_master").all().map((row) => [row.name, true]));
10636
+ if (!schema.has("temporal_decisions")) {
10637
+ db.exec(TEMPORAL_DECISIONS_DDL);
10638
+ if (schema.has("session_meta")) {
10639
+ const rows = db.prepare("SELECT session_id, merged_reasoning_stripped_ids AS entries FROM session_meta WHERE merged_reasoning_stripped_ids LIKE '%temporal-message-v1:%'").all();
10640
+ const insert = db.prepare("INSERT OR IGNORE INTO temporal_decisions(session_id,message_id,marker) VALUES (?,?,?)");
10641
+ for (const row of rows) {
10642
+ let entries;
10643
+ try {
10644
+ entries = JSON.parse(row.entries);
10645
+ } catch {
10646
+ sessionLog(row.session_id, "v4 temporal metadata: malformed JSON skipped; original blob retained");
10647
+ continue;
10648
+ }
10649
+ if (!Array.isArray(entries)) {
10650
+ sessionLog(row.session_id, "v4 temporal metadata: non-array JSON skipped; original blob retained");
10651
+ continue;
10652
+ }
10653
+ const kept = [];
10654
+ for (const entry of entries) {
10655
+ const decision = typeof entry === "string" ? decodeTemporalDecision(entry) : null;
10656
+ if (decision)
10657
+ insert.run(row.session_id, ...decision);
10658
+ else
10659
+ kept.push(entry);
10660
+ }
10661
+ db.prepare("UPDATE session_meta SET merged_reasoning_stripped_ids=? WHERE session_id=?").run(JSON.stringify(kept), row.session_id);
10662
+ }
10663
+ }
10664
+ }
10665
+ }
10666
+
10562
10667
  // src/features/magic-context/migrations.ts
10563
10668
  var FORK_MIGRATION_VERSION_FLOOR = 1e4;
10564
10669
  var MIGRATION_LOCK_RETRY_DELAYS_MS = [1000, 2000, 4000, 8000, 15000];
@@ -10590,6 +10695,20 @@ var MIGRATIONS = [
10590
10695
  splitLkgSlotPrefixes(db);
10591
10696
  splitReplayDecisions(db);
10592
10697
  }
10698
+ },
10699
+ {
10700
+ version: 3,
10701
+ description: "drop redundant single-column session indexes; add FTS rowid-map lookup",
10702
+ up(db) {
10703
+ installV3PerfSchema(db);
10704
+ }
10705
+ },
10706
+ {
10707
+ version: 4,
10708
+ description: "store temporal replay decisions per message identity",
10709
+ up(db) {
10710
+ installV4TemporalDecisions(db);
10711
+ }
10593
10712
  }
10594
10713
  ];
10595
10714
  var LATEST_MIGRATION_VERSION = MIGRATIONS.reduce((max, m) => Math.max(max, m.version), 0);
@@ -10994,7 +11113,7 @@ function getSchemaFenceRejection() {
10994
11113
  function getMigrationOnOpenRefusal() {
10995
11114
  return lastMigrationOnOpenRefusal;
10996
11115
  }
10997
- var LATEST_SUPPORTED_VERSION = 2;
11116
+ var LATEST_SUPPORTED_VERSION = 4;
10998
11117
  var BOOT_SQLITE_BUSY_TIMEOUT_MS = 5000;
10999
11118
  function ensureSecureStorageDir(dir) {
11000
11119
  ensureStorageDirectorySync(dir);
@@ -11386,8 +11505,8 @@ function finishDatabaseOpen(db, dbPath, explicitDbPath, latestSupportedVersion)
11386
11505
  startMessageFtsRowidMapBackfill(db).then(async () => {
11387
11506
  if (!readsOpenCodeStore)
11388
11507
  return;
11389
- const { readRawSessionMessagePage, readRawSessionMessages } = await import("./read-session-chunk-apjwrttc.js");
11390
- const { startMessageTimeBackfill } = await import("./message-time-backfill-5ewk0axe.js");
11508
+ const { readRawSessionMessagePage, readRawSessionMessages } = await import("./read-session-chunk-hp464g13.js");
11509
+ const { startMessageTimeBackfill } = await import("./message-time-backfill-zfernxbw.js");
11391
11510
  await startMessageTimeBackfill(db, Object.assign(readRawSessionMessages, {
11392
11511
  readPage: readRawSessionMessagePage
11393
11512
  }));
@@ -11483,7 +11602,6 @@ function initializeDatabase(db, busyTimeoutMs = BOOT_SQLITE_BUSY_TIMEOUT_MS) {
11483
11602
  harness TEXT NOT NULL DEFAULT 'opencode',
11484
11603
  UNIQUE(session_id, sequence)
11485
11604
  );
11486
- CREATE INDEX IF NOT EXISTS idx_compartments_session ON compartments(session_id);
11487
11605
 
11488
11606
  CREATE TABLE IF NOT EXISTS compartment_chunk_embeddings (
11489
11607
  id INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -11544,7 +11662,6 @@ function initializeDatabase(db, busyTimeoutMs = BOOT_SQLITE_BUSY_TIMEOUT_MS) {
11544
11662
  harness TEXT NOT NULL DEFAULT 'opencode',
11545
11663
  PRIMARY KEY(session_id, message_ordinal)
11546
11664
  );
11547
- CREATE INDEX IF NOT EXISTS idx_compression_depth_session ON compression_depth(session_id);
11548
11665
 
11549
11666
  CREATE TABLE IF NOT EXISTS session_facts (
11550
11667
  id INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -12063,7 +12180,6 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
12063
12180
  stale_reason TEXT,
12064
12181
  PRIMARY KEY (project_path, path)
12065
12182
  );
12066
- CREATE INDEX IF NOT EXISTS idx_project_key_files_project ON project_key_files(project_path);
12067
12183
  CREATE INDEX IF NOT EXISTS idx_project_key_files_generated_at ON project_key_files(project_path, generated_at);
12068
12184
 
12069
12185
  CREATE TABLE IF NOT EXISTS project_key_files_version (
@@ -12423,10 +12539,6 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
12423
12539
  input_tokens INTEGER NOT NULL DEFAULT 0,
12424
12540
  PRIMARY KEY (session_id, harness, message_id)
12425
12541
  );
12426
- CREATE INDEX IF NOT EXISTS idx_transform_decisions_session_harness
12427
- ON transform_decisions(session_id, harness);
12428
-
12429
- CREATE INDEX IF NOT EXISTS idx_tags_session_tag_number ON tags(session_id, tag_number);
12430
12542
  CREATE INDEX IF NOT EXISTS idx_tags_session_message_id ON tags(session_id, message_id);
12431
12543
 
12432
12544
  -- Clone/import paths can write tags before session bootstrap. Keep trigger-created
@@ -12472,10 +12584,7 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
12472
12584
  WHERE NEW.session_id != OLD.session_id
12473
12585
  ON CONFLICT(session_id) DO UPDATE SET tags_version = tags_version + 1;
12474
12586
  END;
12475
- CREATE INDEX IF NOT EXISTS idx_pending_ops_session ON pending_ops(session_id);
12476
12587
  CREATE INDEX IF NOT EXISTS idx_pending_ops_session_tag_id ON pending_ops(session_id, tag_id);
12477
- CREATE INDEX IF NOT EXISTS idx_source_contents_session ON source_contents(session_id);
12478
-
12479
12588
  CREATE TABLE IF NOT EXISTS recomp_compartments (
12480
12589
  id INTEGER PRIMARY KEY AUTOINCREMENT,
12481
12590
  session_id TEXT NOT NULL,
@@ -12820,8 +12929,6 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
12820
12929
  input_tokens INTEGER NOT NULL DEFAULT 0,
12821
12930
  PRIMARY KEY (session_id, harness, message_id)
12822
12931
  );
12823
- CREATE INDEX IF NOT EXISTS idx_transform_decisions_session_harness
12824
- ON transform_decisions(session_id, harness);
12825
12932
  `);
12826
12933
  ensureColumn(db, "transform_decisions", "system_hash_prev", "TEXT");
12827
12934
  ensureColumn(db, "transform_decisions", "system_hash_new", "TEXT");
@@ -12857,6 +12964,8 @@ CREATE INDEX IF NOT EXISTS idx_dream_queue_pending ON dream_queue(started_at, en
12857
12964
  ON tags(session_id, message_id)
12858
12965
  WHERE type = 'tool' AND tool_owner_message_id IS NULL;
12859
12966
  `);
12967
+ installV3PerfSchema(db);
12968
+ installV4TemporalDecisions(db);
12860
12969
  }
12861
12970
  var CHANNEL2_CLAIM_TTL_MS = 10 * 60000;
12862
12971
  var channel2HealStatements = new WeakMap;
@@ -13594,6 +13703,10 @@ var SESSION_SCOPED_TABLES = [
13594
13703
  { table: "tool_owner_backfill_state" },
13595
13704
  { table: "tags", harnessScoped: true },
13596
13705
  { table: "session_meta", harnessScoped: true },
13706
+ {
13707
+ table: "temporal_decisions",
13708
+ extraPredicate: "NOT EXISTS (SELECT 1 FROM session_meta AS remaining WHERE remaining.session_id = temporal_decisions.session_id)"
13709
+ },
13597
13710
  {
13598
13711
  table: "session_replay_decisions",
13599
13712
  extraPredicate: "NOT EXISTS (SELECT 1 FROM session_meta AS remaining WHERE remaining.session_id = session_replay_decisions.session_id)"
@@ -14165,15 +14278,15 @@ function createPreAdoptionToolSweepResolver(db, sessionId) {
14165
14278
  }
14166
14279
 
14167
14280
  // src/features/magic-context/pi-content-decisions.ts
14168
- var PREFIX = "pi-content-replay-v1:";
14281
+ var PREFIX2 = "pi-content-replay-v1:";
14169
14282
  function encodePiContentDecision(kind, messageId) {
14170
- return PREFIX + JSON.stringify([kind, messageId]);
14283
+ return PREFIX2 + JSON.stringify([kind, messageId]);
14171
14284
  }
14172
14285
  function decodePiContentDecision(value) {
14173
- if (!value.startsWith(PREFIX))
14286
+ if (!value.startsWith(PREFIX2))
14174
14287
  return null;
14175
14288
  try {
14176
- const pair = JSON.parse(value.slice(PREFIX.length));
14289
+ const pair = JSON.parse(value.slice(PREFIX2.length));
14177
14290
  if (Array.isArray(pair) && pair.length === 2 && (pair[0] === "reminder-strip" || pair[0] === "seam-temporal-strip") && typeof pair[1] === "string" && pair[1].length > 0)
14178
14291
  return [pair[0], pair[1]];
14179
14292
  } catch {}
@@ -14983,101 +15096,6 @@ function dismissNotes(db, noteIds, scope) {
14983
15096
  function dismissNote(db, noteId, scope) {
14984
15097
  return dismissNotes(db, [noteId], scope)[0]?.outcome === "dismissed";
14985
15098
  }
14986
- // src/features/magic-context/storage-ops.ts
14987
- var queuePendingOpStatements = new WeakMap;
14988
- var queueUnchangedDropStatements = new WeakMap;
14989
- var getPendingOpsStatements = new WeakMap;
14990
- var getPendingOpsCountStatements = new WeakMap;
14991
- var clearPendingOpsStatements = new WeakMap;
14992
- var removePendingOpStatements = new WeakMap;
14993
- function getQueuePendingOpStatement(db) {
14994
- let stmt = queuePendingOpStatements.get(db);
14995
- if (!stmt) {
14996
- stmt = db.prepare("INSERT INTO pending_ops (session_id, tag_id, operation, queued_at, harness) VALUES (?, ?, ?, ?, ?)");
14997
- queuePendingOpStatements.set(db, stmt);
14998
- }
14999
- return stmt;
15000
- }
15001
- function getPendingOpsStatement(db) {
15002
- let stmt = getPendingOpsStatements.get(db);
15003
- if (!stmt) {
15004
- stmt = db.prepare("SELECT id, session_id, tag_id, operation, queued_at FROM pending_ops WHERE session_id = ? ORDER BY queued_at ASC, id ASC");
15005
- getPendingOpsStatements.set(db, stmt);
15006
- }
15007
- return stmt;
15008
- }
15009
- function getClearPendingOpsStatement(db) {
15010
- let stmt = clearPendingOpsStatements.get(db);
15011
- if (!stmt) {
15012
- stmt = db.prepare("DELETE FROM pending_ops WHERE session_id = ?");
15013
- clearPendingOpsStatements.set(db, stmt);
15014
- }
15015
- return stmt;
15016
- }
15017
- function getRemovePendingOpStatement(db) {
15018
- let stmt = removePendingOpStatements.get(db);
15019
- if (!stmt) {
15020
- stmt = db.prepare("DELETE FROM pending_ops WHERE session_id = ? AND tag_id = ?");
15021
- removePendingOpStatements.set(db, stmt);
15022
- }
15023
- return stmt;
15024
- }
15025
- function isPendingOpRow(row) {
15026
- if (row === null || typeof row !== "object")
15027
- return false;
15028
- const r = row;
15029
- return typeof r.id === "number" && typeof r.session_id === "string" && typeof r.tag_id === "number" && typeof r.operation === "string" && typeof r.queued_at === "number";
15030
- }
15031
- function toPendingOp(row) {
15032
- if (row.operation !== "drop") {
15033
- sessionLog(row.session_id, `unknown pending operation "${row.operation}"; ignoring`);
15034
- return null;
15035
- }
15036
- return {
15037
- id: row.id,
15038
- sessionId: row.session_id,
15039
- tagId: row.tag_id,
15040
- operation: row.operation,
15041
- queuedAt: row.queued_at
15042
- };
15043
- }
15044
- function queuePendingOp(db, sessionId, tagId, operation, queuedAt = Date.now()) {
15045
- getQueuePendingOpStatement(db).run(sessionId, tagId, operation, queuedAt, getHarness());
15046
- }
15047
- function queuePendingDropForUnchangedTag(db, sessionId, tag) {
15048
- let statement = queueUnchangedDropStatements.get(db);
15049
- if (!statement) {
15050
- statement = db.prepare(`INSERT INTO pending_ops (session_id, tag_id, operation, queued_at, harness)
15051
- SELECT session_id, tag_number, 'drop', ?, ? FROM tags
15052
- WHERE id = ? AND session_id = ? AND tag_number = ? AND message_id = ?
15053
- AND type = ? AND tool_owner_message_id IS ? AND status = 'active'`);
15054
- queueUnchangedDropStatements.set(db, statement);
15055
- }
15056
- return statement.run(Date.now(), getHarness(), tag.id ?? null, sessionId, tag.tagNumber, tag.messageId, tag.type, tag.toolOwnerMessageId).changes > 0;
15057
- }
15058
- function getPendingOps(db, sessionId) {
15059
- const rows = getPendingOpsStatement(db).all(sessionId).filter(isPendingOpRow);
15060
- return rows.map(toPendingOp).filter((op) => op !== null);
15061
- }
15062
- function getPendingOpsCount(db, sessionId) {
15063
- try {
15064
- let statement = getPendingOpsCountStatements.get(db);
15065
- if (!statement) {
15066
- statement = db.prepare("SELECT COUNT(*) AS count FROM pending_ops WHERE session_id = ?");
15067
- getPendingOpsCountStatements.set(db, statement);
15068
- }
15069
- const row = statement.get(sessionId);
15070
- return typeof row?.count === "number" && Number.isFinite(row.count) ? row.count : null;
15071
- } catch {
15072
- return null;
15073
- }
15074
- }
15075
- function clearPendingOps(db, sessionId) {
15076
- getClearPendingOpsStatement(db).run(sessionId);
15077
- }
15078
- function removePendingOp(db, sessionId, tagId) {
15079
- getRemovePendingOpStatement(db).run(sessionId, tagId);
15080
- }
15081
15099
  // src/features/magic-context/storage-primers.ts
15082
15100
  var PRIMER_CANDIDATE_TTL_MS = 90 * 24 * 60 * 60 * 1000;
15083
15101
  var PRIMER_CANDIDATE_MAX_AGE_MS = 180 * 24 * 60 * 60 * 1000;
@@ -16353,9 +16371,6 @@ function renderCapabilityRefusal(capability) {
16353
16371
  return renderUserFacingFailure(CAPABILITY_FAILURES[capability]);
16354
16372
  }
16355
16373
 
16356
- // src/v2/hooks/hidden-child.ts
16357
- import { createHash as createHash9 } from "node:crypto";
16358
-
16359
16374
  // src/hooks/magic-context/compartment-runner-types.ts
16360
16375
  class HiddenCompletionRefusal extends Error {
16361
16376
  code;
@@ -16369,6 +16384,7 @@ class HiddenCompletionRefusal extends Error {
16369
16384
  }
16370
16385
 
16371
16386
  // src/v2/hooks/hidden-child.ts
16387
+ import { createHash as createHash9 } from "node:crypto";
16372
16388
  var HIDDEN_HISTORIAN_AGENT = "historian";
16373
16389
  var AGENT_TOOL_ALLOWLIST = {
16374
16390
  [HIDDEN_HISTORIAN_AGENT]: [],
@@ -16378,9 +16394,22 @@ var AGENT_TOOL_ALLOWLIST = {
16378
16394
  var AGENT_STEP_CAPS = {
16379
16395
  [MEMORY_MAINTAINER_A_AGENT]: MEMORY_MAINTAINER_A_STEP_CAP
16380
16396
  };
16397
+ function hiddenAgentAllowedTools(agent) {
16398
+ return agent !== undefined && Object.hasOwn(AGENT_TOOL_ALLOWLIST, agent) ? AGENT_TOOL_ALLOWLIST[agent] : undefined;
16399
+ }
16400
+ function hiddenChildPermissions(agent) {
16401
+ return [
16402
+ { action: "*", resource: "*", effect: "deny" },
16403
+ ...(AGENT_TOOL_ALLOWLIST[agent] ?? []).map((tool) => ({
16404
+ action: tool,
16405
+ resource: "*",
16406
+ effect: "allow"
16407
+ }))
16408
+ ];
16409
+ }
16381
16410
  async function registerHiddenChildAgents(agent) {
16382
16411
  await agent.transform((editor) => {
16383
- for (const [id, allowed] of Object.entries(AGENT_TOOL_ALLOWLIST)) {
16412
+ for (const id of Object.keys(AGENT_TOOL_ALLOWLIST)) {
16384
16413
  editor.update(id, (config) => {
16385
16414
  config.system = "Magic Context hidden completion carrier.";
16386
16415
  config.description = "Internal Magic Context hidden completion carrier.";
@@ -16392,14 +16421,7 @@ async function registerHiddenChildAgents(agent) {
16392
16421
  const stepCap = AGENT_STEP_CAPS[id];
16393
16422
  if (stepCap !== undefined)
16394
16423
  config.steps = stepCap;
16395
- config.permissions = [
16396
- { action: "*", resource: "*", effect: "deny" },
16397
- ...allowed.map((tool) => ({
16398
- action: tool,
16399
- resource: "*",
16400
- effect: "allow"
16401
- }))
16402
- ];
16424
+ config.permissions = hiddenChildPermissions(id);
16403
16425
  });
16404
16426
  }
16405
16427
  });
@@ -16492,17 +16514,21 @@ function firstDifference(a, b) {
16492
16514
 
16493
16515
  class HiddenChildHook {
16494
16516
  note;
16495
- childIDs = new Set;
16517
+ childIDs = new Map;
16496
16518
  attempts = new Map;
16497
16519
  active = new Map;
16498
16520
  constructor(note = log) {
16499
16521
  this.note = note;
16500
16522
  }
16501
- registerChild(sessionID) {
16502
- this.childIDs.add(sessionID);
16523
+ registerChild(sessionID, agent) {
16524
+ if (agent !== undefined || !this.childIDs.has(sessionID))
16525
+ this.childIDs.set(sessionID, agent ?? this.childIDs.get(sessionID));
16526
+ }
16527
+ agentFor(sessionID) {
16528
+ return this.childIDs.get(sessionID);
16503
16529
  }
16504
16530
  registerAttempt(marker, attempt) {
16505
- this.registerChild(attempt.childSessionId);
16531
+ this.registerChild(attempt.childSessionId, attempt.agent);
16506
16532
  attempt.marker = marker;
16507
16533
  this.attempts.set(marker, attempt);
16508
16534
  }
@@ -16516,9 +16542,24 @@ class HiddenChildHook {
16516
16542
  owns(sessionID) {
16517
16543
  return this.childIDs.has(sessionID);
16518
16544
  }
16519
- compactionSummary(sessionID) {
16520
- if (!this.owns(sessionID))
16545
+ toolCallRefusal(call) {
16546
+ const owned = this.owns(call.sessionID);
16547
+ const agent = owned ? this.agentFor(call.sessionID) ?? call.agent : call.agent;
16548
+ const allowed = hiddenAgentAllowedTools(agent);
16549
+ if (allowed === undefined) {
16550
+ return owned ? `Magic Context hidden child ${call.sessionID} has no tool allowlist; ${call.tool} refused` : undefined;
16551
+ }
16552
+ if (allowed.includes(call.tool))
16553
+ return;
16554
+ return `Magic Context hidden agent ${agent} may only use ${allowed.length > 0 ? allowed.join(", ") : "no tools"}; ${call.tool} refused`;
16555
+ }
16556
+ compactionSummary(sessionID, agent) {
16557
+ if (!this.owns(sessionID)) {
16558
+ if (hiddenAgentAllowedTools(agent) !== undefined) {
16559
+ this.refuse("Refusing to compact a Magic Context hidden-agent session this instance did not register", { sessionID, messages: [] }, undefined);
16560
+ }
16521
16561
  return;
16562
+ }
16522
16563
  const active = this.active.get(sessionID);
16523
16564
  const pending = [...this.attempts.values()].filter((attempt) => attempt.childSessionId === sessionID && !attempt.shaped);
16524
16565
  const inFlight = active ? [active] : pending;
@@ -16563,8 +16604,12 @@ class HiddenChildHook {
16563
16604
  return parts;
16564
16605
  }
16565
16606
  apply(draft) {
16566
- if (!this.owns(draft.sessionID))
16607
+ if (!this.owns(draft.sessionID)) {
16608
+ if (hiddenAgentAllowedTools(draft.agent) !== undefined) {
16609
+ this.refuse("Refusing a Magic Context hidden-agent turn this instance did not register", draft, newestUserText(draft));
16610
+ }
16567
16611
  return false;
16612
+ }
16568
16613
  const raw = newestUserText(draft);
16569
16614
  let attempt;
16570
16615
  for (const candidate of raw === undefined ? [] : markerCandidates(raw)) {
@@ -17567,19 +17612,19 @@ function findBoundaryUserMessage(sessionId, endMessageId) {
17567
17612
  AND NOT (COALESCE(json_extract(data, '$.summary'), 0) = 1
17568
17613
  AND COALESCE(json_extract(data, '$.finish'), '') = 'stop')
17569
17614
  AND COALESCE(json_extract(data, '$.role'), '') = 'user'
17570
- AND (time_created < ? OR (time_created = ? AND id <= ?))
17615
+ AND (time_created, id) <= (?, ?)
17571
17616
  AND NOT (
17572
17617
  EXISTS (SELECT 1 FROM part p
17573
- WHERE p.message_id = message.id AND +p.session_id = message.session_id
17618
+ WHERE likelihood(p.message_id = message.id, 0.000001) AND +p.session_id = message.session_id
17574
17619
  AND COALESCE(json_extract(p.data, '$.type'), '') <> 'compaction')
17575
17620
  AND NOT EXISTS (SELECT 1 FROM part p
17576
- WHERE p.message_id = message.id AND +p.session_id = message.session_id
17621
+ WHERE likelihood(p.message_id = message.id, 0.000001) AND +p.session_id = message.session_id
17577
17622
  AND COALESCE(json_extract(p.data, '$.type'), '') <> 'compaction'
17578
17623
  AND COALESCE(json_extract(p.data, '$.synthetic'), 0) <> 1
17579
17624
  AND COALESCE(json_extract(p.data, '$.syntheticTodoMarker'), 0) <> 1)
17580
17625
  )
17581
17626
  ORDER BY time_created DESC, id DESC
17582
- LIMIT 1`).get(sessionId, target.timeCreated, target.timeCreated, target.id);
17627
+ LIMIT 1`).get(sessionId, target.timeCreated, target.id);
17583
17628
  if (typeof boundary?.id !== "string" || typeof boundary.time_created !== "number") {
17584
17629
  return null;
17585
17630
  }
@@ -18048,9 +18093,17 @@ function existingMarkerAlreadyCoversTarget(sessionId, existing, targetOrdinal, t
18048
18093
  return true;
18049
18094
  }
18050
18095
  function applyDeferredCompactionMarker(db, sessionId, pending, directory, trustedBoundary) {
18096
+ let stepStartedAt = performance.now();
18097
+ const stepMs = [];
18098
+ const endStep = (name) => {
18099
+ const now = performance.now();
18100
+ stepMs.push(`${name}Ms=${(now - stepStartedAt).toFixed(1)}`);
18101
+ stepStartedAt = now;
18102
+ };
18051
18103
  try {
18052
18104
  const responseFencesTarget = trustedBoundary !== undefined && Number.isSafeInteger(trustedBoundary.rowVersion) && trustedBoundary.rowVersion > 0 && trustedBoundary.ordinal === pending.ordinal && trustedBoundary.endMessageId === pending.endMessageId;
18053
18105
  const validation = responseFencesTarget ? "ok" : validatePendingTarget(db, sessionId, pending);
18106
+ endStep("validate");
18054
18107
  if (validation !== "ok") {
18055
18108
  sessionLog(sessionId, `compaction-marker drain: stale-skip (${validation}) for ordinal ${pending.ordinal} endMessageId=${pending.endMessageId}`);
18056
18109
  return { kind: "stale-skip", reason: validation };
@@ -18060,12 +18113,14 @@ function applyDeferredCompactionMarker(db, sessionId, pending, directory, truste
18060
18113
  return { kind: "already-current" };
18061
18114
  }
18062
18115
  const boundary = findBoundaryUserMessage(sessionId, pending.endMessageId);
18116
+ endStep("boundary");
18063
18117
  if (!boundary) {
18064
18118
  return {
18065
18119
  kind: "retryable-failure",
18066
18120
  error: new Error(`no user boundary found at or before endMessageId ${pending.endMessageId} (ordinal ${pending.ordinal}); preserving existing marker`)
18067
18121
  };
18068
18122
  }
18123
+ endStep("discardCheck");
18069
18124
  const removedSummaryMessageId = existing?.summaryMessageId ?? null;
18070
18125
  const replacement = replaceCompactionMarker(existing, {
18071
18126
  sessionId,
@@ -18075,6 +18130,7 @@ function applyDeferredCompactionMarker(db, sessionId, pending, directory, truste
18075
18130
  directory: directory ?? process.cwd(),
18076
18131
  resolvedBoundary: boundary
18077
18132
  });
18133
+ endStep("replace");
18078
18134
  if (replacement.kind !== "committed") {
18079
18135
  return {
18080
18136
  kind: "retryable-failure",
@@ -18087,7 +18143,8 @@ function applyDeferredCompactionMarker(db, sessionId, pending, directory, truste
18087
18143
  boundaryOrdinal: pending.ordinal,
18088
18144
  targetEndMessageId: pending.endMessageId
18089
18145
  }, removedSummaryMessageId);
18090
- sessionLog(sessionId, `compaction-marker drain: applied at ordinal ${pending.ordinal}, boundary user msg ${result.boundaryMessageId}`);
18146
+ endStep("persist");
18147
+ sessionLog(sessionId, `compaction-marker drain: applied at ordinal ${pending.ordinal}, boundary user msg ${result.boundaryMessageId} ${stepMs.join(" ")}`);
18091
18148
  return {
18092
18149
  kind: "applied",
18093
18150
  markerOrdinal: pending.ordinal
@@ -18192,6 +18249,7 @@ var MEMORY_EPOCH_COMPONENT_PREFIX = "|memory-render:";
18192
18249
  var MURAL_COMPONENT_PREFIX = "|mural-enabled:";
18193
18250
  var BUDGET_COMPONENT_PREFIX = "|render-budgets:";
18194
18251
  var RENDERED_BUDGETS_COMPONENT_PREFIX = "|rendered-budgets:";
18252
+ var M0_MEMORY_IDS_COMPONENT_PREFIX = "|m0-memory-ids:";
18195
18253
  function encodeCachedM0UpgradeIdentity(upgradeState, compartmentRenderEpoch = COMPARTMENT_RENDER_EPOCH, muralEnabled = null, renderBudgetIdentity = null, memoryRenderEpoch = MEMORY_RENDER_FORMAT_EPOCH, renderedBudgets = null) {
18196
18254
  let encoded = upgradeState ?? "";
18197
18255
  if (compartmentRenderEpoch !== null) {
@@ -18236,7 +18294,8 @@ function decodeCachedM0UpgradeIdentity(value) {
18236
18294
  value.indexOf(MEMORY_EPOCH_COMPONENT_PREFIX),
18237
18295
  value.indexOf(MURAL_COMPONENT_PREFIX),
18238
18296
  value.indexOf(BUDGET_COMPONENT_PREFIX),
18239
- value.indexOf(RENDERED_BUDGETS_COMPONENT_PREFIX)
18297
+ value.indexOf(RENDERED_BUDGETS_COMPONENT_PREFIX),
18298
+ value.indexOf(M0_MEMORY_IDS_COMPONENT_PREFIX)
18240
18299
  ].filter((index) => index >= 0);
18241
18300
  const identityEnd = componentIndexes.length > 0 ? Math.min(...componentIndexes) : value.length;
18242
18301
  const upgradeState = value.slice(0, identityEnd);
@@ -18250,6 +18309,22 @@ function decodeCachedM0UpgradeIdentity(value) {
18250
18309
  renderedBudgets: component(value, RENDERED_BUDGETS_COMPONENT_PREFIX)
18251
18310
  };
18252
18311
  }
18312
+ function withCachedM0MemoryIds(identity, ids) {
18313
+ const withoutIds = (identity ?? "").replace(/\|m0-memory-ids:[^|]*/g, "");
18314
+ return `${withoutIds}${M0_MEMORY_IDS_COMPONENT_PREFIX}${JSON.stringify(ids)}`;
18315
+ }
18316
+ function readCachedM0MemoryIds(identity, legacyVisibleIds, maxMemoryId) {
18317
+ const encoded = component(identity ?? "", M0_MEMORY_IDS_COMPONENT_PREFIX);
18318
+ if (encoded !== null) {
18319
+ try {
18320
+ const ids = JSON.parse(encoded);
18321
+ if (Array.isArray(ids) && ids.every((id) => Number.isSafeInteger(id) && id > 0)) {
18322
+ return ids;
18323
+ }
18324
+ } catch {}
18325
+ }
18326
+ return legacyVisibleIds.filter((id) => id <= maxMemoryId);
18327
+ }
18253
18328
  function renderBudgetIdentityChanged(cached, current) {
18254
18329
  const legacy = /^(m[^-]+)-h\d+$/.exec(cached);
18255
18330
  if (legacy && current.startsWith("m") && current.includes("-hp")) {
@@ -18530,6 +18605,7 @@ function formatDate(ms) {
18530
18605
  return `${yyyy}-${mm}-${dd}`;
18531
18606
  }
18532
18607
  var TEMPORAL_MARKER_PATTERN = /^<!-- \+[\d]+[mhdw](?: [\d]+[mhdw])? -->\n/;
18608
+ var TEMPORAL_MARKER_REPLAY_PATTERN = /^<!-- \+[\d]+[mhdw](?: [\d]+[mhdw])? -->(?:\n|$)/;
18533
18609
  function temporalMarkerPrefix(seconds) {
18534
18610
  const marker = formatGap(seconds);
18535
18611
  if (!marker)
@@ -18553,7 +18629,23 @@ function findFirstVisibleTextPart(parts) {
18553
18629
  }
18554
18630
  return null;
18555
18631
  }
18556
- function injectTemporalMarkers(messages) {
18632
+ function collectTemporalCandidates(messages) {
18633
+ const candidates = new Map;
18634
+ let prev = null;
18635
+ for (const raw of messages) {
18636
+ if (!raw || typeof raw !== "object")
18637
+ continue;
18638
+ const msg = raw;
18639
+ if (msg.info?.id && msg.info.role === "user" && Array.isArray(msg.parts) && hasMeaningfulUserText2(msg.parts)) {
18640
+ const current = msg.info.time?.created;
18641
+ const prior = prev?.info?.time;
18642
+ candidates.set(msg.info.id, current !== undefined && prior?.created !== undefined ? temporalMarkerPrefix((current - (prior.completed ?? prior.created)) / 1000) ?? "" : "");
18643
+ }
18644
+ prev = msg;
18645
+ }
18646
+ return candidates;
18647
+ }
18648
+ function injectTemporalMarkers(messages, frozen) {
18557
18649
  let injected = 0;
18558
18650
  let prev = null;
18559
18651
  for (const raw of messages) {
@@ -18561,6 +18653,20 @@ function injectTemporalMarkers(messages) {
18561
18653
  continue;
18562
18654
  const msg = raw;
18563
18655
  const role = msg.info?.role;
18656
+ if (frozen) {
18657
+ const marker = msg.info?.id ? frozen.get(msg.info.id) : undefined;
18658
+ const target = Array.isArray(msg.parts) ? findFirstVisibleTextPart(msg.parts) : null;
18659
+ if (marker !== undefined && target?.text !== undefined) {
18660
+ const { tagPrefix, body } = peelLeadingMcTagNotation(target.text);
18661
+ const source = body.replace(TEMPORAL_MARKER_REPLAY_PATTERN, "");
18662
+ const text = tagPrefix + (source ? marker + source : marker.trimEnd());
18663
+ if (text !== target.text) {
18664
+ target.text = text;
18665
+ injected++;
18666
+ }
18667
+ }
18668
+ continue;
18669
+ }
18564
18670
  const authoredUser = role === "user" && Array.isArray(msg.parts) && hasMeaningfulUserText2(msg.parts);
18565
18671
  if (prev !== null && authoredUser) {
18566
18672
  const prevTime = prev.info?.time;
@@ -19442,6 +19548,9 @@ function mustMaterialize(args) {
19442
19548
  return withToolSetHashComparison({ value: true, reason: "project_change" });
19443
19549
  }
19444
19550
  }
19551
+ if (args.state.cachedM0ProjectMemoryEpoch !== current.projectMemoryEpoch) {
19552
+ return { value: true, reason: "project_memory_epoch" };
19553
+ }
19445
19554
  if (args.state.cachedM0MaxMutationId !== current.maxMutationId) {
19446
19555
  return withToolSetHashComparison({ value: true, reason: "max_mutation_id" });
19447
19556
  }
@@ -19692,7 +19801,7 @@ ${sessionHistory}
19692
19801
 
19693
19802
  `).trim();
19694
19803
  }
19695
- function applyMarkersToState(state, m0Bytes, markers, m1Bytes) {
19804
+ function applyMarkersToState(state, m0Bytes, markers, m1Bytes, renderedM0Ids) {
19696
19805
  state.cachedM0Bytes = m0Bytes;
19697
19806
  if (m1Bytes)
19698
19807
  state.cachedM1Bytes = m1Bytes;
@@ -19706,7 +19815,7 @@ function applyMarkersToState(state, m0Bytes, markers, m1Bytes) {
19706
19815
  state.cachedM0ProjectDocsHash = markers.projectDocsHash;
19707
19816
  state.cachedM0MaterializedAt = markers.materializedAt;
19708
19817
  state.cachedM0SessionFactsVersion = markers.sessionFactsVersion;
19709
- state.cachedM0UpgradeState = encodeCachedM0UpgradeIdentity(markers.upgradeState, markers.compartmentRenderEpoch, markers.muralEnabled, markers.renderBudgetIdentity, markers.memoryRenderEpoch, markers.renderedBudgets ?? null);
19818
+ state.cachedM0UpgradeState = withCachedM0MemoryIds(encodeCachedM0UpgradeIdentity(markers.upgradeState, markers.compartmentRenderEpoch, markers.muralEnabled, markers.renderBudgetIdentity, markers.memoryRenderEpoch, markers.renderedBudgets ?? null), renderedM0Ids);
19710
19819
  state.cachedM0SystemHash = markers.systemHash;
19711
19820
  state.cachedM0ToolSetHash = markers.toolSetHash;
19712
19821
  state.cachedM0ModelKey = markers.modelKey;
@@ -19805,10 +19914,18 @@ function materializeM0(options) {
19805
19914
  snapshotMarkers.materializedAt = foldMaterializedAt;
19806
19915
  const renderedMemoryIds = trimmed.renderOrder.map((m) => m.id);
19807
19916
  options.beforePhase3ForTest?.();
19917
+ const steps = new WriteTransactionSteps;
19918
+ const upgradeIdentity = withCachedM0MemoryIds(encodeCachedM0UpgradeIdentity(snapshotMarkers.upgradeState, snapshotMarkers.compartmentRenderEpoch, snapshotMarkers.muralEnabled, snapshotMarkers.renderBudgetIdentity, snapshotMarkers.memoryRenderEpoch, snapshotMarkers.renderedBudgets ?? null), renderedMemoryIds);
19919
+ const baselineEndMessageId = lastCompartmentBoundaryId(compartments);
19920
+ steps.mark("pre_metadata");
19921
+ const commitFold = options.onFoldPrepare?.();
19922
+ steps.mark("pre_onFoldPrepare");
19808
19923
  let m1Text = M1_EMPTY_PLACEHOLDER;
19809
19924
  let m1Bytes = Buffer4.from(m1Text, "utf8");
19925
+ options.beforeCacheCommitForTest?.();
19810
19926
  const transactionStartedAt = performance.now();
19811
19927
  options.db.exec("BEGIN IMMEDIATE");
19928
+ steps.reset();
19812
19929
  try {
19813
19930
  const currentWorkspace = resolveWorkspaceRenderContext({
19814
19931
  db: options.db,
@@ -19837,23 +19954,26 @@ function materializeM0(options) {
19837
19954
  renderBudgetIdentity: snapshotMarkers.renderBudgetIdentity,
19838
19955
  renderedBudgets: snapshotMarkers.renderedBudgets
19839
19956
  };
19840
- const stale = current.projectUserProfileVersion !== snapshotMarkers.projectUserProfileVersion || current.maxCompartmentSeq !== snapshotMarkers.maxCompartmentSeq || current.maxMutationId !== snapshotMarkers.maxMutationId || current.maxMemoryMutationId !== snapshotMarkers.maxMemoryMutationId || current.sessionFactsVersion !== snapshotMarkers.sessionFactsVersion || current.upgradeState !== snapshotMarkers.upgradeState || (current.projectIdentity ?? null) !== (snapshotMarkers.projectIdentity ?? null);
19957
+ const stale = current.projectUserProfileVersion !== snapshotMarkers.projectUserProfileVersion || current.projectMemoryEpoch !== snapshotMarkers.projectMemoryEpoch || current.maxCompartmentSeq !== snapshotMarkers.maxCompartmentSeq || current.maxMutationId !== snapshotMarkers.maxMutationId || current.maxMemoryMutationId !== snapshotMarkers.maxMemoryMutationId || current.sessionFactsVersion !== snapshotMarkers.sessionFactsVersion || current.upgradeState !== snapshotMarkers.upgradeState || (current.projectIdentity ?? null) !== (snapshotMarkers.projectIdentity ?? null);
19841
19958
  if (stale) {
19842
19959
  options.db.exec("ROLLBACK");
19843
19960
  throw new MaterializeContentionError({ reason: "snapshot changed before Phase 3" });
19844
19961
  }
19845
- const m1Render = renderM1WithMetadata({
19962
+ steps.mark("staleCheck");
19963
+ const rendered = renderM1WithMetadata({
19846
19964
  ...options,
19847
19965
  workspaceIdentitySet: {
19848
19966
  identities: workspace.identities,
19849
19967
  namesByIdentity: workspace.namesByIdentity
19850
19968
  }
19851
19969
  }, snapshotMarkers, renderedMemoryIds);
19852
- m1Text = m1Render.text;
19970
+ m1Text = rendered.text;
19853
19971
  m1Bytes = Buffer4.from(m1Text, "utf8");
19854
19972
  const visibleMemoryIds = [
19855
- ...new Set([...renderedMemoryIds, ...m1Render.renderedMemoryIds])
19973
+ ...new Set([...renderedMemoryIds, ...rendered.renderedMemoryIds])
19856
19974
  ];
19975
+ const visibleIdsJson = JSON.stringify(visibleMemoryIds);
19976
+ steps.mark("m1Render");
19857
19977
  persistCachedM0(options.db, options.sessionId, {
19858
19978
  m0Bytes,
19859
19979
  muralDataUrl: frozenMuralDataUrl,
@@ -19869,21 +19989,24 @@ function materializeM0(options) {
19869
19989
  projectDocsHash: snapshotMarkers.projectDocsHash,
19870
19990
  materializedAt: snapshotMarkers.materializedAt,
19871
19991
  sessionFactsVersion: snapshotMarkers.sessionFactsVersion,
19872
- upgradeState: encodeCachedM0UpgradeIdentity(snapshotMarkers.upgradeState, snapshotMarkers.compartmentRenderEpoch, snapshotMarkers.muralEnabled, snapshotMarkers.renderBudgetIdentity, snapshotMarkers.memoryRenderEpoch, snapshotMarkers.renderedBudgets ?? null),
19992
+ upgradeState: upgradeIdentity,
19873
19993
  systemHash: snapshotMarkers.systemHash,
19874
19994
  toolSetHash: snapshotMarkers.toolSetHash,
19875
19995
  modelKey: snapshotMarkers.modelKey,
19876
19996
  projectIdentity: snapshotMarkers.projectIdentity
19877
19997
  });
19878
- options.db.prepare("UPDATE session_meta SET memory_block_count = ?, memory_block_ids = ? WHERE session_id = ?").run(visibleMemoryIds.length, JSON.stringify(visibleMemoryIds), options.sessionId);
19879
- const baselineEndMessageId = lastCompartmentBoundaryId(compartments);
19998
+ steps.mark("persistCachedM0");
19999
+ options.db.prepare("UPDATE session_meta SET memory_block_count = ?, memory_block_ids = ?, cached_m0_last_baseline_end_message_id = ? WHERE session_id = ?").run(visibleMemoryIds.length, visibleIdsJson, baselineEndMessageId, options.sessionId);
19880
20000
  options.db.prepare("UPDATE session_meta SET cached_m0_last_baseline_end_message_id = ? WHERE session_id = ?").run(baselineEndMessageId, options.sessionId);
19881
- options.onFoldCommit?.(options.db, {
20001
+ steps.mark("sessionMeta");
20002
+ commitFold?.(options.db, {
19882
20003
  m0Bytes,
19883
20004
  m1Bytes
19884
20005
  });
20006
+ steps.mark("onFoldCommit");
19885
20007
  options.db.exec("COMMIT");
19886
- logSlowWriteTransaction("opencode_materialize_cache", transactionStartedAt);
20008
+ steps.mark("commit");
20009
+ logSlowWriteTransaction("opencode_materialize_cache", transactionStartedAt, undefined, performance.now(), steps.durations);
19887
20010
  options.state.cachedM0MuralDataUrl = frozenMuralDataUrl;
19888
20011
  options.state.cachedM0MuralHash = frozenMuralHash;
19889
20012
  } catch (error) {
@@ -20013,7 +20136,7 @@ ${newCompartments.map((compartment) => renderCompartmentAtTier(compartment, 1)).
20013
20136
  const newMemoriesBlock = renderMemoryBlockV2(deltaMemories, "new-memories", newMemoryRenderOptions);
20014
20137
  if (newMemoriesBlock)
20015
20138
  blocks.push(newMemoriesBlock);
20016
- const renderedNewMemoryIds = newMemoriesBlock ? trimmedNewMemories.map((memory) => memory.id) : [];
20139
+ const renderedNewMemoryIds = newMemoriesBlock ? deltaMemories.map((memory) => memory.id) : [];
20017
20140
  if (blocks.length === 0) {
20018
20141
  return {
20019
20142
  text: M1_EMPTY_PLACEHOLDER,
@@ -20156,8 +20279,11 @@ function replayCachedM1(state) {
20156
20279
  return decodeM0Bytes(state.cachedM1Bytes) ?? M1_EMPTY_PLACEHOLDER;
20157
20280
  }
20158
20281
  function softRefreshCachedM1(options) {
20282
+ const steps = new WriteTransactionSteps;
20283
+ options.beforeCacheCommitForTest?.();
20159
20284
  const transactionStartedAt = performance.now();
20160
20285
  options.db.exec("BEGIN IMMEDIATE");
20286
+ steps.reset();
20161
20287
  try {
20162
20288
  const row = readCachedM0M1Row(options.db, options.sessionId);
20163
20289
  if (!row || !cachedRowMatchesState(row, options.state)) {
@@ -20172,23 +20298,28 @@ function softRefreshCachedM1(options) {
20172
20298
  renderedMemoryIds: []
20173
20299
  };
20174
20300
  }
20301
+ steps.mark("staleCheck");
20175
20302
  const markers = markersFromCachedRow(row);
20176
20303
  if (!markers)
20177
20304
  throw new RenderM1InvalidMarkersError(options.sessionId);
20178
- const persistedVisibleIds = parseMemoryBlockIds(row.memory_block_ids);
20179
- const renderedM0Ids = persistedVisibleIds.filter((id) => id <= markers.maxMemoryId);
20180
- const rendered = renderM1WithMetadata({ ...options }, markers, renderedM0Ids);
20305
+ const renderedM0Ids = readCachedM0MemoryIds(row.cached_m0_upgrade_state, parseMemoryBlockIds(row.memory_block_ids), markers.maxMemoryId);
20306
+ const rendered = renderM1WithMetadata(options, markers, renderedM0Ids);
20181
20307
  const visibleMemoryIds = [...new Set([...renderedM0Ids, ...rendered.renderedMemoryIds])];
20182
20308
  const m1Bytes = Buffer4.from(rendered.text, "utf8");
20309
+ const visibleIdsJson = JSON.stringify(visibleMemoryIds);
20183
20310
  const baselineEndMessageId = getLastCompartmentEndMessageId(options.db, options.sessionId);
20311
+ steps.mark("m1Render");
20184
20312
  options.db.prepare(`UPDATE session_meta
20185
20313
  SET cached_m1_bytes = ?,
20186
20314
  cached_m0_last_baseline_end_message_id = ?,
20187
20315
  memory_block_count = ?,
20188
- memory_block_ids = ?
20189
- WHERE session_id = ?`).run(m1Bytes, baselineEndMessageId, visibleMemoryIds.length, JSON.stringify(visibleMemoryIds), options.sessionId);
20316
+ memory_block_ids = ?,
20317
+ cached_m0_upgrade_state = ?
20318
+ WHERE session_id = ?`).run(m1Bytes, baselineEndMessageId, visibleMemoryIds.length, visibleIdsJson, withCachedM0MemoryIds(row.cached_m0_upgrade_state, renderedM0Ids), options.sessionId);
20319
+ steps.mark("sessionMeta");
20190
20320
  options.db.exec("COMMIT");
20191
- logSlowWriteTransaction("opencode_soft_refresh_cache", transactionStartedAt);
20321
+ steps.mark("commit");
20322
+ logSlowWriteTransaction("opencode_soft_refresh_cache", transactionStartedAt, undefined, performance.now(), steps.durations);
20192
20323
  options.state.cachedM1Bytes = m1Bytes;
20193
20324
  options.state.snapshotMarkers = markers;
20194
20325
  return rendered;
@@ -20603,7 +20734,7 @@ function injectM0M1(options) {
20603
20734
  if (decision.value) {
20604
20735
  try {
20605
20736
  const materialized = materializeWithRetry(options);
20606
- applyMarkersToState(options.state, materialized.m0Bytes, materialized.snapshotMarkers, materialized.m1Bytes);
20737
+ applyMarkersToState(options.state, materialized.m0Bytes, materialized.snapshotMarkers, materialized.m1Bytes, materialized.renderedMemoryIds);
20607
20738
  m1Render = {
20608
20739
  text: materialized.m1Text,
20609
20740
  memoryUpdateCount: 0,
@@ -20694,7 +20825,7 @@ function injectM0M1(options) {
20694
20825
  if (!rematerialized && !contentionExhausted && m1Recomputed && options.isCacheBustingPass && (memoryUpdateCount > 40 || m1OverAbsoluteCap || m1HasContent && m0Tokens >= M0_DRIFT_RATIO_FLOOR_TOKENS && m1Tokens > m0Tokens * M1_DRIFT_RATIO)) {
20695
20826
  try {
20696
20827
  const refolded = materializeWithRetry(options);
20697
- applyMarkersToState(options.state, refolded.m0Bytes, refolded.snapshotMarkers, refolded.m1Bytes);
20828
+ applyMarkersToState(options.state, refolded.m0Bytes, refolded.snapshotMarkers, refolded.m1Bytes, refolded.renderedMemoryIds);
20698
20829
  rematerialized = true;
20699
20830
  m0Text = decodeM0Bytes(options.state.cachedM0Bytes) ?? M0_EMPTY_BODY;
20700
20831
  m1Text = refolded.m1Text;
@@ -21743,6 +21874,10 @@ function hasLengthCappedOutput(value) {
21743
21874
  return Object.values(value).some((item) => hasLengthCappedOutput(item));
21744
21875
  }
21745
21876
 
21877
+ // src/shared/provider-output-failure.ts
21878
+ import { AsyncLocalStorage } from "node:async_hooks";
21879
+ var primaryQuotas = new AsyncLocalStorage;
21880
+
21746
21881
  // src/shared/resolve-fallbacks.ts
21747
21882
  function parseProviderModel(spec) {
21748
21883
  const slash = spec.indexOf("/");
@@ -27119,7 +27254,7 @@ Found ${existingStaging.compartments.length} staged compartment(s) from ${existi
27119
27254
  afterPublish("publication-signal", () => deps.onCompartmentStatePublished?.(sessionId));
27120
27255
  if (lastCompartmentEnd > 0) {
27121
27256
  afterPublish("compaction-marker", () => {
27122
- const markerUpdated = updateCompactionMarkerAfterPublication(db, sessionId, lastCompartmentEnd, deps.directory);
27257
+ const markerUpdated = (deps.compactionMarkerStrategy?.publish ?? updateCompactionMarkerAfterPublication)(db, sessionId, lastCompartmentEnd, deps.directory);
27123
27258
  if (markerUpdated) {
27124
27259
  const stalePending = getPendingCompactionMarkerState(db, sessionId);
27125
27260
  if (stalePending) {
@@ -27355,7 +27490,7 @@ Another process acquired the compartment-state lease before recomp could publish
27355
27490
  afterPublish("publication-signal", () => deps.onCompartmentStatePublished?.(sessionId));
27356
27491
  if (lastCompartmentEnd > 0) {
27357
27492
  afterPublish("compaction-marker", () => {
27358
- const markerUpdated = updateCompactionMarkerAfterPublication(db, sessionId, lastCompartmentEnd, deps.directory);
27493
+ const markerUpdated = (deps.compactionMarkerStrategy?.publish ?? updateCompactionMarkerAfterPublication)(db, sessionId, lastCompartmentEnd, deps.directory);
27359
27494
  if (markerUpdated) {
27360
27495
  const stalePending = getPendingCompactionMarkerState(db, sessionId);
27361
27496
  if (stalePending) {
@@ -27508,7 +27643,7 @@ Could not acquire the compartment-state lease for this session.`;
27508
27643
  deps.onCompartmentStatePublished?.(sessionId);
27509
27644
  const lastEnd = merged[merged.length - 1]?.endMessage ?? snapEnd;
27510
27645
  if (lastEnd > 0) {
27511
- const markerUpdated = updateCompactionMarkerAfterPublication(db, sessionId, lastEnd, deps.directory);
27646
+ const markerUpdated = (deps.compactionMarkerStrategy?.publish ?? updateCompactionMarkerAfterPublication)(db, sessionId, lastEnd, deps.directory);
27512
27647
  if (markerUpdated) {
27513
27648
  const stalePending = getPendingCompactionMarkerState(db, sessionId);
27514
27649
  if (stalePending) {
@@ -27880,4 +28015,4 @@ async function executeContextRecomp(deps, options = {}) {
27880
28015
  return (await executeContextRecompWithResult(deps, options)).message;
27881
28016
  }
27882
28017
 
27883
- export { MEMORY_MAINTAINER_A_AGENT, MEMORY_MAINTAINER_B_AGENT, MEMORY_MAINTAINER_A_STEP_CAP, MEMORY_MAINTAINER_A_SYSTEM_PROMPT, MEMORY_MAINTAINER_B_SYSTEM_PROMPT, MEMORY_MAINTAINER_FINALIZE_INSTRUCTION, buildMemoryMaintainerStageAPrompt, buildMemoryMaintainerStageBPrompt, getOpenCodeGlobalConfigDir, getOpenCodeConfigDirs, opencodeUserConfigBasePath, mmcProjectConfigBasePath, buildPrimaryLanguageDirective, resolveModelConfigValue, DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE, PROTECTED_TOKENS_MIN, PER_HARNESS_MIGRATION_INVENTORY, PER_HARNESS_MODEL_KEYS, ConfigProfilesSchema, MagicContextConfigSchema, LIVE_RELOAD_CONFIG_PATHS, formatFailClosedBlockingMessage, formatFailClosedBlockingSummary, createFailClosedBlockingError, isFailClosedBlockingError, setHomeProjectPermission, shouldSkipHomeProjectMemory, ProjectIdentityError, takeDubiousOwnershipProjectIdentityWarning, isUserHomeDirectory, describeUnresolvedProjectIdentity, resolveProjectIdentityForSession, normalizeStoredProjectPath, storedPathBelongsToIdentity, V2_MEMORY_CATEGORIES, CATEGORY_PRIORITY, computeNormalizedHash, hasMemoryShareableColumn, hasMemoryClassifiedAtColumn, ModuleMemoryAuthorityError, insertMemory, insertMemoryIdempotent, getMemoryByHash, getMemoriesByProject, getMemoriesByProjects, getMemoryById, getMemoriesByIds, updateMemorySeenCount, updateMemoryRetrievalCount, supersededMemory, mergeMemoryStats, archiveMemory, relaxedFtsQuery, sanitizeFtsQuery, searchMemoriesFTS, searchMemoriesFTSUnion, clearMemoryVerifications, queueMemoryMutation, registerOwnRpcServerInstance, rpcPortDir, rpcPortFilePath, parseRpcPortFile, inspectProcessesAsync, COMPARTMENT_LEASE_RENEWAL_MS, acquireCompartmentLease, renewCompartmentLease, releaseCompartmentLeaseBestEffort, isCompartmentLeaseHeld, queueM0Mutation, getMaxM0MutationId, clearCachedM0M1, getCompartments, getLastCompartmentEndMessage, getLastCompartmentEndMessageId, getAuthorityManagedMarker, getLastIndexedOrdinal, getIndexedMessageIdAtOrdinal, getIndexedMessageCorpusSize, getMessageIndexReconciliationStartOrdinal, isMessageIndexReconciledThrough, clearIndexedMessages, indexMessagesAfterOrdinal, layoutLkgPrefix, MAX_EXECUTE_THRESHOLD, escalationBands, MERGED_REASONING_PARTS_PREFIX, readFrozenMergedReasoningParts, HYGIENE_PROVIDER_UNITS_VERSION, sessionDecisionCalibration, transitionSessionHygieneUnits, getProtectionWindowForSession, ReplayDocumentError, readReplayEnvelope, updateReplayDocument, isEmergencyRecoveryArmed, loadPersistedUsage, loadProtectedTailMeta, resetProtectedTailNoEligibleHead, getWrapupInProgressState, acquireWrapupInProgress, updateWrapupInProgress, releaseWrapupInProgress, resolveCompactionModeRecord, getCompactionModeRecord, setCompactionModeRecord, clearPersistedReasoningWatermark, getEmergencyInputSample, setEmergencyDropSample, clearEmergencyDropSample, getLastNudgeUndropped, setLastNudgeUndropped, getChannel1NudgeState, setChannel1NudgeState, markChannel1PostReduceGracePending, captureChannel1PostReduceGraceBaseline, getChannel2NudgeState, setChannel2NudgeState, casChannel2NudgeState, claimChannel2NudgeState, casChannel2NudgeClaim, getAutoSearchHintDecisions, appendAutoSearchHintDecision, pruneAutoSearchHintDecisions, getPersistedTodoPermissionDenied, setPersistedTodoPermissionDenied, getPersistedTodoSyntheticAnchor, setPersistedTodoSyntheticAnchor, clearPersistedTodoSyntheticAnchor, getHistorianFailureState, clearHistorianFailureState, getOverflowState, loadTransformPassStateSnapshot, recordOverflowDetected, recordDetectedContextLimit, clearEmergencyRecovery, clearDetectedContextLimit, getPersistedCompactionMarkerState, setPersistedCompactionMarkerState, getDeferredClearedCompactionMarkerState, retireDeferredClearedCompactionMarkerState, applyStrippedPlaceholderDelta, THINKING_BINDING_RECOVERY_FROZEN_PREFIX, thinkingBindingRecoveryFrozenId, clearThinkingBindingRecoveryIf, getMergedReasoningStrippedIds, addMergedReasoningStrippedIds, getTrailingBlankDecisions, addTrailingBlankDecisions, demoteTrailingBlankKeepDecisions, addStaleReduceStrippedIds, addProcessedImageStrippedIds, getPendingCompactionMarkerState, getCompactionMarkerHealth, loadPostprocessReplaySnapshot, clearPendingCompactionMarkerStateIf, setSessionWorkMetrics, getObservedEpochFloor, resolveEpochFloorForPass, BoundedSessionMap, beginLkgPass, lkgContentDigest, captureSlot, getInMemorySlot, getSlot, dropSlot, noteEntry, getLkgSlotHeapStats, useScopedToolSweep, createPreAdoptionToolSweepResolver, copySessionStateForClone, scheduleAfterBootQuiet, getSchemaFenceRejection, getMigrationOnOpenRefusal, LATEST_SUPPORTED_VERSION, getPersistedSchemaVersion, openDatabase, openDatabaseAsync, isDatabasePersisted, getDatabasePersistenceError, gaDatabasePath, RAW_MESSAGE_TYPES, V2StoreReaderPool, getOrCreateSessionMeta, updateSessionMeta, advanceToolReclaimWatermark, markSessionCleanupPending, clearSession, getNoteByIdInScope, getNotes, addNote, getSessionNotes, updateNote, dismissNotes, dismissNote, queuePendingOp, getPendingOps, getPendingOpsCount, clearPendingOps, removePendingOp, getActivePrimers, saveSourceContent, replaceSourceContent, getSourceContents, resolveWorkspaceShareCategories, resolveWorkspaceIdentitySet, expandWorkspaceIdentitySetWithAliases, resolveStoredPathWorkspaceIdentity, storedPathBelongsToWorkspace, sourceNameForMemory, rebaseSessionCoordinatesAsync, renderUserFacingFailure, userFacingFailureCode, renderCapabilityRefusal, HiddenCompletionRefusal, HIDDEN_HISTORIAN_AGENT, registerHiddenChildAgents, HiddenAgentStepLimit, HiddenChildHook, parseProviderModel, toModelEntry, ACTIVE_TOOL_IDS, promptSurfaceHashMaterial, createPromptSurfaceRuntime, createPromptSurfaceGuidanceEpochCache, getOpenCodeDbPath, compareOpenCodeMessagesByCanonicalOrder, removeMcOwnedCompactionMarkers, MARKER_SUMMARY_TEXT, applyDeferredCompactionMarker, HISTORIAN_AGENT, HISTORIAN_RECOMP_AGENT, HISTORIAN_EDITOR_AGENT, runTokenLog, extractM0Block, injectTemporalMarkers, clearInjectionCache, getVisibleMemoryIds, selectHiddenMessagesAtCompactionSeam, prepareCompartmentInjection, renderCompartmentInjection, mustMaterialize, trimMemoriesToBudgetV2, renderMemoryBlockV2, materializeM0, resetPrefixTrimFallbackState, findHostCompactionWindow, capturePrefixTrimSourceOrder, prepareCachedM0M1Replay, hasCompleteCachedM0M1, injectM0M1, describeBoundaryDiagnostics, RECOVERY_NO_HEAD_LIMIT, resolveOpenCodeProtectedTailBoundary, resolveWrapupProtectedTailBoundary, getRawHistoryEligibility, hasRunnableCompartmentWindow, recordHighPressureNoEligibleHead, runCompartmentAgent, getActiveCompartmentRun, markActiveCompartmentRunPublished, registerActiveCompartmentRun, startCompartmentAgent, executeContextRecomp };
28018
+ export { MEMORY_MAINTAINER_A_AGENT, MEMORY_MAINTAINER_B_AGENT, MEMORY_MAINTAINER_A_STEP_CAP, MEMORY_MAINTAINER_A_SYSTEM_PROMPT, MEMORY_MAINTAINER_B_SYSTEM_PROMPT, MEMORY_MAINTAINER_FINALIZE_INSTRUCTION, buildMemoryMaintainerStageAPrompt, buildMemoryMaintainerStageBPrompt, getOpenCodeGlobalConfigDir, getOpenCodeConfigDirs, opencodeUserConfigBasePath, mmcProjectConfigBasePath, buildPrimaryLanguageDirective, resolveModelConfigValue, DEFAULT_EXECUTE_THRESHOLD_PERCENTAGE, PROTECTED_TOKENS_MIN, HISTORIAN_MODEL_RESOLUTION_FIELDS, LEGACY_HARNESS_BLOCK_KEYS, ConfigProfilesSchema, MagicContextConfigSchema, LIVE_RELOAD_CONFIG_PATHS, formatFailClosedBlockingMessage, formatFailClosedBlockingSummary, createFailClosedBlockingError, isFailClosedBlockingError, setHomeProjectPermission, shouldSkipHomeProjectMemory, ProjectIdentityError, takeDubiousOwnershipProjectIdentityWarning, isUserHomeDirectory, describeUnresolvedProjectIdentity, resolveProjectIdentityForSession, normalizeStoredProjectPath, storedPathBelongsToIdentity, V2_MEMORY_CATEGORIES, CATEGORY_PRIORITY, computeNormalizedHash, hasMemoryShareableColumn, hasMemoryClassifiedAtColumn, ModuleMemoryAuthorityError, insertMemory, insertMemoryIdempotent, getMemoryByHash, getMemoriesByProject, getMemoriesByProjects, getMemoryById, getMemoriesByIds, updateMemorySeenCount, updateMemoryRetrievalCount, supersededMemory, mergeMemoryStats, archiveMemory, relaxedFtsQuery, sanitizeFtsQuery, searchMemoriesFTS, searchMemoriesFTSUnion, clearMemoryVerifications, queueMemoryMutation, registerOwnRpcServerInstance, rpcPortDir, rpcPortFilePath, parseRpcPortFile, inspectProcessesAsync, COMPARTMENT_LEASE_RENEWAL_MS, acquireCompartmentLease, renewCompartmentLease, releaseCompartmentLeaseBestEffort, isCompartmentLeaseHeld, queueM0Mutation, getMaxM0MutationId, clearCachedM0M1, getCompartments, getLastCompartmentEndMessage, getLastCompartmentEndMessageId, getAuthorityManagedMarker, getLastIndexedOrdinal, getIndexedMessageIdAtOrdinal, getIndexedMessageCorpusSize, getMessageIndexReconciliationStartOrdinal, isMessageIndexReconciledThrough, clearIndexedMessages, indexMessagesAfterOrdinal, layoutLkgPrefix, assembleLkgPrefix, getTemporalDecisions, observeTemporalDecisions, freezeTemporalDecisions, MAX_EXECUTE_THRESHOLD, escalationBands, MERGED_REASONING_PARTS_PREFIX, readFrozenMergedReasoningParts, HYGIENE_PROVIDER_UNITS_VERSION, sessionDecisionCalibration, transitionSessionHygieneUnits, getProtectionWindowForSession, ReplayDocumentError, readReplayEnvelope, updateReplayDocument, isEmergencyRecoveryArmed, loadPersistedUsage, loadProtectedTailMeta, resetProtectedTailNoEligibleHead, getWrapupInProgressState, acquireWrapupInProgress, updateWrapupInProgress, releaseWrapupInProgress, resolveCompactionModeRecord, getCompactionModeRecord, setCompactionModeRecord, clearPersistedReasoningWatermark, getEmergencyInputSample, setEmergencyDropSample, clearEmergencyDropSample, getLastNudgeUndropped, setLastNudgeUndropped, getChannel1NudgeState, setChannel1NudgeState, markChannel1PostReduceGracePending, captureChannel1PostReduceGraceBaseline, getChannel2NudgeState, setChannel2NudgeState, casChannel2NudgeState, claimChannel2NudgeState, casChannel2NudgeClaim, getAutoSearchHintDecisions, appendAutoSearchHintDecision, pruneAutoSearchHintDecisions, getPersistedTodoPermissionDenied, setPersistedTodoPermissionDenied, getPersistedTodoSyntheticAnchor, setPersistedTodoSyntheticAnchor, clearPersistedTodoSyntheticAnchor, getHistorianFailureState, clearHistorianFailureState, getOverflowState, loadTransformPassStateSnapshot, recordOverflowDetected, recordDetectedContextLimit, clearEmergencyRecovery, clearDetectedContextLimit, getPersistedCompactionMarkerState, setPersistedCompactionMarkerState, getDeferredClearedCompactionMarkerState, retireDeferredClearedCompactionMarkerState, applyStrippedPlaceholderDelta, THINKING_BINDING_RECOVERY_FROZEN_PREFIX, thinkingBindingRecoveryFrozenId, clearThinkingBindingRecoveryIf, getMergedReasoningStrippedIds, addMergedReasoningStrippedIds, getTrailingBlankDecisions, addTrailingBlankDecisions, demoteTrailingBlankKeepDecisions, addStaleReduceStrippedIds, addProcessedImageStrippedIds, getPendingCompactionMarkerState, getCompactionMarkerHealth, loadPostprocessReplaySnapshot, clearPendingCompactionMarkerStateIf, setSessionWorkMetrics, getObservedEpochFloor, resolveEpochFloorForPass, BoundedSessionMap, beginLkgPass, lkgContentDigest, captureSlot, getInMemorySlot, getSlot, dropSlot, noteEntry, getLkgSlotHeapStats, useScopedToolSweep, createPreAdoptionToolSweepResolver, copySessionStateForClone, scheduleAfterBootQuiet, getSchemaFenceRejection, getMigrationOnOpenRefusal, LATEST_SUPPORTED_VERSION, getPersistedSchemaVersion, openDatabase, openDatabaseAsync, isDatabasePersisted, getDatabasePersistenceError, gaDatabasePath, RAW_MESSAGE_TYPES, V2StoreReaderPool, getOrCreateSessionMeta, updateSessionMeta, advanceToolReclaimWatermark, markSessionCleanupPending, clearSession, getNoteByIdInScope, getNotes, addNote, getSessionNotes, updateNote, dismissNotes, dismissNote, getActivePrimers, saveSourceContent, replaceSourceContent, getSourceContents, resolveWorkspaceShareCategories, resolveWorkspaceIdentitySet, expandWorkspaceIdentitySetWithAliases, resolveStoredPathWorkspaceIdentity, storedPathBelongsToWorkspace, sourceNameForMemory, rebaseSessionCoordinatesAsync, renderUserFacingFailure, userFacingFailureCode, renderCapabilityRefusal, HiddenCompletionRefusal, HIDDEN_HISTORIAN_AGENT, hiddenChildPermissions, registerHiddenChildAgents, HiddenAgentStepLimit, HiddenChildHook, parseProviderModel, toModelEntry, ACTIVE_TOOL_IDS, promptSurfaceHashMaterial, createPromptSurfaceRuntime, createPromptSurfaceGuidanceEpochCache, getOpenCodeDbPath, compareOpenCodeMessagesByCanonicalOrder, removeMcOwnedCompactionMarkers, MARKER_SUMMARY_TEXT, applyDeferredCompactionMarker, HISTORIAN_AGENT, HISTORIAN_RECOMP_AGENT, HISTORIAN_EDITOR_AGENT, runTokenLog, extractM0Block, TEMPORAL_MARKER_REPLAY_PATTERN, collectTemporalCandidates, injectTemporalMarkers, clearInjectionCache, getVisibleMemoryIds, selectHiddenMessagesAtCompactionSeam, prepareCompartmentInjection, renderCompartmentInjection, MaterializeContentionError, mustMaterialize, trimMemoriesToBudgetV2, renderMemoryBlockV2, materializeM0, resetPrefixTrimFallbackState, findHostCompactionWindow, capturePrefixTrimSourceOrder, prepareCachedM0M1Replay, hasCompleteCachedM0M1, injectM0M1, describeBoundaryDiagnostics, RECOVERY_NO_HEAD_LIMIT, resolveOpenCodeProtectedTailBoundary, resolveWrapupProtectedTailBoundary, getRawHistoryEligibility, hasRunnableCompartmentWindow, recordHighPressureNoEligibleHead, runCompartmentAgent, getActiveCompartmentRun, markActiveCompartmentRunPublished, registerActiveCompartmentRun, startCompartmentAgent, executeContextRecomp };