@cortexkit/pi-magic-context 0.49.18 → 0.49.20

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 (59) hide show
  1. package/dist/auto-search-worker.js +53 -10
  2. package/dist/chunk-embedding-write-worker.js +29 -22
  3. package/dist/{compaction-marker-candidates-wjzqbspm.js → compaction-marker-candidates-fnm47jat.js} +3 -3
  4. package/dist/compaction-marker-candidates-worker.js +2 -2
  5. package/dist/compartment-chunk-embedding-81qesfjs.js +64 -0
  6. package/dist/embedding-backfill-56e871c6.js +24 -0
  7. package/dist/embedding-worker-process.js +2 -2
  8. package/dist/embedding-worker.js +5 -5
  9. package/dist/historian-calibration-extension.js +1 -1
  10. package/dist/index-54wmg4rj.js +82 -0
  11. package/dist/{index-xnch62s6.js → index-5n5zxs8e.js} +314 -127
  12. package/dist/{index-gdjv1nnd.js → index-5vgt1zeh.js} +6 -7
  13. package/dist/{index-qpq6w67c.js → index-6kb2xpw7.js} +2 -2
  14. package/dist/{index-d43hmn31.js → index-af9t637y.js} +68 -16
  15. package/dist/{index-z2rkv0mb.js → index-b8am7tns.js} +4 -4
  16. package/dist/{index-rhprywn6.js → index-bttctq07.js} +23 -5
  17. package/dist/{index-e1rza8gp.js → index-dzem6gn9.js} +1 -1
  18. package/dist/{index-2mmy81qt.js → index-e19qtjj0.js} +468 -18
  19. package/dist/{index-7bqrfyny.js → index-fgs78jyd.js} +12 -15
  20. package/dist/{index-d4dt19md.js → index-hqw0rt9k.js} +1 -1
  21. package/dist/{index-rrwv9y2k.js → index-hws5f0z9.js} +1 -1
  22. package/dist/{index-f18ec69t.js → index-jn44h81p.js} +1 -1
  23. package/dist/{index-xxn1tpnv.js → index-jt0g3hn0.js} +45 -28
  24. package/dist/{index-d8gc0112.js → index-jxjr7kz9.js} +3 -3
  25. package/dist/{index-4bv5bttd.js → index-kqb3d8bs.js} +9 -5
  26. package/dist/{index-gp928w10.js → index-mtvvhcw4.js} +10 -10
  27. package/dist/{index-1kcfwk9c.js → index-my0dn413.js} +1 -1
  28. package/dist/{index-apgwdby5.js → index-n4wyxcgr.js} +1 -1
  29. package/dist/{index-g7p75667.js → index-p63nwn5v.js} +2 -2
  30. package/dist/{index-svgkv4g2.js → index-qerzchrs.js} +2 -2
  31. package/dist/{index-vktahpdj.js → index-rfyvax95.js} +9 -3
  32. package/dist/{index-yygsh681.js → index-rgfb753z.js} +3 -3
  33. package/dist/{index-d21pdr8v.js → index-tb3d9trm.js} +2 -2
  34. package/dist/{index-vmcgew7x.js → index-v2epyzbm.js} +75 -57
  35. package/dist/{index-fvjthct0.js → index-vdy273xw.js} +107 -20
  36. package/dist/{index-jrap43gc.js → index-w1avzkdt.js} +1 -1
  37. package/dist/{index-r9f4f6s1.js → index-zhwwp8zz.js} +64 -8
  38. package/dist/index.js +1119 -247
  39. package/dist/{logger-dygt96rn.js → logger-shetp43v.js} +1 -1
  40. package/dist/{message-fts-rowid-map-cvpy2dmb.js → message-fts-rowid-map-bpexnsdj.js} +6 -5
  41. package/dist/{message-index-bounded-g9hgresf.js → message-index-bounded-d4r3weh0.js} +14 -13
  42. package/dist/{message-index-74qdqmq7.js → message-index-mvag9crh.js} +14 -13
  43. package/dist/{message-time-backfill-ssshbdy8.js → message-time-backfill-kc10yrcj.js} +3 -3
  44. package/dist/migration-worker.js +12 -11
  45. package/dist/{project-embedding-registry-vf1ncptn.js → project-embedding-registry-cfrg952x.js} +13 -12
  46. package/dist/raw-ordinal-warmup-worker.js +136 -101
  47. package/dist/{read-session-chunk-chepqmw5.js → read-session-chunk-7g4zvpd8.js} +9 -8
  48. package/dist/{read-session-raw-9s3xn7fc.js → read-session-raw-0fsjh10f.js} +4 -3
  49. package/dist/{safe-notification-target-2rkvkmw8.js → safe-notification-target-zcpchea6.js} +2 -2
  50. package/dist/search-archive-qbhp7e89.js +21 -0
  51. package/dist/{search-6ztbx25v.js → search-hp4g3g9v.js} +22 -21
  52. package/dist/{sqlite-fsp0sf3r.js → sqlite-d67n6dtr.js} +1 -1
  53. package/dist/{storage-memory-yxxc5v4n.js → storage-memory-9g882j7a.js} +2 -2
  54. package/dist/{storage-tags-1kets0q8.js → storage-tags-m2qcp1g2.js} +7 -5
  55. package/dist/subagent-entry.js +26 -25
  56. package/dist/tag-snapshot-worker-pi.js +66 -55
  57. package/package.json +1 -1
  58. package/dist/embedding-backfill-vwag34t0.js +0 -23
  59. package/dist/search-archive-jg4a1kcx.js +0 -20
package/dist/index.js CHANGED
@@ -18,7 +18,7 @@ import {
18
18
  log2,
19
19
  sessionLog2,
20
20
  flushLogger2
21
- } from "./index-7bqrfyny.js";
21
+ } from "./index-fgs78jyd.js";
22
22
  import {
23
23
  COMPACTION_ENABLED_PATH,
24
24
  isDreamerRunnable,
@@ -249,7 +249,7 @@ import {
249
249
  registerTodoStateLifecycle,
250
250
  syncCtxMemoryToolEnabled,
251
251
  registerMagicContextTools
252
- } from "./index-xxn1tpnv.js";
252
+ } from "./index-jt0g3hn0.js";
253
253
  import"./index-4knyh1kt.js";
254
254
  import {
255
255
  canonicalModelIdentity,
@@ -290,7 +290,7 @@ import {
290
290
  openCurrentDatabase,
291
291
  openDatabaseAsync,
292
292
  closeDatabase
293
- } from "./index-gp928w10.js";
293
+ } from "./index-mtvvhcw4.js";
294
294
  import {
295
295
  pruneMissingProjectIdentities,
296
296
  setHomeProjectPermission,
@@ -302,7 +302,7 @@ import {
302
302
  resolveProjectIdentityForSession,
303
303
  beginBootQuietPeriod,
304
304
  scheduleAfterBootQuiet
305
- } from "./index-g7p75667.js";
305
+ } from "./index-p63nwn5v.js";
306
306
  import {
307
307
  detectThinkingBindingMismatch,
308
308
  detectLatestTurnThinkingMismatch,
@@ -396,6 +396,7 @@ import {
396
396
  addProcessedImageStrippedIds,
397
397
  getPendingCompactionMarkerState,
398
398
  getCompactionMarkerHealth,
399
+ loadPostprocessReplaySnapshot,
399
400
  clearPendingCompactionMarkerStateIf,
400
401
  getPendingPiCompactionMarkerState,
401
402
  setPendingPiCompactionMarkerState,
@@ -462,7 +463,7 @@ import {
462
463
  getRawSessionTagKeysThrough2,
463
464
  getLegacyProtectedTailStartOrdinal2,
464
465
  readSessionChunk2
465
- } from "./index-r9f4f6s1.js";
466
+ } from "./index-zhwwp8zz.js";
466
467
  import {
467
468
  UNKNOWN_FIT_RATIO,
468
469
  hasMeasuredDecisionCalibration,
@@ -549,7 +550,7 @@ import {
549
550
  getToolTagNumberByOwner2,
550
551
  getNullOwnerToolTag2,
551
552
  adoptNullOwnerToolTag2
552
- } from "./index-rhprywn6.js";
553
+ } from "./index-bttctq07.js";
553
554
  import {
554
555
  textMentionsRecentCommit,
555
556
  hasMeaningfulUserText2,
@@ -561,7 +562,7 @@ import {
561
562
  estimateTokens,
562
563
  estimateFixedPromptTokens,
563
564
  normalizeText
564
- } from "./index-1kcfwk9c.js";
565
+ } from "./index-my0dn413.js";
565
566
  import {
566
567
  inRootAsyncContext2,
567
568
  Database2,
@@ -574,7 +575,7 @@ import {
574
575
  isTransientSqliteError2,
575
576
  withAsyncPrivilegedWriter2,
576
577
  indexCoordinationInput2
577
- } from "./index-rrwv9y2k.js";
578
+ } from "./index-hws5f0z9.js";
578
579
  import {
579
580
  stableStringify,
580
581
  closeQuietly,
@@ -582,14 +583,15 @@ import {
582
583
  observeTemporalDecisions,
583
584
  freezeTemporalDecisions,
584
585
  tagIdentityRevisionKey
585
- } from "./index-jrap43gc.js";
586
+ } from "./index-w1avzkdt.js";
586
587
  import {
587
588
  piHarnessKindFromExecutable
588
- } from "./index-apgwdby5.js";
589
+ } from "./index-n4wyxcgr.js";
589
590
  import {
590
591
  BoundedSessionMap,
591
592
  LkgRecoveryFenceError,
592
593
  clearLkgFenceProcessState,
594
+ takeLkgRecoveryLockSweepPage,
593
595
  lkgFenceRequiresRebuild,
594
596
  lkgRecoveryFenceUnclean,
595
597
  ownsLkgDirtyFence,
@@ -611,7 +613,7 @@ import {
611
613
  indexSingleMessage2,
612
614
  indexMessagesAfterOrdinal2,
613
615
  sweepOrphanedOpenCodeMessageIndexesCooperatively2
614
- } from "./index-fvjthct0.js";
616
+ } from "./index-vdy273xw.js";
615
617
  import {
616
618
  resolveOpenCodeDbPath,
617
619
  assertOpenCodeStoreGeneration,
@@ -621,24 +623,27 @@ import {
621
623
  claimOpenCodeDbDiagnosticOnce
622
624
  } from "./index-8976mezv.js";
623
625
  import"./index-399p688g.js";
626
+ import {
627
+ createWorkerShutdown
628
+ } from "./index-54wmg4rj.js";
624
629
  import {
625
630
  runSessionWarmupWorker,
626
631
  RAW_SUMMARY_TEXT_MAX_CHARS2
627
- } from "./index-vktahpdj.js";
632
+ } from "./index-rfyvax95.js";
628
633
  import {
629
634
  formatSynapseLaneDescriptor
630
- } from "./index-d8gc0112.js";
631
- import"./index-yygsh681.js";
635
+ } from "./index-jxjr7kz9.js";
636
+ import"./index-rgfb753z.js";
632
637
  import {
633
- buildCanonicalChunkTextFromFts,
634
- buildCompartmentSummaryFallbackText,
635
- canonicalizeInMemoryChunkTextForEmbedding,
636
- chunkCanonicalText,
637
- chunkEmbeddingWindowsAreCurrent,
638
- replaceCompartmentChunkEmbeddings,
639
- deleteChunkEmbedBackoffForSession,
640
- chunkWindowSourceKey
641
- } from "./index-xnch62s6.js";
638
+ buildCanonicalChunkTextFromFts2,
639
+ buildCompartmentSummaryFallbackText2,
640
+ canonicalizeInMemoryChunkTextForEmbedding2,
641
+ chunkCanonicalText2,
642
+ chunkEmbeddingWindowsAreCurrent2,
643
+ replaceCompartmentChunkEmbeddings2,
644
+ deleteChunkEmbedBackoffForSession2,
645
+ chunkWindowSourceKey2
646
+ } from "./index-5n5zxs8e.js";
642
647
  import {
643
648
  recordSessionProjectIdentity,
644
649
  GIT_SWEEP_LEASE_RENEWAL_MS,
@@ -647,7 +652,7 @@ import {
647
652
  markGitSweepSuccessAndRelease,
648
653
  parkGitSweepNonIndexable,
649
654
  releaseGitSweepLease
650
- } from "./index-svgkv4g2.js";
655
+ } from "./index-qerzchrs.js";
651
656
  import {
652
657
  embedPauseBySession,
653
658
  embedRunStateBySession,
@@ -673,7 +678,7 @@ import {
673
678
  embedSessionCompartmentChunks2,
674
679
  getEmbeddingCoverageStatus2,
675
680
  getAutoEmbeddingSessionCoverage2
676
- } from "./index-vmcgew7x.js";
681
+ } from "./index-v2epyzbm.js";
677
682
  import {
678
683
  rememberV1HiddenRun
679
684
  } from "./index-6x556c2q.js";
@@ -688,7 +693,7 @@ import {
688
693
  expandWorkspaceIdentitySetWithAliases,
689
694
  sourceNameForMemory,
690
695
  computeWorkspaceEpochFingerprint
691
- } from "./index-gdjv1nnd.js";
696
+ } from "./index-5vgt1zeh.js";
692
697
  import {
693
698
  configureContextDatabasePragmas2
694
699
  } from "./index-fapenpch.js";
@@ -738,7 +743,7 @@ import {
738
743
  normalizeVerificationFiles,
739
744
  indexCommitsForProject,
740
745
  embedUnembeddedCommits
741
- } from "./index-d43hmn31.js";
746
+ } from "./index-af9t637y.js";
742
747
  import {
743
748
  setEmbeddingSessionBusy2,
744
749
  isEmbeddingHostBusy2
@@ -762,18 +767,20 @@ import {
762
767
  setMemoryClassification2,
763
768
  archiveMemory2,
764
769
  getMemoryCountsByStatus2
765
- } from "./index-e1rza8gp.js";
770
+ } from "./index-dzem6gn9.js";
766
771
  import {
767
772
  invalidateMemory2
768
773
  } from "./index-yhzhdp3m.js";
769
774
  import {
770
775
  pushNotification2
771
776
  } from "./index-q1yc6bs0.js";
772
- import"./index-2mmy81qt.js";
777
+ import {
778
+ getCachedLocalEmbeddingPooling
779
+ } from "./index-e19qtjj0.js";
773
780
  import {
774
781
  cosineSimilarity
775
- } from "./index-z2rkv0mb.js";
776
- import"./index-qpq6w67c.js";
782
+ } from "./index-b8am7tns.js";
783
+ import"./index-6kb2xpw7.js";
777
784
  import {
778
785
  DREAMER_PRIMER_INVESTIGATOR_ALLOWED_TOOLS,
779
786
  buildHiddenAgentRegistrations,
@@ -795,10 +802,10 @@ import {
795
802
  drainPiTagSnapshotSession,
796
803
  assertPiTagSnapshotReady,
797
804
  ensurePiTagSnapshotReady
798
- } from "./index-4bv5bttd.js";
799
- import"./index-f18ec69t.js";
805
+ } from "./index-kqb3d8bs.js";
806
+ import"./index-jn44h81p.js";
800
807
  import"./index-1cvyaw9a.js";
801
- import"./index-d21pdr8v.js";
808
+ import"./index-tb3d9trm.js";
802
809
  import {
803
810
  __toESM
804
811
  } from "./index-22jkk6wg.js";
