@cortexkit/opencode-magic-context 0.49.12 → 0.49.13

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 (116) hide show
  1. package/dist/auto-search-worker.js +3 -3
  2. package/dist/chunk-embedding-write-worker.js +89 -0
  3. package/dist/config/schema/agent-overrides.d.ts +12 -12
  4. package/dist/config/schema/magic-context.d.ts +88 -88
  5. package/dist/{conflict-warning-hook-f4x5wed7.js → conflict-warning-hook-mgq17yr3.js} +3 -3
  6. package/dist/{context-dam8p201.js → context-azqk0vfd.js} +31 -65
  7. package/dist/{derive-budgets-5306b1jt.js → derive-budgets-zn7yzd2d.js} +1 -1
  8. package/dist/{embedding-backfill-qbfcbp87.js → embedding-backfill-5e1t5wha.js} +6 -5
  9. package/dist/embedding-worker.js +1 -1
  10. package/dist/features/magic-context/chunk-embedding-write-worker.d.ts +2 -0
  11. package/dist/features/magic-context/chunk-embedding-write-worker.d.ts.map +1 -0
  12. package/dist/features/magic-context/chunk-embedding-writer.d.ts +48 -0
  13. package/dist/features/magic-context/chunk-embedding-writer.d.ts.map +1 -0
  14. package/dist/features/magic-context/compartment-chunk-embedding.d.ts +1 -1
  15. package/dist/features/magic-context/compartment-chunk-embedding.d.ts.map +1 -1
  16. package/dist/features/magic-context/dreamer/hidden-single-shot.d.ts +3 -2
  17. package/dist/features/magic-context/dreamer/hidden-single-shot.d.ts.map +1 -1
  18. package/dist/features/magic-context/dreamer/map-memories.d.ts +8 -1
  19. package/dist/features/magic-context/dreamer/map-memories.d.ts.map +1 -1
  20. package/dist/features/magic-context/dreamer/retrospective-raw-provider.d.ts +2 -0
  21. package/dist/features/magic-context/dreamer/retrospective-raw-provider.d.ts.map +1 -1
  22. package/dist/features/magic-context/dreamer/storage-dream-runs.d.ts +5 -0
  23. package/dist/features/magic-context/dreamer/storage-dream-runs.d.ts.map +1 -1
  24. package/dist/features/magic-context/dreamer/task-executor.d.ts.map +1 -1
  25. package/dist/features/magic-context/dreamer/verify-prompt.d.ts +6 -1
  26. package/dist/features/magic-context/dreamer/verify-prompt.d.ts.map +1 -1
  27. package/dist/features/magic-context/dreamer/verify.d.ts +25 -11
  28. package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
  29. package/dist/features/magic-context/mural/compress-cues.d.ts +3 -0
  30. package/dist/features/magic-context/mural/compress-cues.d.ts.map +1 -1
  31. package/dist/features/magic-context/project-embedding-registry.d.ts +5 -0
  32. package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
  33. package/dist/hooks/magic-context/auto-embed-session.d.ts +10 -0
  34. package/dist/hooks/magic-context/auto-embed-session.d.ts.map +1 -0
  35. package/dist/hooks/magic-context/embed-session-state.d.ts +8 -1
  36. package/dist/hooks/magic-context/embed-session-state.d.ts.map +1 -1
  37. package/dist/hooks/magic-context/hook.d.ts +3 -1
  38. package/dist/hooks/magic-context/hook.d.ts.map +1 -1
  39. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  40. package/dist/{index-yx5kgp2x.js → index-2jr1smmh.js} +92 -71
  41. package/dist/{index-fx90bvjd.js → index-3kdm78zp.js} +2 -2
  42. package/dist/{index-gf0psee3.js → index-3kx0kg0f.js} +60 -3
  43. package/dist/{index-6sytd5w3.js → index-aw1bh90w.js} +6 -6
  44. package/dist/{index-6sz25c3s.js → index-bxdg2nbt.js} +2 -2
  45. package/dist/{index-7h8a1xpc.js → index-e4dsjj1p.js} +1 -1
  46. package/dist/{index-05n6ykca.js → index-hnm8raee.js} +2 -2
  47. package/dist/{index-x2xjyq8f.js → index-qkd9zz0p.js} +8 -8
  48. package/dist/index-saews2s3.js +229 -0
  49. package/dist/{index-qtbdx42g.js → index-sj89f3b0.js} +12 -12
  50. package/dist/{index-wqs4q74r.js → index-v13skev1.js} +7 -7
  51. package/dist/{index-1wwh38fk.js → index-wj6ht7nm.js} +438 -132
  52. package/dist/{index-95s8xaj1.js → index-wz6mzzb1.js} +3 -3
  53. package/dist/{index-7zd5asz9.js → index-y1qysm3q.js} +196 -243
  54. package/dist/index.js +52 -90
  55. package/dist/{message-index-bounded-nq6rp8xa.js → message-index-bounded-vm64mqpq.js} +2 -2
  56. package/dist/{message-index-df7swgy1.js → message-index-seaqpb7c.js} +5 -5
  57. package/dist/migration-worker.js +2 -2
  58. package/dist/plugin/hooks/create-session-hooks.d.ts.map +1 -1
  59. package/dist/{project-embedding-registry-q0ysjyzc.js → project-embedding-registry-x45bv3qr.js} +5 -4
  60. package/dist/raw-ordinal-warmup-worker.js +2 -2
  61. package/dist/{recomp-orchestrator-a0mvby4e.js → recomp-orchestrator-dmbeadwt.js} +21 -20
  62. package/dist/{search-fm002702.js → search-5yd5ytzs.js} +14 -13
  63. package/dist/{send-session-notification-y2wg3fkh.js → send-session-notification-24r4esbh.js} +2 -2
  64. package/dist/shared/model-suggestion-retry.d.ts +2 -0
  65. package/dist/shared/model-suggestion-retry.d.ts.map +1 -1
  66. package/dist/shared/prompt-async-transport.d.ts.map +1 -1
  67. package/dist/{transform-postprocess-phase-s84rdf32.js → transform-postprocess-phase-72v86syx.js} +21 -20
  68. package/dist/v2/auto-search-worker.js +3 -3
  69. package/dist/v2/chunk-embedding-write-worker.js +88 -0
  70. package/dist/v2/{context-x60fa16g.js → context-w055w17c.js} +465 -190
  71. package/dist/v2/{derive-budgets-z25jw3py.js → derive-budgets-2zh4gm2c.js} +2 -2
  72. package/dist/v2/{embedding-backfill-mbjyza2a.js → embedding-backfill-jmaf8zrr.js} +6 -5
  73. package/dist/v2/embedding-worker.js +1 -1
  74. package/dist/v2/hooks/hidden-child.d.ts.map +1 -1
  75. package/dist/v2/hooks/transform-features.d.ts +2 -2
  76. package/dist/v2/hooks/transform-features.d.ts.map +1 -1
  77. package/dist/v2/{message-index-bounded-pgv1ndpb.js → message-index-bounded-wepg5723.js} +2 -2
  78. package/dist/v2/{message-index-5nayhm1r.js → message-index-gcmd0ng0.js} +5 -5
  79. package/dist/v2/migration-worker.js +2 -2
  80. package/dist/v2/{project-embedding-registry-jbmjc0p4.js → project-embedding-registry-0msp56p8.js} +5 -4
  81. package/dist/v2/raw-ordinal-warmup-worker.js +2 -2
  82. package/dist/v2/{recomp-orchestrator-8w3449eb.js → recomp-orchestrator-ca7qt75a.js} +21 -20
  83. package/dist/v2/retrospective-raw-provider.d.ts.map +1 -1
  84. package/dist/v2/{search-mhmxgq0e.js → search-c86dcv14.js} +14 -13
  85. package/dist/v2/{send-session-notification-jevgj9fe.js → send-session-notification-8ghn9tnv.js} +2 -2
  86. package/dist/v2/{server-f7jfmrrz.js → server-34kwfsr4.js} +1 -1
  87. package/dist/v2/server-4gn3z5an.js +229 -0
  88. package/dist/v2/{server-4c10404h.js → server-6cdy4rc0.js} +2 -2
  89. package/dist/v2/{server-5gvkzzrf.js → server-b81w6sw3.js} +92 -69
  90. package/dist/v2/{server-9ewkzqgd.js → server-ef89gdsx.js} +2 -2
  91. package/dist/v2/{server-sz8jj92q.js → server-hek6z3w6.js} +194 -241
  92. package/dist/v2/{server-50mkkhy1.js → server-n8ch9683.js} +8 -8
  93. package/dist/v2/{server-vknbt0gq.js → server-qhfvvfxj.js} +60 -3
  94. package/dist/v2/{server-nmrm2rjy.js → server-t4prcjc1.js} +7 -7
  95. package/dist/v2/{server-25tg45b4.js → server-xh7jar6k.js} +6 -6
  96. package/dist/v2/{server-37ngj8qw.js → server-zc3e54vy.js} +1 -1
  97. package/dist/v2/server.js +9 -8
  98. package/dist/v2/store-reader.d.ts +1 -0
  99. package/dist/v2/store-reader.d.ts.map +1 -1
  100. package/dist/v2/{wrapup-orchestrator-r82y780v.js → wrapup-orchestrator-e1a2w6jh.js} +14 -13
  101. package/dist/{wrapup-orchestrator-vmt6z3q5.js → wrapup-orchestrator-2051r6qm.js} +22 -21
  102. package/package.json +6 -5
  103. package/src/shared/model-suggestion-retry.test.ts +34 -0
  104. package/src/shared/model-suggestion-retry.ts +23 -3
  105. package/src/shared/prompt-async-transport.test.ts +1 -1
  106. package/src/shared/prompt-async-transport.ts +16 -3
  107. package/dist/{index-e6xnpach.js → index-b7p25tm0.js} +0 -0
  108. package/dist/{index-2pgxcncf.js → index-dgs16axy.js} +0 -0
  109. package/dist/{index-9vqb5p1s.js → index-e20m7284.js} +0 -0
  110. package/dist/{index-8ketfacn.js → index-v10f1rjv.js} +3 -3
  111. package/dist/{index-tdn0zkw4.js → index-wk0n1cgt.js} +0 -0
  112. package/dist/v2/{index-e6xnpach.js → index-b7p25tm0.js} +0 -0
  113. package/dist/v2/{server-2x42esxd.js → server-g10mdym6.js} +0 -0
  114. package/dist/v2/{server-fa75w6gp.js → server-k2bzedxk.js} +0 -0
  115. package/dist/v2/{server-kn9n2qgd.js → server-tbe1femw.js} +3 -3
  116. /package/dist/v2/{server-83ygfha2.js → server-vbe4se57.js} +0 -0
