@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
@@ -79,25 +79,8 @@ import {
79
79
  renewGitSweepLease,
80
80
  markGitSweepSuccessAndRelease,
81
81
  parkGitSweepNonIndexable,
82
- releaseGitSweepLease,
83
- describeShadowBackfillWriteRefusal2,
84
- markProjectLoadUntrusted2,
85
- drainProjectEmbeddingIdentityMaintenance2,
86
- drainStaleEmbeddingIdentitiesForProject2,
87
- registerProjectEmbedding2,
88
- registerProjectShadowEmbedding2,
89
- enqueueShadowEmbeddingItems2,
90
- registerProjectInObservationMode2,
91
- unregisterProjectShadowEmbedding2,
92
- getProjectEmbeddingSnapshot2,
93
- embedTextForProject2,
94
- embedBatchForProject2,
95
- embedUnembeddedMemoriesForProject2,
96
- embedUnembeddedMemoriesForProjectOutcome2,
97
- drainCommitBacklogForProject2,
98
- embedSessionCompartmentChunks2,
99
- getEmbeddingCoverageStatus2
100
- } from "./index-7zd5asz9.js";
82
+ releaseGitSweepLease
83
+ } from "./index-saews2s3.js";
101
84
  import {
102
85
  hasTrustedAbsoluteWall,
103
86
  applyProvenInputFloor,
@@ -109,7 +92,7 @@ import {
109
92
  deriveTriggerBudget2,
110
93
  resolveKnownHistorianContextLimit2,
111
94
  resolveHistorianProducerLimits2
112
- } from "./index-8ketfacn.js";
95
+ } from "./index-v10f1rjv.js";
113
96
  import {
114
97
  resolveModelCalibration,
115
98
  calibrateBuckets,
@@ -330,7 +313,7 @@ import {
330
313
  runSqliteOptimize,
331
314
  openDatabase,
332
315
  openCurrentDatabase
333
- } from "./index-x2xjyq8f.js";
316
+ } from "./index-qkd9zz0p.js";
334
317
  import {
335
318
  registerOwnRpcServerInstance,
336
319
  rpcPortDir,
@@ -349,7 +332,7 @@ import {
349
332
  resolveStoredPathWorkspaceIdentity,
350
333
  storedPathBelongsToWorkspace,
351
334
  computeWorkspaceEpochFingerprint
352
- } from "./index-tdn0zkw4.js";
335
+ } from "./index-wk0n1cgt.js";
353
336
  import {
354
337
  V2_MEMORY_CATEGORIES,
355
338
  CATEGORY_PRIORITY
@@ -374,10 +357,6 @@ import {
374
357
  DREAMER_CLASSIFIER_AGENT,
375
358
  DREAMER_DOCS_AGENT,
376
359
  DREAMER_REVIEWER_AGENT,
377
- embedPauseBySession,
378
- embedRunStateBySession,
379
- invalidateAutoEmbedSession,
380
- getEmbedDrainUiStatus,
381
360
  getCompartments,
382
361
  getLastCompartmentEndMessage,
383
362
  getLastCompartmentEndMessageId,
@@ -453,9 +432,11 @@ import {
453
432
  toModelEntry,
454
433
  isPromptTimeoutError,
455
434
  getPromptFailureDetail,
435
+ raceWithSignal,
456
436
  promptSyncWithValidatedOutputRetry,
457
437
  normalizeSDKResponse,
458
438
  failedInvocationStatus,
439
+ sumTokensFromChildMessages,
459
440
  recordChildInvocation,
460
441
  createPromptAsyncTransport,
461
442
  systemPromptFingerprint,
@@ -522,7 +503,35 @@ import {
522
503
  snapRangeToCompartments,
523
504
  getActiveCompartmentRun,
524
505
  startCompartmentAgent
525
- } from "./index-yx5kgp2x.js";
506
+ } from "./index-2jr1smmh.js";
507
+ import {
508
+ embedPauseBySession,
509
+ embedRunStateBySession,
510
+ activeEmbeddingSessions,
511
+ autoEmbedAttemptedBySession,
512
+ autoEmbedIdentityBySession,
513
+ autoEmbedRetryAfterBySession,
514
+ invalidateAutoEmbedSession,
515
+ getEmbedDrainUiStatus,
516
+ describeShadowBackfillWriteRefusal2,
517
+ markProjectLoadUntrusted2,
518
+ drainProjectEmbeddingIdentityMaintenance2,
519
+ drainStaleEmbeddingIdentitiesForProject2,
520
+ registerProjectEmbedding2,
521
+ registerProjectShadowEmbedding2,
522
+ enqueueShadowEmbeddingItems2,
523
+ registerProjectInObservationMode2,
524
+ unregisterProjectShadowEmbedding2,
525
+ getProjectEmbeddingSnapshot2,
526
+ embedTextForProject2,
527
+ embedBatchForProject2,
528
+ embedUnembeddedMemoriesForProject2,
529
+ embedUnembeddedMemoriesForProjectOutcome2,
530
+ drainCommitBacklogForProject2,
531
+ embedSessionCompartmentChunks2,
532
+ getEmbeddingCoverageStatus2,
533
+ getAutoEmbeddingSessionCoverage2
534
+ } from "./index-y1qysm3q.js";
526
535
  import {
527
536
  SubcClient,
528
537
  connectionFileExists,
@@ -551,7 +560,7 @@ import {
551
560
  indexSingleMessage2,
552
561
  indexMessagesAfterOrdinal2,
553
562
  sweepOrphanedOpenCodeMessageIndexes2
554
- } from "./index-wqs4q74r.js";
563
+ } from "./index-v13skev1.js";
555
564
  import {
556
565
  renderUserFacingFailure,
557
566
  userFacingFailureCode,
@@ -595,7 +604,7 @@ import {
595
604
  readGitFileChangeTimesSince,
596
605
  verificationFileExists,
597
606
  normalizeVerificationFiles
598
- } from "./index-6sz25c3s.js";
607
+ } from "./index-bxdg2nbt.js";
599
608
  import {
600
609
  registerNotificationSink2,
601
610
  pushNotification2,
@@ -605,7 +614,7 @@ import {
605
614
  } from "./index-x8a7jmkh.js";
606
615
  import {
607
616
  getLocalEmbeddingNativeMemoryStats
608
- } from "./index-9vqb5p1s.js";
617
+ } from "./index-e20m7284.js";
609
618
  import {
610
619
  saveEmbeddingIfHashMatches,
611
620
  invalidateProject2,
@@ -613,7 +622,7 @@ import {
613
622
  } from "./index-4dhv7mqz.js";
614
623
  import {
615
624
  cosineSimilarity
616
- } from "./index-fx90bvjd.js";
625
+ } from "./index-3kdm78zp.js";
617
626
  import {
618
627
  computeCueContentHash,
619
628
  hasMuralCueColumns,
@@ -660,17 +669,17 @@ import {
660
669
  resolveMemoriesByIdsForSearch2,
661
670
  unifiedSearch2,
662
671
  formatSearchResults2
663
- } from "./index-6sytd5w3.js";
672
+ } from "./index-aw1bh90w.js";
664
673
  import {
665
674
  flushIgnoredMessages2,
666
675
  clearIgnoredMessages2,
667
676
  observeIgnoredNotificationEvent2,
668
677
  sendStatusNotification2
669
- } from "./index-2pgxcncf.js";
678
+ } from "./index-dgs16axy.js";
670
679
  import {
671
680
  setRecompStarting2,
672
681
  setRecompTerminal2
673
- } from "./index-05n6ykca.js";
682
+ } from "./index-hnm8raee.js";
674
683
  import {
675
684
  makeToolCompositeKey,
676
685
  searchMessageHistoryOffThread,
@@ -721,7 +730,7 @@ import {
721
730
  abortSessionFailClosed2,
722
731
  evaluateEmergencyFailClosed2,
723
732
  runPostTransformPhase2
724
- } from "./index-qtbdx42g.js";
733
+ } from "./index-sj89f3b0.js";
725
734
  import {
726
735
  ANNOUNCEMENT_VERSION2,
727
736
  ANNOUNCEMENT_FEATURES2,
@@ -743,6 +752,11 @@ import {
743
752
  import {
744
753
  computeNormalizedHash
745
754
  } from "./index-2bvekkfy.js";
755
+ import {
756
+ canonicalModelIdentity,
757
+ piModelRefToCanonical,
758
+ modelRefLookupOrder
759
+ } from "./index-avwt563y.js";
746
760
  import {
747
761
  canonicalProjectDirectory
748
762
  } from "./index-knvkbfvh.js";
@@ -750,18 +764,6 @@ import {
750
764
  getErrorMessage,
751
765
  describeError
752
766
  } from "./index-y8v6yerm.js";
753
- import {
754
- shouldEnforcePrivateStoragePermissions,
755
- ensureStorageDirectorySync,
756
- writeStorageFileAtomicSync,
757
- writeStorageFileAsync,
758
- createStorageWriteStream
759
- } from "./index-fvnzcnww.js";
760
- import {
761
- canonicalModelIdentity,
762
- piModelRefToCanonical,
763
- modelRefLookupOrder
764
- } from "./index-avwt563y.js";
765
767
  import {
766
768
  closeQuietly,
767
769
  isKnownAutocommit
@@ -769,6 +771,13 @@ import {
769
771
  import {
770
772
  logSlowWriteTransaction
771
773
  } from "./index-k29z4aqh.js";
774
+ import {
775
+ shouldEnforcePrivateStoragePermissions,
776
+ ensureStorageDirectorySync,
777
+ writeStorageFileAtomicSync,
778
+ writeStorageFileAsync,
779
+ createStorageWriteStream
780
+ } from "./index-fvnzcnww.js";
772
781
 
773
782
  // src/config/dependency-notes.ts
774
783
  function scheduledTasks(config) {
@@ -1984,10 +1993,28 @@ async function readRetrospectiveScanWindow(provider, projectIdentity, watermarkM
1984
1993
  }
1985
1994
  function readOpenCodeMessagesSince(db, sessionId, sinceMs, capPerSession) {
1986
1995
  const limit = Math.max(1, Math.floor(capPerSession));
1987
- const rows = db.prepare(`SELECT id, data, time_created
1988
- FROM message
1989
- WHERE session_id = ? AND time_created > ?
1990
- ORDER BY time_created ASC, id ASC
1996
+ const rows = db.prepare(`SELECT current.id, current.data, current.time_created,
1997
+ EXISTS (
1998
+ SELECT 1 FROM message assistant_reply
1999
+ WHERE assistant_reply.session_id = current.session_id
2000
+ AND json_valid(assistant_reply.data)
2001
+ AND json_extract(assistant_reply.data, '$.role') = 'assistant'
2002
+ AND (assistant_reply.time_created < current.time_created
2003
+ OR (assistant_reply.time_created = current.time_created
2004
+ AND assistant_reply.id < current.id))
2005
+ AND EXISTS (
2006
+ SELECT 1 FROM message prior_user
2007
+ WHERE prior_user.session_id = current.session_id
2008
+ AND json_valid(prior_user.data)
2009
+ AND json_extract(prior_user.data, '$.role') = 'user'
2010
+ AND (prior_user.time_created < assistant_reply.time_created
2011
+ OR (prior_user.time_created = assistant_reply.time_created
2012
+ AND prior_user.id < assistant_reply.id))
2013
+ )
2014
+ ) AS has_prior_assistant_reply
2015
+ FROM message current
2016
+ WHERE current.session_id = ? AND current.time_created > ?
2017
+ ORDER BY current.time_created ASC, current.id ASC
1991
2018
  LIMIT ?`).all(sessionId, sinceMs, limit + 1);
1992
2019
  const truncated = rows.length > limit;
1993
2020
  const kept = truncated ? rows.slice(0, limit) : rows;
@@ -2091,7 +2118,8 @@ function normalizeOpenCodeRows(db, sessionId, rows) {
2091
2118
  ordinal,
2092
2119
  role,
2093
2120
  parts,
2094
- ts: row.time_created
2121
+ ts: row.time_created,
2122
+ followsAssistantReply: row.has_prior_assistant_reply === 1
2095
2123
  });
2096
2124
  });
2097
2125
  }
@@ -2105,7 +2133,8 @@ function normalizeOpenCodeMessage(args) {
2105
2133
  ordinal: args.ordinal,
2106
2134
  role: "user",
2107
2135
  text,
2108
- ts: args.ts
2136
+ ts: args.ts,
2137
+ ...args.followsAssistantReply ? { followsAssistantReply: true } : {}
2109
2138
  });
2110
2139
  }
2111
2140
  }
@@ -2530,9 +2559,12 @@ async function runCompressCues(args) {
2530
2559
  let timeoutStreakElapsedMs = [];
2531
2560
  for (let i = 0;i < chunks.length; i += 1) {
2532
2561
  const remainingMs = Math.max(0, args.deadline - Date.now());
2533
- if (remainingMs <= 0)
2562
+ if (remainingMs <= 0) {
2563
+ result.stopReason = "deadline";
2534
2564
  break;
2565
+ }
2535
2566
  if (remainingMs < CHUNK_TIMEOUT_FLOOR_MS) {
2567
+ result.stopReason = "deadline";
2536
2568
  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)`);
2537
2569
  break;
2538
2570
  }
@@ -2541,6 +2573,10 @@ async function runCompressCues(args) {
2541
2573
  if (!chunk)
2542
2574
  break;
2543
2575
  const outcome = await compressOneChunk(args, chunk, sliceMs, abortController.signal);
2576
+ if (outcome.failure) {
2577
+ result.failure = outcome.failure.error;
2578
+ result.failureStage = outcome.failure.stage;
2579
+ }
2544
2580
  result.compressed += outcome.compressed;
2545
2581
  result.skipped += outcome.skipped;
2546
2582
  result.remaining -= outcome.compressed;
@@ -2550,6 +2586,7 @@ async function runCompressCues(args) {
2550
2586
  consecutiveTimeouts += 1;
2551
2587
  timeoutStreakElapsedMs.push(outcome.failure.elapsedMs);
2552
2588
  if (consecutiveTimeouts >= CONSECUTIVE_TIMEOUT_LIMIT) {
2589
+ result.stopReason = "timeout-circuit-breaker";
2553
2590
  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`);
2554
2591
  break;
2555
2592
  }
@@ -2566,7 +2603,7 @@ async function runCompressCues(args) {
2566
2603
  }
2567
2604
  }
2568
2605
  function isTimeoutClassError(error) {
2569
- return error instanceof Error && /^prompt timed out after \d+ms$/.test(error.message);
2606
+ return isPromptTimeoutError(error) || getPromptFailureDetail(error)?.failureClass === "provider_timeout";
2570
2607
  }
2571
2608
  async function compressOneChunk(args, chunk, sliceMs, signal) {
2572
2609
  let agentSessionId = null;
@@ -2574,6 +2611,7 @@ async function compressOneChunk(args, chunk, sliceMs, signal) {
2574
2611
  const executor = resolveHiddenCompletionExecutor(args.hiddenCompletionExecutor, args.client, args.db, args.sessionDirectory, "compress-cues");
2575
2612
  let promptSettled = false;
2576
2613
  const startedAt = Date.now();
2614
+ let stage = "child-start";
2577
2615
  try {
2578
2616
  const prompt = buildCompressCuesPrompt({
2579
2617
  projectPath: args.projectIdentity,
@@ -2594,6 +2632,7 @@ async function compressOneChunk(args, chunk, sliceMs, signal) {
2594
2632
  agentSessionId = handle.id || null;
2595
2633
  if (!agentSessionId)
2596
2634
  throw new Error("Could not create compress-cues session.");
2635
+ stage = "prompt";
2597
2636
  const opened = handle;
2598
2637
  const run = await promptSyncWithValidatedOutputRetry(args.client, {
2599
2638
  path: { id: agentSessionId },
@@ -2645,16 +2684,19 @@ async function compressOneChunk(args, chunk, sliceMs, signal) {
2645
2684
  modelId: run.output.modelId
2646
2685
  });
2647
2686
  }
2687
+ stage = "apply";
2648
2688
  return args.moduleRoute ? await applyCuesThroughModule(args, chunk, run.validated, signal) : applyCues(args, chunk, run.validated);
2649
2689
  } catch (error) {
2650
2690
  const desc = describeError(error);
2651
2691
  log2(`[dreamer] compress-cues chunk failed: ${desc.brief}`, desc.stackHead ? { stackHead: desc.stackHead } : undefined);
2652
- if (signal.aborted || error instanceof HiddenCompletionRefusal || error instanceof DreamerProviderOutputFailureError)
2692
+ if (signal.aborted || error instanceof DreamerModuleFailureError || error instanceof HiddenCompletionRefusal || error instanceof DreamerProviderOutputFailureError)
2653
2693
  throw error;
2654
2694
  return {
2655
2695
  compressed: 0,
2656
2696
  skipped: 0,
2657
2697
  failure: {
2698
+ error,
2699
+ stage,
2658
2700
  class: isTimeoutClassError(error) ? "timeout" : "other",
2659
2701
  brief: desc.brief,
2660
2702
  elapsedMs: Date.now() - startedAt
@@ -2808,7 +2850,7 @@ async function applyCuesThroughModule(args, chunk, manifestText, signal) {
2808
2850
  // src/features/magic-context/dreamer/hidden-single-shot.ts
2809
2851
  async function runHiddenSingleShotPrompt(args) {
2810
2852
  const system = withContentLanguageDirective(args.system, args.language);
2811
- const handle = await args.executor.open({
2853
+ const opening = args.executor.open({
2812
2854
  parentSessionId: args.parentSessionId,
2813
2855
  agent: args.agent,
2814
2856
  kind: "dreamer-task",
@@ -2820,6 +2862,17 @@ async function runHiddenSingleShotPrompt(args) {
2820
2862
  directory: args.sessionDirectory,
2821
2863
  ...args.metadata ? { metadata: args.metadata } : {}
2822
2864
  });
2865
+ opening.then((handle) => {
2866
+ if (args.signal?.aborted)
2867
+ return args.executor.close(handle, {
2868
+ promptSettled: false,
2869
+ privacySensitive: args.privacySensitive ?? true,
2870
+ context: `[dreamer] ${args.callContext}`,
2871
+ log: log2
2872
+ });
2873
+ }).catch(() => {});
2874
+ const handle = await raceWithSignal(opening, args.signal);
2875
+ args.onOpened?.(handle.id);
2823
2876
  let promptSettled = false;
2824
2877
  try {
2825
2878
  if (!handle.id)
@@ -2874,12 +2927,16 @@ async function runHiddenSingleShotPrompt(args) {
2874
2927
  }
2875
2928
  throw error;
2876
2929
  } finally {
2877
- await args.executor.close(handle, {
2930
+ const close = args.executor.close(handle, {
2878
2931
  promptSettled,
2879
2932
  privacySensitive: args.privacySensitive ?? true,
2880
2933
  context: `[dreamer] ${args.callContext}`,
2881
2934
  log: log2
2882
2935
  });
2936
+ if (args.signal?.aborted)
2937
+ close.catch(() => {});
2938
+ else
2939
+ await raceWithSignal(close, args.signal);
2883
2940
  }
2884
2941
  }
2885
2942
 
@@ -5044,7 +5101,7 @@ function getAsyncModule() {
5044
5101
  await beforeModuleLoad();
5045
5102
  const [{ default: singlefileAsyncifyVariant }, { newQuickJSAsyncWASMModuleFromVariant }] = await importPluginModule(() => Promise.all([
5046
5103
  import("./index-e7vx3byk.js").then((m)=>__toESM(m.default,1)),
5047
- import("./index-e6xnpach.js")
5104
+ import("./index-b7p25tm0.js")
5048
5105
  ]));
5049
5106
  const module = await newQuickJSAsyncWASMModuleFromVariant(singlefileAsyncifyVariant);
5050
5107
  return module;
@@ -6949,14 +7006,28 @@ function isDeferred(memory, retries) {
6949
7006
  return !!retry && retry.content === contentKey(memory) && retry.deferUntil > Date.now();
6950
7007
  }
6951
7008
  function assistantText(messages) {
6952
- 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(`
7009
+ 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(`
6953
7010
  `) : "")).join(`
6954
7011
  `);
7012
+ return joined.trim() ? joined : null;
6955
7013
  }
6956
7014
  function currentManifest(text) {
6957
7015
  const start = text.lastIndexOf("<mappings>");
6958
7016
  return start < 0 ? text : text.slice(start);
6959
7017
  }
7018
+ function parseMapMemoriesCompletion(text, completion, expectedIds) {
7019
+ return validateMapMemoriesManifest(currentManifest(assistantText(completion.messages ?? []) || text), expectedIds);
7020
+ }
7021
+ function validateClientMapMemories(messages, expectedIds) {
7022
+ if (hasLengthCappedOutput(messages)) {
7023
+ throw new Error("map-memories returned length-capped output");
7024
+ }
7025
+ const raw = assistantText(messages);
7026
+ if (raw == null) {
7027
+ throw new Error("map-memories returned no output");
7028
+ }
7029
+ return validateMapMemoriesManifest(currentManifest(raw), expectedIds);
7030
+ }
6960
7031
  function logBatchUsage(messages, committed, startedAt) {
6961
7032
  const steps = messages.filter((message) => isRecord(message) && (message.role === "assistant" || isRecord(message.info) && message.info.role === "assistant")).length;
6962
7033
  log2(`[dreamer] map-memories batch: steps=${steps} committed=${committed} steps_per_memory=${committed ? (steps / committed).toFixed(2) : "n/a"} elapsed_ms=${Date.now() - startedAt}`);
@@ -7021,8 +7092,11 @@ async function mapMemories(args) {
7021
7092
  const inputs = allInputs.filter((memory) => !isDeferred(memory, retries));
7022
7093
  result.remaining = allInputs.length;
7023
7094
  result.complete = result.remaining === 0;
7024
- if (inputs.length === 0)
7095
+ if (inputs.length === 0) {
7096
+ if (allInputs.length > 0)
7097
+ result.deferred = true;
7025
7098
  return result;
7099
+ }
7026
7100
  const batches = [];
7027
7101
  for (let i = 0;i < inputs.length; i += MAP_BATCH_SIZE) {
7028
7102
  batches.push({ inputs: inputs.slice(i, i + MAP_BATCH_SIZE), isOmissionRetry: false });
@@ -7048,6 +7122,10 @@ async function mapMemories(args) {
7048
7122
  if (!batch)
7049
7123
  break;
7050
7124
  const outcome = await mapOneBatch(args, batch.inputs, sliceMs, abortController.signal);
7125
+ if (outcome.failure) {
7126
+ result.failure = outcome.failure.error;
7127
+ result.failureStage = outcome.failure.stage;
7128
+ }
7051
7129
  const committed = outcome.mapped + outcome.independent;
7052
7130
  runLeaseGuardedWrite(args.db, args.holderId, args.leaseKey, () => {
7053
7131
  const committedIds = new Set(outcome.committedIds);
@@ -7111,6 +7189,7 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
7111
7189
  const startedAt = Date.now();
7112
7190
  let budgetFinalized = false;
7113
7191
  let failedCompletion;
7192
+ let stage = "child-start";
7114
7193
  const onBudgetUpdate = (state) => {
7115
7194
  budgetFinalized ||= state.finalizeFired;
7116
7195
  args.onBudgetUpdate?.(state);
@@ -7132,15 +7211,19 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
7132
7211
  fallbackModels: args.fallbackModels,
7133
7212
  timeoutMs: sliceMs,
7134
7213
  signal,
7214
+ onOpened: () => {
7215
+ stage = "prompt";
7216
+ },
7135
7217
  onFailureOutput: (completion) => {
7136
7218
  failedCompletion = completion;
7137
7219
  },
7138
- parse: (text, completion) => validateMapMemoriesManifest(currentManifest(assistantText(completion.messages ?? []) || text), new Set(batch.map((memory) => memory.id)))
7220
+ parse: (text, completion) => parseMapMemoriesCompletion(text, completion, new Set(batch.map((memory) => memory.id)))
7139
7221
  });
7140
7222
  recordInvocation2(args, startedAt, {
7141
7223
  status: "completed",
7142
7224
  messages: run.completion.messages ?? []
7143
7225
  });
7226
+ stage = "apply";
7144
7227
  const outcome = await applyParsedBatchMappings(args, batch, run.validated, budgetFinalized, true);
7145
7228
  logBatchUsage(run.completion.messages ?? [], outcome.mapped + outcome.independent, startedAt);
7146
7229
  const returnedIds = new Set(outcome.committedIds);
@@ -7165,6 +7248,7 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
7165
7248
  agentSessionId = typeof created?.id === "string" ? created.id : null;
7166
7249
  if (!agentSessionId)
7167
7250
  throw new Error("Could not create map-memories session.");
7251
+ stage = "prompt";
7168
7252
  const run = await promptSyncWithValidatedOutputRetry(client, {
7169
7253
  path: { id: agentSessionId },
7170
7254
  query: { directory: args.sessionDirectory },
@@ -7192,18 +7276,11 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
7192
7276
  preferResponseOnMissingData: true
7193
7277
  });
7194
7278
  },
7195
- validateOutput: (messages) => {
7196
- if (hasLengthCappedOutput(messages)) {
7197
- throw new Error("map-memories returned length-capped output");
7198
- }
7199
- const text = currentManifest(assistantText(messages));
7200
- if (!text)
7201
- throw new Error("map-memories returned no output");
7202
- return validateMapMemoriesManifest(text, new Set(batch.map((memory) => memory.id)));
7203
- }
7279
+ validateOutput: (messages) => validateClientMapMemories(messages, new Set(batch.map((memory) => memory.id)))
7204
7280
  });
7205
7281
  promptSettled = true;
7206
7282
  recordInvocation2(args, startedAt, { status: "completed", messages: run.output });
7283
+ stage = "apply";
7207
7284
  const outcome = await applyParsedBatchMappings(args, batch, run.validated, budgetFinalized, true);
7208
7285
  logBatchUsage(run.output, outcome.mapped + outcome.independent, startedAt);
7209
7286
  const returnedIds = new Set(outcome.committedIds);
@@ -7232,6 +7309,8 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
7232
7309
  return {
7233
7310
  ...outcome,
7234
7311
  failure: {
7312
+ error,
7313
+ stage,
7235
7314
  class: isTimeoutClassError2(error) ? "timeout" : "other",
7236
7315
  elapsedMs: Date.now() - startedAt
7237
7316
  }
@@ -8751,7 +8830,7 @@ var VERIFY_SYSTEM_PROMPT = `You are a memory verifier for the magic-context syst
8751
8830
 
8752
8831
  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.
8753
8832
 
8754
- 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.
8833
+ 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.
8755
8834
 
8756
8835
  Decide ONE of four outcomes per memory:
8757
8836
  - VERIFIED — still accurate. Keep it as-is.
@@ -8763,7 +8842,7 @@ UPDATE and ARCHIVE are ONLY for claims a repository file can falsify, such as an
8763
8842
 
8764
8843
  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.
8765
8844
 
8766
- Output ONE XML manifest at the very end and NOTHING else — no narration, no per-memory commentary, no reasoning:
8845
+ 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:
8767
8846
  <verify>
8768
8847
  <verified id="N" files="path/a.ts,path/b.ts"/>
8769
8848
  <update id="M" files="path/c.ts">corrected present-tense content</update>
@@ -8776,17 +8855,24 @@ Rules:
8776
8855
  - Every input memory id MUST appear exactly once, in exactly one of verified/update/archive/skip.
8777
8856
  - 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.
8778
8857
  - Default to VERIFIED. skip when code cannot decide the claim. update and archive are the exceptions, not the norm.`;
8858
+ async function seedVerifyCandidates(memories, directory) {
8859
+ const seeded = await seedIdentifierCandidates(memories.map((m) => ({ ...m, candidates: [] })), directory);
8860
+ return memories.map((m, i) => ({ ...m, candidates: seeded[i].candidates }));
8861
+ }
8779
8862
  function buildVerifyPrompt(projectPath, memories, evidence) {
8780
8863
  const list = memories.map((m) => `[${m.id}] ${m.category}
8781
8864
  Content: ${m.content}
8782
- Backing files: ${m.mappedFiles.join(", ")}`).join(`
8865
+ Backing files: ${m.mappedFiles.join(", ")}${m.candidates?.length ? `
8866
+ Likely files (identifier matches, confirm before using): ${m.candidates.join(", ")}` : ""}`).join(`
8783
8867
 
8784
8868
  `);
8785
8869
  return `## Verify these memories against the code
8786
8870
 
8787
8871
  Project: ${projectPath}
8788
8872
 
8789
- ${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.
8873
+ 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.
8874
+
8875
+ ${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.
8790
8876
 
8791
8877
  <memories>
8792
8878
  ${list}
@@ -8863,13 +8949,57 @@ function validateVerifyManifest(text, expectedIds) {
8863
8949
  assertNoDuplicateManifestIds(ids.filter((id) => expectedIds.has(id)), "verify");
8864
8950
  return parsed;
8865
8951
  }
8952
+ function parsePartialVerifyManifest(text, expectedIds) {
8953
+ const out = { verified: [], updated: [], archived: [], skipped: [] };
8954
+ const start = text.lastIndexOf("<verify>");
8955
+ if (start < 0)
8956
+ return out;
8957
+ const entries = new Map;
8958
+ const conflicts = new Set;
8959
+ for (const match of text.slice(start).matchAll(/<(?:verified|archive|skip)\b[^<>]*\/>|<update\b[^<>]*>[\s\S]*?<\/update>/g)) {
8960
+ try {
8961
+ const parsed = parseVerifyManifest(`<verify>${match[0]}</verify>`);
8962
+ const id = verifyIds(parsed)[0];
8963
+ if (!expectedIds.has(id) || conflicts.has(id))
8964
+ continue;
8965
+ const previous = entries.get(id);
8966
+ if (previous && JSON.stringify(previous) !== JSON.stringify(parsed)) {
8967
+ entries.delete(id);
8968
+ conflicts.add(id);
8969
+ } else
8970
+ entries.set(id, parsed);
8971
+ } catch {}
8972
+ }
8973
+ for (const parsed of entries.values()) {
8974
+ out.verified.push(...parsed.verified);
8975
+ out.updated.push(...parsed.updated);
8976
+ out.archived.push(...parsed.archived);
8977
+ out.skipped.push(...parsed.skipped);
8978
+ }
8979
+ return out;
8980
+ }
8866
8981
 
8867
8982
  // src/features/magic-context/dreamer/verify.ts
8868
- var VERIFY_BATCH_SIZE = 20;
8983
+ var VERIFY_BATCH_SIZE = 5;
8984
+ var VERIFY_TOKENS_PER_MEMORY = 1e5;
8985
+ var VERIFY_RUN_TOKEN_BUDGET = 2500000;
8986
+ var VERIFY_RUN_SLICE_MS = 240000;
8987
+ function verifyBatchTokenBudget(size, configured) {
8988
+ return Math.min(configured ?? Number.MAX_SAFE_INTEGER, size * VERIFY_TOKENS_PER_MEMORY);
8989
+ }
8990
+ function verifyAssistantText(messages) {
8991
+ 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(`
8992
+ `) : "")).join(`
8993
+ `);
8994
+ if (!text.trim())
8995
+ return null;
8996
+ const start = text.lastIndexOf("<verify>");
8997
+ return start >= 0 ? text.slice(start) : text;
8998
+ }
8869
8999
  var IDENTICAL_PROVIDER_FAILURE_BATCH_LIMIT = 2;
8870
- var VERIFY_BATCH_FLOOR_MS = 240000;
8871
- function computeVerifyBatchSliceMs(remainingMs, batchesRemaining) {
8872
- return Math.min(remainingMs, Math.max(VERIFY_BATCH_FLOOR_MS, Math.floor(remainingMs / batchesRemaining)));
9000
+ var VERIFY_BATCH_FLOOR_MS = 30000;
9001
+ function computeVerifyBatchSliceMs(remainingMs, _batchesRemaining) {
9002
+ return Math.min(remainingMs, VERIFY_RUN_SLICE_MS);
8873
9003
  }
8874
9004
  function closeBroadCycle(args, cycleStartAt) {
8875
9005
  if (!args.forceBroad || cycleStartAt === undefined)
@@ -8893,6 +9023,7 @@ async function runVerify(args) {
8893
9023
  }
8894
9024
  async function runVerifyWithCooldown(args) {
8895
9025
  const runStartedAt = Date.now();
9026
+ const sliceDeadline = runStartedAt + VERIFY_RUN_SLICE_MS;
8896
9027
  const result = {
8897
9028
  verified: 0,
8898
9029
  updated: 0,
@@ -8935,16 +9066,31 @@ async function runVerifyWithCooldown(args) {
8935
9066
  let consecutiveProviderFailures = 0;
8936
9067
  let priorProviderFailureFingerprint = null;
8937
9068
  let lastProviderFailure = null;
9069
+ let runSpent = 0;
9070
+ const runTokenBudget = Math.min(args.tokenBudget ?? VERIFY_RUN_TOKEN_BUDGET, VERIFY_RUN_TOKEN_BUDGET);
8938
9071
  try {
8939
9072
  for (let i = 0;i < batches.length; i += 1) {
8940
- const remainingMs = Math.max(0, args.deadline - Date.now());
9073
+ const remainingMs = Math.max(0, Math.min(args.deadline, sliceDeadline) - Date.now());
8941
9074
  if (remainingMs < VERIFY_BATCH_FLOOR_MS) {
8942
9075
  result.stopReason = "deadline";
8943
9076
  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`);
8944
9077
  break;
8945
9078
  }
8946
9079
  const sliceMs = computeVerifyBatchSliceMs(remainingMs, batches.length - i);
8947
- const counts = await verifyOneBatch(args, batches[i], sliceMs, abortController.signal);
9080
+ if (runSpent >= runTokenBudget) {
9081
+ result.stopReason = "token-budget";
9082
+ break;
9083
+ }
9084
+ let batchSpent = 0;
9085
+ const counts = await verifyOneBatch({
9086
+ ...args,
9087
+ tokenBudget: runTokenBudget - runSpent,
9088
+ onBudgetUpdate: (state) => {
9089
+ runSpent += Math.max(0, state.spent - batchSpent);
9090
+ batchSpent = Math.max(batchSpent, state.spent);
9091
+ args.onBudgetUpdate?.(state);
9092
+ }
9093
+ }, batches[i], sliceMs, abortController.signal);
8948
9094
  result.verified += counts.verified;
8949
9095
  result.updated += counts.updated;
8950
9096
  result.archived += counts.archived;
@@ -8954,6 +9100,10 @@ async function runVerifyWithCooldown(args) {
8954
9100
  result.remaining -= batchProcessed;
8955
9101
  result.batches += 1;
8956
9102
  args.onProgress?.(result.verified + result.updated + result.archived + result.skipped + result.refused, result.refused);
9103
+ if (counts.tokenLimited) {
9104
+ result.stopReason = "token-budget";
9105
+ break;
9106
+ }
8957
9107
  if (counts.timedOut) {
8958
9108
  result.stopReason = "batch-timeout";
8959
9109
  log2(`[dreamer] ${args.forceBroad ? "verify-broad" : "verify"}: batch ${i + 1}/${batches.length} timed out after its ${sliceMs}ms slice; stopping with ${result.remaining} remaining`);
@@ -8988,18 +9138,41 @@ async function runVerifyWithCooldown(args) {
8988
9138
  }
8989
9139
  }
8990
9140
  async function verifyOneBatch(args, batch, sliceMs, signal) {
9141
+ const batchController = new AbortController;
9142
+ const abort = () => batchController.abort(signal.reason);
9143
+ signal.addEventListener("abort", abort, { once: true });
9144
+ if (signal.aborted)
9145
+ abort();
9146
+ const timer = setTimeout(() => batchController.abort(new Error(`verify slice timed out after ${sliceMs}ms`)), sliceMs);
9147
+ const batchSignal = batchController.signal;
9148
+ const tokenBudget = verifyBatchTokenBudget(batch.length, args.tokenBudget);
8991
9149
  let agentSessionId = null;
9150
+ let hiddenSessionId = null;
8992
9151
  let promptSettled = false;
8993
9152
  const startedAt = Date.now();
8994
9153
  let budgetFinalized = false;
9154
+ let failedCompletion;
9155
+ let headAtPrompt = null;
8995
9156
  const onBudgetUpdate = (state) => {
8996
9157
  budgetFinalized ||= state.finalizeFired;
8997
- args.onBudgetUpdate?.(state);
9158
+ args.onBudgetUpdate?.({
9159
+ ...state,
9160
+ ...hiddenSessionId ? { sessionId: hiddenSessionId } : {}
9161
+ });
9162
+ };
9163
+ const reportUsage = (messages, sessionId, fallbackSpent = 0) => {
9164
+ const usage = sumTokensFromChildMessages(messages);
9165
+ onBudgetUpdate({
9166
+ spent: Math.max(fallbackSpent, usage.input + usage.cacheRead + usage.cacheWrite),
9167
+ finalizeFired: budgetFinalized,
9168
+ ...sessionId ? { sessionId } : {}
9169
+ });
8998
9170
  };
8999
9171
  try {
9000
- const headAtPrompt = await readGitHead(args.sessionDirectory);
9001
- const evidence = !args.forceBroad && batch.every((m) => m.verifiedAt) ? await buildVerifyDiffEvidence(args.sessionDirectory, batch) : null;
9002
- const prompt = buildVerifyPrompt(args.projectIdentity, batch, evidence);
9172
+ headAtPrompt = await raceWithSignal(readGitHead(args.sessionDirectory), batchSignal);
9173
+ const evidence = !args.forceBroad && batch.every((m) => m.verifiedAt) ? await raceWithSignal(buildVerifyDiffEvidence(args.sessionDirectory, batch), batchSignal) : null;
9174
+ const prompt = buildVerifyPrompt(args.projectIdentity, await raceWithSignal(seedVerifyCandidates(batch, args.sessionDirectory), batchSignal), evidence);
9175
+ batchSignal.throwIfAborted();
9003
9176
  if (args.hiddenCompletionExecutor) {
9004
9177
  const run = await runHiddenSingleShotPrompt({
9005
9178
  executor: args.hiddenCompletionExecutor,
@@ -9010,41 +9183,53 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
9010
9183
  prompt,
9011
9184
  title: "magic-context-dream-verify",
9012
9185
  callContext: "dreamer:verify",
9013
- metadata: { tokenBudget: args.tokenBudget, onBudgetUpdate },
9186
+ metadata: { tokenBudget, onBudgetUpdate },
9014
9187
  model: args.model,
9015
9188
  fallbackModels: args.fallbackModels,
9016
9189
  language: args.language,
9017
9190
  timeoutMs: sliceMs,
9018
- signal,
9191
+ signal: batchSignal,
9192
+ onFailureOutput: (completion) => {
9193
+ failedCompletion = completion;
9194
+ },
9195
+ onOpened: (sessionId) => {
9196
+ hiddenSessionId = sessionId;
9197
+ onBudgetUpdate({ spent: 0, finalizeFired: false, sessionId });
9198
+ },
9019
9199
  parse: (text, completion) => {
9020
9200
  const providerFailure = providerOutputFailureFromInvalidManifest(completion.messages ?? [], text);
9021
9201
  if (providerFailure)
9022
9202
  throw providerFailure;
9023
- return validateVerifyManifest(text, new Set(batch.map((memory) => memory.id)));
9203
+ const manifest = verifyAssistantText(completion.messages ?? []) ?? (text.trim() ? text : null);
9204
+ if (!manifest)
9205
+ throw new Error("verify returned no output");
9206
+ return validateVerifyManifest(manifest, new Set(batch.map((memory) => memory.id)));
9024
9207
  }
9025
9208
  });
9026
9209
  recordInvocation4(args, startedAt, {
9027
9210
  status: "completed",
9028
9211
  messages: run.completion.messages ?? []
9029
9212
  });
9030
- return applyParsedVerifyManifest(args, batch, run.validated, evidence?.head ?? headAtPrompt, budgetFinalized);
9213
+ reportUsage(run.completion.messages ?? [], run.childSessionId, run.completion.usage.input + (run.completion.usage.cacheRead ?? 0) + (run.completion.usage.cacheWrite ?? 0));
9214
+ return await applyParsedVerifyManifest(args, batch, run.validated, evidence?.head ?? headAtPrompt, budgetFinalized);
9031
9215
  }
9032
9216
  const client = args.client;
9033
9217
  if (!client)
9034
9218
  throw new Error("verify requires a client or hidden completion executor");
9035
- const createResponse = await createChildSessionWithFence({
9219
+ const createResponse = await raceWithSignal(createChildSessionWithFence({
9036
9220
  client,
9037
9221
  db: args.db,
9038
9222
  parentSessionId: args.parentSessionId,
9039
9223
  title: args.forceBroad ? "magic-context-dream-verify-broad" : "magic-context-dream-verify",
9040
9224
  directory: args.sessionDirectory
9041
- });
9225
+ }), batchSignal);
9042
9226
  const created = normalizeSDKResponse(createResponse, null, {
9043
9227
  preferResponseOnMissingData: true
9044
9228
  });
9045
9229
  agentSessionId = typeof created?.id === "string" ? created.id : null;
9046
9230
  if (!agentSessionId)
9047
9231
  throw new Error("Could not create verify session.");
9232
+ onBudgetUpdate({ spent: 0, finalizeFired: false, sessionId: agentSessionId });
9048
9233
  const run = await promptSyncWithValidatedOutputRetry(client, {
9049
9234
  path: { id: agentSessionId },
9050
9235
  query: { directory: args.sessionDirectory },
@@ -9056,11 +9241,11 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
9056
9241
  }
9057
9242
  }, {
9058
9243
  transport: createPromptAsyncTransport(client, agentSessionId, {
9059
- tokenBudget: args.tokenBudget,
9244
+ tokenBudget,
9060
9245
  onBudgetUpdate
9061
9246
  }),
9062
9247
  timeoutMs: sliceMs,
9063
- signal,
9248
+ signal: batchSignal,
9064
9249
  fallbackModels: args.fallbackModels,
9065
9250
  callContext: "dreamer:verify",
9066
9251
  fetchOutput: async () => {
@@ -9076,7 +9261,7 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
9076
9261
  if (hasLengthCappedOutput(messages)) {
9077
9262
  throw new Error("verify returned length-capped output");
9078
9263
  }
9079
- const text = extractLatestAssistantText(messages);
9264
+ const text = verifyAssistantText(messages);
9080
9265
  if (!text)
9081
9266
  throw new Error("verify returned no output");
9082
9267
  const providerFailure = providerOutputFailureFromInvalidManifest(messages, text);
@@ -9087,27 +9272,31 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
9087
9272
  });
9088
9273
  promptSettled = true;
9089
9274
  recordInvocation4(args, startedAt, { status: "completed", messages: run.output });
9275
+ reportUsage(run.output, agentSessionId);
9090
9276
  return await applyParsedVerifyManifest(args, batch, run.validated, evidence?.head ?? headAtPrompt, budgetFinalized);
9091
9277
  } catch (error) {
9092
9278
  const desc = describeError(error);
9093
9279
  const providerFailure = error instanceof DreamerProviderOutputFailureError ? error : undefined;
9094
9280
  const promptFailure = getPromptFailureDetail(error);
9095
9281
  log2(`[dreamer] verify batch ${providerFailure ? "provider failure" : "failed"}: ${desc.brief}`, desc.stackHead ? { stackHead: desc.stackHead } : undefined);
9282
+ const messages = failedCompletion?.messages ?? await readFailedChildMessages(args.client, agentSessionId, args.sessionDirectory) ?? [];
9283
+ reportUsage(messages, hiddenSessionId ?? agentSessionId, failedCompletion?.usage.input ?? 0);
9096
9284
  recordInvocation4(args, startedAt, {
9097
9285
  status: failedInvocationStatus(error),
9098
9286
  error,
9099
- messages: await readFailedChildMessages(args.client, agentSessionId, args.sessionDirectory)
9287
+ messages
9100
9288
  });
9101
- if (error instanceof DreamerModuleFailureError || error instanceof DreamTokenBudgetExceeded || signal.aborted)
9289
+ if (error instanceof DreamerModuleFailureError || signal.aborted)
9102
9290
  throw error;
9103
- if (promptFailure?.failureClass === "provider_timeout" || isPromptTimeoutError(error)) {
9291
+ const interrupted = batchSignal.aborted || error instanceof DreamTokenBudgetExceeded || promptFailure?.failureClass === "provider_timeout" || isPromptTimeoutError(error);
9292
+ if (interrupted) {
9293
+ const text = verifyAssistantText(messages) ?? failedCompletion?.text ?? "";
9294
+ const recovered = parsePartialVerifyManifest(text, new Set(batch.map((m) => m.id)));
9295
+ const counts = await applyParsedVerifyManifest(args, batch, recovered, headAtPrompt, true);
9104
9296
  return {
9105
- verified: 0,
9106
- updated: 0,
9107
- archived: 0,
9108
- skipped: 0,
9109
- refused: 0,
9110
- timedOut: true
9297
+ ...counts,
9298
+ timedOut: !(error instanceof DreamTokenBudgetExceeded),
9299
+ tokenLimited: error instanceof DreamTokenBudgetExceeded
9111
9300
  };
9112
9301
  }
9113
9302
  if (promptFailure !== null && promptFailure.failureClass !== "parse_failed" && !providerFailure)
@@ -9122,7 +9311,7 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
9122
9311
  };
9123
9312
  } finally {
9124
9313
  if (agentSessionId && args.client)
9125
- await teardownChildSession({
9314
+ await raceWithSignal(teardownChildSession({
9126
9315
  client: args.client,
9127
9316
  sessionId: agentSessionId,
9128
9317
  sessionDirectory: args.sessionDirectory,
@@ -9130,7 +9319,9 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
9130
9319
  privacySensitive: true,
9131
9320
  context: "[dreamer] verify",
9132
9321
  log: log2
9133
- });
9322
+ }), batchSignal).catch(() => {});
9323
+ clearTimeout(timer);
9324
+ signal.removeEventListener("abort", abort);
9134
9325
  }
9135
9326
  }
9136
9327
  async function applyParsedVerifyManifest(args, batch, parsed, headAtPrompt, budgetFinalized = false) {
@@ -9157,7 +9348,7 @@ async function applyParsedVerifyManifest(args, batch, parsed, headAtPrompt, budg
9157
9348
  throw new Error(`verify manifest covers ${validIds.length}/${batch.length} batch ids after filtering unknown entries; rejecting mostly-wrong manifest`);
9158
9349
  }
9159
9350
  if (budgetFinalized && validIds.length < batch.length) {
9160
- log2(`[dreamer] verify: accepted partial manifest after token budget: ${validIds.length}/${batch.length}`);
9351
+ log2(`[dreamer] verify: accepted partial manifest after investigation stop: ${validIds.length}/${batch.length}`);
9161
9352
  }
9162
9353
  if (validIds.length === 0) {
9163
9354
  return { verified: 0, updated: 0, archived: 0, skipped: 0, refused: 0 };
@@ -9392,10 +9583,10 @@ function dreamRunFailureDetail(error) {
9392
9583
  child_session_id: null
9393
9584
  };
9394
9585
  }
9395
- const localRefusal = error instanceof HiddenCompletionRefusal;
9586
+ const localRefusal = error instanceof HiddenCompletionRefusal || error instanceof DreamerModuleFailureError;
9396
9587
  const providerFailure = error instanceof Error && error.name === "DreamerProviderOutputFailureError";
9397
9588
  return {
9398
- failure_class: localRefusal ? "local_refusal" : providerFailure ? "provider_error" : /no models?|model chain is empty/i.test(message) ? "no_models" : "unknown",
9589
+ 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",
9399
9590
  model_attempted: null,
9400
9591
  models_tried: [],
9401
9592
  provider_error: providerFailure ? sanitizeDiagnosticText(message).slice(0, 500) : null,
@@ -9406,6 +9597,10 @@ function dreamRunFailureDetail(error) {
9406
9597
  } : {}
9407
9598
  };
9408
9599
  }
9600
+ function incompleteFailure(error, fallback = "parse_failed") {
9601
+ const detail = dreamRunFailureDetail(error);
9602
+ return detail.failure_class === "unknown" ? { ...detail, failure_class: fallback } : detail;
9603
+ }
9409
9604
  function classifyFailure(error) {
9410
9605
  const described = describeError(error);
9411
9606
  const brief = described.brief;
@@ -9565,6 +9760,7 @@ function createDreamTaskExecutor(deps) {
9565
9760
  const { db, projectIdentity, holderId, leaseKey } = ctx;
9566
9761
  deps.client?.resetDreamTokenBudget?.(config.task);
9567
9762
  const startedAt = Date.now();
9763
+ const effectiveTokenBudget = config.task === "verify" || config.task === "verify-broad" ? Math.min(config.tokenBudget ?? VERIFY_RUN_TOKEN_BUDGET, VERIFY_RUN_TOKEN_BUDGET) : config.tokenBudget;
9568
9764
  const leaseAcquisition = ctx.leaseAcquisition ?? acquireLeaseWithAcquisition(db, holderId, leaseKey) ?? (() => {
9569
9765
  throw new Error("Dream lease unavailable during executor setup");
9570
9766
  })();
@@ -9612,7 +9808,7 @@ function createDreamTaskExecutor(deps) {
9612
9808
  if (state.sessionId) {
9613
9809
  const previous = childSpending.get(state.sessionId) ?? 0;
9614
9810
  budgetSpent += Math.max(0, state.spent - previous);
9615
- childSpending.set(state.sessionId, state.spent);
9811
+ childSpending.set(state.sessionId, Math.max(previous, state.spent));
9616
9812
  } else
9617
9813
  budgetSpent = Math.max(budgetSpent, state.spent);
9618
9814
  budgetFinalized ||= state.finalizeFired;
@@ -9639,9 +9835,15 @@ function createDreamTaskExecutor(deps) {
9639
9835
  failure: extra?.failure ?? dreamRunFailureDetail(error ?? "unknown dreamer failure")
9640
9836
  } : {},
9641
9837
  ...extra?.progress ? { progress: extra.progress } : {},
9642
- ...config.tokenBudget ? {
9838
+ ...childSpending.size ? {
9839
+ children: [...childSpending].map(([sessionId, promptTokens]) => ({
9840
+ sessionId,
9841
+ promptTokens
9842
+ }))
9843
+ } : {},
9844
+ ...effectiveTokenBudget ? {
9643
9845
  tokenBudget: {
9644
- budget: config.tokenBudget,
9846
+ budget: effectiveTokenBudget,
9645
9847
  spent: budgetSpent,
9646
9848
  finalizeFired: budgetFinalized,
9647
9849
  banked: extra?.banked ?? processedDreamTaskItems(backlogAtStart.pending, (extra?.backlogAfter ?? getDreamTaskBacklog(db, projectIdentity, config.task)).pending)
@@ -9730,8 +9932,13 @@ function createDreamTaskExecutor(deps) {
9730
9932
  });
9731
9933
  log2(`[dreamer] compress-cues: compressed=${result.compressed} skipped=${result.skipped} chunks=${result.chunks} remaining=${result.remaining}`);
9732
9934
  if (!result.complete) {
9733
- const error = incompleteMessage(result.remaining);
9734
- recordRun("failed", error);
9935
+ if (result.stopReason === "deadline" && result.chunks === 0)
9936
+ return skip("compress-cues: insufficient time to start a chunk");
9937
+ const error = `${incompleteMessage(result.remaining)}; ${result.failureStage ? `${result.failureStage}: ` : ""}${result.failure ? describeError(result.failure).brief : `${result.skipped} cues rejected by validation`}`;
9938
+ recordRun("failed", error, {
9939
+ banked: result.compressed,
9940
+ failure: incompleteFailure(result.failure, result.failureStage === "child-start" ? "local_refusal" : result.stopReason === "timeout-circuit-breaker" ? "provider_timeout" : "parse_failed")
9941
+ });
9735
9942
  return { status: "failed", transient: true, error };
9736
9943
  }
9737
9944
  recordRun("completed", null);
@@ -9777,9 +9984,15 @@ function createDreamTaskExecutor(deps) {
9777
9984
  });
9778
9985
  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}` : ""}`);
9779
9986
  if (!result.complete) {
9987
+ if (result.deferred)
9988
+ return skip("map-memories: all pending mappings are in content-keyed retry backoff; no child started");
9989
+ if (result.stopReason === "deadline" && result.batches === 0 && !result.failure)
9990
+ return skip("map-memories: insufficient time to start a batch");
9780
9991
  if (result.stopReason === "timeout-circuit-breaker") {
9781
9992
  const error = `map-memories starvation: timeout circuit breaker stopped the run with ${result.remaining} remain`;
9782
- recordRun("failed", error);
9993
+ recordRun("failed", error, {
9994
+ failure: incompleteFailure(result.failure, "provider_timeout")
9995
+ });
9783
9996
  return { status: "failed", transient: true, error };
9784
9997
  }
9785
9998
  const processed = result.mapped + result.independent;
@@ -9788,8 +10001,10 @@ function createDreamTaskExecutor(deps) {
9788
10001
  recordRun("completed", null, { progress });
9789
10002
  return { status: "completed" };
9790
10003
  }
9791
- const error = incompleteMessage(result.remaining);
9792
- recordRun("failed", error);
10004
+ const error = `${incompleteMessage(result.remaining)}; ${result.failureStage ? `${result.failureStage}: ` : ""}${result.failure ? describeError(result.failure).brief : "manifest returned no accepted mapping decisions"}`;
10005
+ recordRun("failed", error, {
10006
+ failure: incompleteFailure(result.failure, result.failureStage === "child-start" ? "local_refusal" : "parse_failed")
10007
+ });
9793
10008
  return { status: "failed", transient: true, error };
9794
10009
  }
9795
10010
  recordRun("completed", null);
@@ -9819,25 +10034,27 @@ function createDreamTaskExecutor(deps) {
9819
10034
  });
9820
10035
  const processed = result.verified + result.updated + result.archived + result.skipped + result.refused;
9821
10036
  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`;
9822
- const broadProgress = config.task === "verify-broad" ? verificationProgress : null;
9823
10037
  const backlogAfter = config.task === "verify-broad" ? { pending: result.remaining, total: backlogAtStart.total } : undefined;
9824
10038
  if (!result.complete) {
9825
- if (broadProgress && processed > 0) {
10039
+ if (processed > 0) {
9826
10040
  recordRun("completed", null, {
9827
- progress: broadProgress,
10041
+ progress: verificationProgress,
9828
10042
  memoryChanges: computeMemoryDelta(memoryBefore),
9829
10043
  backlogAfter,
9830
10044
  banked: result.verified + result.updated + result.archived
9831
10045
  });
9832
10046
  return { status: "completed" };
9833
10047
  }
10048
+ if (result.stopReason === "deadline")
10049
+ return skip(`${config.task}: insufficient time to start a batch`);
9834
10050
  const batchTimedOut = result.stopReason === "batch-timeout";
9835
10051
  const error = batchTimedOut ? `${config.task}: a batch timed out within its time slice; ${result.remaining} remain` : incompleteMessage(result.remaining);
9836
10052
  recordRun("failed", error, {
9837
10053
  progress: verificationProgress,
9838
10054
  memoryChanges: computeMemoryDelta(memoryBefore),
9839
10055
  backlogAfter,
9840
- banked: result.verified + result.updated + result.archived
10056
+ banked: result.verified + result.updated + result.archived,
10057
+ failure: incompleteFailure(error, batchTimedOut ? "provider_timeout" : result.stopReason === "token-budget" ? "token_budget" : "parse_failed")
9841
10058
  });
9842
10059
  return { status: "failed", transient: !batchTimedOut, error };
9843
10060
  }
@@ -9961,6 +10178,7 @@ function createDreamTaskExecutor(deps) {
9961
10178
  if (retro.skipReason)
9962
10179
  return skip(retro.skipReason);
9963
10180
  recordRun("completed", null, {
10181
+ progress: retro.noOpReason,
9964
10182
  memoryChanges: computeMemoryDelta(memoryBefore),
9965
10183
  backlogAfter: retro.retrospectiveWatermarkMs == null ? undefined : getDreamTaskBacklog(db, projectIdentity, "retrospective", {
9966
10184
  retrospectiveWatermarkMs: retro.retrospectiveWatermarkMs
@@ -9968,6 +10186,7 @@ function createDreamTaskExecutor(deps) {
9968
10186
  });
9969
10187
  return {
9970
10188
  status: "completed",
10189
+ ...retro.noOpReason ? { detail: retro.noOpReason } : {},
9971
10190
  schedulePatch: retro.retrospectiveWatermarkMs != null || retro.taskStateJson !== undefined ? {
9972
10191
  ...retro.retrospectiveWatermarkMs != null ? {
9973
10192
  retrospectiveWatermarkMs: retro.retrospectiveWatermarkMs
@@ -10167,20 +10386,28 @@ async function runRetrospectiveTask(config, ctx, helpers) {
10167
10386
  const recencyCutoffMs = helpers.invocationStartedAt - recencyDays * RETROSPECTIVE_DAY_MS;
10168
10387
  const scan = await readRetrospectiveScanWindow(provider, projectIdentity, watermarkMs, RETROSPECTIVE_OVERLAP_USER_LINES, { usableInputTokens, recencyCutoffMs });
10169
10388
  const clearedTaskStateJson = activeOverflow ? writeRetrospectiveOverflowState(taskState.root, null) : undefined;
10170
- const completedWindow = (retrospectiveWatermarkMs) => ({
10389
+ const completedWindow = (retrospectiveWatermarkMs, noOpReason) => ({
10171
10390
  retrospectiveWatermarkMs,
10172
- ...clearedTaskStateJson ? { taskStateJson: clearedTaskStateJson } : {}
10391
+ ...clearedTaskStateJson ? { taskStateJson: clearedTaskStateJson } : {},
10392
+ ...noOpReason ? { noOpReason } : {}
10173
10393
  });
10174
10394
  const messages = withGlobalOrdinals(scan.messages);
10175
10395
  const userMessages = messages.filter((message) => message.role === "user" && message.text.trim().length > 0);
10176
10396
  if (userMessages.length === 0) {
10177
- log2("[dreamer] retrospective: no user messages in window");
10178
- return completedWindow(scan.maxScannedTs);
10397
+ const noOpReason = "no reply-following user lines";
10398
+ log2(`[dreamer] retrospective: ${noOpReason}`);
10399
+ return completedWindow(scan.maxScannedTs, noOpReason);
10179
10400
  }
10180
- const postWatermarkOrdinals = new Set(userMessages.filter((message) => message.ts > watermarkMs).map((message) => message.ordinal));
10181
- if (postWatermarkOrdinals.size === 0) {
10401
+ const newUserOrdinals = new Set(userMessages.filter((message) => message.ts > watermarkMs).map((message) => message.ordinal));
10402
+ if (newUserOrdinals.size === 0) {
10182
10403
  log2("[dreamer] retrospective: only overlap lines, nothing new");
10183
- return completedWindow(scan.maxScannedTs);
10404
+ return completedWindow(scan.maxScannedTs, "only overlap lines, nothing new");
10405
+ }
10406
+ const postWatermarkOrdinals = new Set(userMessages.filter((message) => message.ts > watermarkMs && message.followsAssistantReply === true).map((message) => message.ordinal));
10407
+ if (postWatermarkOrdinals.size === 0) {
10408
+ const noOpReason = "no reply-following user lines";
10409
+ log2(`[dreamer] retrospective: ${noOpReason}`);
10410
+ return completedWindow(scan.maxScannedTs, noOpReason);
10184
10411
  }
10185
10412
  const abortController = new AbortController;
10186
10413
  let leaseLost = false;
@@ -15979,7 +16206,7 @@ function registerRpcHandlers(rpcServer, args) {
15979
16206
  return { count: buildCompartmentCount(db, sessionId, moduleStatus) };
15980
16207
  });
15981
16208
  const buildManagedCtx = async (db) => {
15982
- const { deriveHistorianChunkTokens, resolveHistorianContextLimit } = await importPluginModule(() => import("./derive-budgets-5306b1jt.js"));
16209
+ const { deriveHistorianChunkTokens, resolveHistorianContextLimit } = await importPluginModule(() => import("./derive-budgets-zn7yzd2d.js"));
15983
16210
  const { resolveHistorianModel } = await importPluginModule(() => import("./model-resolution-nx97z3x7.js"));
15984
16211
  const { userObservationCollectionEnabled, userObservationsRequested } = await importPluginModule(() => import("./task-config-x3qmayd2.js"));
15985
16212
  const DEFAULT_HISTORIAN_TIMEOUT_MS = 10 * 60 * 1000;
@@ -16031,8 +16258,8 @@ function registerRpcHandlers(rpcServer, args) {
16031
16258
  const db = readDatabase();
16032
16259
  if (!db)
16033
16260
  return { ok: false, error: "db unavailable" };
16034
- const { runManagedRecomp } = await importPluginModule(() => import("./recomp-orchestrator-a0mvby4e.js"));
16035
- const { sendIgnoredMessage } = await importPluginModule(() => import("./send-session-notification-y2wg3fkh.js"));
16261
+ const { runManagedRecomp } = await importPluginModule(() => import("./recomp-orchestrator-dmbeadwt.js"));
16262
+ const { sendIgnoredMessage } = await importPluginModule(() => import("./send-session-notification-24r4esbh.js"));
16036
16263
  log2(`[rpc] recomp requested for session ${sessionId}`);
16037
16264
  if (!args.client && !args.hiddenCompletionExecutor) {
16038
16265
  return {
@@ -16116,7 +16343,7 @@ function registerRpcHandlers(rpcServer, args) {
16116
16343
  const db = readDatabase();
16117
16344
  if (!db)
16118
16345
  return { ok: false, error: "db unavailable" };
16119
- const { runManagedWrapup } = await importPluginModule(() => import("./wrapup-orchestrator-vmt6z3q5.js"));
16346
+ const { runManagedWrapup } = await importPluginModule(() => import("./wrapup-orchestrator-2051r6qm.js"));
16120
16347
  const model = liveSessionState.liveModelBySession.get(sessionId);
16121
16348
  const contextLimit = model ? resolveContextLimit(model.providerID, model.modelID, { db, sessionID: sessionId }) : 128000;
16122
16349
  const ctx = {
@@ -16190,6 +16417,85 @@ function registerRpcHandlers(rpcServer, args) {
16190
16417
  });
16191
16418
  }
16192
16419
 
16420
+ // src/hooks/magic-context/auto-embed-session.ts
16421
+ function embeddingIdentity(projectIdentity) {
16422
+ const snapshot = getProjectEmbeddingSnapshot2(projectIdentity);
16423
+ return JSON.stringify([
16424
+ projectIdentity,
16425
+ snapshot?.providerIdentity,
16426
+ snapshot?.chunkModelId,
16427
+ snapshot?.runtimeFingerprint
16428
+ ]);
16429
+ }
16430
+ function maybeAutoEmbedSessionBackfill(deps, sessionId) {
16431
+ const markActive = () => activeEmbeddingSessions.set(sessionId, {
16432
+ project: deps.projectIdentity,
16433
+ model: getProjectEmbeddingSnapshot2(deps.projectIdentity)?.chunkModelId ?? "off"
16434
+ });
16435
+ markActive();
16436
+ const identity = embeddingIdentity(deps.projectIdentity);
16437
+ if (autoEmbedIdentityBySession.get(sessionId) !== identity) {
16438
+ invalidateAutoEmbedSession(sessionId);
16439
+ autoEmbedIdentityBySession.set(sessionId, identity);
16440
+ }
16441
+ if (autoEmbedAttemptedBySession.has(sessionId) || embedPauseBySession.has(sessionId) || embedRunStateBySession.has(sessionId) || Date.now() < (autoEmbedRetryAfterBySession.get(sessionId) ?? 0))
16442
+ return;
16443
+ const controller = new AbortController;
16444
+ embedRunStateBySession.set(sessionId, controller);
16445
+ (async () => {
16446
+ let complete = false;
16447
+ let retryDelay = 1000;
16448
+ let started = false;
16449
+ let reason = "error";
16450
+ let registeredIdentity = identity;
16451
+ try {
16452
+ await new Promise((resolve) => setTimeout(resolve, 0));
16453
+ if (controller.signal.aborted)
16454
+ return;
16455
+ await deps.ensureRegistered();
16456
+ if (controller.signal.aborted)
16457
+ return;
16458
+ markActive();
16459
+ registeredIdentity = embeddingIdentity(deps.projectIdentity);
16460
+ autoEmbedIdentityBySession.set(sessionId, registeredIdentity);
16461
+ const coverage = await getAutoEmbeddingSessionCoverage2(deps.db, deps.projectIdentity, sessionId);
16462
+ if (controller.signal.aborted || !coverage.enabled)
16463
+ return;
16464
+ if (coverage.embedded === coverage.total) {
16465
+ complete = true;
16466
+ return;
16467
+ }
16468
+ const model = getProjectEmbeddingSnapshot2(deps.projectIdentity)?.model;
16469
+ log2(`[magic-context] session backfill start session=${sessionId} missing=${coverage.total - coverage.embedded} model=${model}`);
16470
+ started = true;
16471
+ const outcome = await embedSessionCompartmentChunks2(deps.db, deps.projectIdentity, sessionId, { signal: controller.signal, automatic: true });
16472
+ reason = outcome.status;
16473
+ const after = await getAutoEmbeddingSessionCoverage2(deps.db, deps.projectIdentity, sessionId);
16474
+ complete = after.enabled && after.embedded === after.total;
16475
+ if (!complete && outcome.status !== "busy" && outcome.status !== "aborted") {
16476
+ retryDelay = 60000;
16477
+ if (outcome.status === "nothing" || outcome.status === "done")
16478
+ reason = "deferred";
16479
+ }
16480
+ } catch (error) {
16481
+ log2("[magic-context] auto-embed drain failed:", error);
16482
+ retryDelay = 60000;
16483
+ } finally {
16484
+ if (started)
16485
+ log2(`[magic-context] session backfill ${complete ? "complete" : "stop"} session=${sessionId} reason=${reason}`);
16486
+ if (embedRunStateBySession.get(sessionId) === controller) {
16487
+ embedRunStateBySession.delete(sessionId);
16488
+ }
16489
+ if (!controller.signal.aborted && autoEmbedIdentityBySession.get(sessionId) === registeredIdentity && embeddingIdentity(deps.projectIdentity) === registeredIdentity) {
16490
+ if (complete)
16491
+ autoEmbedAttemptedBySession.add(sessionId);
16492
+ else
16493
+ autoEmbedRetryAfterBySession.set(sessionId, Date.now() + retryDelay);
16494
+ }
16495
+ }
16496
+ })();
16497
+ }
16498
+
16193
16499
  // src/features/magic-context/transform-decision-log.ts
16194
16500
  var TRANSFORM_DECISIONS_RETENTION = 2000;
16195
16501
  var canonicalReasons = new Set([
@@ -28845,4 +29151,4 @@ function applyHiddenSubagentTemperature(input, output, log) {
28845
29151
  output.temperature = temperature;
28846
29152
  }
28847
29153
 
28848
- export { logConfigDependencyNotesOnce, openOpenCodeDb, DREAMER_SYSTEM_PROMPT, runSessionProjectBackfill, SMART_NOTE_COMPILER_SYSTEM_PROMPT, createLiveSessionState, RETROSPECTIVE_MAX_USER_MESSAGE_CHARS, RETROSPECTIVE_MESSAGE_TRUNCATION_MARKER, OpenCodeRetrospectiveRawProvider, createDreamTaskExecutor, runManualDream, runDueTasksForProject, scheduleClearAndReindex, startDreamScheduleTimer, createDreamTimerModuleClient, ensureProjectRegisteredFromOpenCodeDirectory, recordOpenCodeProvenInputFloor, resolveOpenCodeProvenInputFloor, resolveContextWindowGeometry, resolveContextLimit, resolveExecuteThresholdDetail, resolveModelKey, resolveSessionId, createScheduler, describeStorageUnavailability, resolveSessionCacheTtl, runEmbedHistoryDrain, pauseEmbedHistoryDrain, formatEmbedStatusText, getSessionProperties, getSessionCreatedInfo, getMessageUpdatedAssistantInfo, getMessageUpdatedInfo, getSessionErrorInfo, getMessageRemovedInfo, summarizeManualDream, createMagicContextCommandHandler, getLiveNotificationParams, createChatMessageHook, createEventHook, createCommandExecuteBeforeHook, createToolExecuteAfterHook, recordHiddenVariantWarning, buildStatusDetail, isDebugRpcEnabled, registerRpcHandlers, clearTransformDecisionSession, scheduleOpenCodeTransformDecisionWrite, stageOpenCodeV2TransformDecision, bindOpenCodeV2TransformDecision, maybeDeliverChannel2, armLatestThinkingRecovery, armBindingRecoverySafely, armLatestThinkingRecoveryFromError, createM0RenderOptions, lkgReplayLimit, measureLkgReplay, STORAGE_BUSY_MESSAGE, StorageBusyRefusalError, bindSystemDateRequestIdentity, bindSystemDateOutput, registerSystemDateRefresh, rustWrapupHistorianFields, UnmanagedOverWindowError, UnresolvedHistoryBoundaryError, clearMessageTokensCache, createTransform, createSubcModuleClient, createModuleToolBackends, createRustRefusalRecovery, createSystemPromptHashHandler, tryMessagesTransformLkgReplay, createMessagesTransformHandler, primaryOnlyToolIds, subagentToolRefusal, guardSubagentTools, hideSubagentTools, createCtxExpandTools, CTX_MEMORY_LIST_TOOL_NAME, CTX_MEMORY_ACTIONS, createCtxMemoryTools, createCtxMemoryListTools, CTX_NOTE_DESCRIPTION, withoutSmartNoteText, createCtxNoteTools, createCtxReduceTools, createCtxSearchTools, parameterDescriptionsFor, applyJsonSchemaParameterDescriptions, MagicContextRpcServer, subagentTemperature, applyHiddenSubagentTemperature };
29154
+ export { logConfigDependencyNotesOnce, openOpenCodeDb, DREAMER_SYSTEM_PROMPT, runSessionProjectBackfill, SMART_NOTE_COMPILER_SYSTEM_PROMPT, createLiveSessionState, RETROSPECTIVE_MAX_USER_MESSAGE_CHARS, RETROSPECTIVE_MESSAGE_TRUNCATION_MARKER, OpenCodeRetrospectiveRawProvider, createDreamTaskExecutor, runManualDream, runDueTasksForProject, scheduleClearAndReindex, startDreamScheduleTimer, createDreamTimerModuleClient, ensureProjectRegisteredFromOpenCodeDirectory, recordOpenCodeProvenInputFloor, resolveOpenCodeProvenInputFloor, resolveContextWindowGeometry, resolveContextLimit, resolveExecuteThresholdDetail, resolveModelKey, resolveSessionId, createScheduler, describeStorageUnavailability, resolveSessionCacheTtl, runEmbedHistoryDrain, pauseEmbedHistoryDrain, formatEmbedStatusText, getSessionProperties, getSessionCreatedInfo, getMessageUpdatedAssistantInfo, getMessageUpdatedInfo, getSessionErrorInfo, getMessageRemovedInfo, summarizeManualDream, createMagicContextCommandHandler, getLiveNotificationParams, createChatMessageHook, createEventHook, createCommandExecuteBeforeHook, createToolExecuteAfterHook, recordHiddenVariantWarning, buildStatusDetail, isDebugRpcEnabled, registerRpcHandlers, maybeAutoEmbedSessionBackfill, clearTransformDecisionSession, scheduleOpenCodeTransformDecisionWrite, stageOpenCodeV2TransformDecision, bindOpenCodeV2TransformDecision, maybeDeliverChannel2, armLatestThinkingRecovery, armBindingRecoverySafely, armLatestThinkingRecoveryFromError, createM0RenderOptions, lkgReplayLimit, measureLkgReplay, STORAGE_BUSY_MESSAGE, StorageBusyRefusalError, bindSystemDateRequestIdentity, bindSystemDateOutput, registerSystemDateRefresh, rustWrapupHistorianFields, UnmanagedOverWindowError, UnresolvedHistoryBoundaryError, clearMessageTokensCache, createTransform, createSubcModuleClient, createModuleToolBackends, createRustRefusalRecovery, createSystemPromptHashHandler, tryMessagesTransformLkgReplay, createMessagesTransformHandler, primaryOnlyToolIds, subagentToolRefusal, guardSubagentTools, hideSubagentTools, createCtxExpandTools, CTX_MEMORY_LIST_TOOL_NAME, CTX_MEMORY_ACTIONS, createCtxMemoryTools, createCtxMemoryListTools, CTX_NOTE_DESCRIPTION, withoutSmartNoteText, createCtxNoteTools, createCtxReduceTools, createCtxSearchTools, parameterDescriptionsFor, applyJsonSchemaParameterDescriptions, MagicContextRpcServer, subagentTemperature, applyHiddenSubagentTemperature };