@@ -814,7 +821,7 @@ import {
814
821
  import {
815
822
  logSlowWriteTransaction,
816
823
  WriteTransactionSteps
817
- } from "./index-d4dt19md.js";
824
+ } from "./index-hqw0rt9k.js";
818
825
  import {
819
826
  setStoragePrivatePermissionEnforcement,
820
827
  ensureStorageDirectorySync,
@@ -1207,6 +1214,9 @@ function resolveHarnessBlock(container, harness) {
1207
1214
  const selected = harness === "omp" ? container?.omp ?? container?.pi : container?.[harness];
1208
1215
  return asRecord(selected);
1209
1216
  }
1217
+ function sourceHarness(container, harness) {
1218
+ return harness === "omp" && container?.omp == null ? "pi" : harness;
1219
+ }
1210
1220
  function normalizeModelEntry(entry, harness) {
1211
1221
  if (typeof entry === "string") {
1212
1222
  const model = readString(entry);
@@ -1253,13 +1263,19 @@ function resolveHistorianModel(config, harness) {
1253
1263
  const block = resolveHarnessBlock(historian, harness);
1254
1264
  if (!block)
1255
1265
  return { fallbacks: [] };
1266
+ const source = `historian.${sourceHarness(historian, harness)}`;
1267
+ const primary = resolvePrimaryEntry({
1268
+ entry: block.model,
1269
+ defaultQualifier: block[harness === "opencode" ? "variant" : "thinking_level"],
1270
+ harness
1271
+ });
1272
+ const fallbacks = resolveFallbackEntries(block.fallback_models, harness);
1256
1273
  return {
1257
- primary: resolvePrimaryEntry({
1258
- entry: block.model,
1259
- defaultQualifier: block[harness === "opencode" ? "variant" : "thinking_level"],
1260
- harness
1261
- }),
1262
- fallbacks: resolveFallbackEntries(block.fallback_models, harness)
1274
+ primary: primary ? { ...primary, sourceConfigKey: `${source}.model` } : undefined,
1275
+ fallbacks: fallbacks.map((entry) => ({
1276
+ ...entry,
1277
+ sourceConfigKey: `${source}.fallback_models`
1278
+ }))
1263
1279
  };
1264
1280
  }
1265
1281
  function resolveDreamerTaskModel(args) {
@@ -1278,15 +1294,25 @@ function resolveDreamerTaskModel(args) {
1278
1294
  const taskQualifier = taskBlock?.[args.harness === "opencode" ? "variant" : "thinking_level"];
1279
1295
  const harnessQualifier = harnessBlock[args.harness === "opencode" ? "variant" : "thinking_level"] ?? normalizeModelEntry(harnessBlock.model, args.harness)?.qualifier;
1280
1296
  const taskHasModel = taskBlock !== undefined && hasOwn(taskBlock, "model");
1297
+ const taskHasFallbacks = taskBlock !== undefined && hasOwn(taskBlock, "fallback_models");
1281
1298
  const primarySource = taskHasModel ? taskBlock?.model : harnessBlock.model;
1282
- const fallbackSource = taskBlock !== undefined && hasOwn(taskBlock, "fallback_models") ? taskBlock.fallback_models : harnessBlock.fallback_models;
1299
+ const fallbackSource = taskHasFallbacks ? taskBlock?.fallback_models : harnessBlock.fallback_models;
1300
+ const source = `dreamer.${sourceHarness(dreamer, args.harness)}`;
1301
+ const primary = resolvePrimaryEntry({
1302
+ entry: primarySource,
1303
+ defaultQualifier: taskQualifier ?? harnessQualifier,
1304
+ harness: args.harness
1305
+ });
1306
+ const fallbacks = resolveFallbackEntries(fallbackSource, args.harness);
1283
1307
  return {
1284
- primary: resolvePrimaryEntry({
1285
- entry: primarySource,
1286
- defaultQualifier: taskQualifier ?? harnessQualifier,
1287
- harness: args.harness
1288
- }),
1289
- fallbacks: resolveFallbackEntries(fallbackSource, args.harness),
1308
+ primary: primary ? {
1309
+ ...primary,
1310
+ sourceConfigKey: taskHasModel ? `${source}.tasks.${args.task}.model` : `${source}.model`
1311
+ } : undefined,
1312
+ fallbacks: fallbacks.map((entry) => ({
1313
+ ...entry,
1314
+ sourceConfigKey: taskHasFallbacks ? `${source}.tasks.${args.task}.fallback_models` : `${source}.fallback_models`
1315
+ })),
1290
1316
  schedule: readString(schedulingTask?.schedule),
1291
1317
  timeoutMinutes: typeof taskBlock?.timeout_minutes === "number" ? taskBlock.timeout_minutes : undefined,
1292
1318
  promotionThreshold: typeof schedulingTask?.promotion_threshold === "number" ? schedulingTask.promotion_threshold : undefined
@@ -1306,6 +1332,7 @@ function buildDreamTaskRuntimeConfigs(dreamer, harness, language, smartNotesEnab
1306
1332
  schedule: resolved.schedule ?? "",
1307
1333
  model: resolved.primary,
1308
1334
  fallbackModels: resolved.fallbacks,
1335
+ modelConfigKey: resolved.primary?.sourceConfigKey ?? resolved.fallbacks[0]?.sourceConfigKey,
1309
1336
  thinkingLevel: harness === "pi" ? resolved.primary?.qualifier : undefined,
1310
1337
  language,
1311
1338
  timeoutMinutes: resolved.timeoutMinutes ?? 20,
@@ -3520,7 +3547,7 @@ function startHostStallProfilerSwitch() {
3520
3547
  // package.json
3521
3548
  var package_default = {
3522
3549
  name: "@cortexkit/pi-magic-context",
3523
- version: "0.49.18",
3550
+ version: "0.49.20",
3524
3551
  type: "module",
3525
3552
  description: "Pi and OMP coding agent extension for Magic Context — cross-session memory and context management",
3526
3553
  main: "dist/index.js",
@@ -4844,9 +4871,33 @@ var promptFailureDetails = new WeakMap;
4844
4871
  function isHostTimeoutError(error) {
4845
4872
  return error !== null && typeof error === "object" && error.name === "TimeoutError";
4846
4873
  }
4874
+
4875
+ class ModelProducedNoOutputError extends Error {
4876
+ waitedMs;
4877
+ constructor(waitedMs) {
4878
+ super(`prompt timed out after ${waitedMs}ms with no model output`);
4879
+ this.waitedMs = waitedMs;
4880
+ this.name = "ModelProducedNoOutputError";
4881
+ }
4882
+ }
4883
+ var modelActivityBySignal = new WeakMap;
4884
+ function noteModelActivityMonitored(signal) {
4885
+ const activity = signal ? modelActivityBySignal.get(signal) : undefined;
4886
+ if (activity)
4887
+ activity.monitored = true;
4888
+ }
4889
+ function noteModelOutputReceived(signal) {
4890
+ const activity = signal ? modelActivityBySignal.get(signal) : undefined;
4891
+ if (activity) {
4892
+ activity.monitored = true;
4893
+ activity.received = true;
4894
+ }
4895
+ }
4847
4896
  function isPromptTimeoutError(error) {
4848
4897
  if (isHostTimeoutError(error))
4849
4898
  return true;
4899
+ if (error instanceof ModelProducedNoOutputError)
4900
+ return true;
4850
4901
  return error instanceof Error && /^prompt timed out after \d+ms$/.test(error.message);
4851
4902
  }
4852
4903
  function getPromptFailureDetail(error) {
@@ -4924,12 +4975,22 @@ function raceWithSignal(work, signal) {
4924
4975
  work.then(resolve, reject).finally(() => signal.removeEventListener("abort", abort));
4925
4976
  });
4926
4977
  }
4927
- async function promptWithTimeout(client, args, timeoutMs, signal, transport) {
4978
+ async function promptWithTimeout(client, args, timeoutMs, signal, transport, firstOutputTimeoutMs) {
4928
4979
  if (signal?.aborted) {
4929
4980
  throw new Error(externalAbortMessage(signal));
4930
4981
  }
4931
4982
  const controller = new AbortController;
4932
4983
  const timeout = setTimeout(() => controller.abort(), timeoutMs);
4984
+ const activity = { monitored: false, received: false };
4985
+ modelActivityBySignal.set(controller.signal, activity);
4986
+ let silent = false;
4987
+ const firstOutputTimer = firstOutputTimeoutMs !== undefined && firstOutputTimeoutMs < timeoutMs ? setTimeout(() => {
4988
+ if (!activity.monitored || activity.received)
4989
+ return;
4990
+ silent = true;
4991
+ controller.abort(new ModelProducedNoOutputError(firstOutputTimeoutMs));
4992
+ }, firstOutputTimeoutMs) : undefined;
4993
+ const timeoutError = () => silent && firstOutputTimeoutMs !== undefined ? new ModelProducedNoOutputError(firstOutputTimeoutMs) : new Error(`prompt timed out after ${timeoutMs}ms`);
4933
4994
  const onExternalAbort = () => controller.abort();
4934
4995
  signal?.addEventListener("abort", onExternalAbort);
4935
4996
  try {
@@ -4952,7 +5013,7 @@ async function promptWithTimeout(client, args, timeoutMs, signal, transport) {
4952
5013
  if (!transport || transport.childSessionId) {
4953
5014
  await abortChildRun(client, transport?.childSessionId ?? args.path.id);
4954
5015
  }
4955
- throw new Error(`prompt timed out after ${timeoutMs}ms`);
5016
+ throw timeoutError();
4956
5017
  }
4957
5018
  if (isHostTimeoutError(error)) {
4958
5019
  if (!transport || transport.childSessionId) {
@@ -4962,13 +5023,15 @@ async function promptWithTimeout(client, args, timeoutMs, signal, transport) {
4962
5023
  throw error;
4963
5024
  } finally {
4964
5025
  clearTimeout(timeout);
5026
+ if (firstOutputTimer)
5027
+ clearTimeout(firstOutputTimer);
4965
5028
  signal?.removeEventListener("abort", onExternalAbort);
4966
5029
  }
4967
5030
  if (signal?.aborted || controller.signal.aborted) {
4968
5031
  if (!transport || transport.childSessionId) {
4969
5032
  await abortChildRun(client, transport?.childSessionId ?? args.path.id);
4970
5033
  }
4971
- throw new Error(signal?.aborted ? externalAbortMessage(signal) : `prompt timed out after ${timeoutMs}ms`);
5034
+ throw signal?.aborted ? new Error(externalAbortMessage(signal)) : timeoutError();
4972
5035
  }
4973
5036
  }
4974
5037
  async function abortChildRun(client, sessionId) {
@@ -4986,6 +5049,8 @@ async function abortChildRun(client, sessionId) {
4986
5049
  function isNonRetryable(error, externalSignal) {
4987
5050
  if (externalSignal?.aborted || error instanceof HiddenCompletionRefusal && error.terminal || error instanceof HiddenAgentStepLimit || error instanceof DreamTokenBudgetExceeded)
4988
5051
  return true;
5052
+ if (error instanceof ModelProducedNoOutputError)
5053
+ return false;
4989
5054
  if (error instanceof Error) {
4990
5055
  if (error.name === "AbortError")
4991
5056
  return true;
@@ -5017,7 +5082,7 @@ function classifyPromptFailure(error, phase, externalSignal) {
5017
5082
  if (externalSignal?.aborted || message === "prompt aborted by external signal") {
5018
5083
  return "child_aborted";
5019
5084
  }
5020
- if (/^prompt timed out after \d+ms$/.test(message) || isHostTimeoutError(error)) {
5085
+ if (error instanceof ModelProducedNoOutputError || /^prompt timed out after \d+ms$/.test(message) || isHostTimeoutError(error)) {
5021
5086
  return "provider_timeout";
5022
5087
  }
5023
5088
  if (phase === "validation") {
@@ -5052,11 +5117,11 @@ function throwWithPromptFailure(legacyError, failedAttempts, args, timeoutMs, tr
5052
5117
  });
5053
5118
  throw error;
5054
5119
  }
5055
- async function attemptOnce(client, args, timeoutMs, signal, callContext, label, transport, allowModelSuggestions = true) {
5120
+ async function attemptOnce(client, args, timeoutMs, signal, callContext, label, transport, allowModelSuggestions = true, firstOutputTimeoutMs) {
5056
5121
  const originalBody = { ...args.body };
5057
5122
  const attemptArgs = copyPromptArgs(args, originalBody);
5058
5123
  try {
5059
- await promptWithTimeout(client, attemptArgs, timeoutMs, signal, transport);
5124
+ await promptWithTimeout(client, attemptArgs, timeoutMs, signal, transport, firstOutputTimeoutMs);
5060
5125
  return;
5061
5126
  } catch (error) {
5062
5127
  if (isNonRetryable(error, signal) || !allowModelSuggestions)
@@ -5075,9 +5140,30 @@ async function attemptOnce(client, args, timeoutMs, signal, callContext, label,
5075
5140
  providerID: suggestion.providerID,
5076
5141
  modelID: suggestion.suggestion
5077
5142
  }
5078
- }), timeoutMs, signal, transport);
5143
+ }), timeoutMs, signal, transport, firstOutputTimeoutMs);
5079
5144
  }
5080
5145
  }
5146
+ function createChainClock(options, timeoutMs) {
5147
+ const fallbacks = options.fallbackModels ?? [];
5148
+ const hasValidFallbackFrom = (index) => fallbacks.slice(index).some((fallback) => {
5149
+ const entry = toModelEntry(fallback);
5150
+ return entry ? parseProviderModel(entry.model) !== null : false;
5151
+ });
5152
+ let silentSpentMs = 0;
5153
+ return {
5154
+ budget(nextFallbackIndex) {
5155
+ const attemptTimeoutMs = Math.max(1, timeoutMs - silentSpentMs);
5156
+ if (options.firstOutputTimeoutMs === undefined || !hasValidFallbackFrom(nextFallbackIndex))
5157
+ return { timeoutMs: attemptTimeoutMs };
5158
+ const bound = Math.min(options.firstOutputTimeoutMs, Math.floor(attemptTimeoutMs / 2));
5159
+ return bound > 0 ? { timeoutMs: attemptTimeoutMs, firstOutputTimeoutMs: bound } : { timeoutMs: attemptTimeoutMs };
5160
+ },
5161
+ settle(error, startedAt) {
5162
+ if (error instanceof ModelProducedNoOutputError)
5163
+ silentSpentMs += Date.now() - startedAt;
5164
+ }
5165
+ };
5166
+ }
5081
5167
  async function promptSyncWithModelSuggestionRetry(client, args, options = {}) {
5082
5168
  const timeoutMs = options.timeoutMs ?? 300000;
5083
5169
  const callContext = options.callContext ?? "subagent";
@@ -5086,11 +5172,15 @@ async function promptSyncWithModelSuggestionRetry(client, args, options = {}) {
5086
5172
  const baseArgs = copyPromptArgs(args, baseBody);
5087
5173
  const explicitPrimaryLabel = baseBody.model?.providerID && baseBody.model.modelID ? `${baseBody.model.providerID}/${baseBody.model.modelID}` : "primary";
5088
5174
  let lastError = null;
5175
+ const clock = createChainClock(options, timeoutMs);
5176
+ const primaryStartedAt = Date.now();
5089
5177
  try {
5090
- await attemptOnce(client, baseArgs, timeoutMs, options.signal, callContext, explicitPrimaryLabel, options.transport, options.allowModelSuggestions);
5178
+ const budget = clock.budget(0);
5179
+ await attemptOnce(client, baseArgs, budget.timeoutMs, options.signal, callContext, explicitPrimaryLabel, options.transport, options.allowModelSuggestions, budget.firstOutputTimeoutMs);
5091
5180
  return;
5092
5181
  } catch (error) {
5093
5182
  lastError = error;
5183
+ clock.settle(error, primaryStartedAt);
5094
5184
  if (isNonRetryable(error, options.signal))
5095
5185
  throw error;
5096
5186
  if (fallbacks.length === 0) {
@@ -5112,12 +5202,15 @@ async function promptSyncWithModelSuggestionRetry(client, args, options = {}) {
5112
5202
  model: parsed,
5113
5203
  ...fallback?.qualifier ? { variant: fallback.qualifier } : {}
5114
5204
  });
5205
+ const attemptStartedAt = Date.now();
5115
5206
  try {
5116
- await attemptOnce(client, attemptArgs, timeoutMs, options.signal, callContext, label, options.transport, options.allowModelSuggestions);
5207
+ const budget = clock.budget(i + 1);
5208
+ await attemptOnce(client, attemptArgs, budget.timeoutMs, options.signal, callContext, label, options.transport, options.allowModelSuggestions, budget.firstOutputTimeoutMs);
5117
5209
  log2(`[${callContext}] fallback succeeded with ${label} (attempt ${i + 2}/${fallbacks.length + 1})`);
5118
5210
  return;
5119
5211
  } catch (error) {
5120
5212
  lastError = error;
5213
+ clock.settle(error, attemptStartedAt);
5121
5214
  if (isNonRetryable(error, options.signal))
5122
5215
  throw error;
5123
5216
  const remaining = fallbacks.length - i - 1;
@@ -5129,9 +5222,9 @@ async function promptSyncWithModelSuggestionRetry(client, args, options = {}) {
5129
5222
  log2(`[${callContext}] all models exhausted; tried: ${[explicitPrimaryLabel, ...fallbacks.map((fallback) => toModelEntry(fallback)?.model ?? String(fallback))].join(", ")}; last error: ${shortErr(lastError)}`);
5130
5223
  throw lastError ?? new Error("All fallback models failed");
5131
5224
  }
5132
- async function attemptAndValidate(client, args, timeoutMs, signal, callContext, attempt, options) {
5225
+ async function attemptAndValidate(client, args, timeoutMs, signal, callContext, attempt, options, firstOutputTimeoutMs) {
5133
5226
  try {
5134
- await attemptOnce(client, args, timeoutMs, signal, callContext, attempt.label, options.transport, options.allowModelSuggestions);
5227
+ await attemptOnce(client, args, timeoutMs, signal, callContext, attempt.label, options.transport, options.allowModelSuggestions, firstOutputTimeoutMs);
5135
5228
  } catch (error) {
5136
5229
  throw {
5137
5230
  error,
@@ -5193,6 +5286,8 @@ async function promptSyncWithValidatedOutputRetry(client, args, options) {
5193
5286
  let firstError = null;
5194
5287
  let lastError = null;
5195
5288
  const cooledPrimary = primaryQuotaFailure(explicitPrimaryLabel);
5289
+ const clock = createChainClock(options, timeoutMs);
5290
+ const primaryStartedAt = Date.now();
5196
5291
  try {
5197
5292
  if (cooledPrimary)
5198
5293
  throw {
@@ -5207,16 +5302,18 @@ async function promptSyncWithValidatedOutputRetry(client, args, options) {
5207
5302
  skipped: true
5208
5303
  }
5209
5304
  };
5210
- return await attemptAndValidate(client, baseArgs, timeoutMs, options.signal, callContext, {
5305
+ const budget = clock.budget(0);
5306
+ return await attemptAndValidate(client, baseArgs, budget.timeoutMs, options.signal, callContext, {
5211
5307
  label: explicitPrimaryLabel,
5212
5308
  attemptIndex: 0,
5213
5309
  isFallback: false,
5214
5310
  totalAttempts,
5215
5311
  model: baseBody.model
5216
- }, options);
5312
+ }, options, budget.firstOutputTimeoutMs);
5217
5313
  } catch (caught) {
5218
5314
  const failure = caught;
5219
5315
  failedAttempts.push(failure);
5316
+ clock.settle(failure.error, primaryStartedAt);
5220
5317
  firstError = failure.error;
5221
5318
  lastError = failure.error;
5222
5319
  if (failure.error instanceof DreamerProviderOutputFailureError && failure.error.quotaResetAt !== undefined)
@@ -5254,13 +5351,16 @@ async function promptSyncWithValidatedOutputRetry(client, args, options) {
5254
5351
  totalAttempts,
5255
5352
  model: parsed
5256
5353
  };
5354
+ const attemptStartedAt = Date.now();
5257
5355
  try {
5258
- const result = await attemptAndValidate(client, attemptArgs, timeoutMs, options.signal, callContext, attempt, options);
5356
+ const budget = clock.budget(i + 1);
5357
+ const result = await attemptAndValidate(client, attemptArgs, budget.timeoutMs, options.signal, callContext, attempt, options, budget.firstOutputTimeoutMs);
5259
5358
  log2(`[${callContext}] fallback succeeded with ${label} (attempt ${i + 2}/${fallbacks.length + 1})`);
5260
5359
  return result;
5261
5360
  } catch (caught) {
5262
5361
  const failure = caught;
5263
5362
  failedAttempts.push(failure);
5363
+ clock.settle(failure.error, attemptStartedAt);
5264
5364
  lastError = failure.error;
5265
5365
  if (isNonRetryable(failure.error, options.signal)) {
5266
5366
  throwWithPromptFailure(failure.error, failedAttempts, args, timeoutMs, options.transport);
@@ -5301,6 +5401,152 @@ function normalizeSDKResponse(response, fallback, options) {
5301
5401
  return fallback;
5302
5402
  }
5303
5403
  // ../plugin/src/features/magic-context/subagent-token-capture.ts
5404
+ var warnedUnknownModels = new Set;
5405
+ var loggedModelReroutes = new Set;
5406
+ var MAX_SUBAGENT_INVOCATION_ERROR_CHARS = 1000;
5407
+ var invocationErrorDetails = new WeakMap;
5408
+ function annotateSubagentInvocationError(error, details) {
5409
+ if (error && typeof error === "object") {
5410
+ const previous = invocationErrorDetails.get(error) ?? {};
5411
+ invocationErrorDetails.set(error, {
5412
+ ...previous,
5413
+ ...details,
5414
+ hostError: details.hostError ?? previous.hostError
5415
+ });
5416
+ }
5417
+ return error;
5418
+ }
5419
+ function errorDetailsOf(error) {
5420
+ const seen = new Set;
5421
+ const visit = (value, depth) => {
5422
+ if (!value || typeof value !== "object" || depth > 4 || seen.has(value))
5423
+ return {};
5424
+ seen.add(value);
5425
+ const direct = invocationErrorDetails.get(value) ?? {};
5426
+ const record = value;
5427
+ const nested = visit(record.hostError, depth + 1);
5428
+ const cause = visit(record.cause, depth + 1);
5429
+ return {
5430
+ ...cause,
5431
+ ...nested,
5432
+ ...direct,
5433
+ hostError: direct.hostError ?? nested.hostError ?? cause.hostError ?? record.hostError
5434
+ };
5435
+ };
5436
+ return visit(error, 0);
5437
+ }
5438
+ function modelRef(value) {
5439
+ const reference = typeof value === "string" ? value : value?.model;
5440
+ return typeof reference === "string" && reference.trim().length > 0 ? reference.trim() : undefined;
5441
+ }
5442
+ function splitModelRef(value) {
5443
+ if (!value)
5444
+ return { providerId: null, modelId: null };
5445
+ const slash = value.indexOf("/");
5446
+ return slash > 0 && slash < value.length - 1 ? { providerId: value.slice(0, slash), modelId: value.slice(slash + 1) } : { providerId: null, modelId: value };
5447
+ }
5448
+ function cleanOneLine(value) {
5449
+ const oneLine = sanitizeDiagnosticText(value).replaceAll("\r", " ").replaceAll(`
5450
+ `, " ").replaceAll("\t", " ").replace(/\s+/g, " ").trim();
5451
+ return oneLine.length <= MAX_SUBAGENT_INVOCATION_ERROR_CHARS ? oneLine : `${oneLine.slice(0, MAX_SUBAGENT_INVOCATION_ERROR_CHARS - 1)}…`;
5452
+ }
5453
+ function recordMessage(error) {
5454
+ if (typeof error === "string")
5455
+ return error;
5456
+ if (!error || typeof error !== "object")
5457
+ return String(error ?? "");
5458
+ const record = error;
5459
+ const data = record.data && typeof record.data === "object" ? record.data : undefined;
5460
+ const message = typeof data?.message === "string" ? data.message : typeof record.message === "string" ? record.message : typeof record.description === "string" ? record.description : "";
5461
+ const name = typeof record.name === "string" ? record.name : typeof record.type === "string" ? record.type : "";
5462
+ return [name, message].filter(Boolean).join(": ") || "The host reported an error without a message.";
5463
+ }
5464
+ function modelNotFoundDetail(error, attemptedModel) {
5465
+ const seen = new Set;
5466
+ const visit = (value, depth) => {
5467
+ if (typeof value === "string") {
5468
+ const modelMatch = value.match(/model not found:\s*(.+?)(?=(?:\.?\s*did you mean|$))/i);
5469
+ if (!modelMatch)
5470
+ return null;
5471
+ const model = modelMatch[1].trim().replace(/[.,;(]+$/, "");
5472
+ const suggestion = value.match(/did you mean:?\s*\(?\s*([^?);]+)/i)?.[1]?.trim();
5473
+ const message = `Model not found: ${model}${suggestion ? ` (did you mean ${suggestion}?)` : ""}`;
5474
+ return { model, ...suggestion ? { suggestion } : {}, message };
5475
+ }
5476
+ if (!value || typeof value !== "object" || depth > 4 || seen.has(value))
5477
+ return null;
5478
+ seen.add(value);
5479
+ const record = value;
5480
+ const data = record.data && typeof record.data === "object" ? record.data : undefined;
5481
+ const modelRecord = data?.model ?? record.model;
5482
+ const modelId = (typeof data?.modelID === "string" ? data.modelID : undefined) ?? (typeof modelRecord?.modelID === "string" ? modelRecord.modelID : undefined) ?? (typeof modelRecord?.id === "string" ? modelRecord.id : undefined);
5483
+ const providerId = (typeof data?.providerID === "string" ? data.providerID : undefined) ?? (typeof modelRecord?.providerID === "string" ? modelRecord.providerID : undefined);
5484
+ const suggestions = data?.suggestions;
5485
+ const suggestion = Array.isArray(suggestions) && typeof suggestions[0] === "string" ? suggestions[0] : typeof data?.suggestion === "string" ? data.suggestion : undefined;
5486
+ const rawMessage = recordMessage(value);
5487
+ const fromMessage = visit(rawMessage, depth + 1);
5488
+ if (fromMessage)
5489
+ return fromMessage.suggestion || !suggestion ? fromMessage : {
5490
+ ...fromMessage,
5491
+ suggestion,
5492
+ message: `Model not found: ${fromMessage.model} (did you mean ${suggestion}?)`
5493
+ };
5494
+ const name = `${String(record.name ?? "")} ${String(record.type ?? "")}`;
5495
+ if (/ProviderModelNotFoundError|model not found/i.test(name) && modelId) {
5496
+ const model = providerId ? `${providerId}/${modelId}` : modelId;
5497
+ const detail = `Model not found: ${model}${suggestion ? ` (did you mean ${suggestion}?)` : ""}`;
5498
+ return { model, ...suggestion ? { suggestion } : {}, message: detail };
5499
+ }
5500
+ for (const key of ["data", "error", "cause", "hostError"]) {
5501
+ const match = visit(record[key], depth + 1);
5502
+ if (match)
5503
+ return match;
5504
+ }
5505
+ return null;
5506
+ };
5507
+ const found = visit(error, 0);
5508
+ if (!found && attemptedModel && (typeof error === "string" && /ProviderModelNotFoundError/i.test(error) || error !== null && typeof error === "object" && /ProviderModelNotFoundError/i.test(`${String(error.name ?? "")} ${String(error.type ?? "")}`))) {
5509
+ return { model: attemptedModel, message: `Model not found: ${attemptedModel}` };
5510
+ }
5511
+ return found;
5512
+ }
5513
+ function hostLabel(harness) {
5514
+ switch (harness) {
5515
+ case "opencode2":
5516
+ return "OpenCode 2";
5517
+ case "opencode":
5518
+ return "OpenCode";
5519
+ case "pi":
5520
+ return "Pi";
5521
+ case "omp":
5522
+ return "Oh My Pi";
5523
+ }
5524
+ }
5525
+ function invocationErrorText(input, details, attemptedModel) {
5526
+ if (input.error == null && input.hostError == null && details.hostError == null)
5527
+ return null;
5528
+ const rawHostError = input.hostError ?? details.hostError;
5529
+ const modelError = modelNotFoundDetail(rawHostError ?? input.error, attemptedModel);
5530
+ if (modelError) {
5531
+ return cleanOneLine(`No reply: ${hostLabel(input.harness)} refused the model: ${modelError.message}`);
5532
+ }
5533
+ if (rawHostError != null) {
5534
+ return cleanOneLine(`No reply: ${hostLabel(input.harness)} reported a child-session error: ${recordMessage(rawHostError)}`);
5535
+ }
5536
+ return cleanOneLine(describeError(input.error).brief);
5537
+ }
5538
+ function warnUnknownModel(input, details, attemptedModel, modelConfigKey) {
5539
+ if (!attemptedModel)
5540
+ return;
5541
+ const issue = modelNotFoundDetail(input.hostError ?? details.hostError ?? input.error, attemptedModel);
5542
+ if (!issue || warnedUnknownModels.has(attemptedModel))
5543
+ return;
5544
+ if (!modelConfigKey)
5545
+ return;
5546
+ warnedUnknownModels.add(attemptedModel);
5547
+ const suggestion = issue.suggestion ? `provider suggests ${cleanOneLine(issue.suggestion)}` : "provider gave no model suggestion";
5548
+ log2(`[magic-context] WARNING: ${modelConfigKey} configured ${attemptedModel}, but ${hostLabel(input.harness)} does not know that model; ${suggestion}`);
5549
+ }
5304
5550
  function asNumber(value) {
5305
5551
  return typeof value === "number" && Number.isFinite(value) ? value : 0;
5306
5552
  }
@@ -5371,8 +5617,11 @@ function sumTokensFromChildMessages(messages) {
5371
5617
  function findLastAssistantModel(messages) {
5372
5618
  for (let index = messages.length - 1;index >= 0; index -= 1) {
5373
5619
  const message = messages[index];
5374
- if (isAssistantMessage(message))
5375
- return modelFromMessage(message);
5620
+ if (isAssistantMessage(message)) {
5621
+ const model = modelFromMessage(message);
5622
+ if (model.providerId || model.modelId)
5623
+ return model;
5624
+ }
5376
5625
  }
5377
5626
  return { providerId: null, modelId: null };
5378
5627
  }
@@ -5381,10 +5630,25 @@ function recordChildInvocation(input) {
5381
5630
  return null;
5382
5631
  const tokens = input.tokens ?? sumTokensFromChildMessages(input.messages ?? []);
5383
5632
  const observedModel = findLastAssistantModel(input.messages ?? []);
5633
+ const details = errorDetailsOf(input.error);
5634
+ const attemptedModel = details.attemptedModel ?? modelRef(input.attemptedModel);
5635
+ const attemptConfig = [input.attemptedModel, ...input.configuredModels ?? []].find((candidate) => modelRef(candidate) === attemptedModel);
5636
+ const modelConfigKey = details.modelConfigKey ?? input.modelConfigKey ?? (typeof attemptConfig === "object" ? attemptConfig?.sourceConfigKey : undefined);
5637
+ const attemptedParts = splitModelRef(attemptedModel);
5384
5638
  const model = {
5385
- providerId: input.providerId ?? observedModel.providerId,
5386
- modelId: input.modelId ?? observedModel.modelId
5639
+ providerId: observedModel.providerId ?? input.providerId ?? attemptedParts.providerId,
5640
+ modelId: observedModel.modelId ?? input.modelId ?? attemptedParts.modelId
5387
5641
  };
5642
+ const reportedModelRef = observedModel.providerId && observedModel.modelId ? `${observedModel.providerId}/${observedModel.modelId}` : input.providerId && input.modelId ? `${input.providerId}/${input.modelId}` : undefined;
5643
+ if (attemptedModel && reportedModelRef && attemptedModel !== reportedModelRef && (observedModel.providerId !== null || input.providerId !== undefined)) {
5644
+ const rerouteKey = `${input.harness}\x00${attemptedModel}\x00${reportedModelRef}`;
5645
+ if (!loggedModelReroutes.has(rerouteKey)) {
5646
+ loggedModelReroutes.add(rerouteKey);
5647
+ sessionLog2(input.parentSessionId, `subagent model rerouted by host: attempted=${attemptedModel} reported=${reportedModelRef}`);
5648
+ }
5649
+ }
5650
+ warnUnknownModel(input, details, attemptedModel, modelConfigKey);
5651
+ const errorText = invocationErrorText(input, details, attemptedModel);
5388
5652
  try {
5389
5653
  return recordSubagentInvocation(input.db, {
5390
5654
  sessionId: input.parentSessionId,
@@ -5400,7 +5664,7 @@ function recordChildInvocation(input) {
5400
5664
  outputTokens: tokens.output,
5401
5665
  cacheReadTokens: tokens.cacheRead,
5402
5666
  cacheWriteTokens: tokens.cacheWrite,
5403
- error: input.error ? describeError(input.error).brief : null,
5667
+ error: errorText,
5404
5668
  parentInvocationId: input.parentInvocationId ?? null
5405
5669
  });
5406
5670
  } catch (error) {
@@ -5428,6 +5692,17 @@ var HOST_SESSION_ERROR = Symbol("promptAsyncHostSessionError");
5428
5692
  function isHostSessionError(error) {
5429
5693
  return error !== null && typeof error === "object" && error[HOST_SESSION_ERROR] === true;
5430
5694
  }
5695
+ function hostSessionErrorOf(error) {
5696
+ if (!isHostSessionError(error))
5697
+ return;
5698
+ return error.hostError;
5699
+ }
5700
+ function requestModelRef(request) {
5701
+ const model = request.body?.model;
5702
+ if (model && typeof model.providerID === "string" && typeof model.modelID === "string")
5703
+ return `${model.providerID}/${model.modelID}`;
5704
+ return;
5705
+ }
5431
5706
  function supportsPromptAsync(client) {
5432
5707
  const session = sessionApi(client);
5433
5708
  return typeof session?.promptAsync === "function" && typeof session?.status === "function" && typeof session?.messages === "function";
@@ -5476,6 +5751,24 @@ function isTerminalAssistant(message) {
5476
5751
  const info = infoOf(message);
5477
5752
  return isSettledAssistant(message) && info.finish !== "tool-calls" && info.finish !== "tool_use" && !(message && typeof message === "object" && Array.isArray(message.parts) && message.parts.some((part) => part.type === "tool"));
5478
5753
  }
5754
+ function showsModelOutput(message) {
5755
+ if (infoOf(message).role !== "assistant")
5756
+ return false;
5757
+ const tokens = sumTokensFromChildMessages([message]);
5758
+ if (tokens.input + tokens.output + tokens.cacheRead + tokens.cacheWrite > 0)
5759
+ return true;
5760
+ const parts = message?.parts;
5761
+ if (!Array.isArray(parts))
5762
+ return false;
5763
+ return parts.some((part) => {
5764
+ if (!part || typeof part !== "object")
5765
+ return false;
5766
+ const { type, text } = part;
5767
+ if (type === "tool")
5768
+ return true;
5769
+ return (type === "text" || type === "reasoning") && typeof text === "string" && text.trim().length > 0;
5770
+ });
5771
+ }
5479
5772
  function unwrapData(response) {
5480
5773
  if (response && typeof response === "object" && "data" in response) {
5481
5774
  return response.data;
@@ -5564,15 +5857,35 @@ async function promptAsyncAndWaitForIdle(client, request, options = {}) {
5564
5857
  const initialBaseline = new Set(completionBaseline);
5565
5858
  activeSessionErrors.set(sessionId, undefined);
5566
5859
  try {
5567
- const sent = await session.promptAsync?.(request);
5860
+ let sent;
5861
+ try {
5862
+ sent = await session.promptAsync?.(request);
5863
+ } catch (error) {
5864
+ annotateSubagentInvocationError(error, {
5865
+ attemptedModel: requestModelRef(request),
5866
+ modelConfigKey: options.modelConfigKey,
5867
+ hostError: error
5868
+ });
5869
+ throw error;
5870
+ }
5568
5871
  if (sent && typeof sent === "object" && "error" in sent) {
5569
5872
  const rejection = sent.error;
5570
5873
  if (rejection) {
5571
- throw new Error(`prompt_async was rejected: ${describeRejection(rejection)}`);
5874
+ const error = new Error(`prompt_async was rejected: ${describeRejection(rejection)}`, {
5875
+ cause: rejection
5876
+ });
5877
+ annotateSubagentInvocationError(error, {
5878
+ attemptedModel: requestModelRef(request),
5879
+ modelConfigKey: options.modelConfigKey,
5880
+ hostError: rejection
5881
+ });
5882
+ throw error;
5572
5883
  }
5573
5884
  }
5574
5885
  let sentAt = Date.now();
5575
5886
  let sawBusy = false;
5887
+ noteModelActivityMonitored(signal);
5888
+ let sawOutput = false;
5576
5889
  for (;; ) {
5577
5890
  await sleep(pollIntervalMs, signal);
5578
5891
  const hostError = activeSessionErrors.get(sessionId);
@@ -5581,12 +5894,25 @@ async function promptAsyncAndWaitForIdle(client, request, options = {}) {
5581
5894
  Object.assign(error, {
5582
5895
  name: "DreamerProviderOutputFailureError",
5583
5896
  transient: true,
5584
- [HOST_SESSION_ERROR]: true
5897
+ [HOST_SESSION_ERROR]: true,
5898
+ hostError
5899
+ });
5900
+ annotateSubagentInvocationError(error, {
5901
+ attemptedModel: requestModelRef(request),
5902
+ modelConfigKey: options.modelConfigKey,
5903
+ hostError
5585
5904
  });
5586
5905
  throw error;
5587
5906
  }
5588
5907
  const status = await readStatus(session, sessionId, dir, signal);
5589
5908
  const messages = await readMessages(session, sessionId, dir, signal);
5909
+ if (!sawOutput && messages.some((message) => {
5910
+ const id = messageId(message);
5911
+ return id !== null && !initialBaseline.has(id) && showsModelOutput(message);
5912
+ })) {
5913
+ sawOutput = true;
5914
+ noteModelOutputReceived(signal);
5915
+ }
5590
5916
  if (budget) {
5591
5917
  const latest = messages.at(-1);
5592
5918
  const latestId = messageId(latest);
@@ -9138,6 +9464,8 @@ function resolveHiddenCompletionExecutor(executor, client, db, directory, entryP
9138
9464
  }
9139
9465
  function createV1HiddenCompletionExecutor(client, db, directory) {
9140
9466
  const historianChildren = new Set;
9467
+ const hostErrors = new Map;
9468
+ const runIdentities = new Map;
9141
9469
  return {
9142
9470
  capabilities: { tools: true, harness: "opencode" },
9143
9471
  async open(run) {
@@ -9154,23 +9482,49 @@ function createV1HiddenCompletionExecutor(client, db, directory) {
9154
9482
  preferResponseOnMissingData: true
9155
9483
  });
9156
9484
  const id = typeof created?.id === "string" ? created.id : "";
9157
- if (id)
9485
+ if (id) {
9158
9486
  rememberV1HiddenRun(id, run);
9487
+ runIdentities.set(id, run);
9488
+ }
9159
9489
  if (id && run.kind !== "dreamer-task") {
9160
9490
  historianChildren.add(id);
9161
9491
  rememberHistorianOutputCap(id, run.maxOutputTokens);
9162
9492
  }
9163
- return { id, childSessionId: id || undefined };
9493
+ const configured = toModelEntry(run.model);
9494
+ return {
9495
+ id,
9496
+ childSessionId: id || undefined,
9497
+ ...configured ? { attemptedModel: configured.model } : {},
9498
+ ...configured?.sourceConfigKey ? { modelConfigKey: configured.sourceConfigKey } : {}
9499
+ };
9164
9500
  },
9165
9501
  async attempt(handle, request) {
9166
9502
  if (!client)
9167
9503
  throw new Error("Hidden completion client is unavailable");
9504
+ const identity = runIdentities.get(handle.id);
9505
+ const requestedModel = request.body?.model;
9506
+ const requestedRef = requestedModel && typeof requestedModel.providerID === "string" && typeof requestedModel.modelID === "string" ? `${requestedModel.providerID}/${requestedModel.modelID}` : undefined;
9507
+ const matchingConfigured = (identity?.configuredModels ?? []).map(toModelEntry).find((entry) => entry?.model === requestedRef);
9508
+ const configured = matchingConfigured ?? (requestedRef && identity?.model && toModelEntry(identity.model)?.model === requestedRef ? toModelEntry(identity.model) : toModelEntry(identity?.model));
9509
+ handle.attemptedModel = requestedRef ?? configured?.model ?? handle.attemptedModel;
9510
+ handle.modelConfigKey = configured?.sourceConfigKey ?? handle.modelConfigKey;
9168
9511
  if (supportsPromptAsync(client)) {
9169
9512
  try {
9170
- await promptAsyncAndWaitForIdle(client, request);
9513
+ await promptAsyncAndWaitForIdle(client, request, {
9514
+ modelConfigKey: handle.modelConfigKey
9515
+ });
9171
9516
  } catch (error) {
9172
- if (historianChildren.has(handle.id) && isHostSessionError(error))
9173
- return;
9517
+ if (isHostSessionError(error)) {
9518
+ const hostError = hostSessionErrorOf(error);
9519
+ hostErrors.set(handle.id, hostError);
9520
+ annotateSubagentInvocationError(error, {
9521
+ attemptedModel: handle.attemptedModel,
9522
+ modelConfigKey: handle.modelConfigKey,
9523
+ hostError
9524
+ });
9525
+ if (historianChildren.has(handle.id))
9526
+ return;
9527
+ }
9174
9528
  throw error;
9175
9529
  }
9176
9530
  return;
@@ -9188,9 +9542,16 @@ function createV1HiddenCompletionExecutor(client, db, directory) {
9188
9542
  preferResponseOnMissingData: true
9189
9543
  });
9190
9544
  const assistantFailure = extractLatestAssistantFailure(messages);
9545
+ const hostError = hostErrors.get(handle.id);
9191
9546
  if (assistantFailure) {
9192
9547
  const finish = assistantFailure.finish ? ` (finish=${assistantFailure.finish})` : "";
9193
- throw new Error(`Historian host recorded an assistant error${finish}: ${describeAssistantFailure(assistantFailure.error)}`);
9548
+ const error = new Error(`Historian host recorded an assistant error${finish}: ${describeAssistantFailure(assistantFailure.error)}`, hostError === undefined ? undefined : { cause: hostError });
9549
+ annotateSubagentInvocationError(error, {
9550
+ attemptedModel: handle.attemptedModel,
9551
+ modelConfigKey: handle.modelConfigKey,
9552
+ hostError
9553
+ });
9554
+ throw error;
9194
9555
  }
9195
9556
  const text = extractLatestAssistantText(messages);
9196
9557
  const latest = Array.isArray(messages) ? messages.filter((message) => isRecord(message) && isRecord(message.info) && message.info.role === "assistant").sort((left, right) => historianMessageCreatedAt(right) - historianMessageCreatedAt(left))[0] : undefined;
@@ -9201,13 +9562,18 @@ function createV1HiddenCompletionExecutor(client, db, directory) {
9201
9562
  reasoning: text ? null : extractLatestHistorianReasoning(messages),
9202
9563
  lengthCapped: hasLengthCappedOutput(messages),
9203
9564
  usage: sumTokensFromChildMessages(messages),
9204
- tokenLog: runTokenLog(info.tokens, undefined, info.finish ?? info.finish_reason ?? info.finishReason)
9565
+ tokenLog: runTokenLog(info.tokens, undefined, info.finish ?? info.finish_reason ?? info.finishReason),
9566
+ attemptedModel: handle.attemptedModel,
9567
+ modelConfigKey: handle.modelConfigKey,
9568
+ ...hostError === undefined ? {} : { hostError }
9205
9569
  };
9206
9570
  },
9207
9571
  async close(handle, settlement) {
9208
9572
  if (handle?.id) {
9209
9573
  rememberV1HiddenRun(handle.id, undefined);
9210
9574
  historianChildren.delete(handle.id);
9575
+ hostErrors.delete(handle.id);
9576
+ runIdentities.delete(handle.id);
9211
9577
  forgetHistorianOutputCap(handle.id);
9212
9578
  }
9213
9579
  if (!client)
@@ -9362,7 +9728,8 @@ async function runHistorianPrompt(args) {
9362
9728
  if (invocationRecorded)
9363
9729
  return null;
9364
9730
  invocationRecorded = true;
9365
- const actualModelRef = completion?.providerId && completion.modelId ? `${completion.providerId}/${completion.modelId}` : null;
9731
+ const configuredModel = toModelEntry(modelOverride);
9732
+ const actualModelRef = completion?.providerId && completion.modelId ? `${completion.providerId}/${completion.modelId}` : handle?.attemptedModel ?? configuredModel?.model ?? null;
9366
9733
  const usedConfiguredFallback = actualModelRef !== null && (fallbackModels ?? []).some((candidate) => toModelEntry(candidate)?.model === actualModelRef);
9367
9734
  return recordChildInvocation({
9368
9735
  db: openDatabase(),
@@ -9378,6 +9745,10 @@ async function runHistorianPrompt(args) {
9378
9745
  providerId: completion.providerId,
9379
9746
  modelId: completion.modelId
9380
9747
  } : {},
9748
+ attemptedModel: handle?.attemptedModel ?? modelOverride,
9749
+ configuredModels: fallbackModels,
9750
+ modelConfigKey: handle?.modelConfigKey ?? configuredModel?.sourceConfigKey,
9751
+ hostError: params.hostError ?? completion?.hostError,
9381
9752
  error: params.error,
9382
9753
  parentInvocationId: agentId === HISTORIAN_EDITOR_AGENT ? parentInvocationId ?? null : null
9383
9754
  });
@@ -9491,7 +9862,8 @@ async function runHistorianPrompt(args) {
9491
9862
  const invocationId = recordInvocation({
9492
9863
  status: emptyError ? "empty" : "completed",
9493
9864
  messages: completion.messages,
9494
- error: emptyError
9865
+ error: emptyError,
9866
+ hostError: completion.hostError
9495
9867
  });
9496
9868
  if (emptyError && (!reasoningResult || lengthCapped)) {
9497
9869
  return {
@@ -10314,7 +10686,9 @@ async function compressOneChunk(args, chunk, sliceMs, signal) {
10314
10686
  status: "completed",
10315
10687
  tokens: run.output.usage,
10316
10688
  providerId: run.output.providerId,
10317
- modelId: run.output.modelId
10689
+ modelId: run.output.modelId,
10690
+ attemptedModel: args.model,
10691
+ configuredModels: args.fallbackModels
10318
10692
  });
10319
10693
  }
10320
10694
  stage = "apply";
@@ -10481,6 +10855,7 @@ async function applyCuesThroughModule(args, chunk, manifestText, signal) {
10481
10855
  }
10482
10856
 
10483
10857
  // ../plugin/src/features/magic-context/dreamer/hidden-single-shot.ts
10858
+ var DREAMER_FIRST_OUTPUT_TIMEOUT_MS = 90000;
10484
10859
  async function runHiddenSingleShotPrompt(args) {
10485
10860
  const system = withContentLanguageDirective(args.system, args.language);
10486
10861
  const opening = args.executor.open({
@@ -10505,6 +10880,7 @@ async function runHiddenSingleShotPrompt(args) {
10505
10880
  });
10506
10881
  }).catch(() => {});
10507
10882
  const handle = await raceWithSignal(opening, args.signal);
10883
+ let completion;
10508
10884
  args.onOpened?.(handle.id);
10509
10885
  let promptSettled = false;
10510
10886
  try {
@@ -10522,10 +10898,14 @@ async function runHiddenSingleShotPrompt(args) {
10522
10898
  }, {
10523
10899
  transport: Object.assign((request) => args.executor.attempt(handle, request), { childSessionId: handle.childSessionId }),
10524
10900
  timeoutMs: args.timeoutMs,
10901
+ ...args.firstOutputTimeoutMs !== undefined ? { firstOutputTimeoutMs: args.firstOutputTimeoutMs } : {},
10525
10902
  ...args.signal ? { signal: args.signal } : {},
10526
10903
  fallbackModels: args.fallbackModels,
10527
10904
  callContext: args.callContext,
10528
- fetchOutput: () => args.executor.collect(handle, 50),
10905
+ fetchOutput: async () => {
10906
+ completion = await args.executor.collect(handle, 50);
10907
+ return completion;
10908
+ },
10529
10909
  validateOutput: (completion) => {
10530
10910
  const tokens = completion.tokenLog ?? runTokenLog(undefined);
10531
10911
  sessionLog2(args.parentSessionId ?? "dreamer", `${args.callContext} response_chars=${(completion.text ?? completion.reasoning ?? "").length} ${formatRunTokenLog(tokens)}`);
@@ -10541,6 +10921,12 @@ async function runHiddenSingleShotPrompt(args) {
10541
10921
  promptSettled = true;
10542
10922
  return { validated: run.validated, completion: run.output, childSessionId: handle.id };
10543
10923
  } catch (error) {
10924
+ const configuredModel = toModelEntry(args.model);
10925
+ annotateSubagentInvocationError(error, {
10926
+ attemptedModel: completion?.attemptedModel ?? handle.attemptedModel ?? configuredModel?.model,
10927
+ modelConfigKey: completion?.modelConfigKey ?? handle.modelConfigKey ?? configuredModel?.sourceConfigKey,
10928
+ ...completion?.hostError === undefined ? {} : { hostError: completion.hostError }
10929
+ });
10544
10930
  if (args.onFailureOutput) {
10545
10931
  let timer;
10546
10932
  try {
@@ -10868,6 +11254,8 @@ If no promotions are warranted, return empty arrays. Always consume reviewed can
10868
11254
  startedAt,
10869
11255
  status: params.status,
10870
11256
  messages: params.messages,
11257
+ attemptedModel: args.model,
11258
+ configuredModels: args.fallbackModels,
10871
11259
  error: params.error
10872
11260
  });
10873
11261
  };
@@ -11375,6 +11763,7 @@ async function classifyOneChunk(args, chunk, anchors, sliceMs, signal) {
11375
11763
  }, {
11376
11764
  transport: Object.assign((request) => executor.attempt(opened, request), { childSessionId: opened.childSessionId }),
11377
11765
  timeoutMs: sliceMs,
11766
+ firstOutputTimeoutMs: args.firstOutputTimeoutMs ?? DREAMER_FIRST_OUTPUT_TIMEOUT_MS,
11378
11767
  signal,
11379
11768
  fallbackModels: args.fallbackModels,
11380
11769
  callContext: "dreamer:classify-memories",
@@ -11654,6 +12043,8 @@ function recordInvocation(args, startedAt, params) {
11654
12043
  startedAt,
11655
12044
  status: params.status,
11656
12045
  messages: params.messages,
12046
+ attemptedModel: args.model,
12047
+ configuredModels: args.fallbackModels,
11657
12048
  ...params.completion && !params.completion.messages ? {
11658
12049
  tokens: params.completion.usage,
11659
12050
  providerId: params.completion.providerId,
@@ -13189,6 +13580,8 @@ Remember: output only the JSON object described by the system prompt.`;
13189
13580
  startedAt,
13190
13581
  status: params.status,
13191
13582
  messages: params.messages,
13583
+ attemptedModel: args.model,
13584
+ configuredModels: args.fallbackModels,
13192
13585
  error: params.error
13193
13586
  });
13194
13587
  };
@@ -13936,6 +14329,8 @@ async function confirmReadOnly(args, noteId, content, surfaceCondition, leaseSig
13936
14329
  startedAt,
13937
14330
  status: params.status,
13938
14331
  messages: params.messages,
14332
+ attemptedModel: args.model,
14333
+ configuredModels: args.fallbackModels,
13939
14334
  error: params.error
13940
14335
  });
13941
14336
  };
@@ -14602,6 +14997,7 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
14602
14997
  model: args.model,
14603
14998
  fallbackModels: args.fallbackModels,
14604
14999
  timeoutMs: sliceMs,
15000
+ firstOutputTimeoutMs: args.firstOutputTimeoutMs ?? DREAMER_FIRST_OUTPUT_TIMEOUT_MS,
14605
15001
  signal,
14606
15002
  onOpened: () => {
14607
15003
  stage = "prompt";
@@ -14656,6 +15052,7 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
14656
15052
  onBudgetUpdate
14657
15053
  }),
14658
15054
  timeoutMs: sliceMs,
15055
+ firstOutputTimeoutMs: args.firstOutputTimeoutMs ?? DREAMER_FIRST_OUTPUT_TIMEOUT_MS,
14659
15056
  signal,
14660
15057
  fallbackModels: args.fallbackModels,
14661
15058
  callContext: "dreamer:map-memories",
@@ -14848,12 +15245,14 @@ function recordInvocation2(args, startedAt, params) {
14848
15245
  recordChildInvocation({
14849
15246
  db: args.db,
14850
15247
  parentSessionId: args.parentSessionId,
14851
- harness: "opencode",
15248
+ harness: args.hiddenCompletionExecutor?.capabilities.harness ?? "opencode",
14852
15249
  subagent: "dreamer",
14853
15250
  task: "map-memories",
14854
15251
  startedAt,
14855
15252
  status: params.status,
14856
15253
  messages: params.messages,
15254
+ attemptedModel: args.model,
15255
+ configuredModels: args.fallbackModels,
14857
15256
  error: params.error
14858
15257
  });
14859
15258
  }
@@ -15478,12 +15877,14 @@ function recordInvocation3(args, startedAt, params) {
15478
15877
  recordChildInvocation({
15479
15878
  db: args.db,
15480
15879
  parentSessionId: args.parentSessionId,
15481
- harness: "opencode",
15880
+ harness: args.hiddenCompletionExecutor?.capabilities.harness ?? "opencode",
15482
15881
  subagent: "dreamer",
15483
15882
  task: "refresh-primers",
15484
15883
  startedAt,
15485
15884
  status: params.status,
15486
15885
  messages: params.messages,
15886
+ attemptedModel: args.model,
15887
+ configuredModels: args.fallbackModels,
15487
15888
  error: params.error
15488
15889
  });
15489
15890
  }
@@ -16706,6 +17107,7 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
16706
17107
  fallbackModels: args.fallbackModels,
16707
17108
  language: args.language,
16708
17109
  timeoutMs: sliceMs,
17110
+ firstOutputTimeoutMs: args.firstOutputTimeoutMs ?? DREAMER_FIRST_OUTPUT_TIMEOUT_MS,
16709
17111
  signal: batchSignal,
16710
17112
  onFailureOutput: (completion) => {
16711
17113
  failedCompletion = completion;
@@ -16763,6 +17165,7 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
16763
17165
  onBudgetUpdate
16764
17166
  }),
16765
17167
  timeoutMs: sliceMs,
17168
+ firstOutputTimeoutMs: args.firstOutputTimeoutMs ?? DREAMER_FIRST_OUTPUT_TIMEOUT_MS,
16766
17169
  signal: batchSignal,
16767
17170
  fallbackModels: args.fallbackModels,
16768
17171
  callContext: "dreamer:verify",
@@ -17055,12 +17458,14 @@ function recordInvocation4(args, startedAt, params) {
17055
17458
  recordChildInvocation({
17056
17459
  db: args.db,
17057
17460
  parentSessionId: args.parentSessionId,
17058
- harness: "opencode",
17461
+ harness: args.hiddenCompletionExecutor?.capabilities.harness ?? "opencode",
17059
17462
  subagent: "dreamer",
17060
17463
  task: args.forceBroad ? "verify-broad" : "verify",
17061
17464
  startedAt,
17062
17465
  status: params.status,
17063
17466
  messages: params.messages,
17467
+ attemptedModel: args.model,
17468
+ configuredModels: args.fallbackModels,
17064
17469
  error: params.error
17065
17470
  });
17066
17471
  }
@@ -17936,6 +18341,25 @@ async function runRetrospectiveTask(config, ctx, helpers) {
17936
18341
  let childSessionId = null;
17937
18342
  let hiddenHandle = null;
17938
18343
  let promptSettled = false;
18344
+ let invocationRecorded = false;
18345
+ const recordInvocation = (status, messages, error) => {
18346
+ if (!parent || !childSessionId || invocationRecorded)
18347
+ return;
18348
+ invocationRecorded = true;
18349
+ recordChildInvocation({
18350
+ db,
18351
+ parentSessionId: parent,
18352
+ harness: deps.hiddenCompletionExecutor?.capabilities.harness ?? "opencode",
18353
+ subagent: "dreamer",
18354
+ task: config.task,
18355
+ startedAt: helpers.invocationStartedAt,
18356
+ status,
18357
+ messages,
18358
+ attemptedModel: config.model,
18359
+ configuredModels: config.fallbackModels,
18360
+ error
18361
+ });
18362
+ };
17939
18363
  try {
17940
18364
  if (deps.hiddenCompletionExecutor) {
17941
18365
  hiddenHandle = await deps.hiddenCompletionExecutor.open({
@@ -18020,18 +18444,8 @@ async function runRetrospectiveTask(config, ctx, helpers) {
18020
18444
  return { ...run, output };
18021
18445
  };
18022
18446
  const finish = (run, watermark) => {
18023
- if (parent && run) {
18024
- recordChildInvocation({
18025
- db,
18026
- parentSessionId: parent,
18027
- harness: "opencode",
18028
- subagent: "dreamer",
18029
- task: config.task,
18030
- startedAt: helpers.invocationStartedAt,
18031
- status: "completed",
18032
- messages: run.output
18033
- });
18034
- }
18447
+ if (run)
18448
+ recordInvocation("completed", run.output);
18035
18449
  return completedWindow(watermark);
18036
18450
  };
18037
18451
  const userLines = renderGateUserLines(messages);
@@ -18124,6 +18538,7 @@ async function runRetrospectiveTask(config, ctx, helpers) {
18124
18538
  log2(`[dreamer] retrospective: flagged=${flagged.length} learnings=${learnings.length} memory=${applied.memoryWritten} observations=${applied.observationsInserted} dropped=${applied.observationsDropped} rejected=${applied.rejected.length}`);
18125
18539
  return finish(deepenRun, scan.maxScannedTs);
18126
18540
  } catch (error) {
18541
+ recordInvocation(abortController.signal.aborted ? "aborted" : failedInvocationStatus(error), undefined, error);
18127
18542
  if (!detectOverflow(error).isOverflow)
18128
18543
  throw error;
18129
18544
  const failures = (activeOverflow?.failures ?? 0) + 1;
@@ -18195,6 +18610,25 @@ async function runAgenticTask(config, ctx, helpers) {
18195
18610
  let childSessionId = null;
18196
18611
  let promptSettled = false;
18197
18612
  let expiredArchived = 0;
18613
+ let invocationRecorded = false;
18614
+ const recordInvocation = (status, messages, error) => {
18615
+ if (!parent || !childSessionId || invocationRecorded)
18616
+ return;
18617
+ invocationRecorded = true;
18618
+ recordChildInvocation({
18619
+ db,
18620
+ parentSessionId: parent,
18621
+ harness: deps.hiddenCompletionExecutor?.capabilities.harness ?? "opencode",
18622
+ subagent: "dreamer",
18623
+ task,
18624
+ startedAt: invocationStartedAt,
18625
+ status,
18626
+ messages,
18627
+ attemptedModel: config.model,
18628
+ configuredModels: config.fallbackModels,
18629
+ error
18630
+ });
18631
+ };
18198
18632
  try {
18199
18633
  let curateMemories;
18200
18634
  let curateCategory;
@@ -18283,6 +18717,9 @@ async function runAgenticTask(config, ctx, helpers) {
18283
18717
  callContext: `dreamer:${task}`,
18284
18718
  metadata: { tokenBudget: config.tokenBudget, onBudgetUpdate },
18285
18719
  allowEmpty: task === "curate",
18720
+ onOpened: (sessionId) => {
18721
+ childSessionId = sessionId;
18722
+ },
18286
18723
  model: config.model,
18287
18724
  fallbackModels: config.fallbackModels,
18288
18725
  language: task === "curate" ? config.language ?? deps.language : undefined,
@@ -18398,18 +18835,7 @@ async function runAgenticTask(config, ctx, helpers) {
18398
18835
  helpers.reportProgress(curateRefused, curateRefused);
18399
18836
  log2(`[dreamer] curate safety summary: refused=${curateRefused}`);
18400
18837
  }
18401
- if (parent) {
18402
- recordChildInvocation({
18403
- db,
18404
- parentSessionId: parent,
18405
- harness: "opencode",
18406
- subagent: "dreamer",
18407
- task,
18408
- startedAt: invocationStartedAt,
18409
- status: "completed",
18410
- messages: run.output
18411
- });
18412
- }
18838
+ recordInvocation("completed", run.output);
18413
18839
  if (task === "maintain-docs" && docsHashes && changes) {
18414
18840
  try {
18415
18841
  if (run.validated === "[]") {
@@ -18463,6 +18889,9 @@ async function runAgenticTask(config, ctx, helpers) {
18463
18889
  }
18464
18890
  } : {}
18465
18891
  };
18892
+ } catch (error) {
18893
+ recordInvocation(abortController.signal.aborted ? "aborted" : failedInvocationStatus(error), undefined, error);
18894
+ throw error;
18466
18895
  } finally {
18467
18896
  heartbeat.stop();
18468
18897
  if (childSessionId)
@@ -19248,6 +19677,11 @@ async function indexSingleMessageOffThread(db, sessionId, message) {
19248
19677
  return result.inserted;
19249
19678
  }
19250
19679
  async function sweepOrphanedOpenCodeMessageIndexesOffThread(db, openSource, options = {}) {
19680
+ if (getHarness2() === "opencode" || getHarness2() === "opencode2")
19681
+ options = {
19682
+ ...options,
19683
+ fenceLockNames: options.fenceLockNames ?? takeLkgRecoveryLockSweepPage()
19684
+ };
19251
19685
  if (getHarness2() === "opencode2")
19252
19686
  openSource = () => new Database2(gaDatabasePath(getDataDir(), process.env.OPENCODE_CHANNEL ?? "latest"), {
19253
19687
  readonly: true,
@@ -20473,7 +20907,8 @@ class PiSubagentRunner {
20473
20907
  ...options,
20474
20908
  model: attempt?.model,
20475
20909
  thinkingLevel: attempt?.qualifier,
20476
- fallbackModels: undefined
20910
+ fallbackModels: undefined,
20911
+ accountingModelConfigKey: typeof attempt === "object" ? attempt.sourceConfigKey ?? options.accountingModelConfigKey : options.accountingModelConfigKey
20477
20912
  };
20478
20913
  const result = await this.runOnce(attemptOptions, runMode, index === 0 ? primaryModelRef : undefined);
20479
20914
  if (result.ok)
@@ -20528,6 +20963,8 @@ class PiSubagentRunner {
20528
20963
  subagent: options.accountingSubagent ?? inferAccountingSubagent(options.agent),
20529
20964
  task: options.accountingTask ?? null,
20530
20965
  startedAt: startTime,
20966
+ attemptedModel: modelRef,
20967
+ modelConfigKey: options.accountingModelConfigKey,
20531
20968
  status: result.ok ? "completed" : result.meta?.failureClass === ZEN_FREE_TIER_FAILURE ? "failed" : result.reason === "abort" ? "aborted" : result.reason === "timeout" ? "timed_out" : result.reason === "no_assistant" || result.reason === "truncated" ? "empty" : "failed",
20532
20969
  messages,
20533
20970
  providerId: hasProvider ? modelRef?.slice(0, providerSeparator) : undefined,
@@ -21077,10 +21514,11 @@ class PiSubagentRunner {
21077
21514
  if (settled)
21078
21515
  return;
21079
21516
  terminateChild(child);
21517
+ const silentCut = options.signal?.reason instanceof ModelProducedNoOutputError ? options.signal.reason : undefined;
21080
21518
  settle({
21081
21519
  ok: false,
21082
- reason: "abort",
21083
- error: "pi subagent aborted by caller",
21520
+ reason: silentCut ? "timeout" : "abort",
21521
+ error: silentCut?.message ?? "pi subagent aborted by caller",
21084
21522
  durationMs: Date.now() - startTime
21085
21523
  });
21086
21524
  };
@@ -21486,6 +21924,28 @@ function terminateChild(child) {
21486
21924
  }
21487
21925
  }
21488
21926
 
21927
+ // src/dreamer/model-activity.ts
21928
+ function piEventShowsModelOutput(event) {
21929
+ if (!isRecord(event))
21930
+ return false;
21931
+ if (event.type !== "message_update" && event.type !== "message_end")
21932
+ return false;
21933
+ const update = event.assistantMessageEvent;
21934
+ if (event.type === "message_update" && isRecord(update)) {
21935
+ if (update.type === "toolcall_start")
21936
+ return true;
21937
+ if (["text_delta", "thinking_delta", "toolcall_delta"].includes(String(update.type)) && typeof update.delta === "string" && update.delta.length > 0)
21938
+ return true;
21939
+ }
21940
+ const message = event.message;
21941
+ if (!isRecord(message) || message.role !== "assistant")
21942
+ return false;
21943
+ if (Array.isArray(message.content) && message.content.some((part) => isRecord(part) && (part.type === "toolCall" || part.type === "text" && typeof part.text === "string" && part.text.length > 0 || part.type === "thinking" && typeof part.thinking === "string" && part.thinking.length > 0)))
21944
+ return true;
21945
+ const usage = message.usage;
21946
+ return isRecord(usage) && ["input", "output", "cacheRead", "cacheWrite"].some((key) => typeof usage[key] === "number" && usage[key] > 0);
21947
+ }
21948
+
21489
21949
  // src/dreamer/primer-raw-provider-pi.ts
21490
21950
  import { join as join13 } from "node:path";
21491
21951
 
@@ -22168,7 +22628,7 @@ function extractPiTextContent(content) {
22168
22628
  }
22169
22629
 
22170
22630
  // src/dreamer/index.ts
22171
- var warnedUnknownModels = new Set;
22631
+ var warnedUnknownModels2 = new Set;
22172
22632
  var modelAvailability = new WeakMap;
22173
22633
  function validatePiDreamerModels(tasks, registry, harness = "pi") {
22174
22634
  let resolved = modelAvailability.get(registry);
@@ -22190,9 +22650,9 @@ function validatePiDreamerModels(tasks, registry, harness = "pi") {
22190
22650
  }
22191
22651
  if (available)
22192
22652
  return true;
22193
- if (!warnedUnknownModels.has(model)) {
22653
+ if (!warnedUnknownModels2.has(model)) {
22194
22654
  log2(`[dreamer] WARNING: dropping Pi model not found: ${model}`);
22195
- warnedUnknownModels.add(model);
22655
+ warnedUnknownModels2.add(model);
22196
22656
  }
22197
22657
  return false;
22198
22658
  });
@@ -22424,6 +22884,8 @@ function createPiDreamerClient(opts, onAdjunctsRefreshNeeded = opts.onAdjunctsRe
22424
22884
  const systemPrompt = extractSystemPrompt(args);
22425
22885
  const perTaskModel = extractBodyModel(args);
22426
22886
  const requestedAgent = extractBodyAgent(args) ?? "magic-context-dreamer";
22887
+ const accountingTask = accountingTaskFromTitle(dreamSession.title);
22888
+ const taskConfig = accountingTask ? buildDreamTaskRuntimeConfigs(getDreamerConfig(), opts.harness).find((entry) => entry.task === accountingTask) : undefined;
22427
22889
  const controller = new AbortController;
22428
22890
  let controllers = dreamAbortControllers.get(opts.registrationOwner);
22429
22891
  if (!controllers) {
@@ -22431,7 +22893,12 @@ function createPiDreamerClient(opts, onAdjunctsRefreshNeeded = opts.onAdjunctsRe
22431
22893
  dreamAbortControllers.set(opts.registrationOwner, controllers);
22432
22894
  }
22433
22895
  controllers.add(controller);
22896
+ noteModelActivityMonitored(args.signal ?? undefined);
22434
22897
  const runPromise = runner.run({
22898
+ onProgress: (progress) => {
22899
+ if (progress.type === "raw_event" && piEventShowsModelOutput(progress.event))
22900
+ noteModelOutputReceived(args.signal ?? undefined);
22901
+ },
22435
22902
  agent: requestedAgent,
22436
22903
  systemPrompt,
22437
22904
  userMessage,
@@ -22444,15 +22911,9 @@ function createPiDreamerClient(opts, onAdjunctsRefreshNeeded = opts.onAdjunctsRe
22444
22911
  maxOutputTokens: getMaxOutputTokens(),
22445
22912
  accountingSessionId: opts.projectIdentity,
22446
22913
  accountingSubagent: "dreamer",
22447
- accountingTask: accountingTaskFromTitle(dreamSession.title),
22448
- tokenBudget: (() => {
22449
- if (args.tokenBudget !== undefined)
22450
- return args.tokenBudget;
22451
- const task = accountingTaskFromTitle(dreamSession.title);
22452
- if (!task)
22453
- return;
22454
- return buildDreamTaskRuntimeConfigs(getDreamerConfig(), opts.harness).find((entry) => entry.task === task)?.tokenBudget;
22455
- })()
22914
+ accountingTask,
22915
+ accountingModelConfigKey: taskConfig?.modelConfigKey,
22916
+ tokenBudget: args.tokenBudget ?? taskConfig?.tokenBudget
22456
22917
  });
22457
22918
  inFlightDreams.set(runPromise, opts.registrationOwner);
22458
22919
  try {
@@ -22900,6 +23361,13 @@ Unknown task "${requested}".`,
22900
23361
  }
22901
23362
 
22902
23363
  // ../plugin/src/hooks/magic-context/auto-embed-session.ts
23364
+ function localPoolingPreflightPending(projectIdentity) {
23365
+ const snapshot = getProjectEmbeddingSnapshot2(projectIdentity);
23366
+ if (snapshot?.provider !== "local")
23367
+ return false;
23368
+ const metadata = getCachedLocalEmbeddingPooling(snapshot.model);
23369
+ return !metadata || metadata.status === "unresolved";
23370
+ }
22903
23371
  function embeddingIdentity(projectIdentity) {
22904
23372
  const snapshot = getProjectEmbeddingSnapshot2(projectIdentity);
22905
23373
  return JSON.stringify([
@@ -22920,7 +23388,8 @@ function maybeAutoEmbedSessionBackfill(deps, sessionId) {
22920
23388
  invalidateAutoEmbedSession(sessionId);
22921
23389
  autoEmbedIdentityBySession.set(sessionId, identity);
22922
23390
  }
22923
- if (autoEmbedAttemptedBySession.has(sessionId) || embedPauseBySession.has(sessionId) || embedRunStateBySession.has(sessionId) || Date.now() < (autoEmbedRetryAfterBySession.get(sessionId) ?? 0))
23391
+ const poolingPreflightPending = localPoolingPreflightPending(deps.projectIdentity);
23392
+ if (embedPauseBySession.has(sessionId) || embedRunStateBySession.has(sessionId) || Date.now() < (autoEmbedRetryAfterBySession.get(sessionId) ?? 0) || autoEmbedAttemptedBySession.has(sessionId) && !poolingPreflightPending)
22924
23393
  return;
22925
23394
  const controller = new AbortController;
22926
23395
  embedRunStateBySession.set(sessionId, controller);
@@ -22930,6 +23399,7 @@ function maybeAutoEmbedSessionBackfill(deps, sessionId) {
22930
23399
  let started = false;
22931
23400
  let reason = "error";
22932
23401
  let registeredIdentity = identity;
23402
+ let poolingPendingAfterRegistration = poolingPreflightPending;
22933
23403
  try {
22934
23404
  await new Promise((resolve) => setTimeout(resolve, 0));
22935
23405
  if (controller.signal.aborted)
@@ -22937,6 +23407,7 @@ function maybeAutoEmbedSessionBackfill(deps, sessionId) {
22937
23407
  await deps.ensureRegistered();
22938
23408
  if (controller.signal.aborted)
22939
23409
  return;
23410
+ poolingPendingAfterRegistration = localPoolingPreflightPending(deps.projectIdentity);
22940
23411
  markActive();
22941
23412
  registeredIdentity = embeddingIdentity(deps.projectIdentity);
22942
23413
  autoEmbedIdentityBySession.set(sessionId, registeredIdentity);
@@ -22944,7 +23415,9 @@ function maybeAutoEmbedSessionBackfill(deps, sessionId) {
22944
23415
  if (controller.signal.aborted || !coverage.enabled)
22945
23416
  return;
22946
23417
  if (coverage.embedded === coverage.total) {
22947
- complete = true;
23418
+ complete = !poolingPendingAfterRegistration;
23419
+ if (!complete)
23420
+ retryDelay = 60000;
22948
23421
  return;
22949
23422
  }
22950
23423
  const model = getProjectEmbeddingSnapshot2(deps.projectIdentity)?.model;
@@ -22953,8 +23426,11 @@ function maybeAutoEmbedSessionBackfill(deps, sessionId) {
22953
23426
  const outcome = await embedSessionCompartmentChunks2(deps.db, deps.projectIdentity, sessionId, { signal: controller.signal, automatic: true });
22954
23427
  reason = outcome.status;
22955
23428
  const after = await getAutoEmbeddingSessionCoverage2(deps.db, deps.projectIdentity, sessionId);
22956
- complete = after.enabled && after.embedded === after.total;
22957
- if (!complete && outcome.status !== "busy" && outcome.status !== "aborted") {
23429
+ complete = after.enabled && after.embedded === after.total && !poolingPendingAfterRegistration;
23430
+ if (poolingPendingAfterRegistration) {
23431
+ retryDelay = 60000;
23432
+ reason = "pooling metadata unavailable";
23433
+ } else if (!complete && outcome.status !== "busy" && outcome.status !== "aborted") {
22958
23434
  retryDelay = 60000;
22959
23435
  if (outcome.status === "nothing" || outcome.status === "done")
22960
23436
  reason = "deferred";
@@ -23227,7 +23703,9 @@ function maybeAutoEmbedPiSession(deps, sessionId, projectDir, projectIdentity) {
23227
23703
  maybeAutoEmbedSessionBackfill({
23228
23704
  db: deps.db,
23229
23705
  projectIdentity,
23230
- ensureRegistered: () => ensureProjectRegisteredFromPiDirectory(projectDir, deps.db)
23706
+ ensureRegistered: () => ensureProjectRegisteredFromPiDirectory(projectDir, deps.db, {
23707
+ preflightLocalPooling: true
23708
+ })
23231
23709
  }, sessionId);
23232
23710
  }
23233
23711
 
@@ -24241,7 +24719,8 @@ function capturePendingDropEligibility(targets, protectedTagIds) {
24241
24719
  eligible.add(number);
24242
24720
  } else {
24243
24721
  const content = target.getContent?.();
24244
- if (typeof content === "string" && content.length > `[dropped §${number}§]`.length)
24722
+ const replacement = `[dropped §${number}§]`;
24723
+ if (typeof content === "string" && content.length > replacement.length && target.canSetContent?.(replacement) !== false)
24245
24724
  eligible.add(number);
24246
24725
  }
24247
24726
  }
@@ -24528,12 +25007,16 @@ function applyPendingOperations(sessionId, db, targets, protectedTagIds, preload
24528
25007
  }
24529
25008
  } else if (target) {
24530
25009
  const replacement = buildReplacementContent(pendingOp.tagId);
25010
+ if (target.canSetContent?.(replacement) === false) {
25011
+ reject("content_unchanged");
25012
+ continue;
25013
+ }
24531
25014
  persistDrop();
24532
25015
  mutations.push(() => {
24533
25016
  const priorContent = target.getContent?.();
24534
25017
  const changed = target.setContent(replacement);
24535
- record(changed);
24536
25018
  if (changed) {
25019
+ record(true);
24537
25020
  const originalCharacters = typeof priorContent === "string" ? priorContent.length : tagById.get(pendingOp.tagId)?.byteSize ?? replacement.length;
24538
25021
  onTagReduced?.({
24539
25022
  tagNumber: pendingOp.tagId,
@@ -24624,7 +25107,7 @@ function applyFlushedStatuses(sessionId, db, targets, preloadedTags) {
24624
25107
 
24625
25108
  // ../plugin/src/hooks/magic-context/cache-busting-signals.ts
24626
25109
  function hasReclaimRide(signals) {
24627
- return signals.hardFold || signals.force || signals.explicitFlush || signals.publishedHistory || signals.subagentExecute === true;
25110
+ return signals.hardFold || signals.force || signals.explicitFlush || signals.publishedHistory || signals.subagentExecute === true || signals.executeReclaim === true;
24628
25111
  }
24629
25112
  function prefixMutationPermitted(gate) {
24630
25113
  return !gate.signedThinkingHold || gate.firstRender || gate.idleExpiry || gate.emergency;
@@ -24637,7 +25120,8 @@ var RECLAIM_RIDE_NAMES = [
24637
25120
  "force",
24638
25121
  "explicitFlush",
24639
25122
  "publishedHistory",
24640
- "subagentExecute"
25123
+ "subagentExecute",
25124
+ "executeReclaim"
24641
25125
  ];
24642
25126
  function reclaimRideLabel(signals) {
24643
25127
  const active = RECLAIM_RIDE_NAMES.filter((name) => signals[name]);
@@ -24870,6 +25354,140 @@ function rearmChannel2AfterMeasuredCollapse(input) {
24870
25354
  return casChannel2NudgeState(input.db, input.sessionId, "delivered", "");
24871
25355
  }
24872
25356
 
25357
+ // ../plugin/src/hooks/magic-context/postprocess-read-cache.ts
25358
+ var connections = new WeakMap;
25359
+ function snapshot(db, sessionId) {
25360
+ const transaction = db;
25361
+ try {
25362
+ if (transaction.inTransaction || transaction.isTransaction) {
25363
+ connections.delete(db);
25364
+ return { version: -1, changes: -1 };
25365
+ }
25366
+ } catch {
25367
+ connections.delete(db);
25368
+ return { version: -1, changes: -1 };
25369
+ }
25370
+ let connection = connections.get(db);
25371
+ if (!connection) {
25372
+ connection = {
25373
+ stamp: db.prepare("SELECT total_changes() AS changes, data_version AS version FROM pragma_data_version"),
25374
+ sessions: new BoundedSessionMap(100)
25375
+ };
25376
+ connections.set(db, connection);
25377
+ }
25378
+ const stamp = connection.stamp.get();
25379
+ const previous = connection.sessions.get(sessionId);
25380
+ if (previous?.version === stamp.version && previous.changes === stamp.changes) {
25381
+ return previous;
25382
+ }
25383
+ const value = { ...stamp };
25384
+ connection.sessions.set(sessionId, value);
25385
+ return value;
25386
+ }
25387
+ function postprocessReplaySnapshot(db, sessionId) {
25388
+ const state = snapshot(db, sessionId);
25389
+ const replay = state.replay ??= loadPostprocessReplaySnapshot(db, sessionId);
25390
+ return {
25391
+ ...replay,
25392
+ staleReduceStrippedIds: new Set(replay.staleReduceStrippedIds),
25393
+ processedImageStrippedIds: new Set(replay.processedImageStrippedIds),
25394
+ processedImageMarkers: new Map(replay.processedImageMarkers),
25395
+ strippedPlaceholderIds: new Set(replay.strippedPlaceholderIds),
25396
+ hiddenSeamPlaceholderIds: new Set(replay.hiddenSeamPlaceholderIds),
25397
+ mergedReasoningStrippedIds: new Set(replay.mergedReasoningStrippedIds),
25398
+ trailingBlankDecisions: new Map(replay.trailingBlankDecisions),
25399
+ noteNudgeAnchors: structuredClone(replay.noteNudgeAnchors),
25400
+ autoSearchHintDecisions: structuredClone(replay.autoSearchHintDecisions),
25401
+ todoSyntheticAnchor: structuredClone(replay.todoSyntheticAnchor),
25402
+ pendingCompactionMarker: structuredClone(replay.pendingCompactionMarker),
25403
+ compactionMarker: structuredClone(replay.compactionMarker)
25404
+ };
25405
+ }
25406
+
25407
+ // ../plugin/src/hooks/magic-context/execute-reclaim.ts
25408
+ var NAMESPACE2 = "executeReclaim";
25409
+ var failedWrites = new WeakMap;
25410
+ function readExecuteReclaimState(db, sessionId) {
25411
+ return parseState2(postprocessReplaySnapshot(db, sessionId).executeReclaim);
25412
+ }
25413
+ function parseState2(lane) {
25414
+ const value = lane;
25415
+ return {
25416
+ heldPasses: typeof value?.heldPasses === "number" ? Math.max(0, value.heldPasses) : 0,
25417
+ floorOrdinal: typeof value?.floorOrdinal === "number" ? value.floorOrdinal : null,
25418
+ floorPromptId: typeof value?.floorPromptId === "string" ? value.floorPromptId : null
25419
+ };
25420
+ }
25421
+ function writeExecuteReclaimState(db, sessionId, patch) {
25422
+ if (failedWrites.get(db)?.has(sessionId))
25423
+ return false;
25424
+ try {
25425
+ const current = readExecuteReclaimState(db, sessionId);
25426
+ if (JSON.stringify(current) === JSON.stringify({ ...current, ...patch }))
25427
+ return true;
25428
+ if (!updateReplayDocument(db, sessionId, (doc) => {
25429
+ const previous = parseState2(doc[NAMESPACE2]);
25430
+ const state = { ...previous, ...patch };
25431
+ if (JSON.stringify(previous) === JSON.stringify(state))
25432
+ return false;
25433
+ doc.version = 2;
25434
+ doc[NAMESPACE2] = state;
25435
+ return true;
25436
+ }))
25437
+ throw new Error("Could not persist execute reclaim state");
25438
+ return true;
25439
+ } catch (error) {
25440
+ let failed = failedWrites.get(db);
25441
+ if (!failed)
25442
+ failedWrites.set(db, failed = new Set);
25443
+ failed.add(sessionId);
25444
+ sessionLog2(sessionId, `execute reclaim state persistence failed; retaining existing policy: ${String(error)}`);
25445
+ return false;
25446
+ }
25447
+ }
25448
+ function clearExecuteReclaimState(db, sessionId) {
25449
+ writeExecuteReclaimState(db, sessionId, {
25450
+ heldPasses: 0,
25451
+ floorOrdinal: null,
25452
+ floorPromptId: null
25453
+ });
25454
+ }
25455
+ function maintainExecuteFloorMark(db, sessionId, promptId, belowExecute) {
25456
+ failedWrites.get(db)?.delete(sessionId);
25457
+ const state = readExecuteReclaimState(db, sessionId);
25458
+ if (state.floorOrdinal !== null && (belowExecute || promptId !== null && promptId !== state.floorPromptId)) {
25459
+ writeExecuteReclaimState(db, sessionId, { floorOrdinal: null, floorPromptId: null });
25460
+ }
25461
+ }
25462
+ function estimateExecuteReclaimTokens(args) {
25463
+ const eligible = capturePendingDropEligibility(args.targets, args.protectedTagIds);
25464
+ const queued = new Set(args.pendingOps.filter((op) => op.operation === "drop").map((op) => op.tagId));
25465
+ const candidates = args.tags.filter((tag) => tag.status === "active" && queued.has(tag.tagNumber) && eligible.has(tag.tagNumber));
25466
+ const preparationTargets = new Map;
25467
+ for (const tag of candidates) {
25468
+ const target = args.targets.get(tag.tagNumber);
25469
+ if (target?.prepareDrop)
25470
+ preparationTargets.set(tag.tagNumber, target);
25471
+ }
25472
+ const prepared = preparationTargets.size === 0 ? new Set : args.probePreparation?.(preparationTargets) ?? new Set([...preparationTargets].filter(([, target]) => target.prepareDrop?.() !== false).map(([number]) => number));
25473
+ const seed = sessionDecisionCalibration(args.db, args.sessionId);
25474
+ return candidates.reduce((total, tag) => {
25475
+ if (preparationTargets.has(tag.tagNumber) && !prepared.has(tag.tagNumber))
25476
+ return total;
25477
+ const ratio = tag.type === "tool" ? seed.toolsRatio : seed.proseRatio;
25478
+ return total + Math.max(0, (tag.tokenCount ?? Math.ceil(tag.byteSize / 4)) * ratio);
25479
+ }, 0);
25480
+ }
25481
+ function originateExecuteReclaim(args) {
25482
+ if (failedWrites.get(args.db)?.has(args.sessionId))
25483
+ return false;
25484
+ const state = readExecuteReclaimState(args.db, args.sessionId);
25485
+ const heldPasses = args.primaryExecute && args.reclaimableTokens > 0 && !args.alreadyBusting ? state.heldPasses + 1 : 0;
25486
+ if (!writeExecuteReclaimState(args.db, args.sessionId, { heldPasses }))
25487
+ return false;
25488
+ return args.primaryExecute && !args.alreadyBusting && !args.summaryCanCome && args.reclaimableTokens > 0 && (args.usableWindow > 0 && args.reclaimableTokens >= args.usableWindow * 0.02 || heldPasses >= 3);
25489
+ }
25490
+
24873
25491
  // ../plugin/src/hooks/magic-context/file-token-coverage.ts
24874
25492
  function omitIncompleteFileTokenTotals(db, sessionId, messages, totals) {
24875
25493
  const filesByMessage = new Map;
@@ -25257,7 +25875,8 @@ function resolveProtectedTailBoundary(ctx) {
25257
25875
  break;
25258
25876
  }
25259
25877
  livePromptFloor.ordinal = lastMeaningfulUserOrdinal || null;
25260
- if (lastMeaningfulUserOrdinal >= offset) {
25878
+ livePromptFloor.messageId = boundaryMessageId(index, lastMeaningfulUserOrdinal);
25879
+ if (!ctx.liftLivePromptFloor && lastMeaningfulUserOrdinal >= offset) {
25261
25880
  protectedTailStart = Math.min(protectedTailStart, lastMeaningfulUserOrdinal);
25262
25881
  }
25263
25882
  }
@@ -25385,6 +26004,7 @@ function resolveBoundaryContext(args) {
25385
26004
  protectedTailPolicyVersion: meta.protectedTailPolicyVersion,
25386
26005
  migrationFloorActive,
25387
26006
  emergencyTailScale: args.emergencyTailScale,
26007
+ liftLivePromptFloor: args.liftLivePromptFloor,
25388
26008
  providerShapeVersion: args.providerShapeVersion ?? "opencode-v1",
25389
26009
  cacheNamespace: args.cacheNamespace ?? `opencode:${args.sessionId}`,
25390
26010
  storedTokenTotalsForMessages,
@@ -25766,7 +26386,7 @@ function resolveBoundaryContextLimit(usage, fallbackContextLimit) {
25766
26386
  }
25767
26387
  return 128000;
25768
26388
  }
25769
- function getUnsummarizedTailInfo(db, sessionId, triggerBudget, usage, executeThresholdPercentage, contextLimit, inMemoryTail, taggerFloor = 0) {
26389
+ function getUnsummarizedTailInfo(db, sessionId, triggerBudget, usage, executeThresholdPercentage, contextLimit, inMemoryTail, taggerFloor = 0, liftLivePromptFloor = false) {
25770
26390
  return withRawSessionMessageCache2(() => {
25771
26391
  try {
25772
26392
  const memoryPrimed = inMemoryTail ? primeInMemoryTailRawMessageCache2({
@@ -25796,7 +26416,8 @@ function getUnsummarizedTailInfo(db, sessionId, triggerBudget, usage, executeThr
25796
26416
  executeThresholdPercentage,
25797
26417
  usage,
25798
26418
  usageSource: "live",
25799
- taggerFloor
26419
+ taggerFloor,
26420
+ liftLivePromptFloor
25800
26421
  });
25801
26422
  const hasProtectedEligibleHead = boundary.offset < Math.min(boundary.protectedTailStart, boundary.eligibleEndOrdinal);
25802
26423
  if (!hasProtectedEligibleHead) {
@@ -25832,7 +26453,10 @@ function getUnsummarizedTailInfo(db, sessionId, triggerBudget, usage, executeThr
25832
26453
  function formatProjectedPostDropPercentage(value) {
25833
26454
  return value === null ? "none" : `${value.toFixed(1)}%`;
25834
26455
  }
25835
- function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPercentage, executeThresholdPercentage, triggerBudget, keepReasoningTokens, commitClusterTrigger, preloadedActiveTags, contextLimit, inMemoryTail, taggerFloorOverride, reasoningProjection, reclaimRide, eligiblePendingDropTagIds) {
26456
+ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPercentage, executeThresholdPercentage, triggerBudget, keepReasoningTokens, commitClusterTrigger, preloadedActiveTags, contextLimit, inMemoryTail, taggerFloorOverride, reasoningProjection, reclaimRide, eligiblePendingDropTagIds, primaryExecute = false) {
26457
+ if (usage.percentage < executeThresholdPercentage) {
26458
+ writeExecuteReclaimState(db, sessionId, { floorOrdinal: null, floorPromptId: null });
26459
+ }
25836
26460
  if (sessionMeta.compartmentInProgress) {
25837
26461
  sessionLog2(sessionId, `compartment trigger: skipped — historian already in progress (usage=${usage.percentage.toFixed(1)}%)`);
25838
26462
  return { shouldFire: false };
@@ -25885,7 +26509,22 @@ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPer
25885
26509
  resolvedInMemoryTail = undefined;
25886
26510
  }
25887
26511
  }
25888
- const tailInfo = getUnsummarizedTailInfo(db, sessionId, triggerBudget, usage, executeThresholdPercentage, contextLimit, resolvedInMemoryTail, taggerFloor);
26512
+ let tailInfo = getUnsummarizedTailInfo(db, sessionId, triggerBudget, usage, executeThresholdPercentage, contextLimit, resolvedInMemoryTail, taggerFloor);
26513
+ const markState = readExecuteReclaimState(db, sessionId);
26514
+ const mark = markState.floorOrdinal;
26515
+ const livePromptOrdinal = tailInfo.boundarySnapshot?.diagnostics?.livePromptFloor.ordinal;
26516
+ let consumedFloorMark = false;
26517
+ if (mark !== null) {
26518
+ const consumed = writeExecuteReclaimState(db, sessionId, {
26519
+ floorOrdinal: null,
26520
+ floorPromptId: null
26521
+ });
26522
+ if (consumed && mark === livePromptOrdinal && markState.floorPromptId === tailInfo.boundarySnapshot?.diagnostics?.livePromptFloor.messageId && usage.percentage >= executeThresholdPercentage) {
26523
+ consumedFloorMark = true;
26524
+ sessionLog2(sessionId, `compartment trigger: live-prompt floor mark consumed at ${mark}`);
26525
+ tailInfo = getUnsummarizedTailInfo(db, sessionId, triggerBudget, usage, executeThresholdPercentage, contextLimit, resolvedInMemoryTail, taggerFloor, true);
26526
+ }
26527
+ }
25889
26528
  if (!tailInfo.hasNewRawHistory) {
25890
26529
  try {
25891
26530
  const lastCompartmentEnd = getLastCompartmentEndMessage(db, sessionId);
@@ -25969,7 +26608,21 @@ function checkCompartmentTrigger(db, sessionId, sessionMeta, usage, _previousPer
25969
26608
  return { shouldFire: false };
25970
26609
  }
25971
26610
  if (!tailInfo.hasProtectedEligibleHead || !tailInfo.isMeaningful) {
25972
- sessionLog2(sessionId, `compartment trigger: not firing at ${usage.percentage.toFixed(1)}% because unsummarized tail from ${tailInfo.nextStartOrdinal} is too small`);
26611
+ let floorOnly = false;
26612
+ const boundary = tailInfo.boundarySnapshot;
26613
+ const floor = boundary?.diagnostics?.livePromptFloor;
26614
+ if (!consumedFloorMark && floor?.ordinal && floor.from > floor.to) {
26615
+ const withoutFloor = getUnsummarizedTailInfo(db, sessionId, triggerBudget, usage, executeThresholdPercentage, contextLimit, resolvedInMemoryTail, taggerFloor, true);
26616
+ floorOnly = withoutFloor.hasProtectedEligibleHead && withoutFloor.isMeaningful;
26617
+ if (floorOnly && primaryExecute && usage.percentage >= executeThresholdPercentage && writeExecuteReclaimState(db, sessionId, {
26618
+ floorOrdinal: floor.ordinal,
26619
+ floorPromptId: floor.messageId ?? null
26620
+ })) {
26621
+ sessionLog2(sessionId, `compartment trigger: live-prompt floor mark set at ${floor.ordinal}`);
26622
+ }
26623
+ }
26624
+ const refusal = floorOnly ? `no eligible head (live-prompt floor at ${floor?.ordinal})` : tailInfo.hasProtectedEligibleHead ? "below meaningfulness" : "no eligible head";
26625
+ sessionLog2(sessionId, `compartment trigger: not firing at ${usage.percentage.toFixed(1)}% — ${refusal}; offset=${tailInfo.nextStartOrdinal} protectedStart=${boundary?.protectedTailStart ?? "none"} eligibleEnd=${boundary?.eligibleEndOrdinal ?? "none"} rawTokens=${tailInfo.trueRawEligibleTokens} chunkTokens=${tailInfo.tokenEstimate}`);
25973
26626
  return { shouldFire: false };
25974
26627
  }
25975
26628
  sessionLog2(sessionId, `compartment trigger: proactive fire at ${usage.percentage.toFixed(1)}% (floor=${proactiveTriggerPercentage}% projected post-drop=${formatProjectedPostDropPercentage(projectedPostDropPercentage)} target=${relativePostDropTarget.toFixed(1)}%)`);
@@ -26138,6 +26791,9 @@ function latestAssistantTurnStart(messages) {
26138
26791
  function latestAssistantTurnMessages(messages) {
26139
26792
  return new Set(messages.slice(latestAssistantTurnStart(messages)));
26140
26793
  }
26794
+ function isAnthropicThinkingPart(part, familyRoute) {
26795
+ return isRecord(part) && THINKING_TYPES.has(String(part.type ?? part.kind)) && (familyRoute || isRecord(part.metadata) && isRecord(part.metadata.anthropic));
26796
+ }
26141
26797
  function hasActiveAnthropicThinkingTurn(messages, provider, model) {
26142
26798
  const familyRoute = isAnthropicFamilyRoute(provider, model);
26143
26799
  for (const message of messages.slice(latestAssistantTurnStart(messages))) {
@@ -26146,7 +26802,7 @@ function hasActiveAnthropicThinkingTurn(messages, provider, model) {
26146
26802
  const parts = content(message);
26147
26803
  if (!Array.isArray(parts))
26148
26804
  continue;
26149
- if (parts.some((part) => isRecord(part) && THINKING_TYPES.has(String(part.type ?? part.kind)) && (familyRoute || isRecord(part.metadata) && isRecord(part.metadata.anthropic))))
26805
+ if (parts.some((part) => isAnthropicThinkingPart(part, familyRoute)))
26150
26806
  return true;
26151
26807
  }
26152
26808
  return false;
@@ -27915,7 +28571,8 @@ ${trimmedBody}…
27915
28571
  return wrapped;
27916
28572
  }
27917
28573
  function selectAutoSearchResults(results, threshold) {
27918
- return results.filter((result) => (result.relevanceScore ?? result.score) >= threshold);
28574
+ const relevance = (result) => result.relevanceScore ?? result.score;
28575
+ return results.filter((result) => relevance(result) >= threshold).sort((left, right) => relevance(right) - relevance(left));
27919
28576
  }
27920
28577
 
27921
28578
  // ../plugin/src/hooks/magic-context/auto-search-worker-client.ts
@@ -28008,6 +28665,13 @@ function retryUnpublishedAutoSearchNoHint(db, sessionId, messageId, startedAt) {
28008
28665
  }
28009
28666
  return true;
28010
28667
  }
28668
+
28669
+ class AutoSearchBusyError extends Error {
28670
+ constructor() {
28671
+ super("an earlier auto-search of this session is still running");
28672
+ this.name = "AutoSearchBusyError";
28673
+ }
28674
+ }
28011
28675
  async function searchAutoHint(db, sessionId, projectPath, query, options, entry = new URL(new URL(import.meta.url).pathname.endsWith(".ts") ? "./auto-search-worker.ts" : "./auto-search-worker.js", import.meta.url)) {
28012
28676
  return executeAutoSearchWorker(db, sessionId, projectPath, query, options, entry, "search");
28013
28677
  }
@@ -28016,14 +28680,19 @@ var searchWorkers = new WeakMap;
28016
28680
  var liveSearchWorkers = new Set;
28017
28681
  var MAX_IDLE_SEARCH_WORKERS = 4;
28018
28682
  var SEARCH_WORKER_IDLE_MS = 5 * 60000;
28683
+ var DETACHED_SEARCH_LIMIT_MS = 30000;
28684
+ var AUTO_SEARCH_WORKER_CLOSE_DEADLINE_MS = 2000;
28019
28685
  var workersCreated = 0;
28020
28686
  var workersReused = 0;
28687
+ var searchesSkippedBusy = 0;
28021
28688
  async function acquireSearchWorker(db, key, entry, input, signal) {
28022
28689
  const pool = searchWorkers.get(db) ?? new Map;
28023
28690
  searchWorkers.set(db, pool);
28024
28691
  while (!signal.aborted) {
28025
28692
  let slot = pool.get(key);
28026
28693
  if (slot?.busy) {
28694
+ if (input.job === "search" && (slot.detached || slot.busySessionId === input.sessionId))
28695
+ return "busy";
28027
28696
  const current = slot;
28028
28697
  await new Promise((resolve) => {
28029
28698
  const done = () => {
@@ -28032,6 +28701,8 @@ async function acquireSearchWorker(db, key, entry, input, signal) {
28032
28701
  };
28033
28702
  signal.addEventListener("abort", done, { once: true });
28034
28703
  current.busy?.then(done);
28704
+ if (!current.detached)
28705
+ current.detachedSignal?.then(done);
28035
28706
  if (signal.aborted)
28036
28707
  done();
28037
28708
  });
@@ -28040,14 +28711,16 @@ async function acquireSearchWorker(db, key, entry, input, signal) {
28040
28711
  const fresh = !slot;
28041
28712
  if (!slot) {
28042
28713
  const worker = inRootAsyncContext2(() => new Worker(entry, { workerData: { ...input, persistent: true } }));
28714
+ const shutdown = createWorkerShutdown(worker, "auto-search", AUTO_SEARCH_WORKER_CLOSE_DEADLINE_MS);
28043
28715
  slot = {
28044
28716
  worker,
28045
28717
  dispose() {
28718
+ this.disposed = true;
28046
28719
  clearTimeout(this.idleTimer);
28047
28720
  if (pool.get(key) === this)
28048
28721
  pool.delete(key);
28049
28722
  liveSearchWorkers.delete(this);
28050
- worker.terminate();
28723
+ shutdown.close();
28051
28724
  worker.unref();
28052
28725
  }
28053
28726
  };
@@ -28061,9 +28734,14 @@ async function acquireSearchWorker(db, key, entry, input, signal) {
28061
28734
  workersReused++;
28062
28735
  clearTimeout(slot.idleTimer);
28063
28736
  const current = slot;
28737
+ current.busySessionId = input.sessionId;
28738
+ current.detached = false;
28064
28739
  current.busy = new Promise((resolve) => {
28065
28740
  current.release = resolve;
28066
28741
  });
28742
+ current.detachedSignal = new Promise((resolve) => {
28743
+ current.markDetached = resolve;
28744
+ });
28067
28745
  current.worker.ref();
28068
28746
  return { slot: current, fresh };
28069
28747
  }
@@ -28072,6 +28750,9 @@ async function acquireSearchWorker(db, key, entry, input, signal) {
28072
28750
  function queueAutoSearchBackfill(db, sessionId, projectPath, query) {
28073
28751
  if (isEmbeddingHostBusy2())
28074
28752
  return Promise.resolve();
28753
+ const snapshot = getProjectEmbeddingSnapshot2(projectPath);
28754
+ if (!snapshot?.enabled || !snapshot.features.memoryEnabled)
28755
+ return Promise.resolve();
28075
28756
  const key = `${sessionId}\x00${projectPath}`;
28076
28757
  const pending = pendingBackfills.get(db) ?? new Map;
28077
28758
  pendingBackfills.set(db, pending);
@@ -28119,6 +28800,7 @@ async function executeAutoSearchWorker(db, sessionId, projectPath, query, option
28119
28800
  signal: deadlineSignal,
28120
28801
  readMessages: _readMessages,
28121
28802
  searchMessageHistory: _searchMessageHistory,
28803
+ stepTimings: _stepTimings,
28122
28804
  ...serializable
28123
28805
  } = options;
28124
28806
  const lifecycle = registerAutoSearchWork(sessionId);
@@ -28154,30 +28836,55 @@ async function executeAutoSearchWorker(db, sessionId, projectPath, query, option
28154
28836
  lifecycle.done();
28155
28837
  return [];
28156
28838
  }
28839
+ if (lease === "busy") {
28840
+ lifecycle.done();
28841
+ searchesSkippedBusy++;
28842
+ throw new AutoSearchBusyError;
28843
+ }
28157
28844
  const { slot, fresh } = lease;
28158
28845
  const worker = slot.worker;
28846
+ const detachable = job === "search" && entry.href === defaultAutoSearchWorkerEntry().href;
28847
+ const startedAt = performance.now();
28848
+ let detachedAt;
28849
+ let ownerVectorMs;
28850
+ let abandonTimer;
28159
28851
  return new Promise((resolve, reject) => {
28160
28852
  let settled = false;
28161
- const finish = (results, error) => {
28853
+ let released = false;
28854
+ const settle = (results, error) => {
28162
28855
  if (settled)
28163
28856
  return;
28164
28857
  settled = true;
28858
+ if (error)
28859
+ reject(error);
28860
+ else
28861
+ resolve(results);
28862
+ };
28863
+ const release = (dispose) => {
28864
+ if (released)
28865
+ return;
28866
+ released = true;
28867
+ clearTimeout(abandonTimer);
28165
28868
  signal?.removeEventListener("abort", abort);
28166
28869
  lifecycle.signal.removeEventListener("abort", abort);
28167
28870
  lifecycle.done();
28168
28871
  worker.off("message", onMessage);
28169
28872
  worker.off("error", onError);
28170
28873
  worker.off("exit", onExit);
28171
- if (error || signal.aborted || entry.href !== defaultAutoSearchWorkerEntry().href)
28874
+ if (dispose || !detachable)
28172
28875
  slot.dispose();
28173
- else {
28876
+ else if (!slot.disposed) {
28174
28877
  slot.idleTimer = setTimeout(() => slot.dispose(), SEARCH_WORKER_IDLE_MS);
28175
28878
  slot.idleTimer.unref?.();
28176
28879
  }
28177
- const release = slot.release;
28880
+ const free = slot.release;
28178
28881
  slot.busy = undefined;
28179
28882
  slot.release = undefined;
28180
- release?.();
28883
+ slot.busySessionId = undefined;
28884
+ slot.detached = false;
28885
+ slot.detachedSignal = undefined;
28886
+ slot.markDetached = undefined;
28887
+ free?.();
28181
28888
  const reusable = liveSearchWorkers.delete(slot);
28182
28889
  if (reusable)
28183
28890
  liveSearchWorkers.add(slot);
@@ -28185,51 +28892,82 @@ async function executeAutoSearchWorker(db, sessionId, projectPath, query, option
28185
28892
  for (const prior of idle.slice(0, Math.max(0, idle.length - MAX_IDLE_SEARCH_WORKERS)))
28186
28893
  prior.dispose();
28187
28894
  worker.unref();
28188
- if (error)
28189
- reject(error);
28190
- else
28191
- resolve(results);
28192
28895
  };
28193
- const abort = () => finish([]);
28896
+ const finish = (results, error) => {
28897
+ settle(results, error);
28898
+ release(Boolean(error) || signal.aborted);
28899
+ };
28900
+ const abort = () => {
28901
+ if (lifecycle.signal.aborted || !detachable) {
28902
+ finish([]);
28903
+ return;
28904
+ }
28905
+ if (settled)
28906
+ return;
28907
+ detachedAt = performance.now();
28908
+ slot.detached = true;
28909
+ slot.markDetached?.();
28910
+ settle([]);
28911
+ abandonTimer = setTimeout(() => {
28912
+ log2(`[auto-search] session ${sessionId}: search still running ${DETACHED_SEARCH_LIMIT_MS} ms after its deadline; disposing its worker (owner vector wait ${formatMs(ownerVectorMs)})`);
28913
+ release(true);
28914
+ }, DETACHED_SEARCH_LIMIT_MS);
28915
+ abandonTimer.unref?.();
28916
+ };
28194
28917
  signal?.addEventListener("abort", abort, { once: true });
28195
28918
  lifecycle.signal.addEventListener("abort", abort, { once: true });
28196
28919
  const onError = (error) => finish([], error);
28197
28920
  const onExit = (code) => finish([], new Error(`auto-search worker exited (${code})`));
28198
28921
  const onMessage = async (reply) => {
28199
- if (settled)
28922
+ if (released)
28200
28923
  return;
28201
- if (reply.kind === "result") {
28924
+ if (reply.kind === "result" || reply.kind === "error") {
28925
+ if (detachedAt !== undefined) {
28926
+ logLateSearch(sessionId, performance.now() - detachedAt, detachedAt - startedAt, ownerVectorMs, reply.kind === "result" ? reply.timings : undefined, reply.kind === "error");
28927
+ release(reply.kind === "error");
28928
+ return;
28929
+ }
28930
+ if (reply.kind === "error") {
28931
+ finish([], new Error(reply.error));
28932
+ return;
28933
+ }
28202
28934
  if (snapshot && getProjectEmbeddingSnapshot2(projectPath)?.generation !== snapshot.generation)
28203
28935
  finish([]);
28204
28936
  else
28205
28937
  finish(reply.results);
28206
28938
  return;
28207
28939
  }
28208
- if (reply.kind === "error") {
28209
- finish([], new Error(reply.error));
28210
- return;
28211
- }
28212
28940
  if (reply.kind === "messages" || reply.kind === "accepted")
28213
28941
  return;
28214
28942
  const response = { id: reply.id };
28215
- try {
28943
+ if (!signal.aborted) {
28944
+ const requestedAt = performance.now();
28945
+ try {
28946
+ if (reply.kind === "query")
28947
+ response.result = await (job === "backfill" ? embedTextForProject2(projectPath, reply.text, signal, "query") : boundedHintEmbedding(embedQuery, reply.text, signal)) ?? null;
28948
+ else {
28949
+ const passage = await embedBatchForProject2(projectPath, reply.texts, signal, reply.purpose);
28950
+ const current = getProjectEmbeddingSnapshot2(projectPath);
28951
+ response.passage = passage && current ? {
28952
+ ...passage,
28953
+ providerIdentity: current.providerIdentity,
28954
+ runtimeFingerprint: current.runtimeFingerprint,
28955
+ dimensions: passage.vectors.find((vector) => vector !== null)?.length ?? null
28956
+ } : null;
28957
+ }
28958
+ } catch (error) {
28959
+ response.error = error instanceof Error ? error.message : String(error);
28960
+ }
28216
28961
  if (reply.kind === "query")
28217
- response.result = await (job === "backfill" ? embedTextForProject2(projectPath, reply.text, signal, "query") : boundedHintEmbedding(embedQuery, reply.text, signal)) ?? null;
28218
- else {
28219
- const passage = await embedBatchForProject2(projectPath, reply.texts, signal, reply.purpose);
28220
- const current = getProjectEmbeddingSnapshot2(projectPath);
28221
- response.passage = passage && current ? {
28222
- ...passage,
28223
- providerIdentity: current.providerIdentity,
28224
- runtimeFingerprint: current.runtimeFingerprint,
28225
- dimensions: passage.vectors.find((vector) => vector !== null)?.length ?? null
28226
- } : null;
28962
+ ownerVectorMs = performance.now() - requestedAt;
28963
+ if (signal.aborted) {
28964
+ response.result = undefined;
28965
+ response.passage = undefined;
28966
+ response.error = undefined;
28227
28967
  }
28228
- } catch (error) {
28229
- response.error = error instanceof Error ? error.message : String(error);
28230
28968
  }
28231
28969
  response.embeddingHostBusy = isEmbeddingHostBusy2();
28232
- if (!settled && !signal?.aborted) {
28970
+ if (!released) {
28233
28971
  try {
28234
28972
  worker.postMessage(response);
28235
28973
  } catch (error) {
@@ -28251,6 +28989,15 @@ async function executeAutoSearchWorker(db, sessionId, projectPath, query, option
28251
28989
  }
28252
28990
  });
28253
28991
  }
28992
+ function formatMs(value) {
28993
+ return value === undefined ? "n/a" : `${Math.round(value)} ms`;
28994
+ }
28995
+ function logLateSearch(sessionId, lateMs, waitedMs, ownerVectorMs, timings, failed) {
28996
+ const steps = timings?.steps;
28997
+ const warm = timings?.lastPoolWarm;
28998
+ const pool = warm ? `last pool refresh ${warm.outcome} in ${formatMs(warm.totalMs)} (probe ${formatMs(warm.probeMs)}, read ${formatMs(warm.readMs)}, decode ${formatMs(warm.decodeMs)}, ${warm.probedRows} rows probed, ${warm.decodedRows} decoded)` : "no pool refresh yet";
28999
+ log2(`[auto-search] session ${sessionId}: deadline passed after ${formatMs(waitedMs)}; the search ${failed ? "failed" : "finished"} ${formatMs(lateMs)} later. Steps: message FTS ${formatMs(steps?.messageMs)}, vector wait ${formatMs(steps?.vectorWaitMs)} (owner embedding ${formatMs(ownerVectorMs)}), chunk lane ${formatMs(steps?.chunkMs)} (pool ${steps?.chunkPool ?? "n/a"}), other lanes ${formatMs(steps?.otherLanesMs)}, job ${formatMs(timings?.jobMs)}; ${pool}`);
29000
+ }
28254
29001
  async function boundedHintEmbedding(embed, text, signal) {
28255
29002
  const controller = new AbortController;
28256
29003
  const combined = AbortSignal.any([signal, controller.signal]);
@@ -28474,7 +29221,8 @@ async function runAutoSearchHintForPi(args) {
28474
29221
  },
28475
29222
  isEmbeddingRuntimeEnabled: () => embeddingEnabled === true,
28476
29223
  visibleMemoryIds: options.visibleMemoryIds ?? null,
28477
- sources: ["memory", "message", "git_commit"]
29224
+ sources: ["memory", "message", "git_commit"],
29225
+ chunkPoolWarmOnly: true
28478
29226
  };
28479
29227
  return searchAutoHint(db, sessionId, options.projectPath, rawPrompt, {
28480
29228
  ...searchOptions,
@@ -28486,6 +29234,11 @@ async function runAutoSearchHintForPi(args) {
28486
29234
  args.passGuard?.assert();
28487
29235
  if (lifecycleSignal.aborted)
28488
29236
  return messages;
29237
+ if (error instanceof AutoSearchBusyError) {
29238
+ sessionLog2(sessionId, "auto-search: an earlier search of this session is still running, skipping hint for this turn");
29239
+ persistAutoSearchSkip(db, sessionId, userMsgId);
29240
+ return messages;
29241
+ }
28489
29242
  log2(`[auto-search] unified search failed for session ${sessionId} (no-hint frozen for this turn): ${error instanceof Error ? error.message : String(error)}`);
28490
29243
  await writeNoHintAndReconcile("error");
28491
29244
  return messages;
@@ -28537,7 +29290,7 @@ ${hintText}`;
28537
29290
  if (outcome.decision.decision === "hint") {
28538
29291
  appendHintToUserMessage(userMsg, outcome.decision.text);
28539
29292
  }
28540
- sessionLog2(sessionId, `auto-search: attached hint to ${userMsgId} (${results.length} fragments, top score ${results[0].score.toFixed(3)})`);
29293
+ sessionLog2(sessionId, `auto-search: attached hint to ${userMsgId} (${results.length} fragments, top relevance ${(results[0].relevanceScore ?? results[0].score).toFixed(3)})`);
28541
29294
  return messages;
28542
29295
  } finally {
28543
29296
  if (!lifecycleSignal.aborted && results !== null) {
@@ -28573,19 +29326,19 @@ async function embedAndStoreCompartmentChunks(db, sessionId, projectPath, compar
28573
29326
  const maxInputTokens = getProjectEmbeddingMaxInputTokens2(projectPath);
28574
29327
  for (const compartment of compartments) {
28575
29328
  try {
28576
- const fromMemory = compartment.sourceChunkText ? canonicalizeInMemoryChunkTextForEmbedding(compartment.sourceChunkText, compartment.startMessage, compartment.endMessage) : "";
28577
- const mappedText = fromMemory ? fromMemory : buildCanonicalChunkTextFromFts(db, sessionId, compartment.startMessage, compartment.endMessage);
29329
+ const fromMemory = compartment.sourceChunkText ? canonicalizeInMemoryChunkTextForEmbedding2(compartment.sourceChunkText, compartment.startMessage, compartment.endMessage) : "";
29330
+ const mappedText = fromMemory ? fromMemory : buildCanonicalChunkTextFromFts2(db, sessionId, compartment.startMessage, compartment.endMessage);
28578
29331
  if (mappedText === null)
28579
29332
  continue;
28580
- const canonicalText = mappedText || buildCompartmentSummaryFallbackText(db, compartment.id);
29333
+ const canonicalText = mappedText || buildCompartmentSummaryFallbackText2(db, compartment.id);
28581
29334
  if (canonicalText.length === 0)
28582
29335
  continue;
28583
- const windows = chunkCanonicalText(canonicalText, compartment.startMessage, compartment.endMessage, maxInputTokens);
29336
+ const windows = chunkCanonicalText2(canonicalText, compartment.startMessage, compartment.endMessage, maxInputTokens);
28584
29337
  if (windows.length === 0)
28585
29338
  continue;
28586
- const windowSourceKey = chunkWindowSourceKey(canonicalText, compartment.startMessage, compartment.endMessage, maxInputTokens);
29339
+ const windowSourceKey = chunkWindowSourceKey2(canonicalText, compartment.startMessage, compartment.endMessage, maxInputTokens);
28587
29340
  const currentModelId = getProjectChunkEmbeddingModelId2(projectPath);
28588
- if (currentModelId !== "off" && chunkEmbeddingWindowsAreCurrent(db, compartment.id, currentModelId, windows, projectPath)) {
29341
+ if (currentModelId !== "off" && chunkEmbeddingWindowsAreCurrent2(db, compartment.id, currentModelId, windows, projectPath)) {
28589
29342
  continue;
28590
29343
  }
28591
29344
  const result = await embedItemsForProject2(projectPath, windows.map((window) => ({
@@ -28595,7 +29348,7 @@ async function embedAndStoreCompartmentChunks(db, sessionId, projectPath, compar
28595
29348
  })), undefined, db, sessionId);
28596
29349
  if (!result)
28597
29350
  continue;
28598
- if (chunkEmbeddingWindowsAreCurrent(db, compartment.id, currentModelId, windows, projectPath)) {
29351
+ if (chunkEmbeddingWindowsAreCurrent2(db, compartment.id, currentModelId, windows, projectPath)) {
28599
29352
  continue;
28600
29353
  }
28601
29354
  const rows = [];
@@ -28613,7 +29366,7 @@ async function embedAndStoreCompartmentChunks(db, sessionId, projectPath, compar
28613
29366
  });
28614
29367
  }
28615
29368
  if (rows.length === windows.length) {
28616
- replaceCompartmentChunkEmbeddings(db, rows, windowSourceKey);
29369
+ replaceCompartmentChunkEmbeddings2(db, rows, windowSourceKey);
28617
29370
  enqueueShadowEmbeddingItems2(projectPath, "chunk", [String(compartment.id)]);
28618
29371
  }
28619
29372
  } catch (error) {
@@ -29382,7 +30135,8 @@ ${chunkText}`,
29382
30135
  maxOutputTokens,
29383
30136
  onProgress: buildProgressLogger("first"),
29384
30137
  accountingSessionId: sessionId,
29385
- accountingSubagent: "historian"
30138
+ accountingSubagent: "historian",
30139
+ accountingModelConfigKey: deps.modelConfigKey
29386
30140
  }
29387
30141
  });
29388
30142
  let validatedPass = await validateHistorianResult(firstResult, sessionId, chunk, priorCompartments, sequenceOffset);
@@ -29442,6 +30196,7 @@ ${chunkText}`,
29442
30196
  onProgress: buildProgressLogger("fallback"),
29443
30197
  accountingSessionId: sessionId,
29444
30198
  accountingSubagent: "historian",
30199
+ accountingModelConfigKey: candidate.sourceConfigKey ?? deps.modelConfigKey,
29445
30200
  accountingTask: "fallback"
29446
30201
  }
29447
30202
  });
@@ -29493,7 +30248,8 @@ ${chunkText}`,
29493
30248
  maxOutputTokens,
29494
30249
  onProgress: buildProgressLogger("editor"),
29495
30250
  accountingSessionId: sessionId,
29496
- accountingSubagent: "historian_editor"
30251
+ accountingSubagent: "historian_editor",
30252
+ accountingModelConfigKey: deps.modelConfigKey
29497
30253
  }
29498
30254
  });
29499
30255
  const editorPass = await validateHistorianResult(editorResult, sessionId, chunk, priorCompartments, sequenceOffset);
@@ -31548,7 +32304,7 @@ function promoteRecompStagingWithM0Mutation(db, sessionId, holderId) {
31548
32304
  finished = true;
31549
32305
  return null;
31550
32306
  }
31551
- deleteChunkEmbedBackoffForSession(db, sessionId);
32307
+ deleteChunkEmbedBackoffForSession2(db, sessionId);
31552
32308
  db.prepare("DELETE FROM compartments WHERE session_id = ?").run(sessionId);
31553
32309
  db.prepare("DELETE FROM session_facts WHERE session_id = ?").run(sessionId);
31554
32310
  insertRecompCompartmentRows(db, sessionId, staging.compartments, now);
@@ -32456,7 +33212,7 @@ function dropCompartmentsAfter(db, sessionId, anchor, holderId, activeBranch = f
32456
33212
  if (marker && clearPendingPiCompactionMarkerStateIf(db, sessionId, marker, null))
32457
33213
  clearedMarker = marker;
32458
33214
  }
32459
- deleteChunkEmbedBackoffForSession(db, sessionId);
33215
+ deleteChunkEmbedBackoffForSession2(db, sessionId);
32460
33216
  queueM0Mutation(db, { sessionId, mutationType: "recomp_boundary_change" });
32461
33217
  clearCachedM0M1(db, sessionId);
32462
33218
  db.exec("COMMIT");
@@ -34414,7 +35170,7 @@ function isSentinelPart(part) {
34414
35170
 
34415
35171
  // src/pi-append-compaction.ts
34416
35172
  var loggedIncompatibleHost = false;
34417
- var failedWrites = new WeakMap;
35173
+ var failedWrites2 = new WeakMap;
34418
35174
  function adaptPiAppendCompaction(sessionManager) {
34419
35175
  if (!sessionManager || typeof sessionManager !== "object")
34420
35176
  return;
@@ -34422,7 +35178,7 @@ function adaptPiAppendCompaction(sessionManager) {
34422
35178
  const append = host.appendCompaction;
34423
35179
  if (typeof append !== "function")
34424
35180
  return;
34425
- if (failedWrites.has(host))
35181
+ if (failedWrites2.has(host))
34426
35182
  return;
34427
35183
  const harness = resolvePiHarnessKind();
34428
35184
  if ((harness === "omp" ? append.length !== 4 && append.length !== 7 : append.length !== 5 && append.length !== 6) || typeof host.getEntry !== "function") {
@@ -34434,7 +35190,7 @@ function adaptPiAppendCompaction(sessionManager) {
34434
35190
  }
34435
35191
  const getEntry = host.getEntry.bind(host);
34436
35192
  return (summary, firstKeptEntryId, tokensBefore, details, fromHook) => {
34437
- const previousFailure = failedWrites.get(host);
35193
+ const previousFailure = failedWrites2.get(host);
34438
35194
  if (previousFailure)
34439
35195
  throw previousFailure;
34440
35196
  let id;
@@ -34452,7 +35208,7 @@ function adaptPiAppendCompaction(sessionManager) {
34452
35208
  }
34453
35209
  } catch {
34454
35210
  const error = new Error("Compaction marker read-back failed; writes disabled for this session manager until restart");
34455
- failedWrites.set(host, error);
35211
+ failedWrites2.set(host, error);
34456
35212
  log2(`ERROR: compaction marker read-back failed harness=${harness} compactionId=${typeof id === "string" ? id : "<missing>"} expectedFirstKept=${firstKeptEntryId}; further writes disabled for this session manager until restart; leaving marker pending`);
34457
35213
  throw error;
34458
35214
  }
@@ -44017,6 +44773,20 @@ function registerPiContextHandler(pi, baseOptions) {
44017
44773
  elapsedMs: performance.now() - fitInputStart,
44018
44774
  extra: inputForFitReclaim ? "snapshot" : "no-snapshot"
44019
44775
  });
44776
+ if (!options.compactionOff && !sessionMeta.isSubagent) {
44777
+ let promptId = null;
44778
+ for (let i = event.messages.length - 1;i >= 0; i--) {
44779
+ const message = event.messages[i];
44780
+ if (message?.role !== "user")
44781
+ continue;
44782
+ const parts = typeof message.content === "string" ? [{ type: "text", text: message.content }] : message.content;
44783
+ if (!hasMeaningfulUserText2(parts))
44784
+ continue;
44785
+ promptId = entryIds?.[i] ?? null;
44786
+ break;
44787
+ }
44788
+ maintainExecuteFloorMark(options.db, sessionId, promptId, usagePercentage < effectiveExecuteThresholdPercentage);
44789
+ }
44020
44790
  const pipelineArgs = {
44021
44791
  recoveryPrefix: recovery.prefix,
44022
44792
  recoveryRebuildReason: recovery.rebuildReason,
@@ -44118,6 +44888,65 @@ function registerPiContextHandler(pi, baseOptions) {
44118
44888
  };
44119
44889
  if (!options.compactionOff)
44120
44890
  assertPiTagSnapshotReady(options.db, sessionId);
44891
+ let historianEvaluatedThisPass = false;
44892
+ const historian = options.historian;
44893
+ const scheduleHistorian = (result) => {
44894
+ if (historianEvaluatedThisPass)
44895
+ return;
44896
+ historianEvaluatedThisPass = true;
44897
+ const tHistorianScheduling = performance.now();
44898
+ budget.stage = "historian scheduling";
44899
+ if (historian && !options.compactionOff && budget.remainingWork() > 0) {
44900
+ guardSqliteTransformPass2({
44901
+ assert: budget.assert,
44902
+ remainingMs: budget.remainingWork
44903
+ });
44904
+ try {
44905
+ budget.assert();
44906
+ maybeFireHistorian({
44907
+ startGuard: () => {
44908
+ if (!budget.completed)
44909
+ budget.assertOwner();
44910
+ if (budget.abandoned || budget.remainingWork() === 0)
44911
+ throw new PiContextDeadlineError(budget.diagnostic());
44912
+ },
44913
+ pi,
44914
+ ctx,
44915
+ sessionId,
44916
+ db: options.db,
44917
+ historian,
44918
+ isFirstContextPassForSession,
44919
+ activeTags: result.activeTags,
44920
+ eligiblePendingDropTagIds: result.eligiblePendingDropTagIds,
44921
+ rawMessageProvider,
44922
+ ordinalAlignment: ordinalAlignment(),
44923
+ taggerFloor,
44924
+ sessionMeta,
44925
+ piUsage,
44926
+ pressureSnapshot: {
44927
+ percentage: usagePercentage,
44928
+ inputTokens: usageInputTokens
44929
+ },
44930
+ minimumPercentage: usagePercentage,
44931
+ liveIsRawBranchEstimate: piLiveUsageIsRawBranchEstimate,
44932
+ historianStateSnapshot: historianStateForPass,
44933
+ publishedHistoryRide: isCacheBusting,
44934
+ primaryExecute: schedulerDecision === "execute" && !sessionMeta.isSubagent,
44935
+ signedThinkingHeld: result.strictThinkingKept
44936
+ });
44937
+ } catch (error) {
44938
+ budget.assertOutcome();
44939
+ sessionLog2(sessionId, `historian scheduling skipped: ${String(error)}`);
44940
+ } finally {
44941
+ guardSqliteTransformPass2({
44942
+ assert: budget.assertOutcome,
44943
+ remainingMs: budget.remainingOutcome
44944
+ });
44945
+ }
44946
+ }
44947
+ logTransformTiming(sessionId, "historianScheduling", tHistorianScheduling);
44948
+ };
44949
+ pipelineArgs.evaluateHistorianBeforeReclaim = scheduleHistorian;
44121
44950
  let result = await budget.waitMandatory(runPipeline(pipelineArgs));
44122
44951
  observePipelineResultForTests(sessionId, result);
44123
44952
  logTransformTiming(sessionId, "runPipeline", tRunPipeline);
@@ -44149,57 +44978,7 @@ function registerPiContextHandler(pi, baseOptions) {
44149
44978
  }, piDecisionSnapshotNewestAssistant, budget.assertDecisionPublication);
44150
44979
  } : undefined;
44151
44980
  logTransformTiming(sessionId, "transformDecisionAndReuseState", tTransformDecision);
44152
- const tHistorianScheduling = performance.now();
44153
- const historian = options.historian;
44154
- budget.stage = "historian scheduling";
44155
- if (historian && !options.compactionOff && budget.remainingWork() > 0) {
44156
- guardSqliteTransformPass2({
44157
- assert: budget.assert,
44158
- remainingMs: budget.remainingWork
44159
- });
44160
- try {
44161
- budget.assert();
44162
- maybeFireHistorian({
44163
- startGuard: () => {
44164
- if (!budget.completed)
44165
- budget.assertOwner();
44166
- if (budget.abandoned || budget.remainingWork() === 0)
44167
- throw new PiContextDeadlineError(budget.diagnostic());
44168
- },
44169
- pi,
44170
- ctx,
44171
- sessionId,
44172
- db: options.db,
44173
- historian,
44174
- isFirstContextPassForSession,
44175
- activeTags: result.activeTags,
44176
- eligiblePendingDropTagIds: result.eligiblePendingDropTagIds,
44177
- rawMessageProvider,
44178
- ordinalAlignment: ordinalAlignment(),
44179
- taggerFloor,
44180
- sessionMeta,
44181
- piUsage,
44182
- pressureSnapshot: {
44183
- percentage: usagePercentage,
44184
- inputTokens: usageInputTokens
44185
- },
44186
- minimumPercentage: usagePercentage,
44187
- liveIsRawBranchEstimate: piLiveUsageIsRawBranchEstimate,
44188
- historianStateSnapshot: historianStateForPass,
44189
- publishedHistoryRide: isCacheBusting,
44190
- signedThinkingHeld: result.strictThinkingKept
44191
- });
44192
- } catch (error) {
44193
- budget.assertOutcome();
44194
- sessionLog2(sessionId, `historian scheduling skipped: ${String(error)}`);
44195
- } finally {
44196
- guardSqliteTransformPass2({
44197
- assert: budget.assertOutcome,
44198
- remainingMs: budget.remainingOutcome
44199
- });
44200
- }
44201
- }
44202
- logTransformTiming(sessionId, "historianScheduling", tHistorianScheduling);
44981
+ scheduleHistorian(result);
44203
44982
  const tPostTransform = performance.now();
44204
44983
  let outputMessages = result.messages;
44205
44984
  let assertTailHygieneLastWriter;
@@ -45028,6 +45807,7 @@ function spawnPiHistorianRun(args) {
45028
45807
  runner: historian.runner,
45029
45808
  signal: controller.signal,
45030
45809
  historianModel: historian.model,
45810
+ modelConfigKey: historian.modelConfigKey,
45031
45811
  fallbackModels: historian.fallbackModels,
45032
45812
  fallbackModelId,
45033
45813
  historianChunkTokens: historian.historianChunkTokens,
@@ -45350,7 +46130,7 @@ Historian previously failed ${failureCount} time(s), so Magic Context is retryin
45350
46130
  idleExpiry: false,
45351
46131
  emergency: usage.percentage >= historianForceMaterializationPercentage
45352
46132
  }
45353
- }, args.eligiblePendingDropTagIds);
46133
+ }, args.eligiblePendingDropTagIds, args.primaryExecute === true);
45354
46134
  if (!trigger.shouldFire) {
45355
46135
  sessionLog2(sessionId, `historian trigger eval: shouldFire=false (no trigger condition met)`);
45356
46136
  try {
@@ -45449,6 +46229,8 @@ function captureReasoningMutationRollback(messages) {
45449
46229
  }
45450
46230
  async function runCompactionOffPipeline(args) {
45451
46231
  let injectionResult = null;
46232
+ const transcript = [...args.messages];
46233
+ let headChangedUnderSignedThinking = false;
45452
46234
  if (args.injection) {
45453
46235
  const state = {
45454
46236
  sessionId: args.sessionId,
@@ -45462,10 +46244,36 @@ async function runCompactionOffPipeline(args) {
45462
46244
  muralEnabled: args.injection.muralEnabled === true,
45463
46245
  compactionOff: true
45464
46246
  };
45465
- if (args.reasoningClearing?.prefixBound === true && hasActiveAnthropicThinkingTurn(args.messages, args.resolvedProviderID, args.resolvedModelID))
46247
+ const signedTurnHoldsHead = args.reasoningClearing?.prefixBound === true && hasActiveAnthropicThinkingTurn(args.messages, args.resolvedProviderID, args.resolvedModelID);
46248
+ if (signedTurnHoldsHead)
45466
46249
  state.preparedPrefix = prepareCachedM0M1PiReplay(state, args.db, args.injectionPassSnapshot?.cachedRow);
46250
+ const servedBeforeFirstRender = signedTurnHoldsHead && !state.preparedPrefix ? args.readLastServedMessages?.() ?? null : undefined;
45467
46251
  injectionResult = injectM0M1Pi(state, args.db, args.messages, args.entryIds, false, args.injectionPassSnapshot);
45468
- }
46252
+ if (servedBeforeFirstRender !== undefined) {
46253
+ const headCount = injectionResult?.syntheticLeadingCount ?? 0;
46254
+ const head = JSON.stringify(args.messages.slice(0, headCount));
46255
+ headChangedUnderSignedThinking = servedBeforeFirstRender === null || JSON.stringify(servedBeforeFirstRender.slice(0, headCount)) !== head;
46256
+ } else if (!signedTurnHoldsHead && args.reasoningClearing?.prefixBound === true && (injectionResult?.m0Materialized === true || injectionResult?.m1RenderedCoverage != null)) {
46257
+ const served = args.readLastServedMessages?.() ?? null;
46258
+ const headCount = injectionResult?.syntheticLeadingCount ?? 0;
46259
+ headChangedUnderSignedThinking = served === null || JSON.stringify(served.slice(0, headCount)) !== JSON.stringify(args.messages.slice(0, headCount));
46260
+ if (headChangedUnderSignedThinking)
46261
+ sessionLog2(args.sessionId, "compaction-off fold changed the head: stripping signed thinking");
46262
+ }
46263
+ }
46264
+ if (headChangedUnderSignedThinking)
46265
+ applyPiProactiveThinkingStrip({
46266
+ db: args.db,
46267
+ sessionId: args.sessionId,
46268
+ messages: transcript,
46269
+ entryIds: transcript.map((message, index) => resolvePiRealStableId(message, index, args.entryIds, args.entryIdByRef ?? undefined)),
46270
+ provider: args.resolvedProviderID,
46271
+ model: args.resolvedModelID,
46272
+ cacheBustingPass: true,
46273
+ stripActiveTurn: true,
46274
+ requirePersistence: true,
46275
+ report: (line) => sessionLog2(args.sessionId, line)
46276
+ });
45469
46277
  return {
45470
46278
  messages: args.messages,
45471
46279
  prefixBustPermitted: false,
@@ -45767,6 +46575,7 @@ async function runPipeline(args) {
45767
46575
  logTransformTiming(args.sessionId, "injectTemporalMarkers", tTemporal);
45768
46576
  }
45769
46577
  let nativeRemovalInputs;
46578
+ let probingExecuteRemoval = false;
45770
46579
  try {
45771
46580
  nativeRemovalInputs = getNativeReplayState(args.db, args.sessionId).toolInputs;
45772
46581
  } catch {}
@@ -45778,7 +46587,7 @@ async function runPipeline(args) {
45778
46587
  sessionId: args.sessionId,
45779
46588
  callId,
45780
46589
  saved: nativeRemovalInputs,
45781
- canApply: isCacheBustingPass
46590
+ canApply: isCacheBustingPass || probingExecuteRemoval
45782
46591
  }),
45783
46592
  authorizeToolRemovals: (callIds) => preparePiToolRemovalMeasurements({
45784
46593
  db: args.db,
@@ -45810,6 +46619,7 @@ async function runPipeline(args) {
45810
46619
  const heldIdleExpiryRebuild = protectedSignedPrefix && piHardSignals?.cacheExpired === true;
45811
46620
  const systemPrefixChangedThisPass = !prefixPreflightContended && effectiveSystemChangedThisPass;
45812
46621
  const rideSignals = {
46622
+ executeReclaim: false,
45813
46623
  subagentExecute: args.sessionMeta.isSubagent && args.schedulerDecision === "execute",
45814
46624
  hardFold: foldBustsServedPrefixThisPass || systemPrefixChangedThisPass || firstRenderBust || heldIdleExpiryRebuild || isCacheBustingPass,
45815
46625
  force: (args.forceMaterialization === true || emergencyDropEligible) && (args.contextUsage.percentage >= 95 || getEmergencyInputSample(args.db, args.sessionId) === 0),
@@ -45922,11 +46732,14 @@ async function runPipeline(args) {
45922
46732
  }
45923
46733
  }
45924
46734
  }
45925
- if (args.temporalAwareness && isCacheBustingPass && !protectedSignedPrefix) {
46735
+ const applyTemporalOnRide = () => {
46736
+ if (!args.temporalAwareness || !isCacheBustingPass || protectedSignedPrefix)
46737
+ return;
45926
46738
  temporalDecisions = freezeTemporalDecisions(args.db, args.sessionId, temporalCandidates);
45927
46739
  if (injectPiTemporalMarkers(args.messages, temporalDecisions, stableIdResolver) > 0)
45928
46740
  recordFirstApplicationWireEdit(true);
45929
- }
46741
+ };
46742
+ applyTemporalOnRide();
45930
46743
  logPiUnresolvedIdentities(args.sessionId, [
45931
46744
  ...guardPiToolAllocations(args.db, args.sessionId, args.messages, stableIdResolver, args.tagger, fallbackIndex.guardIndexes),
45932
46745
  ...guardPiMessageAllocations(args.db, args.sessionId, entryFingerprintByMessageId)
@@ -46076,6 +46889,62 @@ async function runPipeline(args) {
46076
46889
  const protectionWindowForPass = getProtectionWindowForSession(args.db, args.sessionId, protectionFloorResolution.floor);
46077
46890
  const protectedTagNumbersForPass = usesTokenProtection ? protectionWindowForPass.protectedTagNumbers : newestActiveTagNumbersByCount(getActiveTagsBySession2(args.db, args.sessionId), args.protectedTags);
46078
46891
  const pendingOperationTags = pendingOps.length > 0 ? getTagsForPendingOperations2(args.db, args.sessionId, pendingOps.map((operation) => operation.tagId), usesTokenProtection ? 0 : args.protectedTags, RECENT_TOOL_SKELETON_WINDOW) : [];
46892
+ if (!args.sessionMeta.isSubagent && args.schedulerDecision === "execute") {
46893
+ args.evaluateHistorianBeforeReclaim?.({
46894
+ activeTags: getActiveTagsBySession2(args.db, args.sessionId),
46895
+ eligiblePendingDropTagIds,
46896
+ strictThinkingKept: protectedSignedPrefix
46897
+ });
46898
+ }
46899
+ rideSignals.executeReclaim = originateExecuteReclaim({
46900
+ db: args.db,
46901
+ sessionId: args.sessionId,
46902
+ primaryExecute: !args.sessionMeta.isSubagent && args.schedulerDecision === "execute" && args.contextUsage.percentage < forceMaterializationPercentage,
46903
+ alreadyBusting: isCacheBustingPass || identityRebuild,
46904
+ summaryCanCome: args.sessionMeta.compartmentInProgress || inFlightHistorian.has(args.sessionId) || (prefixPreflightContended || protectedSignedPrefix) && (deferredHistoryRefreshSessions.has(args.sessionId) || deferredMaterializationSessions.has(args.sessionId) || historyRefreshSessions.has(args.sessionId)) || readExecuteReclaimState(args.db, args.sessionId).floorOrdinal !== null,
46905
+ reclaimableTokens: estimateExecuteReclaimTokens({
46906
+ db: args.db,
46907
+ sessionId: args.sessionId,
46908
+ pendingOps,
46909
+ tags: pendingOperationTags,
46910
+ targets: newTargets,
46911
+ protectedTagIds: new Set([
46912
+ ...protectedTagNumbersForPass,
46913
+ ...protectedToolTags
46914
+ ]),
46915
+ probePreparation: (targets) => {
46916
+ const saved = nativeRemovalInputs;
46917
+ const rollback = Symbol("execute removal probe");
46918
+ const allowed = new Set;
46919
+ try {
46920
+ nativeRemovalInputs = saved && new Map(saved);
46921
+ probingExecuteRemoval = true;
46922
+ args.db.transaction(() => {
46923
+ for (const [number, target] of targets) {
46924
+ if (target.prepareDrop?.() !== false)
46925
+ allowed.add(number);
46926
+ }
46927
+ throw rollback;
46928
+ }).immediate();
46929
+ } catch (error) {
46930
+ if (error !== rollback)
46931
+ allowed.clear();
46932
+ } finally {
46933
+ nativeRemovalInputs = saved;
46934
+ probingExecuteRemoval = false;
46935
+ }
46936
+ return allowed;
46937
+ }
46938
+ }),
46939
+ usableWindow: args.usableSoft ?? args.contextUsage.inputTokens / (args.contextUsage.percentage / 100)
46940
+ });
46941
+ if (rideSignals.executeReclaim) {
46942
+ isCacheBustingPass = reclaimRidePermitted(rideSignals, ridePermissionGate);
46943
+ publishedWorkDrainAllowed = isCacheBustingPass;
46944
+ shouldRunHeuristics ||= isCacheBustingPass && args.heuristics !== undefined;
46945
+ stripUnheldSignedTurnOnBust();
46946
+ applyTemporalOnRide();
46947
+ }
46079
46948
  const deferredMaterialize = canConsumeDeferredLate && deferredMaterializationWasPending;
46080
46949
  const deferredHistoryRefresh = canConsumeDeferredLate && deferredHistoryRefreshWasPending;
46081
46950
  const shouldApplyPendingOps = publishedWorkDrainAllowed;
@@ -46808,6 +47677,8 @@ async function runPipeline(args) {
46808
47677
  servedTagNumbers.add(tag.tagNumber);
46809
47678
  }
46810
47679
  }
47680
+ if (bustedThisPass)
47681
+ clearExecuteReclaimState(args.db, args.sessionId);
46811
47682
  return {
46812
47683
  messages: outputMessages,
46813
47684
  recoveryNormalized,
@@ -50968,6 +51839,7 @@ function resolveHistorianFromConfig(config, harness = PI_HARNESS_KIND, modelRegi
50968
51839
  return {
50969
51840
  runner: new PiSubagentRunner,
50970
51841
  model,
51842
+ modelConfigKey: resolved.primary?.sourceConfigKey,
50971
51843
  fallbackModels,
50972
51844
  historianChunkTokens,
50973
51845
  historianContextLimit: resolveKnownHistorianContextLimit(model),