@@ -6,7 +6,7 @@ import {
6
6
  resolveLegacyConfigSources,
7
7
  getProtectedTokensTierOverrides,
8
8
  loadPluginConfigDetailed
9
- } from "./server-37ngj8qw.js";
9
+ } from "./server-zc3e54vy.js";
10
10
  import {
11
11
  getHarness2,
12
12
  harnessOwnsOpenCodeStore2
@@ -33,7 +33,7 @@ import {
33
33
  getSdkContextLimit,
34
34
  getSdkOutputLimit,
35
35
  getModelsDevCacheState
36
- } from "./server-kn9n2qgd.js";
36
+ } from "./server-tbe1femw.js";
37
37
  import {
38
38
  isValidLanguageCode,
39
39
  withContentLanguageDirective,
@@ -71,13 +71,6 @@ import {
71
71
  pluginConfigReader,
72
72
  currentPluginConfigReader,
73
73
  withLiveDreamerOutputCap,
74
- embedPauseBySession,
75
- embedRunStateBySession,
76
- autoEmbedAttemptedBySession,
77
- autoEmbedIdentityBySession,
78
- invalidateAutoEmbedSession,
79
- getEmbedDrainUiStatus,
80
- clearEmbedSessionState,
81
74
  acquireCompartmentLease,
82
75
  releaseCompartmentLeaseBestEffort,
83
76
  isCompartmentLeaseHeld,
@@ -214,9 +207,11 @@ import {
214
207
  toModelEntry,
215
208
  isPromptTimeoutError,
216
209
  getPromptFailureDetail,
210
+ raceWithSignal,
217
211
  promptSyncWithValidatedOutputRetry,
218
212
  normalizeSDKResponse,
219
213
  failedInvocationStatus,
214
+ sumTokensFromChildMessages,
220
215
  recordChildInvocation,
221
216
  createPromptAsyncTransport,
222
217
  CTX_NOTE_LIGHT_DESCRIPTION,
@@ -286,7 +281,7 @@ import {
286
281
  startCompartmentAgent,
287
282
  setRecompStarting2,
288
283
  setRecompTerminal2
289
- } from "./server-5gvkzzrf.js";
284
+ } from "./server-b81w6sw3.js";
290
285
  import {
291
286
  resolveHistorianModel2
292
287
  } from "./server-8cd2j99z.js";
@@ -311,7 +306,7 @@ import {
311
306
  openDatabaseAsync,
312
307
  isDatabasePersisted,
313
308
  getDatabasePersistenceError
314
- } from "./server-50mkkhy1.js";
309
+ } from "./server-n8ch9683.js";
315
310
  import {
316
311
  setHomeProjectPermission,
317
312
  shouldSkipHomeProjectMemory,
@@ -515,6 +510,35 @@ import {
515
510
  readSessionChunk2,
516
511
  readRawSessionSeedTail2
517
512
  } from "./server-m97brnat.js";
513
+ import {
514
+ embedPauseBySession,
515
+ embedRunStateBySession,
516
+ activeEmbeddingSessions,
517
+ autoEmbedAttemptedBySession,
518
+ autoEmbedIdentityBySession,
519
+ autoEmbedRetryAfterBySession,
520
+ invalidateAutoEmbedSession,
521
+ getEmbedDrainUiStatus,
522
+ clearEmbedSessionState,
523
+ describeShadowBackfillWriteRefusal2,
524
+ markProjectLoadUntrusted2,
525
+ drainProjectEmbeddingIdentityMaintenance2,
526
+ drainStaleEmbeddingIdentitiesForProject2,
527
+ registerProjectEmbedding2,
528
+ registerProjectShadowEmbedding2,
529
+ enqueueShadowEmbeddingItems2,
530
+ registerProjectInObservationMode2,
531
+ unregisterProjectShadowEmbedding2,
532
+ getProjectEmbeddingSnapshot2,
533
+ embedTextForProject2,
534
+ embedBatchForProject2,
535
+ embedUnembeddedMemoriesForProject2,
536
+ embedUnembeddedMemoriesForProjectOutcome2,
537
+ drainCommitBacklogForProject2,
538
+ embedSessionCompartmentChunks2,
539
+ getEmbeddingCoverageStatus2,
540
+ getAutoEmbeddingSessionCoverage2
541
+ } from "./server-hek6z3w6.js";
518
542
  import {
519
543
  textMentionsRecentCommit,
520
544
  hasMeaningfulUserText2,
@@ -551,7 +575,7 @@ import {
551
575
  import"./server-yrvqaswb.js";
552
576
  import {
553
577
  deleteChunkEmbedBackoffForSession
554
- } from "./server-vknbt0gq.js";
578
+ } from "./server-qhfvvfxj.js";
555
579
  import {
556
580
  registerOwnRpcServerInstance,
557
581
  rpcPortDir,
@@ -577,7 +601,7 @@ import {
577
601
  isMessageIndexReconciledThrough2,
578
602
  indexMessagesAfterOrdinal2,
579
603
  sweepOrphanedOpenCodeMessageIndexes2
580
- } from "./server-nmrm2rjy.js";
604
+ } from "./server-t4prcjc1.js";
581
605
  import {
582
606
  stableStringify,
583
607
  getTemporalDecisions,
@@ -719,35 +743,7 @@ import {
719
743
  resolveStoredPathWorkspaceIdentity,
720
744
  storedPathBelongsToWorkspace,
721
745
  computeWorkspaceEpochFingerprint
722
- } from "./server-fa75w6gp.js";
723
- import {
724
- GIT_SWEEP_LEASE_RENEWAL_MS,
725
- acquireGitSweepLease,
726
- renewGitSweepLease,
727
- markGitSweepSuccessAndRelease,
728
- parkGitSweepNonIndexable,
729
- releaseGitSweepLease,
730
- recordSessionProjectIdentity,
731
- hasRecordedSessionProjectIdentity,
732
- describeShadowBackfillWriteRefusal2,
733
- markProjectLoadUntrusted2,
734
- drainProjectEmbeddingIdentityMaintenance2,
735
- drainStaleEmbeddingIdentitiesForProject2,
736
- registerProjectEmbedding2,
737
- registerProjectShadowEmbedding2,
738
- enqueueShadowEmbeddingItems2,
739
- registerProjectInObservationMode2,
740
- unregisterProjectShadowEmbedding2,
741
- getProjectEmbeddingSnapshot2,
742
- embedTextForProject2,
743
- embedBatchForProject2,
744
- embedUnembeddedMemoriesForProject2,
745
- embedUnembeddedMemoriesForProjectOutcome2,
746
- drainCommitBacklogForProject2,
747
- embedSessionCompartmentChunks2,
748
- getEmbeddingCoverageStatus2,
749
- getAutoEmbeddingSessionCoverage2
750
- } from "./server-sz8jj92q.js";
746
+ } from "./server-k2bzedxk.js";
751
747
  import {
752
748
  configureContextDatabasePragmas2
753
749
  } from "./server-fb3zxn06.js";
@@ -793,18 +789,28 @@ import {
793
789
  readGitFileChangeTimesSince,
794
790
  verificationFileExists,
795
791
  normalizeVerificationFiles
796
- } from "./server-4c10404h.js";
792
+ } from "./server-6cdy4rc0.js";
797
793
  import {
798
794
  deriveTriggerBudget2,
799
795
  deriveHistorianChunkTokens2,
800
796
  resolveKnownHistorianContextLimit2,
801
797
  resolveHistorianProducerLimits2,
802
798
  resolveHistorianContextLimit2
803
- } from "./server-f7jfmrrz.js";
799
+ } from "./server-34kwfsr4.js";
804
800
  import"./server-05xjtq6c.js";
805
801
  import {
806
802
  isEmbeddingHostBusy2
807
803
  } from "./server-qt1qqasc.js";
804
+ import {
805
+ GIT_SWEEP_LEASE_RENEWAL_MS,
806
+ acquireGitSweepLease,
807
+ renewGitSweepLease,
808
+ markGitSweepSuccessAndRelease,
809
+ parkGitSweepNonIndexable,
810
+ releaseGitSweepLease,
811
+ recordSessionProjectIdentity,
812
+ hasRecordedSessionProjectIdentity
813
+ } from "./server-4gn3z5an.js";
808
814
  import {
809
815
  saveEmbeddingIfHashMatches,
810
816
  invalidateProject2,
@@ -812,10 +818,10 @@ import {
812
818
  } from "./server-4dhv7mqz.js";
813
819
  import {
814
820
  getLocalEmbeddingNativeMemoryStats
815
- } from "./server-2x42esxd.js";
821
+ } from "./server-g10mdym6.js";
816
822
  import {
817
823
  cosineSimilarity
818
- } from "./server-9ewkzqgd.js";
824
+ } from "./server-ef89gdsx.js";
819
825
  import {
820
826
  computeCueContentHash,
821
827
  hasMuralCueColumns,
@@ -852,7 +858,7 @@ import"./server-h0410h0v.js";
852
858
  import {
853
859
  flushIgnoredMessages2,
854
860
  sendStatusNotification2
855
- } from "./server-83ygfha2.js";
861
+ } from "./server-vbe4se57.js";
856
862
  import {
857
863
  renderSingleStoreMigrationRequiredRefusal,
858
864
  SingleStoreMigrationRequiredError,
@@ -873,7 +879,7 @@ import {
873
879
  resolveMemoriesByIdsForSearch2,
874
880
  unifiedSearch2,
875
881
  formatSearchResults2
876
- } from "./server-25tg45b4.js";
882
+ } from "./server-xh7jar6k.js";
877
883
  import {
878
884
  resolvePromptContext2
879
885
  } from "./server-fmsr7v69.js";
@@ -893,21 +899,6 @@ import {
893
899
  import {
894
900
  computeNormalizedHash
895
901
  } from "./server-2bvekkfy.js";
896
- import {
897
- sameProjectDirectory,
898
- canonicalProjectDirectory
899
- } from "./server-knvkbfvh.js";
900
- import {
901
- getErrorMessage,
902
- describeError
903
- } from "./server-y8v6yerm.js";
904
- import {
905
- shouldEnforcePrivateStoragePermissions,
906
- ensureStorageDirectorySync,
907
- writeStorageFileAtomicSync,
908
- writeStorageFileAsync,
909
- createStorageWriteStream
910
- } from "./server-fvnzcnww.js";
911
902
  import {
912
903
  normalizeProtectedToolName,
913
904
  mergeProtectedTools
@@ -917,6 +908,14 @@ import {
917
908
  piModelRefToCanonical,
918
909
  modelRefLookupOrder
919
910
  } from "./server-avwt563y.js";
911
+ import {
912
+ sameProjectDirectory,
913
+ canonicalProjectDirectory
914
+ } from "./server-knvkbfvh.js";
915
+ import {
916
+ getErrorMessage,
917
+ describeError
918
+ } from "./server-y8v6yerm.js";
920
919
  import {
921
920
  closeQuietly,
922
921
  isKnownAutocommit
@@ -924,6 +923,13 @@ import {
924
923
  import {
925
924
  logSlowWriteTransaction
926
925
  } from "./server-6pmqg9m4.js";
926
+ import {
927
+ shouldEnforcePrivateStoragePermissions,
928
+ ensureStorageDirectorySync,
929
+ writeStorageFileAtomicSync,
930
+ writeStorageFileAsync,
931
+ createStorageWriteStream
932
+ } from "./server-fvnzcnww.js";
927
933
 
928
934
  // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/classic/external.js
929
935
  var exports_external = {};
@@ -9809,11 +9815,6 @@ async function runPostTransformPhase(args) {
9809
9815
  }
9810
9816
  sessionLog2(args.sessionId, `m[0] HARD fold decision: reason=${m0MaterializeReason ?? foldDueDecision.reason ?? (foldExecutedThisPass ? "drift" : "soft_refresh")} executed=${foldExecutedThisPass} bustsServedPrefix=${foldBustsServedPrefixThisPass}`);
9811
9817
  }
9812
- if (args.normalizeRecoveryTail && (foldBustsServedPrefixThisPass || firstRenderBust)) {
9813
- args.normalizeRecoveryTail();
9814
- args.tags = getTagsBySession2(args.db, args.sessionId);
9815
- newTargets = protectNewTagMutations(args.messages, args.targets, retainedThinking, args.thinkingBindingRecoveryEnabledForModel === true);
9816
- }
9817
9818
  logTransformTiming(args.sessionId, "pp.prefixPreflight", tPostprocessSetup, `foldExecuted=${foldExecutedThisPass} m1Refreshed=${publishedM1RefreshedThisPass}`);
9818
9819
  const tPassDecisions = performance.now();
9819
9820
  const frontToolCandidates = args.tags.filter((tag) => tag.type === "tool" && tag.status === "active" && args.targets.get(tag.tagNumber)?.canDrop?.());
@@ -9847,6 +9848,11 @@ async function runPostTransformPhase(args) {
9847
9848
  const shouldApplyPendingOps = publishedWorkDrainAllowed;
9848
9849
  const shouldRunHeuristics = publishedWorkDrainAllowed && (rideSignals.publishedHistory || materializationRequested || forceMaterialization || foldBustsServedPrefixThisPass || firstRenderBust || heldIdleExpiryRebuild || emergencyDropEligible || args.schedulerDecision === "execute" && (!alreadyRanThisTurn || !args.fullFeatureMode));
9849
9850
  const isCacheBustingPass = publishedWorkDrainAllowed;
9851
+ if (args.normalizeRecoveryTail && isCacheBustingPass) {
9852
+ args.normalizeRecoveryTail();
9853
+ args.tags = getTagsBySession2(args.db, args.sessionId);
9854
+ newTargets = protectNewTagMutations(args.messages, args.targets, retainedThinking, args.thinkingBindingRecoveryEnabledForModel === true);
9855
+ }
9850
9856
  const reclaimDistance = isCacheBustingPass ? toolReclaimDistanceEntries(args.messages, args.targets) : [];
9851
9857
  const canEditWholePrefix = isCacheBustingPass && !activeThinkingPrefixHold;
9852
9858
  const previousTemporalDecisions = args.temporalCandidates && !compactionOff ? new Map([
@@ -20533,7 +20539,7 @@ function getAsyncModule() {
20533
20539
  await beforeModuleLoad();
20534
20540
  const [{ default: singlefileAsyncifyVariant }, { newQuickJSAsyncWASMModuleFromVariant }] = await importPluginModule(() => Promise.all([
20535
20541
  import("./index-6e4mwffh.js").then((m)=>__toESM(m.default,1)),
20536
- import("./index-e6xnpach.js")
20542
+ import("./index-b7p25tm0.js")
20537
20543
  ]));
20538
20544
  const module = await newQuickJSAsyncWASMModuleFromVariant(singlefileAsyncifyVariant);
20539
20545
  return module;
@@ -22559,7 +22565,7 @@ function registerRpcHandlers(rpcServer, args) {
22559
22565
  return { count: buildCompartmentCount(db, sessionId, moduleStatus) };
22560
22566
  });
22561
22567
  const buildManagedCtx = async (db) => {
22562
- const { deriveHistorianChunkTokens, resolveHistorianContextLimit } = await importPluginModule(() => import("./derive-budgets-z25jw3py.js"));
22568
+ const { deriveHistorianChunkTokens, resolveHistorianContextLimit } = await importPluginModule(() => import("./derive-budgets-2zh4gm2c.js"));
22563
22569
  const { resolveHistorianModel } = await importPluginModule(() => import("./model-resolution-nx97z3x7.js"));
22564
22570
  const { userObservationCollectionEnabled, userObservationsRequested } = await importPluginModule(() => import("./task-config-nvz8mapa.js"));
22565
22571
  const DEFAULT_HISTORIAN_TIMEOUT_MS = 10 * 60 * 1000;
@@ -22611,8 +22617,8 @@ function registerRpcHandlers(rpcServer, args) {
22611
22617
  const db = readDatabase();
22612
22618
  if (!db)
22613
22619
  return { ok: false, error: "db unavailable" };
22614
- const { runManagedRecomp } = await importPluginModule(() => import("./recomp-orchestrator-8w3449eb.js"));
22615
- const { sendIgnoredMessage } = await importPluginModule(() => import("./send-session-notification-jevgj9fe.js"));
22620
+ const { runManagedRecomp } = await importPluginModule(() => import("./recomp-orchestrator-ca7qt75a.js"));
22621
+ const { sendIgnoredMessage } = await importPluginModule(() => import("./send-session-notification-8ghn9tnv.js"));
22616
22622
  log2(`[rpc] recomp requested for session ${sessionId}`);
22617
22623
  if (!args.client && !args.hiddenCompletionExecutor) {
22618
22624
  return {
@@ -22696,7 +22702,7 @@ function registerRpcHandlers(rpcServer, args) {
22696
22702
  const db = readDatabase();
22697
22703
  if (!db)
22698
22704
  return { ok: false, error: "db unavailable" };
22699
- const { runManagedWrapup } = await importPluginModule(() => import("./wrapup-orchestrator-r82y780v.js"));
22705
+ const { runManagedWrapup } = await importPluginModule(() => import("./wrapup-orchestrator-e1a2w6jh.js"));
22700
22706
  const model = liveSessionState.liveModelBySession.get(sessionId);
22701
22707
  const contextLimit = model ? resolveContextLimit(model.providerID, model.modelID, { db, sessionID: sessionId }) : 128000;
22702
22708
  const ctx = {
@@ -26804,9 +26810,12 @@ async function runCompressCues(args) {
26804
26810
  let timeoutStreakElapsedMs = [];
26805
26811
  for (let i = 0;i < chunks.length; i += 1) {
26806
26812
  const remainingMs = Math.max(0, args.deadline - Date.now());
26807
- if (remainingMs <= 0)
26813
+ if (remainingMs <= 0) {
26814
+ result.stopReason = "deadline";
26808
26815
  break;
26816
+ }
26809
26817
  if (remainingMs < CHUNK_TIMEOUT_FLOOR_MS) {
26818
+ result.stopReason = "deadline";
26810
26819
  log2(`[dreamer] compress-cues: stopping before chunk ${i + 1}/${chunks.length} — remaining budget ${remainingMs}ms is below the ${CHUNK_TIMEOUT_FLOOR_MS}ms chunk floor; banking ${result.compressed} compressed cue(s)`);
26811
26820
  break;
26812
26821
  }
@@ -26815,6 +26824,10 @@ async function runCompressCues(args) {
26815
26824
  if (!chunk)
26816
26825
  break;
26817
26826
  const outcome = await compressOneChunk(args, chunk, sliceMs, abortController.signal);
26827
+ if (outcome.failure) {
26828
+ result.failure = outcome.failure.error;
26829
+ result.failureStage = outcome.failure.stage;
26830
+ }
26818
26831
  result.compressed += outcome.compressed;
26819
26832
  result.skipped += outcome.skipped;
26820
26833
  result.remaining -= outcome.compressed;
@@ -26824,6 +26837,7 @@ async function runCompressCues(args) {
26824
26837
  consecutiveTimeouts += 1;
26825
26838
  timeoutStreakElapsedMs.push(outcome.failure.elapsedMs);
26826
26839
  if (consecutiveTimeouts >= CONSECUTIVE_TIMEOUT_LIMIT) {
26840
+ result.stopReason = "timeout-circuit-breaker";
26827
26841
  log2(`[dreamer] compress-cues: circuit breaker tripped — ${consecutiveTimeouts} consecutive chunk timeouts (model too slow for its time slice); per-chunk elapsed [${timeoutStreakElapsedMs.join("ms, ")}ms] vs ${sliceMs}ms slice; stopping run incomplete with ${chunks.length - i - 1} chunk(s) unattempted`);
26828
26842
  break;
26829
26843
  }
@@ -26840,7 +26854,7 @@ async function runCompressCues(args) {
26840
26854
  }
26841
26855
  }
26842
26856
  function isTimeoutClassError(error) {
26843
- return error instanceof Error && /^prompt timed out after \d+ms$/.test(error.message);
26857
+ return isPromptTimeoutError(error) || getPromptFailureDetail(error)?.failureClass === "provider_timeout";
26844
26858
  }
26845
26859
  async function compressOneChunk(args, chunk, sliceMs, signal) {
26846
26860
  let agentSessionId = null;
@@ -26848,6 +26862,7 @@ async function compressOneChunk(args, chunk, sliceMs, signal) {
26848
26862
  const executor = resolveHiddenCompletionExecutor(args.hiddenCompletionExecutor, args.client, args.db, args.sessionDirectory, "compress-cues");
26849
26863
  let promptSettled = false;
26850
26864
  const startedAt = Date.now();
26865
+ let stage = "child-start";
26851
26866
  try {
26852
26867
  const prompt = buildCompressCuesPrompt({
26853
26868
  projectPath: args.projectIdentity,
@@ -26868,6 +26883,7 @@ async function compressOneChunk(args, chunk, sliceMs, signal) {
26868
26883
  agentSessionId = handle.id || null;
26869
26884
  if (!agentSessionId)
26870
26885
  throw new Error("Could not create compress-cues session.");
26886
+ stage = "prompt";
26871
26887
  const opened = handle;
26872
26888
  const run = await promptSyncWithValidatedOutputRetry(args.client, {
26873
26889
  path: { id: agentSessionId },
@@ -26919,16 +26935,19 @@ async function compressOneChunk(args, chunk, sliceMs, signal) {
26919
26935
  modelId: run.output.modelId
26920
26936
  });
26921
26937
  }
26938
+ stage = "apply";
26922
26939
  return args.moduleRoute ? await applyCuesThroughModule(args, chunk, run.validated, signal) : applyCues(args, chunk, run.validated);
26923
26940
  } catch (error) {
26924
26941
  const desc = describeError(error);
26925
26942
  log2(`[dreamer] compress-cues chunk failed: ${desc.brief}`, desc.stackHead ? { stackHead: desc.stackHead } : undefined);
26926
- if (signal.aborted || error instanceof HiddenCompletionRefusal || error instanceof DreamerProviderOutputFailureError)
26943
+ if (signal.aborted || error instanceof DreamerModuleFailureError || error instanceof HiddenCompletionRefusal || error instanceof DreamerProviderOutputFailureError)
26927
26944
  throw error;
26928
26945
  return {
26929
26946
  compressed: 0,
26930
26947
  skipped: 0,
26931
26948
  failure: {
26949
+ error,
26950
+ stage,
26932
26951
  class: isTimeoutClassError(error) ? "timeout" : "other",
26933
26952
  brief: desc.brief,
26934
26953
  elapsedMs: Date.now() - startedAt
@@ -27082,7 +27101,7 @@ async function applyCuesThroughModule(args, chunk, manifestText, signal) {
27082
27101
  // src/features/magic-context/dreamer/hidden-single-shot.ts
27083
27102
  async function runHiddenSingleShotPrompt(args) {
27084
27103
  const system = withContentLanguageDirective(args.system, args.language);
27085
- const handle = await args.executor.open({
27104
+ const opening = args.executor.open({
27086
27105
  parentSessionId: args.parentSessionId,
27087
27106
  agent: args.agent,
27088
27107
  kind: "dreamer-task",
@@ -27094,6 +27113,17 @@ async function runHiddenSingleShotPrompt(args) {
27094
27113
  directory: args.sessionDirectory,
27095
27114
  ...args.metadata ? { metadata: args.metadata } : {}
27096
27115
  });
27116
+ opening.then((handle) => {
27117
+ if (args.signal?.aborted)
27118
+ return args.executor.close(handle, {
27119
+ promptSettled: false,
27120
+ privacySensitive: args.privacySensitive ?? true,
27121
+ context: `[dreamer] ${args.callContext}`,
27122
+ log: log2
27123
+ });
27124
+ }).catch(() => {});
27125
+ const handle = await raceWithSignal(opening, args.signal);
27126
+ args.onOpened?.(handle.id);
27097
27127
  let promptSettled = false;
27098
27128
  try {
27099
27129
  if (!handle.id)
@@ -27148,12 +27178,16 @@ async function runHiddenSingleShotPrompt(args) {
27148
27178
  }
27149
27179
  throw error;
27150
27180
  } finally {
27151
- await args.executor.close(handle, {
27181
+ const close = args.executor.close(handle, {
27152
27182
  promptSettled,
27153
27183
  privacySensitive: args.privacySensitive ?? true,
27154
27184
  context: `[dreamer] ${args.callContext}`,
27155
27185
  log: log2
27156
27186
  });
27187
+ if (args.signal?.aborted)
27188
+ close.catch(() => {});
27189
+ else
27190
+ await raceWithSignal(close, args.signal);
27157
27191
  }
27158
27192
  }
27159
27193
 
@@ -30228,14 +30262,28 @@ function isDeferred(memory, retries) {
30228
30262
  return !!retry && retry.content === contentKey2(memory) && retry.deferUntil > Date.now();
30229
30263
  }
30230
30264
  function assistantText2(messages) {
30231
- return messages.filter((message) => isRecord(message) && (message.role === "assistant" || isRecord(message.info) && message.info.role === "assistant")).map((message) => extractLatestAssistantText([message]) ?? (isRecord(message) && Array.isArray(message.content) ? message.content.filter(isRecord).filter((part) => part.type === "text" && typeof part.text === "string").map((part) => part.text).join(`
30265
+ const joined = messages.filter((message) => isRecord(message) && (message.role === "assistant" || isRecord(message.info) && message.info.role === "assistant")).map((message) => extractLatestAssistantText([message]) ?? (isRecord(message) && Array.isArray(message.content) ? message.content.filter(isRecord).filter((part) => part.type === "text" && typeof part.text === "string").map((part) => part.text).join(`
30232
30266
  `) : "")).join(`
30233
30267
  `);
30268
+ return joined.trim() ? joined : null;
30234
30269
  }
30235
30270
  function currentManifest(text) {
30236
30271
  const start = text.lastIndexOf("<mappings>");
30237
30272
  return start < 0 ? text : text.slice(start);
30238
30273
  }
30274
+ function parseMapMemoriesCompletion(text, completion, expectedIds) {
30275
+ return validateMapMemoriesManifest(currentManifest(assistantText2(completion.messages ?? []) || text), expectedIds);
30276
+ }
30277
+ function validateClientMapMemories(messages, expectedIds) {
30278
+ if (hasLengthCappedOutput(messages)) {
30279
+ throw new Error("map-memories returned length-capped output");
30280
+ }
30281
+ const raw = assistantText2(messages);
30282
+ if (raw == null) {
30283
+ throw new Error("map-memories returned no output");
30284
+ }
30285
+ return validateMapMemoriesManifest(currentManifest(raw), expectedIds);
30286
+ }
30239
30287
  function logBatchUsage(messages, committed, startedAt) {
30240
30288
  const steps = messages.filter((message) => isRecord(message) && (message.role === "assistant" || isRecord(message.info) && message.info.role === "assistant")).length;
30241
30289
  log2(`[dreamer] map-memories batch: steps=${steps} committed=${committed} steps_per_memory=${committed ? (steps / committed).toFixed(2) : "n/a"} elapsed_ms=${Date.now() - startedAt}`);
@@ -30300,8 +30348,11 @@ async function mapMemories(args) {
30300
30348
  const inputs = allInputs.filter((memory) => !isDeferred(memory, retries));
30301
30349
  result.remaining = allInputs.length;
30302
30350
  result.complete = result.remaining === 0;
30303
- if (inputs.length === 0)
30351
+ if (inputs.length === 0) {
30352
+ if (allInputs.length > 0)
30353
+ result.deferred = true;
30304
30354
  return result;
30355
+ }
30305
30356
  const batches = [];
30306
30357
  for (let i = 0;i < inputs.length; i += MAP_BATCH_SIZE) {
30307
30358
  batches.push({ inputs: inputs.slice(i, i + MAP_BATCH_SIZE), isOmissionRetry: false });
@@ -30327,6 +30378,10 @@ async function mapMemories(args) {
30327
30378
  if (!batch)
30328
30379
  break;
30329
30380
  const outcome = await mapOneBatch(args, batch.inputs, sliceMs, abortController.signal);
30381
+ if (outcome.failure) {
30382
+ result.failure = outcome.failure.error;
30383
+ result.failureStage = outcome.failure.stage;
30384
+ }
30330
30385
  const committed = outcome.mapped + outcome.independent;
30331
30386
  runLeaseGuardedWrite(args.db, args.holderId, args.leaseKey, () => {
30332
30387
  const committedIds = new Set(outcome.committedIds);
@@ -30390,6 +30445,7 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
30390
30445
  const startedAt = Date.now();
30391
30446
  let budgetFinalized = false;
30392
30447
  let failedCompletion;
30448
+ let stage = "child-start";
30393
30449
  const onBudgetUpdate = (state) => {
30394
30450
  budgetFinalized ||= state.finalizeFired;
30395
30451
  args.onBudgetUpdate?.(state);
@@ -30411,15 +30467,19 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
30411
30467
  fallbackModels: args.fallbackModels,
30412
30468
  timeoutMs: sliceMs,
30413
30469
  signal,
30470
+ onOpened: () => {
30471
+ stage = "prompt";
30472
+ },
30414
30473
  onFailureOutput: (completion) => {
30415
30474
  failedCompletion = completion;
30416
30475
  },
30417
- parse: (text, completion) => validateMapMemoriesManifest(currentManifest(assistantText2(completion.messages ?? []) || text), new Set(batch.map((memory) => memory.id)))
30476
+ parse: (text, completion) => parseMapMemoriesCompletion(text, completion, new Set(batch.map((memory) => memory.id)))
30418
30477
  });
30419
30478
  recordInvocation2(args, startedAt, {
30420
30479
  status: "completed",
30421
30480
  messages: run.completion.messages ?? []
30422
30481
  });
30482
+ stage = "apply";
30423
30483
  const outcome = await applyParsedBatchMappings(args, batch, run.validated, budgetFinalized, true);
30424
30484
  logBatchUsage(run.completion.messages ?? [], outcome.mapped + outcome.independent, startedAt);
30425
30485
  const returnedIds = new Set(outcome.committedIds);
@@ -30444,6 +30504,7 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
30444
30504
  agentSessionId = typeof created?.id === "string" ? created.id : null;
30445
30505
  if (!agentSessionId)
30446
30506
  throw new Error("Could not create map-memories session.");
30507
+ stage = "prompt";
30447
30508
  const run = await promptSyncWithValidatedOutputRetry(client, {
30448
30509
  path: { id: agentSessionId },
30449
30510
  query: { directory: args.sessionDirectory },
@@ -30471,18 +30532,11 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
30471
30532
  preferResponseOnMissingData: true
30472
30533
  });
30473
30534
  },
30474
- validateOutput: (messages) => {
30475
- if (hasLengthCappedOutput(messages)) {
30476
- throw new Error("map-memories returned length-capped output");
30477
- }
30478
- const text = currentManifest(assistantText2(messages));
30479
- if (!text)
30480
- throw new Error("map-memories returned no output");
30481
- return validateMapMemoriesManifest(text, new Set(batch.map((memory) => memory.id)));
30482
- }
30535
+ validateOutput: (messages) => validateClientMapMemories(messages, new Set(batch.map((memory) => memory.id)))
30483
30536
  });
30484
30537
  promptSettled = true;
30485
30538
  recordInvocation2(args, startedAt, { status: "completed", messages: run.output });
30539
+ stage = "apply";
30486
30540
  const outcome = await applyParsedBatchMappings(args, batch, run.validated, budgetFinalized, true);
30487
30541
  logBatchUsage(run.output, outcome.mapped + outcome.independent, startedAt);
30488
30542
  const returnedIds = new Set(outcome.committedIds);
@@ -30511,6 +30565,8 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
30511
30565
  return {
30512
30566
  ...outcome,
30513
30567
  failure: {
30568
+ error,
30569
+ stage,
30514
30570
  class: isTimeoutClassError2(error) ? "timeout" : "other",
30515
30571
  elapsedMs: Date.now() - startedAt
30516
30572
  }
@@ -31667,10 +31723,28 @@ async function readRetrospectiveScanWindow(provider, projectIdentity, watermarkM
31667
31723
  }
31668
31724
  function readOpenCodeMessagesSince(db, sessionId, sinceMs, capPerSession) {
31669
31725
  const limit = Math.max(1, Math.floor(capPerSession));
31670
- const rows = db.prepare(`SELECT id, data, time_created
31671
- FROM message
31672
- WHERE session_id = ? AND time_created > ?
31673
- ORDER BY time_created ASC, id ASC
31726
+ const rows = db.prepare(`SELECT current.id, current.data, current.time_created,
31727
+ EXISTS (
31728
+ SELECT 1 FROM message assistant_reply
31729
+ WHERE assistant_reply.session_id = current.session_id
31730
+ AND json_valid(assistant_reply.data)
31731
+ AND json_extract(assistant_reply.data, '$.role') = 'assistant'
31732
+ AND (assistant_reply.time_created < current.time_created
31733
+ OR (assistant_reply.time_created = current.time_created
31734
+ AND assistant_reply.id < current.id))
31735
+ AND EXISTS (
31736
+ SELECT 1 FROM message prior_user
31737
+ WHERE prior_user.session_id = current.session_id
31738
+ AND json_valid(prior_user.data)
31739
+ AND json_extract(prior_user.data, '$.role') = 'user'
31740
+ AND (prior_user.time_created < assistant_reply.time_created
31741
+ OR (prior_user.time_created = assistant_reply.time_created
31742
+ AND prior_user.id < assistant_reply.id))
31743
+ )
31744
+ ) AS has_prior_assistant_reply
31745
+ FROM message current
31746
+ WHERE current.session_id = ? AND current.time_created > ?
31747
+ ORDER BY current.time_created ASC, current.id ASC
31674
31748
  LIMIT ?`).all(sessionId, sinceMs, limit + 1);
31675
31749
  const truncated = rows.length > limit;
31676
31750
  const kept = truncated ? rows.slice(0, limit) : rows;
@@ -31774,7 +31848,8 @@ function normalizeOpenCodeRows(db, sessionId, rows) {
31774
31848
  ordinal,
31775
31849
  role,
31776
31850
  parts,
31777
- ts: row.time_created
31851
+ ts: row.time_created,
31852
+ followsAssistantReply: row.has_prior_assistant_reply === 1
31778
31853
  });
31779
31854
  });
31780
31855
  }
@@ -31788,7 +31863,8 @@ function normalizeOpenCodeMessage(args) {
31788
31863
  ordinal: args.ordinal,
31789
31864
  role: "user",
31790
31865
  text,
31791
- ts: args.ts
31866
+ ts: args.ts,
31867
+ ...args.followsAssistantReply ? { followsAssistantReply: true } : {}
31792
31868
  });
31793
31869
  }
31794
31870
  }
@@ -32154,7 +32230,7 @@ var VERIFY_SYSTEM_PROMPT = `You are a memory verifier for the magic-context syst
32154
32230
 
32155
32231
  Each memory below comes with its backing file(s) — the code it makes a claim about. For EACH memory: use the provided git diff as evidence when present. If no diff is supplied, read its backing files (you may read more if needed) and decide whether the memory is still accurate.
32156
32232
 
32157
- Tools (read-only): read, grep, glob. Request line ranges and keep reads short. You read code only when the evidence requires it; you change nothing.
32233
+ Tools (read-only): read, grep, glob, plus any available AFT navigation tools. Use at most 3 tool calls per memory, including searches and reads. Start with the backing files and likely identifier matches. Never read the same file twice in a batch; reuse evidence. Request short useful line ranges unless the claim concerns the file as a whole. If evidence is insufficient when the call budget runs out, SKIP that memory; uncertainty never justifies archival. You change nothing.
32158
32234
 
32159
32235
  Decide ONE of four outcomes per memory:
32160
32236
  - VERIFIED — still accurate. Keep it as-is.
@@ -32166,7 +32242,7 @@ UPDATE and ARCHIVE are ONLY for claims a repository file can falsify, such as an
32166
32242
 
32167
32243
  BE CONSERVATIVE ABOUT ARCHIVING. Wrong archival of a TRUE memory is the worst possible outcome — far worse than leaving a slightly-stale memory. If you cannot find the code, or you are unsure, or it might still be true somewhere you didn't look: mark it VERIFIED or SKIPPED, never archived. Archive ONLY when you have positive evidence the code contradicts a code fact.
32168
32244
 
32169
- Output ONE XML manifest at the very end and NOTHING else — no narration, no per-memory commentary, no reasoning:
32245
+ Output ONE XML manifest and NOTHING else — no narration or reasoning. Open <verify> before investigating and emit each complete verdict immediately before investigating the next memory, so interruption preserves finished work. Close </verify> when done:
32170
32246
  <verify>
32171
32247
  <verified id="N" files="path/a.ts,path/b.ts"/>
32172
32248
  <update id="M" files="path/c.ts">corrected present-tense content</update>
@@ -32179,17 +32255,24 @@ Rules:
32179
32255
  - Every input memory id MUST appear exactly once, in exactly one of verified/update/archive/skip.
32180
32256
  - files = the COMPLETE current backing set (repo-relative, comma-separated). It may differ from the given mapping if a file moved — record what you actually verified against.
32181
32257
  - Default to VERIFIED. skip when code cannot decide the claim. update and archive are the exceptions, not the norm.`;
32258
+ async function seedVerifyCandidates(memories, directory) {
32259
+ const seeded = await seedIdentifierCandidates(memories.map((m) => ({ ...m, candidates: [] })), directory);
32260
+ return memories.map((m, i) => ({ ...m, candidates: seeded[i].candidates }));
32261
+ }
32182
32262
  function buildVerifyPrompt(projectPath, memories, evidence) {
32183
32263
  const list = memories.map((m) => `[${m.id}] ${m.category}
32184
32264
  Content: ${m.content}
32185
- Backing files: ${m.mappedFiles.join(", ")}`).join(`
32265
+ Backing files: ${m.mappedFiles.join(", ")}${m.candidates?.length ? `
32266
+ Likely files (identifier matches, confirm before using): ${m.candidates.join(", ")}` : ""}`).join(`
32186
32267
 
32187
32268
  `);
32188
32269
  return `## Verify these memories against the code
32189
32270
 
32190
32271
  Project: ${projectPath}
32191
32272
 
32192
- ${evidence ? "The git diff below is the evidence. If changed hunks do not touch a claim, mark it verified without opening files. Open files only when a diff suggests the claim may have changed. A rename or deletion requires an update or archive when positively supported; do not archive on uncertainty." : "Read each memory's backing files to check its claims."} Decide verified / update / archive / skip (default verified; behavioral directives only permit verified or skip), then output ONE <verify> manifest covering every id.
32273
+ When available in this session, use aft_outline to outline the backing file and aft_zoom on the claimed symbol (or aft_search to locate it), instead of paging through whole files. Read a whole file only when the claim is about the file as a whole. Otherwise use the available read-only tools.
32274
+
32275
+ ${evidence ? "The git diff below is the evidence. If changed hunks do not touch a claim, mark it verified without opening files. Open files only when a diff suggests the claim may have changed. A rename or deletion requires an update or archive when positively supported; do not archive on uncertainty." : "Check each memory's claim against its backing files."} Decide verified / update / archive / skip (default verified; behavioral directives only permit verified or skip), then output ONE <verify> manifest covering every id.
32193
32276
 
32194
32277
  <memories>
32195
32278
  ${list}
@@ -32266,13 +32349,57 @@ function validateVerifyManifest(text, expectedIds) {
32266
32349
  assertNoDuplicateManifestIds(ids.filter((id) => expectedIds.has(id)), "verify");
32267
32350
  return parsed;
32268
32351
  }
32352
+ function parsePartialVerifyManifest(text, expectedIds) {
32353
+ const out = { verified: [], updated: [], archived: [], skipped: [] };
32354
+ const start = text.lastIndexOf("<verify>");
32355
+ if (start < 0)
32356
+ return out;
32357
+ const entries = new Map;
32358
+ const conflicts = new Set;
32359
+ for (const match of text.slice(start).matchAll(/<(?:verified|archive|skip)\b[^<>]*\/>|<update\b[^<>]*>[\s\S]*?<\/update>/g)) {
32360
+ try {
32361
+ const parsed = parseVerifyManifest(`<verify>${match[0]}</verify>`);
32362
+ const id = verifyIds(parsed)[0];
32363
+ if (!expectedIds.has(id) || conflicts.has(id))
32364
+ continue;
32365
+ const previous = entries.get(id);
32366
+ if (previous && JSON.stringify(previous) !== JSON.stringify(parsed)) {
32367
+ entries.delete(id);
32368
+ conflicts.add(id);
32369
+ } else
32370
+ entries.set(id, parsed);
32371
+ } catch {}
32372
+ }
32373
+ for (const parsed of entries.values()) {
32374
+ out.verified.push(...parsed.verified);
32375
+ out.updated.push(...parsed.updated);
32376
+ out.archived.push(...parsed.archived);
32377
+ out.skipped.push(...parsed.skipped);
32378
+ }
32379
+ return out;
32380
+ }
32269
32381
 
32270
32382
  // src/features/magic-context/dreamer/verify.ts
32271
- var VERIFY_BATCH_SIZE = 20;
32383
+ var VERIFY_BATCH_SIZE = 5;
32384
+ var VERIFY_TOKENS_PER_MEMORY = 1e5;
32385
+ var VERIFY_RUN_TOKEN_BUDGET = 2500000;
32386
+ var VERIFY_RUN_SLICE_MS = 240000;
32387
+ function verifyBatchTokenBudget(size, configured) {
32388
+ return Math.min(configured ?? Number.MAX_SAFE_INTEGER, size * VERIFY_TOKENS_PER_MEMORY);
32389
+ }
32390
+ function verifyAssistantText(messages) {
32391
+ const text = messages.filter((m) => isRecord(m) && (m.role === "assistant" || isRecord(m.info) && m.info.role === "assistant")).map((m) => extractLatestAssistantText([m]) || (isRecord(m) && Array.isArray(m.content) ? m.content.filter(isRecord).filter((p) => p.type === "text").map((p) => p.text).join(`
32392
+ `) : "")).join(`
32393
+ `);
32394
+ if (!text.trim())
32395
+ return null;
32396
+ const start = text.lastIndexOf("<verify>");
32397
+ return start >= 0 ? text.slice(start) : text;
32398
+ }
32272
32399
  var IDENTICAL_PROVIDER_FAILURE_BATCH_LIMIT = 2;
32273
- var VERIFY_BATCH_FLOOR_MS = 240000;
32274
- function computeVerifyBatchSliceMs(remainingMs, batchesRemaining) {
32275
- return Math.min(remainingMs, Math.max(VERIFY_BATCH_FLOOR_MS, Math.floor(remainingMs / batchesRemaining)));
32400
+ var VERIFY_BATCH_FLOOR_MS = 30000;
32401
+ function computeVerifyBatchSliceMs(remainingMs, _batchesRemaining) {
32402
+ return Math.min(remainingMs, VERIFY_RUN_SLICE_MS);
32276
32403
  }
32277
32404
  function closeBroadCycle(args, cycleStartAt) {
32278
32405
  if (!args.forceBroad || cycleStartAt === undefined)
@@ -32296,6 +32423,7 @@ async function runVerify(args) {
32296
32423
  }
32297
32424
  async function runVerifyWithCooldown(args) {
32298
32425
  const runStartedAt = Date.now();
32426
+ const sliceDeadline = runStartedAt + VERIFY_RUN_SLICE_MS;
32299
32427
  const result = {
32300
32428
  verified: 0,
32301
32429
  updated: 0,
@@ -32338,16 +32466,31 @@ async function runVerifyWithCooldown(args) {
32338
32466
  let consecutiveProviderFailures = 0;
32339
32467
  let priorProviderFailureFingerprint = null;
32340
32468
  let lastProviderFailure = null;
32469
+ let runSpent = 0;
32470
+ const runTokenBudget = Math.min(args.tokenBudget ?? VERIFY_RUN_TOKEN_BUDGET, VERIFY_RUN_TOKEN_BUDGET);
32341
32471
  try {
32342
32472
  for (let i = 0;i < batches.length; i += 1) {
32343
- const remainingMs = Math.max(0, args.deadline - Date.now());
32473
+ const remainingMs = Math.max(0, Math.min(args.deadline, sliceDeadline) - Date.now());
32344
32474
  if (remainingMs < VERIFY_BATCH_FLOOR_MS) {
32345
32475
  result.stopReason = "deadline";
32346
32476
  log2(`[dreamer] ${args.forceBroad ? "verify-broad" : "verify"}: stopping before batch ${i + 1}/${batches.length} — remaining budget ${remainingMs}ms is below the ${VERIFY_BATCH_FLOOR_MS}ms batch floor`);
32347
32477
  break;
32348
32478
  }
32349
32479
  const sliceMs = computeVerifyBatchSliceMs(remainingMs, batches.length - i);
32350
- const counts = await verifyOneBatch(args, batches[i], sliceMs, abortController.signal);
32480
+ if (runSpent >= runTokenBudget) {
32481
+ result.stopReason = "token-budget";
32482
+ break;
32483
+ }
32484
+ let batchSpent = 0;
32485
+ const counts = await verifyOneBatch({
32486
+ ...args,
32487
+ tokenBudget: runTokenBudget - runSpent,
32488
+ onBudgetUpdate: (state) => {
32489
+ runSpent += Math.max(0, state.spent - batchSpent);
32490
+ batchSpent = Math.max(batchSpent, state.spent);
32491
+ args.onBudgetUpdate?.(state);
32492
+ }
32493
+ }, batches[i], sliceMs, abortController.signal);
32351
32494
  result.verified += counts.verified;
32352
32495
  result.updated += counts.updated;
32353
32496
  result.archived += counts.archived;
@@ -32357,6 +32500,10 @@ async function runVerifyWithCooldown(args) {
32357
32500
  result.remaining -= batchProcessed;
32358
32501
  result.batches += 1;
32359
32502
  args.onProgress?.(result.verified + result.updated + result.archived + result.skipped + result.refused, result.refused);
32503
+ if (counts.tokenLimited) {
32504
+ result.stopReason = "token-budget";
32505
+ break;
32506
+ }
32360
32507
  if (counts.timedOut) {
32361
32508
  result.stopReason = "batch-timeout";
32362
32509
  log2(`[dreamer] ${args.forceBroad ? "verify-broad" : "verify"}: batch ${i + 1}/${batches.length} timed out after its ${sliceMs}ms slice; stopping with ${result.remaining} remaining`);
@@ -32391,18 +32538,41 @@ async function runVerifyWithCooldown(args) {
32391
32538
  }
32392
32539
  }
32393
32540
  async function verifyOneBatch(args, batch, sliceMs, signal) {
32541
+ const batchController = new AbortController;
32542
+ const abort = () => batchController.abort(signal.reason);
32543
+ signal.addEventListener("abort", abort, { once: true });
32544
+ if (signal.aborted)
32545
+ abort();
32546
+ const timer = setTimeout(() => batchController.abort(new Error(`verify slice timed out after ${sliceMs}ms`)), sliceMs);
32547
+ const batchSignal = batchController.signal;
32548
+ const tokenBudget = verifyBatchTokenBudget(batch.length, args.tokenBudget);
32394
32549
  let agentSessionId = null;
32550
+ let hiddenSessionId = null;
32395
32551
  let promptSettled = false;
32396
32552
  const startedAt = Date.now();
32397
32553
  let budgetFinalized = false;
32554
+ let failedCompletion;
32555
+ let headAtPrompt = null;
32398
32556
  const onBudgetUpdate = (state) => {
32399
32557
  budgetFinalized ||= state.finalizeFired;
32400
- args.onBudgetUpdate?.(state);
32558
+ args.onBudgetUpdate?.({
32559
+ ...state,
32560
+ ...hiddenSessionId ? { sessionId: hiddenSessionId } : {}
32561
+ });
32562
+ };
32563
+ const reportUsage = (messages, sessionId, fallbackSpent = 0) => {
32564
+ const usage = sumTokensFromChildMessages(messages);
32565
+ onBudgetUpdate({
32566
+ spent: Math.max(fallbackSpent, usage.input + usage.cacheRead + usage.cacheWrite),
32567
+ finalizeFired: budgetFinalized,
32568
+ ...sessionId ? { sessionId } : {}
32569
+ });
32401
32570
  };
32402
32571
  try {
32403
- const headAtPrompt = await readGitHead(args.sessionDirectory);
32404
- const evidence = !args.forceBroad && batch.every((m) => m.verifiedAt) ? await buildVerifyDiffEvidence(args.sessionDirectory, batch) : null;
32405
- const prompt = buildVerifyPrompt(args.projectIdentity, batch, evidence);
32572
+ headAtPrompt = await raceWithSignal(readGitHead(args.sessionDirectory), batchSignal);
32573
+ const evidence = !args.forceBroad && batch.every((m) => m.verifiedAt) ? await raceWithSignal(buildVerifyDiffEvidence(args.sessionDirectory, batch), batchSignal) : null;
32574
+ const prompt = buildVerifyPrompt(args.projectIdentity, await raceWithSignal(seedVerifyCandidates(batch, args.sessionDirectory), batchSignal), evidence);
32575
+ batchSignal.throwIfAborted();
32406
32576
  if (args.hiddenCompletionExecutor) {
32407
32577
  const run = await runHiddenSingleShotPrompt({
32408
32578
  executor: args.hiddenCompletionExecutor,
@@ -32413,41 +32583,53 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
32413
32583
  prompt,
32414
32584
  title: "magic-context-dream-verify",
32415
32585
  callContext: "dreamer:verify",
32416
- metadata: { tokenBudget: args.tokenBudget, onBudgetUpdate },
32586
+ metadata: { tokenBudget, onBudgetUpdate },
32417
32587
  model: args.model,
32418
32588
  fallbackModels: args.fallbackModels,
32419
32589
  language: args.language,
32420
32590
  timeoutMs: sliceMs,
32421
- signal,
32591
+ signal: batchSignal,
32592
+ onFailureOutput: (completion) => {
32593
+ failedCompletion = completion;
32594
+ },
32595
+ onOpened: (sessionId) => {
32596
+ hiddenSessionId = sessionId;
32597
+ onBudgetUpdate({ spent: 0, finalizeFired: false, sessionId });
32598
+ },
32422
32599
  parse: (text, completion) => {
32423
32600
  const providerFailure = providerOutputFailureFromInvalidManifest(completion.messages ?? [], text);
32424
32601
  if (providerFailure)
32425
32602
  throw providerFailure;
32426
- return validateVerifyManifest(text, new Set(batch.map((memory) => memory.id)));
32603
+ const manifest = verifyAssistantText(completion.messages ?? []) ?? (text.trim() ? text : null);
32604
+ if (!manifest)
32605
+ throw new Error("verify returned no output");
32606
+ return validateVerifyManifest(manifest, new Set(batch.map((memory) => memory.id)));
32427
32607
  }
32428
32608
  });
32429
32609
  recordInvocation4(args, startedAt, {
32430
32610
  status: "completed",
32431
32611
  messages: run.completion.messages ?? []
32432
32612
  });
32433
- return applyParsedVerifyManifest(args, batch, run.validated, evidence?.head ?? headAtPrompt, budgetFinalized);
32613
+ reportUsage(run.completion.messages ?? [], run.childSessionId, run.completion.usage.input + (run.completion.usage.cacheRead ?? 0) + (run.completion.usage.cacheWrite ?? 0));
32614
+ return await applyParsedVerifyManifest(args, batch, run.validated, evidence?.head ?? headAtPrompt, budgetFinalized);
32434
32615
  }
32435
32616
  const client = args.client;
32436
32617
  if (!client)
32437
32618
  throw new Error("verify requires a client or hidden completion executor");
32438
- const createResponse = await createChildSessionWithFence({
32619
+ const createResponse = await raceWithSignal(createChildSessionWithFence({
32439
32620
  client,
32440
32621
  db: args.db,
32441
32622
  parentSessionId: args.parentSessionId,
32442
32623
  title: args.forceBroad ? "magic-context-dream-verify-broad" : "magic-context-dream-verify",
32443
32624
  directory: args.sessionDirectory
32444
- });
32625
+ }), batchSignal);
32445
32626
  const created = normalizeSDKResponse(createResponse, null, {
32446
32627
  preferResponseOnMissingData: true
32447
32628
  });
32448
32629
  agentSessionId = typeof created?.id === "string" ? created.id : null;
32449
32630
  if (!agentSessionId)
32450
32631
  throw new Error("Could not create verify session.");
32632
+ onBudgetUpdate({ spent: 0, finalizeFired: false, sessionId: agentSessionId });
32451
32633
  const run = await promptSyncWithValidatedOutputRetry(client, {
32452
32634
  path: { id: agentSessionId },
32453
32635
  query: { directory: args.sessionDirectory },
@@ -32459,11 +32641,11 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
32459
32641
  }
32460
32642
  }, {
32461
32643
  transport: createPromptAsyncTransport(client, agentSessionId, {
32462
- tokenBudget: args.tokenBudget,
32644
+ tokenBudget,
32463
32645
  onBudgetUpdate
32464
32646
  }),
32465
32647
  timeoutMs: sliceMs,
32466
- signal,
32648
+ signal: batchSignal,
32467
32649
  fallbackModels: args.fallbackModels,
32468
32650
  callContext: "dreamer:verify",
32469
32651
  fetchOutput: async () => {
@@ -32479,7 +32661,7 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
32479
32661
  if (hasLengthCappedOutput(messages)) {
32480
32662
  throw new Error("verify returned length-capped output");
32481
32663
  }
32482
- const text = extractLatestAssistantText(messages);
32664
+ const text = verifyAssistantText(messages);
32483
32665
  if (!text)
32484
32666
  throw new Error("verify returned no output");
32485
32667
  const providerFailure = providerOutputFailureFromInvalidManifest(messages, text);
@@ -32490,27 +32672,31 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
32490
32672
  });
32491
32673
  promptSettled = true;
32492
32674
  recordInvocation4(args, startedAt, { status: "completed", messages: run.output });
32675
+ reportUsage(run.output, agentSessionId);
32493
32676
  return await applyParsedVerifyManifest(args, batch, run.validated, evidence?.head ?? headAtPrompt, budgetFinalized);
32494
32677
  } catch (error) {
32495
32678
  const desc = describeError(error);
32496
32679
  const providerFailure = error instanceof DreamerProviderOutputFailureError ? error : undefined;
32497
32680
  const promptFailure = getPromptFailureDetail(error);
32498
32681
  log2(`[dreamer] verify batch ${providerFailure ? "provider failure" : "failed"}: ${desc.brief}`, desc.stackHead ? { stackHead: desc.stackHead } : undefined);
32682
+ const messages = failedCompletion?.messages ?? await readFailedChildMessages(args.client, agentSessionId, args.sessionDirectory) ?? [];
32683
+ reportUsage(messages, hiddenSessionId ?? agentSessionId, failedCompletion?.usage.input ?? 0);
32499
32684
  recordInvocation4(args, startedAt, {
32500
32685
  status: failedInvocationStatus(error),
32501
32686
  error,
32502
- messages: await readFailedChildMessages(args.client, agentSessionId, args.sessionDirectory)
32687
+ messages
32503
32688
  });
32504
- if (error instanceof DreamerModuleFailureError || error instanceof DreamTokenBudgetExceeded || signal.aborted)
32689
+ if (error instanceof DreamerModuleFailureError || signal.aborted)
32505
32690
  throw error;
32506
- if (promptFailure?.failureClass === "provider_timeout" || isPromptTimeoutError(error)) {
32691
+ const interrupted = batchSignal.aborted || error instanceof DreamTokenBudgetExceeded || promptFailure?.failureClass === "provider_timeout" || isPromptTimeoutError(error);
32692
+ if (interrupted) {
32693
+ const text = verifyAssistantText(messages) ?? failedCompletion?.text ?? "";
32694
+ const recovered = parsePartialVerifyManifest(text, new Set(batch.map((m) => m.id)));
32695
+ const counts = await applyParsedVerifyManifest(args, batch, recovered, headAtPrompt, true);
32507
32696
  return {
32508
- verified: 0,
32509
- updated: 0,
32510
- archived: 0,
32511
- skipped: 0,
32512
- refused: 0,
32513
- timedOut: true
32697
+ ...counts,
32698
+ timedOut: !(error instanceof DreamTokenBudgetExceeded),
32699
+ tokenLimited: error instanceof DreamTokenBudgetExceeded
32514
32700
  };
32515
32701
  }
32516
32702
  if (promptFailure !== null && promptFailure.failureClass !== "parse_failed" && !providerFailure)
@@ -32525,7 +32711,7 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
32525
32711
  };
32526
32712
  } finally {
32527
32713
  if (agentSessionId && args.client)
32528
- await teardownChildSession({
32714
+ await raceWithSignal(teardownChildSession({
32529
32715
  client: args.client,
32530
32716
  sessionId: agentSessionId,
32531
32717
  sessionDirectory: args.sessionDirectory,
@@ -32533,7 +32719,9 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
32533
32719
  privacySensitive: true,
32534
32720
  context: "[dreamer] verify",
32535
32721
  log: log2
32536
- });
32722
+ }), batchSignal).catch(() => {});
32723
+ clearTimeout(timer);
32724
+ signal.removeEventListener("abort", abort);
32537
32725
  }
32538
32726
  }
32539
32727
  async function applyParsedVerifyManifest(args, batch, parsed, headAtPrompt, budgetFinalized = false) {
@@ -32560,7 +32748,7 @@ async function applyParsedVerifyManifest(args, batch, parsed, headAtPrompt, budg
32560
32748
  throw new Error(`verify manifest covers ${validIds.length}/${batch.length} batch ids after filtering unknown entries; rejecting mostly-wrong manifest`);
32561
32749
  }
32562
32750
  if (budgetFinalized && validIds.length < batch.length) {
32563
- log2(`[dreamer] verify: accepted partial manifest after token budget: ${validIds.length}/${batch.length}`);
32751
+ log2(`[dreamer] verify: accepted partial manifest after investigation stop: ${validIds.length}/${batch.length}`);
32564
32752
  }
32565
32753
  if (validIds.length === 0) {
32566
32754
  return { verified: 0, updated: 0, archived: 0, skipped: 0, refused: 0 };
@@ -32795,10 +32983,10 @@ function dreamRunFailureDetail(error) {
32795
32983
  child_session_id: null
32796
32984
  };
32797
32985
  }
32798
- const localRefusal = error instanceof HiddenCompletionRefusal;
32986
+ const localRefusal = error instanceof HiddenCompletionRefusal || error instanceof DreamerModuleFailureError;
32799
32987
  const providerFailure = error instanceof Error && error.name === "DreamerProviderOutputFailureError";
32800
32988
  return {
32801
- failure_class: localRefusal ? "local_refusal" : providerFailure ? "provider_error" : /no models?|model chain is empty/i.test(message) ? "no_models" : "unknown",
32989
+ failure_class: localRefusal ? "local_refusal" : providerFailure ? "provider_error" : /lease_(?:lost|expired)|Dream lease (?:lost|unavailable)/i.test(message) ? "child_aborted" : /no models?|model chain is empty/i.test(message) ? "no_models" : "unknown",
32802
32990
  model_attempted: null,
32803
32991
  models_tried: [],
32804
32992
  provider_error: providerFailure ? sanitizeDiagnosticText(message).slice(0, 500) : null,
@@ -32809,6 +32997,10 @@ function dreamRunFailureDetail(error) {
32809
32997
  } : {}
32810
32998
  };
32811
32999
  }
33000
+ function incompleteFailure(error, fallback = "parse_failed") {
33001
+ const detail = dreamRunFailureDetail(error);
33002
+ return detail.failure_class === "unknown" ? { ...detail, failure_class: fallback } : detail;
33003
+ }
32812
33004
  function classifyFailure(error) {
32813
33005
  const described = describeError(error);
32814
33006
  const brief = described.brief;
@@ -32968,6 +33160,7 @@ function createDreamTaskExecutor(deps) {
32968
33160
  const { db, projectIdentity, holderId, leaseKey } = ctx;
32969
33161
  deps.client?.resetDreamTokenBudget?.(config.task);
32970
33162
  const startedAt = Date.now();
33163
+ const effectiveTokenBudget = config.task === "verify" || config.task === "verify-broad" ? Math.min(config.tokenBudget ?? VERIFY_RUN_TOKEN_BUDGET, VERIFY_RUN_TOKEN_BUDGET) : config.tokenBudget;
32971
33164
  const leaseAcquisition = ctx.leaseAcquisition ?? acquireLeaseWithAcquisition(db, holderId, leaseKey) ?? (() => {
32972
33165
  throw new Error("Dream lease unavailable during executor setup");
32973
33166
  })();
@@ -33015,7 +33208,7 @@ function createDreamTaskExecutor(deps) {
33015
33208
  if (state.sessionId) {
33016
33209
  const previous = childSpending.get(state.sessionId) ?? 0;
33017
33210
  budgetSpent += Math.max(0, state.spent - previous);
33018
- childSpending.set(state.sessionId, state.spent);
33211
+ childSpending.set(state.sessionId, Math.max(previous, state.spent));
33019
33212
  } else
33020
33213
  budgetSpent = Math.max(budgetSpent, state.spent);
33021
33214
  budgetFinalized ||= state.finalizeFired;
@@ -33042,9 +33235,15 @@ function createDreamTaskExecutor(deps) {
33042
33235
  failure: extra?.failure ?? dreamRunFailureDetail(error ?? "unknown dreamer failure")
33043
33236
  } : {},
33044
33237
  ...extra?.progress ? { progress: extra.progress } : {},
33045
- ...config.tokenBudget ? {
33238
+ ...childSpending.size ? {
33239
+ children: [...childSpending].map(([sessionId, promptTokens]) => ({
33240
+ sessionId,
33241
+ promptTokens
33242
+ }))
33243
+ } : {},
33244
+ ...effectiveTokenBudget ? {
33046
33245
  tokenBudget: {
33047
- budget: config.tokenBudget,
33246
+ budget: effectiveTokenBudget,
33048
33247
  spent: budgetSpent,
33049
33248
  finalizeFired: budgetFinalized,
33050
33249
  banked: extra?.banked ?? processedDreamTaskItems(backlogAtStart.pending, (extra?.backlogAfter ?? getDreamTaskBacklog(db, projectIdentity, config.task)).pending)
@@ -33133,8 +33332,13 @@ function createDreamTaskExecutor(deps) {
33133
33332
  });
33134
33333
  log2(`[dreamer] compress-cues: compressed=${result.compressed} skipped=${result.skipped} chunks=${result.chunks} remaining=${result.remaining}`);
33135
33334
  if (!result.complete) {
33136
- const error = incompleteMessage(result.remaining);
33137
- recordRun("failed", error);
33335
+ if (result.stopReason === "deadline" && result.chunks === 0)
33336
+ return skip("compress-cues: insufficient time to start a chunk");
33337
+ const error = `${incompleteMessage(result.remaining)}; ${result.failureStage ? `${result.failureStage}: ` : ""}${result.failure ? describeError(result.failure).brief : `${result.skipped} cues rejected by validation`}`;
33338
+ recordRun("failed", error, {
33339
+ banked: result.compressed,
33340
+ failure: incompleteFailure(result.failure, result.failureStage === "child-start" ? "local_refusal" : result.stopReason === "timeout-circuit-breaker" ? "provider_timeout" : "parse_failed")
33341
+ });
33138
33342
  return { status: "failed", transient: true, error };
33139
33343
  }
33140
33344
  recordRun("completed", null);
@@ -33180,9 +33384,15 @@ function createDreamTaskExecutor(deps) {
33180
33384
  });
33181
33385
  log2(`[dreamer] map-memories: committed=${result.mapped + result.independent} mapped=${result.mapped} independent=${result.independent} batches=${result.batches} remaining=${result.remaining} complete=${result.complete}${result.stopReason ? ` stop_reason=${result.stopReason}` : ""}`);
33182
33386
  if (!result.complete) {
33387
+ if (result.deferred)
33388
+ return skip("map-memories: all pending mappings are in content-keyed retry backoff; no child started");
33389
+ if (result.stopReason === "deadline" && result.batches === 0 && !result.failure)
33390
+ return skip("map-memories: insufficient time to start a batch");
33183
33391
  if (result.stopReason === "timeout-circuit-breaker") {
33184
33392
  const error = `map-memories starvation: timeout circuit breaker stopped the run with ${result.remaining} remain`;
33185
- recordRun("failed", error);
33393
+ recordRun("failed", error, {
33394
+ failure: incompleteFailure(result.failure, "provider_timeout")
33395
+ });
33186
33396
  return { status: "failed", transient: true, error };
33187
33397
  }
33188
33398
  const processed = result.mapped + result.independent;
@@ -33191,8 +33401,10 @@ function createDreamTaskExecutor(deps) {
33191
33401
  recordRun("completed", null, { progress });
33192
33402
  return { status: "completed" };
33193
33403
  }
33194
- const error = incompleteMessage(result.remaining);
33195
- recordRun("failed", error);
33404
+ const error = `${incompleteMessage(result.remaining)}; ${result.failureStage ? `${result.failureStage}: ` : ""}${result.failure ? describeError(result.failure).brief : "manifest returned no accepted mapping decisions"}`;
33405
+ recordRun("failed", error, {
33406
+ failure: incompleteFailure(result.failure, result.failureStage === "child-start" ? "local_refusal" : "parse_failed")
33407
+ });
33196
33408
  return { status: "failed", transient: true, error };
33197
33409
  }
33198
33410
  recordRun("completed", null);
@@ -33222,25 +33434,27 @@ function createDreamTaskExecutor(deps) {
33222
33434
  });
33223
33435
  const processed = result.verified + result.updated + result.archived + result.skipped + result.refused;
33224
33436
  const verificationProgress = `${config.task}${config.task === "verify-broad" ? ` cycle ${result.broadCycleStartAt ?? "open"}` : ""}: processed ${processed} (verified ${result.verified}, updated ${result.updated}, archived ${result.archived}, skipped ${result.skipped}, refused ${result.refused}); ${result.remaining} remain`;
33225
- const broadProgress = config.task === "verify-broad" ? verificationProgress : null;
33226
33437
  const backlogAfter = config.task === "verify-broad" ? { pending: result.remaining, total: backlogAtStart.total } : undefined;
33227
33438
  if (!result.complete) {
33228
- if (broadProgress && processed > 0) {
33439
+ if (processed > 0) {
33229
33440
  recordRun("completed", null, {
33230
- progress: broadProgress,
33441
+ progress: verificationProgress,
33231
33442
  memoryChanges: computeMemoryDelta(memoryBefore),
33232
33443
  backlogAfter,
33233
33444
  banked: result.verified + result.updated + result.archived
33234
33445
  });
33235
33446
  return { status: "completed" };
33236
33447
  }
33448
+ if (result.stopReason === "deadline")
33449
+ return skip(`${config.task}: insufficient time to start a batch`);
33237
33450
  const batchTimedOut = result.stopReason === "batch-timeout";
33238
33451
  const error = batchTimedOut ? `${config.task}: a batch timed out within its time slice; ${result.remaining} remain` : incompleteMessage(result.remaining);
33239
33452
  recordRun("failed", error, {
33240
33453
  progress: verificationProgress,
33241
33454
  memoryChanges: computeMemoryDelta(memoryBefore),
33242
33455
  backlogAfter,
33243
- banked: result.verified + result.updated + result.archived
33456
+ banked: result.verified + result.updated + result.archived,
33457
+ failure: incompleteFailure(error, batchTimedOut ? "provider_timeout" : result.stopReason === "token-budget" ? "token_budget" : "parse_failed")
33244
33458
  });
33245
33459
  return { status: "failed", transient: !batchTimedOut, error };
33246
33460
  }
@@ -33364,6 +33578,7 @@ function createDreamTaskExecutor(deps) {
33364
33578
  if (retro.skipReason)
33365
33579
  return skip(retro.skipReason);
33366
33580
  recordRun("completed", null, {
33581
+ progress: retro.noOpReason,
33367
33582
  memoryChanges: computeMemoryDelta(memoryBefore),
33368
33583
  backlogAfter: retro.retrospectiveWatermarkMs == null ? undefined : getDreamTaskBacklog(db, projectIdentity, "retrospective", {
33369
33584
  retrospectiveWatermarkMs: retro.retrospectiveWatermarkMs
@@ -33371,6 +33586,7 @@ function createDreamTaskExecutor(deps) {
33371
33586
  });
33372
33587
  return {
33373
33588
  status: "completed",
33589
+ ...retro.noOpReason ? { detail: retro.noOpReason } : {},
33374
33590
  schedulePatch: retro.retrospectiveWatermarkMs != null || retro.taskStateJson !== undefined ? {
33375
33591
  ...retro.retrospectiveWatermarkMs != null ? {
33376
33592
  retrospectiveWatermarkMs: retro.retrospectiveWatermarkMs
@@ -33570,20 +33786,28 @@ async function runRetrospectiveTask(config, ctx, helpers) {
33570
33786
  const recencyCutoffMs = helpers.invocationStartedAt - recencyDays * RETROSPECTIVE_DAY_MS;
33571
33787
  const scan = await readRetrospectiveScanWindow(provider, projectIdentity, watermarkMs, RETROSPECTIVE_OVERLAP_USER_LINES, { usableInputTokens, recencyCutoffMs });
33572
33788
  const clearedTaskStateJson = activeOverflow ? writeRetrospectiveOverflowState(taskState.root, null) : undefined;
33573
- const completedWindow = (retrospectiveWatermarkMs) => ({
33789
+ const completedWindow = (retrospectiveWatermarkMs, noOpReason) => ({
33574
33790
  retrospectiveWatermarkMs,
33575
- ...clearedTaskStateJson ? { taskStateJson: clearedTaskStateJson } : {}
33791
+ ...clearedTaskStateJson ? { taskStateJson: clearedTaskStateJson } : {},
33792
+ ...noOpReason ? { noOpReason } : {}
33576
33793
  });
33577
33794
  const messages = withGlobalOrdinals(scan.messages);
33578
33795
  const userMessages = messages.filter((message) => message.role === "user" && message.text.trim().length > 0);
33579
33796
  if (userMessages.length === 0) {
33580
- log2("[dreamer] retrospective: no user messages in window");
33581
- return completedWindow(scan.maxScannedTs);
33797
+ const noOpReason = "no reply-following user lines";
33798
+ log2(`[dreamer] retrospective: ${noOpReason}`);
33799
+ return completedWindow(scan.maxScannedTs, noOpReason);
33582
33800
  }
33583
- const postWatermarkOrdinals = new Set(userMessages.filter((message) => message.ts > watermarkMs).map((message) => message.ordinal));
33584
- if (postWatermarkOrdinals.size === 0) {
33801
+ const newUserOrdinals = new Set(userMessages.filter((message) => message.ts > watermarkMs).map((message) => message.ordinal));
33802
+ if (newUserOrdinals.size === 0) {
33585
33803
  log2("[dreamer] retrospective: only overlap lines, nothing new");
33586
- return completedWindow(scan.maxScannedTs);
33804
+ return completedWindow(scan.maxScannedTs, "only overlap lines, nothing new");
33805
+ }
33806
+ const postWatermarkOrdinals = new Set(userMessages.filter((message) => message.ts > watermarkMs && message.followsAssistantReply === true).map((message) => message.ordinal));
33807
+ if (postWatermarkOrdinals.size === 0) {
33808
+ const noOpReason = "no reply-following user lines";
33809
+ log2(`[dreamer] retrospective: ${noOpReason}`);
33810
+ return completedWindow(scan.maxScannedTs, noOpReason);
33587
33811
  }
33588
33812
  const abortController = new AbortController;
33589
33813
  let leaseLost = false;
@@ -34537,7 +34761,8 @@ class V2RetrospectiveRawProvider {
34537
34761
  ordinal: row.seq,
34538
34762
  role: "user",
34539
34763
  text: cleanUserText2(row.text),
34540
- ts: row.time_created
34764
+ ts: row.time_created,
34765
+ ...row.follows_assistant_reply === 1 ? { followsAssistantReply: true } : {}
34541
34766
  }));
34542
34767
  }
34543
34768
  readUserMessagesSince(sessionId, sinceMs, capPerSession) {
@@ -50533,6 +50758,85 @@ function bindV2TransformDecision(args) {
50533
50758
  }
50534
50759
  }
50535
50760
 
50761
+ // src/hooks/magic-context/auto-embed-session.ts
50762
+ function embeddingIdentity(projectIdentity) {
50763
+ const snapshot = getProjectEmbeddingSnapshot2(projectIdentity);
50764
+ return JSON.stringify([
50765
+ projectIdentity,
50766
+ snapshot?.providerIdentity,
50767
+ snapshot?.chunkModelId,
50768
+ snapshot?.runtimeFingerprint
50769
+ ]);
50770
+ }
50771
+ function maybeAutoEmbedSessionBackfill(deps, sessionId) {
50772
+ const markActive = () => activeEmbeddingSessions.set(sessionId, {
50773
+ project: deps.projectIdentity,
50774
+ model: getProjectEmbeddingSnapshot2(deps.projectIdentity)?.chunkModelId ?? "off"
50775
+ });
50776
+ markActive();
50777
+ const identity = embeddingIdentity(deps.projectIdentity);
50778
+ if (autoEmbedIdentityBySession.get(sessionId) !== identity) {
50779
+ invalidateAutoEmbedSession(sessionId);
50780
+ autoEmbedIdentityBySession.set(sessionId, identity);
50781
+ }
50782
+ if (autoEmbedAttemptedBySession.has(sessionId) || embedPauseBySession.has(sessionId) || embedRunStateBySession.has(sessionId) || Date.now() < (autoEmbedRetryAfterBySession.get(sessionId) ?? 0))
50783
+ return;
50784
+ const controller = new AbortController;
50785
+ embedRunStateBySession.set(sessionId, controller);
50786
+ (async () => {
50787
+ let complete = false;
50788
+ let retryDelay = 1000;
50789
+ let started = false;
50790
+ let reason = "error";
50791
+ let registeredIdentity = identity;
50792
+ try {
50793
+ await new Promise((resolve) => setTimeout(resolve, 0));
50794
+ if (controller.signal.aborted)
50795
+ return;
50796
+ await deps.ensureRegistered();
50797
+ if (controller.signal.aborted)
50798
+ return;
50799
+ markActive();
50800
+ registeredIdentity = embeddingIdentity(deps.projectIdentity);
50801
+ autoEmbedIdentityBySession.set(sessionId, registeredIdentity);
50802
+ const coverage = await getAutoEmbeddingSessionCoverage2(deps.db, deps.projectIdentity, sessionId);
50803
+ if (controller.signal.aborted || !coverage.enabled)
50804
+ return;
50805
+ if (coverage.embedded === coverage.total) {
50806
+ complete = true;
50807
+ return;
50808
+ }
50809
+ const model = getProjectEmbeddingSnapshot2(deps.projectIdentity)?.model;
50810
+ log2(`[magic-context] session backfill start session=${sessionId} missing=${coverage.total - coverage.embedded} model=${model}`);
50811
+ started = true;
50812
+ const outcome = await embedSessionCompartmentChunks2(deps.db, deps.projectIdentity, sessionId, { signal: controller.signal, automatic: true });
50813
+ reason = outcome.status;
50814
+ const after = await getAutoEmbeddingSessionCoverage2(deps.db, deps.projectIdentity, sessionId);
50815
+ complete = after.enabled && after.embedded === after.total;
50816
+ if (!complete && outcome.status !== "busy" && outcome.status !== "aborted") {
50817
+ retryDelay = 60000;
50818
+ if (outcome.status === "nothing" || outcome.status === "done")
50819
+ reason = "deferred";
50820
+ }
50821
+ } catch (error) {
50822
+ log2("[magic-context] auto-embed drain failed:", error);
50823
+ retryDelay = 60000;
50824
+ } finally {
50825
+ if (started)
50826
+ log2(`[magic-context] session backfill ${complete ? "complete" : "stop"} session=${sessionId} reason=${reason}`);
50827
+ if (embedRunStateBySession.get(sessionId) === controller) {
50828
+ embedRunStateBySession.delete(sessionId);
50829
+ }
50830
+ if (!controller.signal.aborted && autoEmbedIdentityBySession.get(sessionId) === registeredIdentity && embeddingIdentity(deps.projectIdentity) === registeredIdentity) {
50831
+ if (complete)
50832
+ autoEmbedAttemptedBySession.add(sessionId);
50833
+ else
50834
+ autoEmbedRetryAfterBySession.set(sessionId, Date.now() + retryDelay);
50835
+ }
50836
+ }
50837
+ })();
50838
+ }
50839
+
50536
50840
  // src/v2/hooks/transform-features.ts
50537
50841
  function createV2TransformFeatureDeps(config, compactionOff, directory) {
50538
50842
  return {
@@ -50568,47 +50872,18 @@ function createV2TransformFeatureDeps(config, compactionOff, directory) {
50568
50872
  }
50569
50873
  function createV2AutoEmbedSession(deps) {
50570
50874
  return (sessionId) => {
50571
- if (isEmbeddingHostBusy2())
50572
- return;
50573
50875
  const directory = deps.resolveDirectory(sessionId);
50574
- const identity = resolveProjectIdentityForSession(directory, deps.allowHomeProject);
50575
- const snapshot = identity ? getProjectEmbeddingSnapshot2(identity) : undefined;
50576
- const embedIdentity = snapshot ? JSON.stringify([
50577
- snapshot.providerIdentity,
50578
- snapshot.chunkModelId,
50579
- snapshot.runtimeFingerprint
50580
- ]) : "off";
50581
- if (autoEmbedIdentityBySession.get(sessionId) !== embedIdentity)
50582
- invalidateAutoEmbedSession(sessionId);
50583
- if (autoEmbedAttemptedBySession.has(sessionId) || embedPauseBySession.has(sessionId))
50876
+ const projectIdentity = resolveProjectIdentityForSession(directory, deps.allowHomeProject);
50877
+ if (!projectIdentity)
50584
50878
  return;
50585
- autoEmbedAttemptedBySession.add(sessionId);
50586
- autoEmbedIdentityBySession.set(sessionId, embedIdentity);
50587
- (async () => {
50588
- try {
50589
- await new Promise((resolve) => setTimeout(resolve, 0));
50590
- if (isEmbeddingHostBusy2()) {
50591
- invalidateAutoEmbedSession(sessionId);
50592
- return;
50593
- }
50879
+ maybeAutoEmbedSessionBackfill({
50880
+ db: deps.db,
50881
+ projectIdentity,
50882
+ ensureRegistered: async () => {
50594
50883
  await ensureProjectRegisteredFromOpenCodeDirectory(directory, deps.db);
50595
- const project = resolveProjectIdentityForSession(directory, deps.allowHomeProject);
50596
- if (!project) {
50597
- invalidateAutoEmbedSession(sessionId);
50598
- return;
50599
- }
50600
- const coverage = await getAutoEmbeddingSessionCoverage2(deps.db, project, sessionId);
50601
- if (!coverage.enabled) {
50602
- invalidateAutoEmbedSession(sessionId);
50603
- return;
50604
- }
50605
- if (coverage.total <= coverage.embedded)
50606
- return;
50607
- await runEmbedHistoryDrain(deps, sessionId, { silent: true });
50608
- } catch (error) {
50609
- log2("[magic-context] auto-embed drain failed:", error);
50884
+ deps.onDirectoryResolved?.(sessionId, directory);
50610
50885
  }
50611
- })();
50886
+ }, sessionId);
50612
50887
  };
50613
50888
  }
50614
50889