@cortexkit/opencode-magic-context 0.44.2 → 0.44.4

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/{conflict-warning-hook-1msyvb51.js → conflict-warning-hook-hmpzxep6.js} +3 -3
  2. package/dist/{derive-budgets-gd2270s0.js → derive-budgets-ncwn1jk9.js} +4 -2
  3. package/dist/features/magic-context/dreamer/classify.d.ts.map +1 -1
  4. package/dist/features/magic-context/dreamer/hidden-single-shot.d.ts.map +1 -1
  5. package/dist/features/magic-context/dreamer/lease.d.ts +1 -1
  6. package/dist/features/magic-context/dreamer/lease.d.ts.map +1 -1
  7. package/dist/features/magic-context/dreamer/map-memories.d.ts.map +1 -1
  8. package/dist/features/magic-context/dreamer/verify.d.ts.map +1 -1
  9. package/dist/features/magic-context/memory/embedding-openai.d.ts +1 -0
  10. package/dist/features/magic-context/memory/embedding-openai.d.ts.map +1 -1
  11. package/dist/features/magic-context/memory/project-identity.d.ts +8 -4
  12. package/dist/features/magic-context/memory/project-identity.d.ts.map +1 -1
  13. package/dist/features/magic-context/message-index-async.d.ts +1 -1
  14. package/dist/features/magic-context/message-index-async.d.ts.map +1 -1
  15. package/dist/features/magic-context/project-embedding-registry.d.ts.map +1 -1
  16. package/dist/features/magic-context/session-project-storage.d.ts +5 -5
  17. package/dist/features/magic-context/session-project-storage.d.ts.map +1 -1
  18. package/dist/features/magic-context/storage-db.d.ts +6 -1
  19. package/dist/features/magic-context/storage-db.d.ts.map +1 -1
  20. package/dist/features/magic-context/storage-embedding-measurements.d.ts.map +1 -1
  21. package/dist/features/magic-context/v22-deferred-backfill.d.ts.map +1 -1
  22. package/dist/hooks/magic-context/compartment-render-epoch.d.ts +12 -1
  23. package/dist/hooks/magic-context/compartment-render-epoch.d.ts.map +1 -1
  24. package/dist/hooks/magic-context/compartment-runner-historian.d.ts +2 -1
  25. package/dist/hooks/magic-context/compartment-runner-historian.d.ts.map +1 -1
  26. package/dist/hooks/magic-context/compartment-runner-incremental.d.ts.map +1 -1
  27. package/dist/hooks/magic-context/compartment-runner-types.d.ts +1 -0
  28. package/dist/hooks/magic-context/compartment-runner-types.d.ts.map +1 -1
  29. package/dist/hooks/magic-context/derive-budgets.d.ts +4 -0
  30. package/dist/hooks/magic-context/derive-budgets.d.ts.map +1 -1
  31. package/dist/hooks/magic-context/drop-stale-reduce-calls.d.ts.map +1 -1
  32. package/dist/hooks/magic-context/event-resolvers.d.ts +7 -0
  33. package/dist/hooks/magic-context/event-resolvers.d.ts.map +1 -1
  34. package/dist/hooks/magic-context/heuristic-cleanup.d.ts.map +1 -1
  35. package/dist/hooks/magic-context/historian-host-runner.d.ts.map +1 -1
  36. package/dist/hooks/magic-context/inject-compartments.d.ts +5 -0
  37. package/dist/hooks/magic-context/inject-compartments.d.ts.map +1 -1
  38. package/dist/hooks/magic-context/lkg-persist.d.ts +1 -4
  39. package/dist/hooks/magic-context/lkg-persist.d.ts.map +1 -1
  40. package/dist/hooks/magic-context/module-wire.d.ts.map +1 -1
  41. package/dist/hooks/magic-context/producer-window-guard.d.ts +4 -1
  42. package/dist/hooks/magic-context/producer-window-guard.d.ts.map +1 -1
  43. package/dist/hooks/magic-context/read-session-chunk.d.ts +4 -2
  44. package/dist/hooks/magic-context/read-session-chunk.d.ts.map +1 -1
  45. package/dist/hooks/magic-context/read-session-raw.d.ts +2 -2
  46. package/dist/hooks/magic-context/read-session-raw.d.ts.map +1 -1
  47. package/dist/hooks/magic-context/rust-mode-transform.d.ts +1 -0
  48. package/dist/hooks/magic-context/rust-mode-transform.d.ts.map +1 -1
  49. package/dist/hooks/magic-context/storage-busy-refusal.d.ts +6 -0
  50. package/dist/hooks/magic-context/storage-busy-refusal.d.ts.map +1 -1
  51. package/dist/hooks/magic-context/tokenizer-calibration.d.ts +1 -1
  52. package/dist/hooks/magic-context/tool-drop-target.d.ts.map +1 -1
  53. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts +1 -0
  54. package/dist/hooks/magic-context/transform-postprocess-phase.d.ts.map +1 -1
  55. package/dist/hooks/magic-context/transform.d.ts.map +1 -1
  56. package/dist/{index-r9vkp4n9.js → index-33q7s9y2.js} +1 -1
  57. package/dist/{index-egkfvhms.js → index-4an2p8qa.js} +80 -14
  58. package/dist/{index-18tjha8g.js → index-638hf49n.js} +1 -1
  59. package/dist/{index-gtzcmv90.js → index-mrc0twf3.js} +12 -6
  60. package/dist/{index-stb5fg12.js → index-msqr3x6m.js} +32 -2
  61. package/dist/{index-y5145x8k.js → index-n96ag4rk.js} +15 -1
  62. package/dist/{index-esxfcz5z.js → index-qm36k34q.js} +56 -13
  63. package/dist/{index-ttdn47aq.js → index-sqp1hz9v.js} +311 -82
  64. package/dist/{index-40s1xz22.js → index-wprsye9w.js} +1 -1
  65. package/dist/{index-3x9caerx.js → index-zx7pmr39.js} +3 -3
  66. package/dist/index.d.ts.map +1 -1
  67. package/dist/index.js +530 -250
  68. package/dist/plugin/dream-timer.d.ts.map +1 -1
  69. package/dist/plugin/embedding-bootstrap.d.ts.map +1 -1
  70. package/dist/plugin/messages-transform.d.ts.map +1 -1
  71. package/dist/plugin/rpc-handlers.d.ts.map +1 -1
  72. package/dist/{read-session-chunk-wmvgnd24.js → read-session-chunk-339hg90t.js} +3 -3
  73. package/dist/{recomp-orchestrator-rk40ff15.js → recomp-orchestrator-0ers6smx.js} +7 -7
  74. package/dist/{send-session-notification-6xsrcxnp.js → send-session-notification-04hvd54c.js} +2 -2
  75. package/dist/shared/rpc-utils.d.ts +7 -0
  76. package/dist/shared/rpc-utils.d.ts.map +1 -1
  77. package/dist/shared/run-token-log.d.ts +13 -0
  78. package/dist/shared/run-token-log.d.ts.map +1 -0
  79. package/dist/shared/sqlite.d.ts +7 -0
  80. package/dist/shared/sqlite.d.ts.map +1 -1
  81. package/dist/shared/transcript.d.ts +2 -0
  82. package/dist/shared/transcript.d.ts.map +1 -1
  83. package/dist/shared/user-answer.d.ts +4 -0
  84. package/dist/shared/user-answer.d.ts.map +1 -0
  85. package/dist/{transform-postprocess-phase-t7xgdhdf.js → transform-postprocess-phase-ttdkrm6r.js} +7 -7
  86. package/dist/v2/hidden-completion.d.ts +7 -1
  87. package/dist/v2/hidden-completion.d.ts.map +1 -1
  88. package/dist/v2/hooks/context.d.ts.map +1 -1
  89. package/dist/v2/hooks/hidden-terminal-error.d.ts +8 -0
  90. package/dist/v2/hooks/hidden-terminal-error.d.ts.map +1 -0
  91. package/dist/v2/hooks/payload.d.ts.map +1 -1
  92. package/dist/v2/hooks/store.d.ts +1 -1
  93. package/dist/v2/hooks/store.d.ts.map +1 -1
  94. package/dist/v2/hooks/tools.d.ts +1 -1
  95. package/dist/v2/hooks/tools.d.ts.map +1 -1
  96. package/dist/v2/server.js +916 -221
  97. package/dist/v2/store-reader.d.ts +2 -1
  98. package/dist/v2/store-reader.d.ts.map +1 -1
  99. package/dist/{wrapup-orchestrator-h8tr10c6.js → wrapup-orchestrator-x0jvvrqn.js} +8 -8
  100. package/package.json +1 -1
  101. package/src/config/latch-permanence-guard.test.ts +4 -0
  102. package/src/shared/data-path.test.ts +1 -1
  103. package/src/shared/models-dev-cache.test.ts +30 -1
  104. package/src/shared/rpc-utils.test.ts +27 -2
  105. package/src/shared/rpc-utils.ts +44 -15
  106. package/src/shared/run-token-log.test.ts +65 -0
  107. package/src/shared/run-token-log.ts +39 -0
  108. package/src/shared/sqlite-acquisition-routing.test.ts +19 -11
  109. package/src/shared/sqlite-pass-scope.test.ts +115 -144
  110. package/src/shared/sqlite.ts +123 -20
  111. package/src/shared/storage-busy.test.ts +34 -57
  112. package/src/shared/tag-transcript.ts +4 -1
  113. package/src/shared/transcript.ts +3 -0
  114. package/src/shared/user-answer.test.ts +40 -0
  115. package/src/shared/user-answer.ts +17 -0
  116. package/src/shared/write-transaction-attribution.test.ts +13 -11
package/dist/index.js CHANGED
@@ -23,6 +23,9 @@ import {
23
23
  isDreamerRunnable,
24
24
  isHistorianRunnable,
25
25
  isCompactionEnabled,
26
+ cortexKitUserConfigBasePath,
27
+ cortexKitProjectConfigBasePath,
28
+ resolveLegacyConfigSources,
26
29
  migrateMagicContextConfigLocations,
27
30
  string,
28
31
  unknown,
@@ -60,6 +63,8 @@ import {
60
63
  recordHookInitFailure,
61
64
  clearHookInitFailure,
62
65
  getLastHookInitFailure,
66
+ setHomeProjectPermission,
67
+ shouldSkipHomeProjectMemory,
63
68
  ProjectIdentityError,
64
69
  resolveProjectIdentityStrict,
65
70
  takeDubiousOwnershipProjectIdentityWarning,
@@ -397,6 +402,8 @@ import {
397
402
  readGitFileChangeTimesSince,
398
403
  verificationFileExists,
399
404
  normalizeVerificationFiles,
405
+ runTokenLog,
406
+ formatRunTokenLog,
400
407
  resolveHiddenCompletionExecutor,
401
408
  createV1HiddenCompletionExecutor,
402
409
  USER_MEMORY_CANDIDATE_TTL_MS,
@@ -452,7 +459,7 @@ import {
452
459
  snapRangeToCompartments,
453
460
  getActiveCompartmentRun,
454
461
  startCompartmentAgent
455
- } from "./index-ttdn47aq.js";
462
+ } from "./index-sqp1hz9v.js";
456
463
  import"./index-sd3egckz.js";
457
464
  import {
458
465
  canonicalModelIdentity,
@@ -476,8 +483,9 @@ import {
476
483
  deriveTriggerBudget2,
477
484
  deriveHistorianChunkTokens2,
478
485
  resolveKnownHistorianContextLimit2,
486
+ resolveHistorianProducerLimits2,
479
487
  resolveHistorianContextLimit2
480
- } from "./index-stb5fg12.js";
488
+ } from "./index-msqr3x6m.js";
481
489
  import {
482
490
  resolveOpenCodeDbPath,
483
491
  assertOpenCodeStoreGeneration,
@@ -491,11 +499,12 @@ import {
491
499
  claimOpenCodeDbDiagnosticOnce,
492
500
  Database,
493
501
  getSqliteMemoryStats,
502
+ withSqliteBackgroundWriter,
494
503
  withSqliteTransformPass,
495
504
  withoutSqliteTransformPass,
496
505
  isTransientSqliteError,
497
506
  SqliteAcquisitionBusyError,
498
- withPrivilegedWriter,
507
+ withAsyncPrivilegedWriter,
499
508
  closeQuietly,
500
509
  openCodeDbExists,
501
510
  withReadOnlySessionDb,
@@ -504,7 +513,7 @@ import {
504
513
  assistantAwaitingTools,
505
514
  latestPersistedMessageForRecovery,
506
515
  findLastAssistantModelFromOpenCodeDb
507
- } from "./index-egkfvhms.js";
516
+ } from "./index-4an2p8qa.js";
508
517
  import {
509
518
  hasMeaningfulUserText2,
510
519
  extractTexts2,
@@ -549,6 +558,7 @@ import {
549
558
  buildInMemoryTailRawMessages,
550
559
  estimateTrueRawMessageTokens,
551
560
  invalidateTrueRawTokenCache,
561
+ toolPartHasUserAnswer,
552
562
  DreamTokenBudgetExceeded,
553
563
  createDreamTokenBudget,
554
564
  recordToolParameters,
@@ -575,7 +585,7 @@ import {
575
585
  readRawSessionMessageById2,
576
586
  readSessionChunk2,
577
587
  readRawSessionSeedTail2
578
- } from "./index-esxfcz5z.js";
588
+ } from "./index-qm36k34q.js";
579
589
  import"./index-kwe03yde.js";
580
590
  import {
581
591
  getErrorMessage,
@@ -585,17 +595,17 @@ import {
585
595
  clearIgnoredMessages2,
586
596
  observeIgnoredNotificationEvent2,
587
597
  sendStatusNotification2
588
- } from "./index-r9vkp4n9.js";
598
+ } from "./index-33q7s9y2.js";
589
599
  import {
590
600
  detectConflicts,
591
601
  resolveCompactionForBoot,
592
602
  sendConflictWarning2,
593
603
  cleanupConflictWarnings2
594
- } from "./index-18tjha8g.js";
604
+ } from "./index-638hf49n.js";
595
605
  import {
596
606
  resolveModelCalibration,
597
607
  calibrateBuckets
598
- } from "./index-y5145x8k.js";
608
+ } from "./index-n96ag4rk.js";
599
609
  import {
600
610
  resolveHistorianModel2,
601
611
  resolveOpenCodeAgentOverrides2,
@@ -672,12 +682,12 @@ import {
672
682
  abortSessionFailClosed2,
673
683
  evaluateEmergencyFailClosed2,
674
684
  runPostTransformPhase2
675
- } from "./index-gtzcmv90.js";
685
+ } from "./index-mrc0twf3.js";
676
686
  import {
677
687
  setRecompStarting2,
678
688
  setRecompTerminal2,
679
689
  runManagedRecomp2
680
- } from "./index-40s1xz22.js";
690
+ } from "./index-wprsye9w.js";
681
691
  import {
682
692
  isValidSemver,
683
693
  compareSemverCore,
@@ -692,7 +702,7 @@ import {
692
702
  } from "./index-fmsr7v69.js";
693
703
  import {
694
704
  runManagedWrapup2
695
- } from "./index-3x9caerx.js";
705
+ } from "./index-zx7pmr39.js";
696
706
  import {
697
707
  logSlowWriteTransaction
698
708
  } from "./index-kr5qehbd.js";
@@ -9370,7 +9380,7 @@ function countFailures(db) {
9370
9380
  function classifyBackfillError(error) {
9371
9381
  if (error instanceof ProjectIdentityError) {
9372
9382
  return {
9373
- errorClass: error.errorClass === "dubious_ownership" || error.errorClass === "home_project_disabled" || error.errorClass === "git_identity_unavailable" ? "unknown" : error.errorClass,
9383
+ errorClass: error.errorClass === "dubious_ownership" || error.errorClass === "home_project_disabled" || error.errorClass === "git_identity_unavailable" || error.errorClass === "no_commits" ? "unknown" : error.errorClass,
9374
9384
  errorMessage: error.message
9375
9385
  };
9376
9386
  }
@@ -11244,7 +11254,7 @@ function startLeaseHeartbeat(db, holderId, leaseKey, onLost, intervalOrAcquisiti
11244
11254
  }
11245
11255
  };
11246
11256
  beat();
11247
- const timer = lost ? undefined : setInterval(beat, intervalMs);
11257
+ const timer = lost ? undefined : setInterval(() => withSqliteBackgroundWriter(beat), intervalMs);
11248
11258
  return {
11249
11259
  stop: () => {
11250
11260
  if (timer)
@@ -12618,8 +12628,10 @@ async function runHiddenSingleShotPrompt(args) {
12618
12628
  callContext: args.callContext,
12619
12629
  fetchOutput: () => args.executor.collect(handle, 50),
12620
12630
  validateOutput: (completion) => {
12631
+ const tokens = completion.tokenLog ?? runTokenLog(undefined);
12632
+ sessionLog(args.parentSessionId ?? "dreamer", `${args.callContext} response_chars=${(completion.text ?? completion.reasoning ?? "").length} ${formatRunTokenLog(tokens)}`);
12621
12633
  if (completion.lengthCapped) {
12622
- throw new Error(completion.reasoning && !completion.text ? `${args.callContext} ran out of output budget while reasoning (length-capped at ${completion.usage.output} tokens, no text) — set dreamer.maxTokens or use a low-reasoning model` : `${args.callContext} returned length-capped output`);
12634
+ throw new Error(completion.reasoning && !completion.text ? `${args.callContext} ran out of output budget while reasoning (length-capped at ${completion.usage.output} tokens, no text; ${formatRunTokenLog(tokens)}) — set dreamer.maxTokens or use a low-reasoning model` : `${args.callContext} returned length-capped output; ${formatRunTokenLog(tokens)}`);
12623
12635
  }
12624
12636
  const text = completion.text;
12625
12637
  if (!text && !args.allowEmpty)
@@ -13273,8 +13285,10 @@ async function classifyOneChunk(args, chunk, anchors, sliceMs, signal) {
13273
13285
  fetchOutput: () => executor.collect(opened, 50),
13274
13286
  validateOutput: (completion) => {
13275
13287
  const messages = completion.messages ?? [];
13288
+ const tokens = completion.tokenLog ?? runTokenLog(undefined);
13289
+ sessionLog(args.parentSessionId ?? "dreamer", `dreamer:classify response_chars=${(completion.text ?? completion.reasoning ?? "").length} ${formatRunTokenLog(tokens)}`);
13276
13290
  if (completion.lengthCapped) {
13277
- throw new Error(completion.reasoning && !completion.text ? `classify ran out of output budget while reasoning (length-capped at ${completion.usage.output} tokens, no text) — set dreamer.maxTokens or use a low-reasoning model` : "classify returned length-capped output");
13291
+ throw new Error(completion.reasoning && !completion.text ? `classify ran out of output budget while reasoning (length-capped at ${completion.usage.output} tokens, no text; ${formatRunTokenLog(tokens)}) — set dreamer.maxTokens or use a low-reasoning model` : `classify returned length-capped output; ${formatRunTokenLog(tokens)}`);
13278
13292
  }
13279
13293
  const text = completion.text;
13280
13294
  if (!text)
@@ -16307,6 +16321,11 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
16307
16321
  let agentSessionId = null;
16308
16322
  let promptSettled = false;
16309
16323
  const startedAt = Date.now();
16324
+ let budgetFinalized = false;
16325
+ const onBudgetUpdate = (state) => {
16326
+ budgetFinalized ||= state.finalizeFired;
16327
+ args.onBudgetUpdate?.(state);
16328
+ };
16310
16329
  try {
16311
16330
  const prompt = buildMapMemoriesPrompt(args.projectIdentity, batch);
16312
16331
  if (args.hiddenCompletionExecutor) {
@@ -16319,7 +16338,7 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
16319
16338
  prompt,
16320
16339
  title: "magic-context-dream-map-memories",
16321
16340
  callContext: "dreamer:map-memories",
16322
- metadata: { tokenBudget: args.tokenBudget, onBudgetUpdate: args.onBudgetUpdate },
16341
+ metadata: { tokenBudget: args.tokenBudget, onBudgetUpdate },
16323
16342
  model: args.model,
16324
16343
  fallbackModels: args.fallbackModels,
16325
16344
  timeoutMs: sliceMs,
@@ -16330,9 +16349,12 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
16330
16349
  status: "completed",
16331
16350
  messages: run.completion.messages ?? []
16332
16351
  });
16333
- const outcome = await applyParsedBatchMappings(args, batch, run.validated);
16352
+ const outcome = await applyParsedBatchMappings(args, batch, run.validated, budgetFinalized);
16334
16353
  const returnedIds = new Set(run.validated.map((entry) => entry.id));
16335
- return { ...outcome, requeue: batch.filter((memory) => !returnedIds.has(memory.id)) };
16354
+ return {
16355
+ ...outcome,
16356
+ requeue: budgetFinalized ? [] : batch.filter((memory) => !returnedIds.has(memory.id))
16357
+ };
16336
16358
  }
16337
16359
  const client = args.client;
16338
16360
  if (!client)
@@ -16362,7 +16384,7 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
16362
16384
  }, {
16363
16385
  transport: createPromptAsyncTransport(client, agentSessionId, {
16364
16386
  tokenBudget: args.tokenBudget,
16365
- onBudgetUpdate: args.onBudgetUpdate
16387
+ onBudgetUpdate
16366
16388
  }),
16367
16389
  timeoutMs: sliceMs,
16368
16390
  signal,
@@ -16389,11 +16411,11 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
16389
16411
  });
16390
16412
  promptSettled = true;
16391
16413
  recordInvocation2(args, startedAt, { status: "completed", messages: run.output });
16392
- const outcome = await applyParsedBatchMappings(args, batch, run.validated);
16414
+ const outcome = await applyParsedBatchMappings(args, batch, run.validated, budgetFinalized);
16393
16415
  const returnedIds = new Set(run.validated.filter((entry) => batch.some((memory) => memory.id === entry.id)).map((entry) => entry.id));
16394
16416
  return {
16395
16417
  ...outcome,
16396
- requeue: batch.filter((memory) => !returnedIds.has(memory.id))
16418
+ requeue: budgetFinalized ? [] : batch.filter((memory) => !returnedIds.has(memory.id))
16397
16419
  };
16398
16420
  } catch (error) {
16399
16421
  const desc = describeError(error);
@@ -16428,7 +16450,7 @@ async function mapOneBatch(args, batch, sliceMs, signal) {
16428
16450
  });
16429
16451
  }
16430
16452
  }
16431
- async function applyParsedBatchMappings(args, batch, parsed) {
16453
+ async function applyParsedBatchMappings(args, batch, parsed, budgetFinalized = false) {
16432
16454
  const batchIds = new Set(batch.map((memory) => memory.id));
16433
16455
  const valid = parsed.filter((entry) => batchIds.has(entry.id));
16434
16456
  const unknown = parsed.filter((entry) => !batchIds.has(entry.id));
@@ -16436,9 +16458,12 @@ async function applyParsedBatchMappings(args, batch, parsed) {
16436
16458
  log(`[dreamer] map-memories warning: dropping ${unknown.length} unknown mapping entr${unknown.length === 1 ? "y" : "ies"} outside the current batch (${unknown.map((entry) => entry.id).join(", ")})`);
16437
16459
  }
16438
16460
  assertNoDuplicateManifestIds(valid.map((entry) => entry.id), "mappings");
16439
- if (valid.length * 2 < batch.length) {
16461
+ if (!budgetFinalized && valid.length * 2 < batch.length) {
16440
16462
  throw new Error(`mappings manifest covers ${valid.length}/${batch.length} batch ids after filtering unknown entries; rejecting mostly-wrong manifest`);
16441
16463
  }
16464
+ if (budgetFinalized && valid.length < batch.length) {
16465
+ log(`[dreamer] map-memories: accepted partial manifest after token budget: ${valid.length}/${batch.length}`);
16466
+ }
16442
16467
  if (valid.length === 0)
16443
16468
  return { mapped: 0, independent: 0 };
16444
16469
  const planned = [];
@@ -18011,6 +18036,11 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
18011
18036
  let agentSessionId = null;
18012
18037
  let promptSettled = false;
18013
18038
  const startedAt = Date.now();
18039
+ let budgetFinalized = false;
18040
+ const onBudgetUpdate = (state) => {
18041
+ budgetFinalized ||= state.finalizeFired;
18042
+ args.onBudgetUpdate?.(state);
18043
+ };
18014
18044
  try {
18015
18045
  const headAtPrompt = await readGitHead(args.sessionDirectory);
18016
18046
  const evidence = !args.forceBroad && batch.every((m) => m.verifiedAt) ? await buildVerifyDiffEvidence(args.sessionDirectory, batch) : null;
@@ -18025,7 +18055,7 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
18025
18055
  prompt,
18026
18056
  title: "magic-context-dream-verify",
18027
18057
  callContext: "dreamer:verify",
18028
- metadata: { tokenBudget: args.tokenBudget, onBudgetUpdate: args.onBudgetUpdate },
18058
+ metadata: { tokenBudget: args.tokenBudget, onBudgetUpdate },
18029
18059
  model: args.model,
18030
18060
  fallbackModels: args.fallbackModels,
18031
18061
  language: args.language,
@@ -18042,7 +18072,7 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
18042
18072
  status: "completed",
18043
18073
  messages: run.completion.messages ?? []
18044
18074
  });
18045
- return applyParsedVerifyManifest(args, batch, run.validated, evidence?.head ?? headAtPrompt);
18075
+ return applyParsedVerifyManifest(args, batch, run.validated, evidence?.head ?? headAtPrompt, budgetFinalized);
18046
18076
  }
18047
18077
  const client = args.client;
18048
18078
  if (!client)
@@ -18072,7 +18102,7 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
18072
18102
  }, {
18073
18103
  transport: createPromptAsyncTransport(client, agentSessionId, {
18074
18104
  tokenBudget: args.tokenBudget,
18075
- onBudgetUpdate: args.onBudgetUpdate
18105
+ onBudgetUpdate
18076
18106
  }),
18077
18107
  timeoutMs: sliceMs,
18078
18108
  signal,
@@ -18102,7 +18132,7 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
18102
18132
  });
18103
18133
  promptSettled = true;
18104
18134
  recordInvocation4(args, startedAt, { status: "completed", messages: run.output });
18105
- return await applyParsedVerifyManifest(args, batch, run.validated, evidence?.head ?? headAtPrompt);
18135
+ return await applyParsedVerifyManifest(args, batch, run.validated, evidence?.head ?? headAtPrompt, budgetFinalized);
18106
18136
  } catch (error) {
18107
18137
  const desc = describeError(error);
18108
18138
  const providerFailure = error instanceof DreamerProviderOutputFailureError ? error : undefined;
@@ -18148,7 +18178,7 @@ async function verifyOneBatch(args, batch, sliceMs, signal) {
18148
18178
  });
18149
18179
  }
18150
18180
  }
18151
- async function applyParsedVerifyManifest(args, batch, parsed, headAtPrompt) {
18181
+ async function applyParsedVerifyManifest(args, batch, parsed, headAtPrompt, budgetFinalized = false) {
18152
18182
  const batchIds = new Set(batch.map((m) => m.id));
18153
18183
  const batchById = new Map(batch.map((memory) => [memory.id, memory]));
18154
18184
  const valid = {
@@ -18168,9 +18198,12 @@ async function applyParsedVerifyManifest(args, batch, parsed, headAtPrompt) {
18168
18198
  }
18169
18199
  const validIds = [...valid.verified, ...valid.updated, ...valid.archived, ...valid.skipped].map((entry) => entry.id);
18170
18200
  assertNoDuplicateManifestIds(validIds, "verify");
18171
- if (validIds.length * 2 < batch.length) {
18201
+ if (!budgetFinalized && validIds.length * 2 < batch.length) {
18172
18202
  throw new Error(`verify manifest covers ${validIds.length}/${batch.length} batch ids after filtering unknown entries; rejecting mostly-wrong manifest`);
18173
18203
  }
18204
+ if (budgetFinalized && validIds.length < batch.length) {
18205
+ log(`[dreamer] verify: accepted partial manifest after token budget: ${validIds.length}/${batch.length}`);
18206
+ }
18174
18207
  if (validIds.length === 0) {
18175
18208
  return { verified: 0, updated: 0, archived: 0, skipped: 0, refused: 0 };
18176
18209
  }
@@ -20050,6 +20083,205 @@ function clearDreamerTickFailure(db) {
20050
20083
  db.prepare("DELETE FROM schema_migrations_meta WHERE key = ?").run(DREAMER_TICK_FAILURE_KEY);
20051
20084
  }
20052
20085
 
20086
+ // src/hooks/magic-context/lkg-persist.ts
20087
+ import { createHash as createHash10 } from "node:crypto";
20088
+ function parseStringArray(value) {
20089
+ if (typeof value !== "string")
20090
+ return null;
20091
+ let parsed;
20092
+ try {
20093
+ parsed = JSON.parse(value);
20094
+ } catch {
20095
+ return null;
20096
+ }
20097
+ if (!Array.isArray(parsed))
20098
+ return null;
20099
+ const result = [];
20100
+ for (const entry of parsed) {
20101
+ if (typeof entry !== "string" || entry.length === 0)
20102
+ return null;
20103
+ result.push(entry);
20104
+ }
20105
+ return result;
20106
+ }
20107
+ function parseNullableString(value) {
20108
+ if (value === null || value === undefined)
20109
+ return null;
20110
+ return typeof value === "string" ? value : undefined;
20111
+ }
20112
+ function parseNullableInteger(value) {
20113
+ if (value === null || value === undefined)
20114
+ return;
20115
+ return typeof value === "number" && Number.isSafeInteger(value) ? value : undefined;
20116
+ }
20117
+ function parsePersistedLkgSlot(row) {
20118
+ if (!row || typeof row !== "object")
20119
+ return;
20120
+ const record = row;
20121
+ const jsonPrefix = record.json_prefix;
20122
+ const lastInputMessageId = record.last_input_message_id;
20123
+ const capturedAt = record.captured_at;
20124
+ let inputIdsRaw = record.input_id_seq;
20125
+ let piOutputEntryIds;
20126
+ if (typeof inputIdsRaw === "string") {
20127
+ try {
20128
+ const metadata = JSON.parse(inputIdsRaw);
20129
+ if (metadata && !Array.isArray(metadata) && metadata.version === 1 && Array.isArray(metadata.piOutputEntryIds)) {
20130
+ if (!metadata.piOutputEntryIds.every((id) => id === null || typeof id === "string" && id.length > 0))
20131
+ return;
20132
+ piOutputEntryIds = metadata.piOutputEntryIds;
20133
+ inputIdsRaw = JSON.stringify(metadata.inputIds);
20134
+ }
20135
+ } catch {
20136
+ return;
20137
+ }
20138
+ }
20139
+ const inputIdSeq = parseStringArray(inputIdsRaw);
20140
+ const inputContentDigests = parseStringArray(record.input_content_digests);
20141
+ const modelKey = parseNullableString(record.model_key);
20142
+ const providerKey = parseNullableString(record.provider_key);
20143
+ if (typeof jsonPrefix !== "string" || typeof lastInputMessageId !== "string" || lastInputMessageId.length === 0 || typeof capturedAt !== "number" || !Number.isFinite(capturedAt) || inputIdSeq === null || inputContentDigests === null || inputContentDigests.length !== inputIdSeq.length || modelKey === undefined || providerKey === undefined) {
20144
+ return;
20145
+ }
20146
+ if (piOutputEntryIds) {
20147
+ try {
20148
+ const output = JSON.parse(jsonPrefix);
20149
+ const inputs = new Set(inputIdSeq);
20150
+ if (!Array.isArray(output) || output.length !== piOutputEntryIds.length || piOutputEntryIds.some((id) => id !== null && !inputs.has(id)))
20151
+ return;
20152
+ } catch {
20153
+ return;
20154
+ }
20155
+ }
20156
+ let inputContentSignatures;
20157
+ if (record.input_content_signatures !== null && record.input_content_signatures !== undefined) {
20158
+ const parsed = parseStringArray(record.input_content_signatures);
20159
+ if (parsed === null || parsed.length !== inputIdSeq.length)
20160
+ return;
20161
+ inputContentSignatures = parsed;
20162
+ }
20163
+ const slot = {
20164
+ jsonPrefix,
20165
+ inputIdSeq,
20166
+ inputContentDigests,
20167
+ lastInputMessageId,
20168
+ modelKey,
20169
+ providerKey,
20170
+ capturedAt
20171
+ };
20172
+ if (inputContentSignatures)
20173
+ slot.inputContentSignatures = inputContentSignatures;
20174
+ if (piOutputEntryIds)
20175
+ slot.piOutputEntryIds = piOutputEntryIds;
20176
+ const rowVersion = parseNullableInteger(record.row_version);
20177
+ if (rowVersion !== undefined)
20178
+ slot.rowVersion = rowVersion;
20179
+ const captureSequence = parseNullableInteger(record.capture_sequence);
20180
+ if (captureSequence !== undefined)
20181
+ slot.captureSequence = captureSequence;
20182
+ return slot;
20183
+ }
20184
+ var persistedFingerprints = new WeakMap;
20185
+ function saveLkgSlotToDb(db, sessionId, slot) {
20186
+ const fingerprint = createHash10("sha256").update(JSON.stringify([
20187
+ slot.jsonPrefix,
20188
+ slot.inputIdSeq,
20189
+ slot.inputContentDigests,
20190
+ slot.inputContentSignatures,
20191
+ slot.piOutputEntryIds,
20192
+ slot.lastInputMessageId,
20193
+ slot.modelKey,
20194
+ slot.providerKey,
20195
+ slot.rowVersion,
20196
+ slot.captureSequence
20197
+ ])).digest("hex");
20198
+ let saved = persistedFingerprints.get(db);
20199
+ if (saved?.get(sessionId) === fingerprint)
20200
+ return true;
20201
+ try {
20202
+ db.prepare(`INSERT INTO lkg_slots (
20203
+ session_id, json_prefix, input_id_seq, input_content_digests,
20204
+ input_content_signatures, last_input_message_id, model_key, provider_key,
20205
+ captured_at, row_version, capture_sequence
20206
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
20207
+ ON CONFLICT(session_id) DO UPDATE SET
20208
+ json_prefix = excluded.json_prefix,
20209
+ input_id_seq = excluded.input_id_seq,
20210
+ input_content_digests = excluded.input_content_digests,
20211
+ input_content_signatures = excluded.input_content_signatures,
20212
+ last_input_message_id = excluded.last_input_message_id,
20213
+ model_key = excluded.model_key,
20214
+ provider_key = excluded.provider_key,
20215
+ captured_at = excluded.captured_at,
20216
+ row_version = excluded.row_version,
20217
+ capture_sequence = excluded.capture_sequence`).run(sessionId, slot.jsonPrefix, JSON.stringify(slot.piOutputEntryIds ? {
20218
+ version: 1,
20219
+ inputIds: slot.inputIdSeq,
20220
+ piOutputEntryIds: slot.piOutputEntryIds
20221
+ } : slot.inputIdSeq), JSON.stringify(slot.inputContentDigests), slot.inputContentSignatures ? JSON.stringify(slot.inputContentSignatures) : null, slot.lastInputMessageId, slot.modelKey, slot.providerKey, slot.capturedAt, slot.rowVersion ?? null, slot.captureSequence ?? null);
20222
+ if (!saved) {
20223
+ saved = new Map;
20224
+ persistedFingerprints.set(db, saved);
20225
+ }
20226
+ if (saved.size >= 1000) {
20227
+ const oldest = saved.keys().next().value;
20228
+ if (oldest !== undefined)
20229
+ saved.delete(oldest);
20230
+ }
20231
+ saved.set(sessionId, fingerprint);
20232
+ return true;
20233
+ } catch (error) {
20234
+ sessionLog(sessionId, "LKG snapshot persistence failed (in-memory slot retained):", error);
20235
+ return false;
20236
+ }
20237
+ }
20238
+ function clearPersistedLkgSlot(db, sessionId) {
20239
+ try {
20240
+ db.prepare("DELETE FROM lkg_slots WHERE session_id = ?").run(sessionId);
20241
+ persistedFingerprints.get(db)?.delete(sessionId);
20242
+ } catch (error) {
20243
+ sessionLog(sessionId, "LKG snapshot durable clear failed:", error);
20244
+ }
20245
+ }
20246
+ function loadPersistedLkgSlot(db, sessionId) {
20247
+ let row;
20248
+ try {
20249
+ row = db.prepare("SELECT * FROM lkg_slots WHERE session_id = ?").get(sessionId);
20250
+ } catch (error) {
20251
+ sessionLog(sessionId, "LKG snapshot durable load failed:", error);
20252
+ return;
20253
+ }
20254
+ if (!row)
20255
+ return;
20256
+ const slot = parsePersistedLkgSlot(row);
20257
+ if (!slot) {
20258
+ clearPersistedLkgSlot(db, sessionId);
20259
+ return;
20260
+ }
20261
+ return slot;
20262
+ }
20263
+ function pruneStaleLkgSlots(db, now = Date.now()) {
20264
+ const previousTimeout = db.prepare("PRAGMA busy_timeout").get();
20265
+ try {
20266
+ db.exec("PRAGMA busy_timeout = 0");
20267
+ const result = db.prepare(`DELETE FROM lkg_slots WHERE captured_at < ? AND NOT EXISTS (
20268
+ SELECT 1 FROM session_projects sp
20269
+ WHERE sp.session_id = lkg_slots.session_id AND sp.updated_at >= ?
20270
+ )`).run(now - 7 * 24 * 60 * 60 * 1000, now - 7 * 24 * 60 * 60 * 1000);
20271
+ if (result.changes)
20272
+ persistedFingerprints.delete(db);
20273
+ return result.changes;
20274
+ } finally {
20275
+ db.exec(`PRAGMA busy_timeout = ${Number(previousTimeout.timeout) || 0}`);
20276
+ }
20277
+ }
20278
+ function createDbLkgPersistence(db) {
20279
+ return {
20280
+ load: (sessionId) => loadPersistedLkgSlot(db, sessionId),
20281
+ clear: (sessionId) => clearPersistedLkgSlot(db, sessionId)
20282
+ };
20283
+ }
20284
+
20053
20285
  // src/plugin/dream-timer.ts
20054
20286
  var DREAM_TIMER_INTERVAL_MS = 15 * 60 * 1000;
20055
20287
  var GIT_COMMIT_BACKLOG_DRAIN_MAX_MS = 5 * 60 * 1000;
@@ -20212,6 +20444,11 @@ function persistTickOutcome(db, failure) {
20212
20444
  }
20213
20445
  }
20214
20446
  async function runMessageHistoryMaintenance(db) {
20447
+ try {
20448
+ pruneStaleLkgSlots(db);
20449
+ } catch (error) {
20450
+ log("[magic-context] LKG pruning deferred:", error);
20451
+ }
20215
20452
  const cleanup = retryPendingSessionCleanups(db);
20216
20453
  if (cleanup.cleared > 0 || cleanup.failedSessionIds.length > 0) {
20217
20454
  log(`[message-index] pending session cleanup: cleared=${cleanup.cleared} failed=${cleanup.failedSessionIds.length}`);
@@ -20489,8 +20726,11 @@ function createDreamTimerModuleClient(moduleClient) {
20489
20726
  };
20490
20727
  }
20491
20728
 
20729
+ // src/plugin/embedding-bootstrap.ts
20730
+ import { readFileSync as readFileSync7, statSync as statSync4 } from "node:fs";
20731
+
20492
20732
  // src/plugin/embedding-bootstrap-helpers.ts
20493
- import { createHash as createHash10 } from "node:crypto";
20733
+ import { createHash as createHash11 } from "node:crypto";
20494
20734
  var EMBEDDING_AFFECTING_KEYS = new Set([
20495
20735
  "embedding.api_key",
20496
20736
  "embedding.endpoint",
@@ -20538,7 +20778,7 @@ var EMBEDDING_WARNING_TERMS = [
20538
20778
  ];
20539
20779
  var loggedFailureSignatures = new Map;
20540
20780
  function sha256Prefix(value, length = 16) {
20541
- return createHash10("sha256").update(value).digest("hex").slice(0, length);
20781
+ return createHash11("sha256").update(value).digest("hex").slice(0, length);
20542
20782
  }
20543
20783
  function warningLooksEmbeddingRelated(message) {
20544
20784
  const lower = message.toLowerCase();
@@ -20733,12 +20973,41 @@ async function resolveEmbeddingRouting(args) {
20733
20973
  }
20734
20974
 
20735
20975
  // src/plugin/embedding-bootstrap.ts
20736
- async function ensureProjectRegisteredFromOpenCodeDirectory(directory, db) {
20976
+ var configCache = new Map;
20977
+ function loadRegistrationConfig(directory) {
20978
+ const legacy = resolveLegacyConfigSources(directory);
20979
+ const paths = [cortexKitUserConfigBasePath(), cortexKitProjectConfigBasePath(directory)].flatMap((base) => [`${base}.jsonc`, `${base}.json`]).concat(legacy.user.map((source) => source.path), legacy.project.map((source) => source.path));
20980
+ const key = paths.map((path) => {
20981
+ const stat = statSync4(path, { throwIfNoEntry: false });
20982
+ return `${path}:${stat?.mtimeMs ?? "missing"}:${stat?.size ?? 0}`;
20983
+ }).join("|");
20984
+ const cached = configCache.get(directory);
20985
+ if (cached?.key === key)
20986
+ return cached.detailed;
20737
20987
  const detailed = loadPluginConfigDetailed(directory);
20988
+ const dynamic = paths.some((path) => {
20989
+ try {
20990
+ return /\{(?:env|file):/.test(readFileSync7(path, "utf8"));
20991
+ } catch {
20992
+ return false;
20993
+ }
20994
+ });
20995
+ if (!dynamic) {
20996
+ if (configCache.size >= 64) {
20997
+ const oldest = configCache.keys().next().value;
20998
+ if (oldest !== undefined)
20999
+ configCache.delete(oldest);
21000
+ }
21001
+ configCache.set(directory, { key, detailed });
21002
+ } else
21003
+ configCache.delete(directory);
21004
+ return detailed;
21005
+ }
21006
+ async function ensureProjectRegisteredFromOpenCodeDirectory(directory, db) {
21007
+ const detailed = loadRegistrationConfig(directory);
20738
21008
  const projectIdentity = resolveProjectIdentityForSession(directory, detailed.config.allow_home_project);
20739
21009
  if (!projectIdentity)
20740
21010
  return;
20741
- invalidateProject(projectIdentity);
20742
21011
  if (isConfigLoadUntrusted(detailed)) {
20743
21012
  handleUntrustedLoad(db, projectIdentity, directory, detailed);
20744
21013
  return;
@@ -20755,7 +21024,10 @@ async function ensureProjectRegisteredFromOpenCodeDirectory(directory, db) {
20755
21024
  memoryEnabled: detailed.config.memory.enabled,
20756
21025
  gitCommitEnabled: detailed.config.memory.git_commit_indexing.enabled
20757
21026
  };
20758
- registerProjectEmbedding(db, projectIdentity, routing.primary, features, directory);
21027
+ const before = getProjectEmbeddingSnapshot(projectIdentity);
21028
+ const registered = registerProjectEmbedding(db, projectIdentity, routing.primary, features, directory);
21029
+ if (!before || before.providerIdentity !== registered.providerIdentity || before.runtimeFingerprint !== registered.runtimeFingerprint)
21030
+ invalidateProject(projectIdentity);
20759
21031
  if (routing.shadow) {
20760
21032
  registerProjectShadowEmbedding(db, projectIdentity, routing.shadow, directory);
20761
21033
  } else {
@@ -21090,6 +21362,12 @@ function resolveSessionId(properties) {
21090
21362
  }
21091
21363
  return;
21092
21364
  }
21365
+ function historyBudgetPolicyIdentity(historyBudgetPercentage, executeThresholdPercentage, modelKey, executeThresholdTokens) {
21366
+ if (!historyBudgetPercentage)
21367
+ return "pdefault";
21368
+ const threshold = resolveExecuteThresholdDetail(executeThresholdPercentage ?? 65, modelKey, 65, { tokensConfig: executeThresholdTokens, contextLimit: Number.MAX_SAFE_INTEGER });
21369
+ return `p${historyBudgetPercentage}:${threshold.mode}:${threshold.absoluteTokens ?? threshold.percentage}`;
21370
+ }
21093
21371
 
21094
21372
  // src/features/magic-context/scheduler.ts
21095
21373
  var TTL_PATTERN = /^(\d+)([smh])$/;
@@ -21323,7 +21601,7 @@ async function reconcileSessionIndex(db, sessionId, readMessages) {
21323
21601
  const messages = readMessages.readPage ? readMessages.readPage(sessionId, cursor, RECONCILIATION_BATCH_SIZE, finalWatermark) : (fallbackSnapshot ?? []).filter((message) => message.ordinal > cursor && message.ordinal <= pageEnd);
21324
21602
  const retainedMessages = fallbackSnapshot ?? messages;
21325
21603
  heapHolder.activeReconcilerBuffers.set(sessionId, retainedMessages);
21326
- indexMessagesAfterOrdinal(db, sessionId, messages, cursor, pageEnd);
21604
+ withSqliteBackgroundWriter(() => indexMessagesAfterOrdinal(db, sessionId, messages, cursor, pageEnd));
21327
21605
  const nextCursor = getMessageIndexReconciliationStartOrdinal(db, sessionId);
21328
21606
  if (nextCursor <= cursor)
21329
21607
  break;
@@ -21349,6 +21627,8 @@ function scheduleReconciliation(db, sessionId, readMessages) {
21349
21627
  defer(() => {
21350
21628
  reconcileSessionIndex(db, sessionId, readMessages).catch((error) => {
21351
21629
  logIndexingError(sessionId, "reconciliation", error);
21630
+ if (isDatabaseLockedError(error))
21631
+ setTimeout(() => scheduleReconciliation(db, sessionId, readMessages), 1000).unref();
21352
21632
  }).finally(() => {
21353
21633
  heapHolder.reconciliationScheduledSessions.delete(sessionId);
21354
21634
  });
@@ -21378,7 +21658,7 @@ function scheduleIncrementalIndex(db, sessionId, messageId, messageSource) {
21378
21658
  return;
21379
21659
  }
21380
21660
  const wasReconciled = heapHolder.reconciledSessions.delete(sessionId);
21381
- indexSingleMessage(db, sessionId, message);
21661
+ withSqliteBackgroundWriter(() => indexSingleMessage(db, sessionId, message));
21382
21662
  const finalWatermark = getLastIndexedOrdinal(db, sessionId);
21383
21663
  if (wasReconciled && isMessageIndexReconciledThrough(db, sessionId, finalWatermark)) {
21384
21664
  heapHolder.reconciledSessions.add(sessionId);
@@ -21387,6 +21667,8 @@ function scheduleIncrementalIndex(db, sessionId, messageId, messageSource) {
21387
21667
  }).catch((error) => {
21388
21668
  heapHolder.reconciledSessions.delete(sessionId);
21389
21669
  logIndexingError(sessionId, `incremental index for ${messageId}`, error);
21670
+ if (isDatabaseLockedError(error))
21671
+ setTimeout(() => scheduleIncrementalIndex(db, sessionId, messageId, messageSource), 1000).unref();
21390
21672
  }).finally(() => {
21391
21673
  heapHolder.pendingIncrementalKeys.delete(schedulingKey);
21392
21674
  });
@@ -24293,6 +24575,7 @@ function encodeOpenCodeMessagesToCk(messages) {
24293
24575
  const synthetic = syntheticParts.length > 0 && syntheticParts.every((part) => part !== null && typeof part === "object" && (part.synthetic === true || part.syntheticTodoMarker === true));
24294
24576
  const content = [];
24295
24577
  const recoveryToolTitles = {};
24578
+ const userAnswerBlocks = [];
24296
24579
  for (const partValue of parts) {
24297
24580
  if (partValue === null || typeof partValue !== "object")
24298
24581
  continue;
@@ -24340,6 +24623,8 @@ function encodeOpenCodeMessagesToCk(messages) {
24340
24623
  if (title)
24341
24624
  recoveryToolTitles[callId] = title;
24342
24625
  const output = typeof state.output === "string" ? state.output : typeof state.error === "string" ? state.error : "";
24626
+ if (toolPartHasUserAnswer(part))
24627
+ userAnswerBlocks.push(content.length);
24343
24628
  content.push({
24344
24629
  kind: {
24345
24630
  type: "tool_result",
@@ -24371,9 +24656,12 @@ function encodeOpenCodeMessagesToCk(messages) {
24371
24656
  ck: {
24372
24657
  role,
24373
24658
  content,
24374
- ...Object.keys(recoveryToolTitles).length > 0 ? {
24659
+ ...Object.keys(recoveryToolTitles).length > 0 || userAnswerBlocks.length > 0 ? {
24375
24660
  provider_extras: {
24376
- opencode: { ctx_expand_tool_titles: recoveryToolTitles }
24661
+ opencode: {
24662
+ ...Object.keys(recoveryToolTitles).length > 0 ? { ctx_expand_tool_titles: recoveryToolTitles } : {},
24663
+ ...userAnswerBlocks.length > 0 ? { user_answer_block_indices: userAnswerBlocks } : {}
24664
+ }
24377
24665
  }
24378
24666
  } : {},
24379
24667
  meta: {
@@ -25819,7 +26107,9 @@ function resolveConfigValue(cfg, key, modelKey, defaultValue) {
25819
26107
  }
25820
26108
  function buildSidebarSnapshot(db, sessionId, directory, liveSessionState, injectionBudgetTokens, config, moduleStatus, compactionEnabled = true) {
25821
26109
  try {
25822
- const projectIdentity = resolveProjectIdentity(directory);
26110
+ const projectIdentity = resolveProjectIdentityForSession(directory);
26111
+ if (projectIdentity === undefined)
26112
+ throw new ProjectIdentityError("git_identity_unavailable", directory, "Memory features paused while project identity is unavailable");
25823
26113
  const meta = db.prepare("SELECT * FROM session_meta WHERE session_id = ?").get(sessionId);
25824
26114
  const usagePercentage = meta ? Number(meta.last_context_percentage ?? meta.last_usage_percentage ?? 0) : 0;
25825
26115
  const inputTokens = meta ? Number(meta.last_input_tokens ?? 0) : 0;
@@ -26023,11 +26313,16 @@ function buildSidebarSnapshot(db, sessionId, directory, liveSessionState, inject
26023
26313
  };
26024
26314
  return applyStickySnapshotCache(sessionId, fresh);
26025
26315
  } catch (err) {
26026
- log("[rpc] sidebar-snapshot error:", err);
26316
+ if (!(err instanceof ProjectIdentityError))
26317
+ log("[rpc] sidebar-snapshot error:", err);
26027
26318
  throw err;
26028
26319
  }
26029
26320
  }
26030
26321
  function buildSidebarSnapshotRpcResponse(db, sessionId, directory, liveSessionState, injectionBudgetTokens, config, moduleStatus, compactionEnabled = true) {
26322
+ if (shouldSkipHomeProjectMemory(directory))
26323
+ return { sessionId, disabled: true };
26324
+ if (resolveProjectIdentityForSession(directory) === undefined)
26325
+ return { sessionId, disabled: true, paused: true };
26031
26326
  try {
26032
26327
  return buildSidebarSnapshot(db, sessionId, directory, liveSessionState, injectionBudgetTokens, config, moduleStatus, compactionEnabled);
26033
26328
  } catch {
@@ -26044,7 +26339,7 @@ function safeTickFailure(db) {
26044
26339
  function buildStatusDetail(db, sessionId, directory, modelKey, config, liveSessionState, injectionBudgetTokens, moduleStatus, compactionEnabled = true) {
26045
26340
  const base = buildSidebarSnapshot(db, sessionId, directory, liveSessionState, injectionBudgetTokens, config, moduleStatus, compactionEnabled);
26046
26341
  const rustMode = config?.transform_mode === "rust";
26047
- const projectIdentity = rustMode ? resolveProjectIdentity(directory) : null;
26342
+ const projectIdentity = rustMode && !shouldSkipHomeProjectMemory(directory) ? resolveProjectIdentity(directory) : null;
26048
26343
  const moduleMemoryAuthority = moduleStatus?.authority?.memories;
26049
26344
  const moduleMemoryState = moduleMemoryAuthority?.state;
26050
26345
  const moduleFeedHead = moduleStatus?.memory_mirror?.feed_head;
@@ -26487,6 +26782,10 @@ function registerRpcHandlers(rpcServer, args) {
26487
26782
  rpcServer.handle("status-detail", async (params) => {
26488
26783
  const sessionId = String(params.sessionId ?? "");
26489
26784
  const dir = String(params.directory ?? directory);
26785
+ if (shouldSkipHomeProjectMemory(dir))
26786
+ return { sessionId, disabled: true };
26787
+ if (resolveProjectIdentityForSession(dir) === undefined)
26788
+ return { sessionId, disabled: true, paused: true };
26490
26789
  const modelKey = params.modelKey ? String(params.modelKey) : undefined;
26491
26790
  const db = readDatabase();
26492
26791
  if (!db || !sessionId)
@@ -26507,6 +26806,10 @@ function registerRpcHandlers(rpcServer, args) {
26507
26806
  rpcServer.handle("embed-detail", async (params) => {
26508
26807
  const sessionId = String(params.sessionId ?? "");
26509
26808
  const dir = String(params.directory ?? directory);
26809
+ if (shouldSkipHomeProjectMemory(dir))
26810
+ return { sessionId, disabled: true };
26811
+ if (resolveProjectIdentityForSession(dir) === undefined)
26812
+ return { sessionId, disabled: true, paused: true };
26510
26813
  const db = readDatabase();
26511
26814
  if (!db || !sessionId)
26512
26815
  return { error: "unavailable" };
@@ -26534,7 +26837,7 @@ function registerRpcHandlers(rpcServer, args) {
26534
26837
  return { count: buildCompartmentCount(db, sessionId, moduleStatus) };
26535
26838
  });
26536
26839
  const buildManagedCtx = async (db) => {
26537
- const { deriveHistorianChunkTokens, resolveHistorianContextLimit } = await import("./derive-budgets-gd2270s0.js");
26840
+ const { deriveHistorianChunkTokens, resolveHistorianContextLimit } = await import("./derive-budgets-ncwn1jk9.js");
26538
26841
  const { resolveHistorianModel } = await import("./model-resolution-dxatzjde.js");
26539
26842
  const { userMemoryCollectionEnabled } = await import("./task-config-2bm68628.js");
26540
26843
  const DEFAULT_HISTORIAN_TIMEOUT_MS = 600000;
@@ -26568,8 +26871,8 @@ function registerRpcHandlers(rpcServer, args) {
26568
26871
  const db = readDatabase();
26569
26872
  if (!db)
26570
26873
  return { ok: false, error: "db unavailable" };
26571
- const { runManagedRecomp } = await import("./recomp-orchestrator-rk40ff15.js");
26572
- const { sendIgnoredMessage } = await import("./send-session-notification-6xsrcxnp.js");
26874
+ const { runManagedRecomp } = await import("./recomp-orchestrator-0ers6smx.js");
26875
+ const { sendIgnoredMessage } = await import("./send-session-notification-04hvd54c.js");
26573
26876
  log(`[rpc] recomp requested for session ${sessionId}`);
26574
26877
  const ctx = await buildManagedCtx(db);
26575
26878
  runManagedRecomp(ctx, sessionId).then((message) => {
@@ -26627,7 +26930,7 @@ function registerRpcHandlers(rpcServer, args) {
26627
26930
  const db = readDatabase();
26628
26931
  if (!db)
26629
26932
  return { ok: false, error: "db unavailable" };
26630
- const { runManagedWrapup } = await import("./wrapup-orchestrator-h8tr10c6.js");
26933
+ const { runManagedWrapup } = await import("./wrapup-orchestrator-x0jvvrqn.js");
26631
26934
  const model = liveSessionState.liveModelBySession.get(sessionId);
26632
26935
  const contextLimit = model ? resolveContextLimit(model.providerID, model.modelID, { db, sessionID: sessionId }) : 128000;
26633
26936
  const ctx = {
@@ -27493,162 +27796,6 @@ class EmergencyFailClosedError extends Error {
27493
27796
  }
27494
27797
  }
27495
27798
 
27496
- // src/hooks/magic-context/lkg-persist.ts
27497
- function parseStringArray(value) {
27498
- if (typeof value !== "string")
27499
- return null;
27500
- let parsed;
27501
- try {
27502
- parsed = JSON.parse(value);
27503
- } catch {
27504
- return null;
27505
- }
27506
- if (!Array.isArray(parsed))
27507
- return null;
27508
- const result = [];
27509
- for (const entry of parsed) {
27510
- if (typeof entry !== "string" || entry.length === 0)
27511
- return null;
27512
- result.push(entry);
27513
- }
27514
- return result;
27515
- }
27516
- function parseNullableString(value) {
27517
- if (value === null || value === undefined)
27518
- return null;
27519
- return typeof value === "string" ? value : undefined;
27520
- }
27521
- function parseNullableInteger(value) {
27522
- if (value === null || value === undefined)
27523
- return;
27524
- return typeof value === "number" && Number.isSafeInteger(value) ? value : undefined;
27525
- }
27526
- function parsePersistedLkgSlot(row) {
27527
- if (!row || typeof row !== "object")
27528
- return;
27529
- const record = row;
27530
- const jsonPrefix = record.json_prefix;
27531
- const lastInputMessageId = record.last_input_message_id;
27532
- const capturedAt = record.captured_at;
27533
- let inputIdsRaw = record.input_id_seq;
27534
- let piOutputEntryIds;
27535
- if (typeof inputIdsRaw === "string") {
27536
- try {
27537
- const metadata = JSON.parse(inputIdsRaw);
27538
- if (metadata && !Array.isArray(metadata) && metadata.version === 1 && Array.isArray(metadata.piOutputEntryIds)) {
27539
- if (!metadata.piOutputEntryIds.every((id) => id === null || typeof id === "string" && id.length > 0))
27540
- return;
27541
- piOutputEntryIds = metadata.piOutputEntryIds;
27542
- inputIdsRaw = JSON.stringify(metadata.inputIds);
27543
- }
27544
- } catch {
27545
- return;
27546
- }
27547
- }
27548
- const inputIdSeq = parseStringArray(inputIdsRaw);
27549
- const inputContentDigests = parseStringArray(record.input_content_digests);
27550
- const modelKey = parseNullableString(record.model_key);
27551
- const providerKey = parseNullableString(record.provider_key);
27552
- if (typeof jsonPrefix !== "string" || typeof lastInputMessageId !== "string" || lastInputMessageId.length === 0 || typeof capturedAt !== "number" || !Number.isFinite(capturedAt) || inputIdSeq === null || inputContentDigests === null || inputContentDigests.length !== inputIdSeq.length || modelKey === undefined || providerKey === undefined) {
27553
- return;
27554
- }
27555
- if (piOutputEntryIds) {
27556
- try {
27557
- const output = JSON.parse(jsonPrefix);
27558
- const inputs = new Set(inputIdSeq);
27559
- if (!Array.isArray(output) || output.length !== piOutputEntryIds.length || piOutputEntryIds.some((id) => id !== null && !inputs.has(id)))
27560
- return;
27561
- } catch {
27562
- return;
27563
- }
27564
- }
27565
- let inputContentSignatures;
27566
- if (record.input_content_signatures !== null && record.input_content_signatures !== undefined) {
27567
- const parsed = parseStringArray(record.input_content_signatures);
27568
- if (parsed === null || parsed.length !== inputIdSeq.length)
27569
- return;
27570
- inputContentSignatures = parsed;
27571
- }
27572
- const slot = {
27573
- jsonPrefix,
27574
- inputIdSeq,
27575
- inputContentDigests,
27576
- lastInputMessageId,
27577
- modelKey,
27578
- providerKey,
27579
- capturedAt
27580
- };
27581
- if (inputContentSignatures)
27582
- slot.inputContentSignatures = inputContentSignatures;
27583
- if (piOutputEntryIds)
27584
- slot.piOutputEntryIds = piOutputEntryIds;
27585
- const rowVersion = parseNullableInteger(record.row_version);
27586
- if (rowVersion !== undefined)
27587
- slot.rowVersion = rowVersion;
27588
- const captureSequence = parseNullableInteger(record.capture_sequence);
27589
- if (captureSequence !== undefined)
27590
- slot.captureSequence = captureSequence;
27591
- return slot;
27592
- }
27593
- function saveLkgSlotToDb(db, sessionId, slot) {
27594
- try {
27595
- db.prepare(`INSERT INTO lkg_slots (
27596
- session_id, json_prefix, input_id_seq, input_content_digests,
27597
- input_content_signatures, last_input_message_id, model_key, provider_key,
27598
- captured_at, row_version, capture_sequence
27599
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
27600
- ON CONFLICT(session_id) DO UPDATE SET
27601
- json_prefix = excluded.json_prefix,
27602
- input_id_seq = excluded.input_id_seq,
27603
- input_content_digests = excluded.input_content_digests,
27604
- input_content_signatures = excluded.input_content_signatures,
27605
- last_input_message_id = excluded.last_input_message_id,
27606
- model_key = excluded.model_key,
27607
- provider_key = excluded.provider_key,
27608
- captured_at = excluded.captured_at,
27609
- row_version = excluded.row_version,
27610
- capture_sequence = excluded.capture_sequence`).run(sessionId, slot.jsonPrefix, JSON.stringify(slot.piOutputEntryIds ? {
27611
- version: 1,
27612
- inputIds: slot.inputIdSeq,
27613
- piOutputEntryIds: slot.piOutputEntryIds
27614
- } : slot.inputIdSeq), JSON.stringify(slot.inputContentDigests), slot.inputContentSignatures ? JSON.stringify(slot.inputContentSignatures) : null, slot.lastInputMessageId, slot.modelKey, slot.providerKey, slot.capturedAt, slot.rowVersion ?? null, slot.captureSequence ?? null);
27615
- return true;
27616
- } catch (error) {
27617
- sessionLog(sessionId, "LKG snapshot persistence failed (in-memory slot retained):", error);
27618
- return false;
27619
- }
27620
- }
27621
- function clearPersistedLkgSlot(db, sessionId) {
27622
- try {
27623
- db.prepare("DELETE FROM lkg_slots WHERE session_id = ?").run(sessionId);
27624
- } catch (error) {
27625
- sessionLog(sessionId, "LKG snapshot durable clear failed:", error);
27626
- }
27627
- }
27628
- function loadPersistedLkgSlot(db, sessionId) {
27629
- let row;
27630
- try {
27631
- row = db.prepare("SELECT * FROM lkg_slots WHERE session_id = ?").get(sessionId);
27632
- } catch (error) {
27633
- sessionLog(sessionId, "LKG snapshot durable load failed:", error);
27634
- return;
27635
- }
27636
- if (!row)
27637
- return;
27638
- const slot = parsePersistedLkgSlot(row);
27639
- if (!slot) {
27640
- clearPersistedLkgSlot(db, sessionId);
27641
- return;
27642
- }
27643
- return slot;
27644
- }
27645
- function createDbLkgPersistence(db) {
27646
- return {
27647
- load: (sessionId) => loadPersistedLkgSlot(db, sessionId),
27648
- clear: (sessionId) => clearPersistedLkgSlot(db, sessionId)
27649
- };
27650
- }
27651
-
27652
27799
  // src/hooks/magic-context/openai-compat-adjacency.ts
27653
27800
  function assertOpenAiCompatAdjacency(messages) {
27654
27801
  const violations = [];
@@ -28210,7 +28357,7 @@ function createPassOutcome() {
28210
28357
  }
28211
28358
 
28212
28359
  // src/hooks/magic-context/rust-mode-transform.ts
28213
- import { createHash as createHash12, randomUUID as randomUUID6 } from "node:crypto";
28360
+ import { createHash as createHash13, randomUUID as randomUUID6 } from "node:crypto";
28214
28361
 
28215
28362
  // src/features/magic-context/memory/mirror-reembed.ts
28216
28363
  async function reembedMirrorInvalidatedMemories(db) {
@@ -28674,13 +28821,16 @@ class HistorianHostRunner {
28674
28821
  this.log(`producer window unknown for ${key}: sending unguarded`);
28675
28822
  }
28676
28823
  const output = provider && parts.length ? getSdkOutputLimit(provider, parts.join("/")) : undefined;
28677
- const reserve = historianProducerReserve(window, undefined, output);
28824
+ const producerLimits = resolveHistorianProducerLimits2(key);
28825
+ const context = producerLimits.context ?? (producerLimits.input === undefined ? window : undefined);
28826
+ const reserve = historianProducerReserve(context, undefined, output);
28678
28827
  const failure = producerPromptFailureReason({
28679
28828
  sourceLocal: estimateTokens(claim.user),
28680
28829
  systemLocal: estimateTokens(claim.system),
28681
28830
  toolsLocal: 0,
28682
28831
  modelKey: key,
28683
- contextLimitTokens: window,
28832
+ contextLimitTokens: context,
28833
+ inputLimitTokens: producerLimits.input,
28684
28834
  maxOutputTokens: reserve
28685
28835
  });
28686
28836
  if (failure)
@@ -28790,6 +28940,16 @@ class RawFallbackContextLimitError extends Error {
28790
28940
 
28791
28941
  // src/hooks/magic-context/storage-busy-refusal.ts
28792
28942
  var STORAGE_BUSY_MESSAGE = "Magic Context's database is busy (another process held it too long); send your message again.";
28943
+ function describeStorageBusyCause(cause) {
28944
+ let original = cause;
28945
+ for (let depth = 0;original instanceof SqliteAcquisitionBusyError && depth < 5; depth++) {
28946
+ original = original.cause;
28947
+ }
28948
+ if (!(original instanceof Error))
28949
+ return String(original);
28950
+ return original.stack ? `${original.message}
28951
+ ${original.stack}` : original.message;
28952
+ }
28793
28953
 
28794
28954
  class StorageBusyRefusalError extends Error {
28795
28955
  code = "STORAGE_BUSY_REFUSAL";
@@ -28797,8 +28957,7 @@ class StorageBusyRefusalError extends Error {
28797
28957
  constructor(cause, stage) {
28798
28958
  super(STORAGE_BUSY_MESSAGE, { cause });
28799
28959
  this.name = "StorageBusyRefusalError";
28800
- const original = cause instanceof SqliteAcquisitionBusyError ? cause.cause : cause;
28801
- const detail = original instanceof Error ? original.stack ?? original.message : String(original);
28960
+ const detail = describeStorageBusyCause(cause);
28802
28961
  log(`[magic-context] storage-busy refusal stage=${stage}${cause instanceof SqliteAcquisitionBusyError ? ` acquisition=${cause.stage}` : ""}: ${detail}`);
28803
28962
  }
28804
28963
  }
@@ -29087,10 +29246,10 @@ function messageCacheSignature(message) {
29087
29246
  const parts = Array.isArray(message.parts) ? message.parts : [];
29088
29247
  const serializedParts = JSON.stringify(parts) ?? "null";
29089
29248
  const serializedMessage = JSON.stringify(message) ?? "null";
29090
- return `${messageIdOf(message) ?? ""}:${parts.length}:${Buffer.byteLength(serializedParts)}:${createHash12("sha256").update(serializedMessage).digest("hex")}`;
29249
+ return `${messageIdOf(message) ?? ""}:${parts.length}:${Buffer.byteLength(serializedParts)}:${createHash13("sha256").update(serializedMessage).digest("hex")}`;
29091
29250
  }
29092
29251
  function advanceWireFingerprint(previous, encoded) {
29093
- return createHash12("sha256").update(previous).update("\\0").update(JSON.stringify(encoded) ?? "null").digest("hex");
29252
+ return createHash13("sha256").update(previous).update("\\0").update(JSON.stringify(encoded) ?? "null").digest("hex");
29094
29253
  }
29095
29254
  function buildWireFingerprint(encoded) {
29096
29255
  let fingerprint = "rust-wire-v1";
@@ -29446,7 +29605,7 @@ function canonicalizeForChecksum(value) {
29446
29605
  return Object.fromEntries(Object.keys(value).sort().map((key) => [key, canonicalizeForChecksum(value[key])]));
29447
29606
  }
29448
29607
  function checksumSeedRows(rows) {
29449
- return createHash12("sha256").update(JSON.stringify(rows.map(canonicalizeForChecksum))).digest("hex");
29608
+ return createHash13("sha256").update(JSON.stringify(rows.map(canonicalizeForChecksum))).digest("hex");
29450
29609
  }
29451
29610
  function authoritySeedRows(db, projectPath, domain) {
29452
29611
  const snapshots = domain === "memories" ? db.prepare("SELECT * FROM memories WHERE project_path = ? ORDER BY id ASC").all(projectPath) : db.prepare(`SELECT n.*
@@ -29674,13 +29833,15 @@ function resolvedHistorianModelLimits(chain) {
29674
29833
  return Object.fromEntries(chain.map((key) => {
29675
29834
  const [provider, ...parts] = key.split("/");
29676
29835
  const output = provider && parts.length ? getSdkOutputLimit(provider, parts.join("/")) : undefined;
29677
- const known = resolveKnownHistorianContextLimit2(key);
29836
+ const producerLimits = resolveHistorianProducerLimits2(key);
29837
+ const known = producerLimits.input === undefined ? resolveKnownHistorianContextLimit2(key) : undefined;
29678
29838
  const learned = provider && parts.length ? getSdkWindowGeometry(provider, parts.join("/"))?.derivation.window : undefined;
29679
- const context = known === undefined ? learned : learned === undefined ? known : Math.min(known, learned);
29839
+ const context = producerLimits.context ?? (known === undefined ? learned : learned === undefined ? known : Math.min(known, learned));
29680
29840
  return [
29681
29841
  key,
29682
29842
  {
29683
29843
  ...context !== undefined ? { context } : {},
29844
+ ...producerLimits.input !== undefined ? { input: producerLimits.input } : {},
29684
29845
  ...output !== undefined ? { output } : {}
29685
29846
  }
29686
29847
  ];
@@ -31083,6 +31244,16 @@ function createRustModeTransform(deps, options) {
31083
31244
  }
31084
31245
  pendingWireCache.nativeOutput = moduleMessages;
31085
31246
  if (!replayedFrozenRepresentation) {
31247
+ if (materializedBoundary && !deps.compactionOff) {
31248
+ try {
31249
+ await withAsyncPrivilegedWriter(deps.db, () => {
31250
+ return;
31251
+ });
31252
+ } catch (error) {
31253
+ if (!isTransientSqliteError(error))
31254
+ throw error;
31255
+ }
31256
+ }
31086
31257
  const postprocess = runRustModePostprocess2({
31087
31258
  db: deps.db,
31088
31259
  sessionId,
@@ -31307,7 +31478,7 @@ function createRustModeTransform(deps, options) {
31307
31478
  if (mirrorDrain.rowsApplied > 0) {
31308
31479
  await reembedMirrorInvalidatedMemories(deps.db);
31309
31480
  }
31310
- await drainSingleStoreEmbeddingWatermarks(deps.db);
31481
+ await withSqliteBackgroundWriter(() => drainSingleStoreEmbeddingWatermarks(deps.db));
31311
31482
  if (mirrorDrain.complete) {
31312
31483
  state.memoryMirrorProjectionKey = projectionKey;
31313
31484
  } else if (mirrorDrain.budgetExhausted) {
@@ -32255,7 +32426,9 @@ function createTransform(deps) {
32255
32426
  const persistedUsageFreshForBoundary = persistedUsageBeforeResets && Date.now() - persistedUsageBeforeResets.updatedAt <= 10 * 60 * 1000 && (persistedUsageBeforeResets.lastObservedModelKey === null || currentModelKeyForBoundary === undefined || piModelRefToCanonical(persistedUsageBeforeResets.lastObservedModelKey) === piModelRefToCanonical(currentModelKeyForBoundary)) && (resolvedContextLimit === undefined || persistedUsageBeforeResets.lastUsageContextLimit === 0 || persistedUsageBeforeResets.lastUsageContextLimit === resolvedContextLimit) ? persistedUsageBeforeResets.usage : null;
32256
32427
  const boundaryUsageForProtectedTail = persistedUsageFreshForBoundary ?? contextUsageEarly;
32257
32428
  const boundaryUsageSource = persistedUsageFreshForBoundary ? "persisted" : "live";
32258
- const historyBudgetTokens = resolveHistoryBudgetTokens(deps.historyBudgetPercentage, contextUsageEarly, deps.executeThresholdPercentage, deps.getModelKey?.(sessionId), deps.executeThresholdTokens, resolvedContextLimit);
32429
+ const historyPolicyIdentity = historyBudgetPolicyIdentity(deps.historyBudgetPercentage, deps.executeThresholdPercentage, currentModelKeyForBoundary, deps.executeThresholdTokens);
32430
+ const historyContextLimit = resolvedContextLimit ?? (currentModelKeyForBoundary && persistedUsageBeforeResets?.lastObservedModelKey && piModelRefToCanonical(currentModelKeyForBoundary) === piModelRefToCanonical(persistedUsageBeforeResets.lastObservedModelKey) && persistedUsageBeforeResets.lastUsageContextLimit > 0 ? persistedUsageBeforeResets.lastUsageContextLimit : undefined);
32431
+ const historyBudgetTokens = resolveHistoryBudgetTokens(deps.historyBudgetPercentage, contextUsageEarly, deps.executeThresholdPercentage, deps.getModelKey?.(sessionId), deps.executeThresholdTokens, historyContextLimit);
32259
32432
  const emergencyCeilingLimit = thresholdContextLimit ?? 0;
32260
32433
  const emergencyCeilingTokens = Number.isFinite(emergencyCeilingLimit) && emergencyCeilingLimit > 0 ? Math.floor(emergencyCeilingLimit * (effectiveExecuteThresholdPercentage / 100)) : undefined;
32261
32434
  const schedulerDecision = compactionOff ? "defer" : resolveSchedulerDecision(deps.scheduler, sessionMeta, contextUsageEarly, sessionId, deps.getModelKey?.(sessionId), resolvedContextLimit);
@@ -32629,6 +32802,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
32629
32802
  muralEnabled: deps.muralEnabled,
32630
32803
  memoryInjectionBudgetTokens: deps.memoryConfig?.injectionBudgetTokens,
32631
32804
  historyBudgetTokens,
32805
+ historyBudgetPolicyIdentity: historyPolicyIdentity,
32632
32806
  hardSignals: m0HardSignals
32633
32807
  }).value;
32634
32808
  const protectionCacheBustingPass = !compactionOff && (schedulerDecision === "execute" || isCacheBusting || contextUsage.percentage >= forceMaterializationPercentage || deps.pendingMaterializationSessions.has(sessionId) || canConsumeDeferredLate && deferredMaterializationSessions.has(sessionId) || protectionFoldWillBust);
@@ -32752,6 +32926,7 @@ Historian previously failed ${historianFailureState.failureCount} time(s), so Ma
32752
32926
  memoryEnabled: deps.memoryConfig?.enabled,
32753
32927
  memoryInjectionBudgetTokens: deps.memoryConfig?.injectionBudgetTokens,
32754
32928
  historyBudgetTokens,
32929
+ historyBudgetPolicyIdentity: historyPolicyIdentity,
32755
32930
  temporalAwareness: deps.experimentalTemporalAwareness,
32756
32931
  hardSignals: m0HardSignals,
32757
32932
  muralEnabled: deps.muralEnabled
@@ -34241,7 +34416,7 @@ function createTextCompleteHandler() {
34241
34416
  }
34242
34417
 
34243
34418
  // src/hooks/magic-context/system-prompt-hash.ts
34244
- import { createHash as createHash13 } from "node:crypto";
34419
+ import { createHash as createHash14 } from "node:crypto";
34245
34420
  var MAGIC_CONTEXT_MARKER = "## Magic Context";
34246
34421
  var SYSTEM_PROMPT_GUIDANCE_SEPARATOR = `
34247
34422
 
@@ -34338,7 +34513,7 @@ function createSystemPromptHashHandler(deps) {
34338
34513
  }
34339
34514
  const stickyDate = stickyDateBySession.get(sessionId);
34340
34515
  const stableCandidate = currentDate && stickyDate && currentDate !== stickyDate ? liveSystemContent.replace(DATE_PATTERN_ALL, stickyDate) : liveSystemContent;
34341
- const stableCandidateHash = createHash13("md5").update(promptSurfaceHashMaterial(stableCandidate, promptSurface.preset)).digest("hex");
34516
+ const stableCandidateHash = createHash14("md5").update(promptSurfaceHashMaterial(stableCandidate, promptSurface.preset)).digest("hex");
34342
34517
  const contentOrPresetChanged = hasPersistedHash && stableCandidateHash !== previousHash;
34343
34518
  const dateMayAdvance = isCacheBusting || contentOrPresetChanged;
34344
34519
  if (currentDate && !stickyDate) {
@@ -34358,7 +34533,7 @@ function createSystemPromptHashHandler(deps) {
34358
34533
  `);
34359
34534
  if (!availability.frozen || !modelKey)
34360
34535
  return;
34361
- const currentHash = createHash13("md5").update(promptSurfaceHashMaterial(systemContent, promptSurface.preset)).digest("hex");
34536
+ const currentHash = createHash14("md5").update(promptSurfaceHashMaterial(systemContent, promptSurface.preset)).digest("hex");
34362
34537
  if (!sessionMetaEarly) {
34363
34538
  return;
34364
34539
  }
@@ -35283,6 +35458,13 @@ function createMessagesTransformHandler(args) {
35283
35458
  }
35284
35459
  })() : null;
35285
35460
  try {
35461
+ if (!args.compactionOff && magicContext) {
35462
+ const admissionDb = openDatabase();
35463
+ if (admissionDb)
35464
+ await withAsyncPrivilegedWriter(admissionDb, () => {
35465
+ return;
35466
+ });
35467
+ }
35286
35468
  await magicContext?.["experimental.chat.messages.transform"]?.(input, output);
35287
35469
  return output.messages;
35288
35470
  } catch (error) {
@@ -37433,7 +37615,7 @@ Keep: user messages (never stamp one for its directive), your own conversation t
37433
37615
 
37434
37616
  Look at each tag before stamping it; never blanket-stamp a range like "1-50". Many small targeted stamps beat one sweep. \`drop\` accepts "3-5", "1,2,9", "1-5,8,12-15".`;
37435
37617
  // src/tools/ctx-reduce/tools.ts
37436
- import { createHash as createHash14 } from "node:crypto";
37618
+ import { createHash as createHash15 } from "node:crypto";
37437
37619
  import { tool as tool4 } from "@opencode-ai/plugin";
37438
37620
 
37439
37621
  // src/features/magic-context/range-parser.ts
@@ -37503,11 +37685,11 @@ function createCtxReduceTool(deps) {
37503
37685
  const stableId = `oc-${sessionId}-${callId}`;
37504
37686
  if (Buffer.byteLength(stableId) <= 128)
37505
37687
  return stableId;
37506
- return `oc-${createHash14("sha256").update(stableId).digest("hex")}`;
37688
+ return `oc-${createHash15("sha256").update(stableId).digest("hex")}`;
37507
37689
  }
37508
37690
  fallbackCommandSequence += 1;
37509
37691
  const monotonicId = `oc-${sessionId}-${fallbackCommandSequence}`;
37510
- return Buffer.byteLength(monotonicId) <= 128 ? monotonicId : `oc-${createHash14("sha256").update(monotonicId).digest("hex")}`;
37692
+ return Buffer.byteLength(monotonicId) <= 128 ? monotonicId : `oc-${createHash15("sha256").update(monotonicId).digest("hex")}`;
37511
37693
  };
37512
37694
  return tool4({
37513
37695
  description: CTX_REDUCE_DESCRIPTION,
@@ -38071,7 +38253,7 @@ import {
38071
38253
  chmodSync as chmodSync2,
38072
38254
  mkdirSync as mkdirSync5,
38073
38255
  readdirSync as readdirSync2,
38074
- readFileSync as readFileSync7,
38256
+ readFileSync as readFileSync8,
38075
38257
  renameSync as renameSync5,
38076
38258
  rmSync as rmSync5,
38077
38259
  unlinkSync,
@@ -38218,7 +38400,7 @@ class MagicContextRpcServer {
38218
38400
  for (const entry of readdirSync2(this.portDir)) {
38219
38401
  if (!entry.startsWith("port-") || !entry.endsWith(".json"))
38220
38402
  continue;
38221
- const record = parseRpcPortFile(readFileSync7(`${this.portDir}/${entry}`, "utf-8"));
38403
+ const record = parseRpcPortFile(readFileSync8(`${this.portDir}/${entry}`, "utf-8"));
38222
38404
  if (!record || record.pid === process.pid)
38223
38405
  continue;
38224
38406
  const processes = await inspectProcessesAsync();
@@ -38534,8 +38716,8 @@ function hostMediaAsset(data, mediaType) {
38534
38716
  }
38535
38717
 
38536
38718
  // src/v2/fold/owner.ts
38537
- import { createHash as createHash15 } from "node:crypto";
38538
- var foldDigest = (value) => createHash15("sha256").update(value).digest("hex");
38719
+ import { createHash as createHash16 } from "node:crypto";
38720
+ var foldDigest = (value) => createHash16("sha256").update(value).digest("hex");
38539
38721
 
38540
38722
  class FoldOwner {
38541
38723
  storage;
@@ -38838,7 +39020,7 @@ ${data.output?.output ?? ""}`
38838
39020
  }
38839
39021
 
38840
39022
  // src/v2/host-service.ts
38841
- import { readdirSync as readdirSync3, readFileSync as readFileSync8 } from "node:fs";
39023
+ import { readdirSync as readdirSync3, readFileSync as readFileSync9 } from "node:fs";
38842
39024
  import { homedir as homedir3 } from "node:os";
38843
39025
  import { join as join11 } from "node:path";
38844
39026
 
@@ -39009,7 +39191,7 @@ class V2StoreReader {
39009
39191
  return { rows, cursor: rows.at(-1)?.seq };
39010
39192
  });
39011
39193
  }
39012
- messagePage(sessionID, afterOrdinal, limit, finalWatermark) {
39194
+ messagePage(sessionID, afterOrdinal, limit, finalWatermark, after) {
39013
39195
  return trackDecodeOperation("messagePage", () => {
39014
39196
  if (!Number.isSafeInteger(afterOrdinal) || afterOrdinal < 0)
39015
39197
  throw new Error("Invalid raw-message ordinal cursor");
@@ -39020,6 +39202,14 @@ class V2StoreReader {
39020
39202
  const pageSize = Math.min(limit, finalWatermark - afterOrdinal);
39021
39203
  if (pageSize <= 0)
39022
39204
  return [];
39205
+ if (after) {
39206
+ const anchor = this.db.prepare("SELECT seq FROM session_message WHERE session_id = ? AND id = ?").get(sessionID, after.id);
39207
+ if (anchor) {
39208
+ return this.db.prepare(`SELECT id, session_id, type, seq, time_created, data
39209
+ FROM session_message WHERE session_id = ? AND seq > ?
39210
+ AND type IN (${RAW_MESSAGE_TYPE_PARAMETERS}) ORDER BY seq ASC LIMIT ?`).all(sessionID, anchor.seq, ...RAW_MESSAGE_TYPES, pageSize).map(decode);
39211
+ }
39212
+ }
39023
39213
  const maximumSeq = Number.MAX_SAFE_INTEGER;
39024
39214
  const rows = this.db.prepare(V2_MESSAGE_PAGE_SQL).all(afterOrdinal, sessionID, ...RAW_MESSAGE_TYPES, Math.max(0, afterOrdinal - 1), sessionID, ...RAW_MESSAGE_TYPES, finalWatermark - 1, maximumSeq, sessionID, ...RAW_MESSAGE_TYPES, pageSize);
39025
39215
  return rows.map(decode);
@@ -39254,7 +39444,7 @@ class HostServiceUnavailable extends Error {
39254
39444
  function parseRegistration(path) {
39255
39445
  let text;
39256
39446
  try {
39257
- text = readFileSync8(path, "utf8");
39447
+ text = readFileSync9(path, "utf8");
39258
39448
  } catch {
39259
39449
  return;
39260
39450
  }
@@ -39368,8 +39558,8 @@ var POLL_INTERVAL_MS = 200;
39368
39558
  var REMOVAL_SPACING_MS = 250;
39369
39559
  var RETIRED_CHILDREN_LIMIT = 200;
39370
39560
  var LEGACY_CLEANUP_BOOT_LIMIT = 5;
39371
- function hiddenChildrenMetaKey(projectIdentity) {
39372
- return `${META_PREFIX}${projectIdentity}`;
39561
+ function hiddenChildrenMetaKey(projectIdentity, directory) {
39562
+ return directory === undefined ? `${META_PREFIX}${projectIdentity}` : `${META_PREFIX}${JSON.stringify([projectIdentity, directory])}`;
39373
39563
  }
39374
39564
  function emptyMeta() {
39375
39565
  return { version: 1, active: {}, retired_children: [] };
@@ -39431,9 +39621,49 @@ function parseMeta(value) {
39431
39621
  class HiddenChildStateStore {
39432
39622
  db;
39433
39623
  key;
39434
- constructor(db, projectIdentity) {
39624
+ constructor(db, projectIdentity, directory) {
39435
39625
  this.db = db;
39436
- this.key = hiddenChildrenMetaKey(projectIdentity);
39626
+ this.key = hiddenChildrenMetaKey(projectIdentity, directory);
39627
+ this.legacyKey = hiddenChildrenMetaKey(projectIdentity);
39628
+ }
39629
+ legacyKey;
39630
+ migrateStale(isStale) {
39631
+ this.db.transaction(() => {
39632
+ const legacyRow = this.db.prepare("SELECT value FROM schema_migrations_meta WHERE key = ?").get(this.legacyKey);
39633
+ if (!legacyRow)
39634
+ return;
39635
+ const legacy = parseMeta(legacyRow.value);
39636
+ const scoped = this.read();
39637
+ for (const role of ["historian", "dreamer"]) {
39638
+ const child = legacy.active[role];
39639
+ if (!child || !isStale(child))
39640
+ continue;
39641
+ scoped.retired_children.push({
39642
+ ...child,
39643
+ retired_at: Date.now(),
39644
+ reason: "legacy-directory-scope"
39645
+ });
39646
+ delete legacy.active[role];
39647
+ }
39648
+ const remaining = [];
39649
+ for (const child of legacy.retired_children) {
39650
+ if (isStale(child))
39651
+ scoped.retired_children.push(child);
39652
+ else
39653
+ remaining.push(child);
39654
+ }
39655
+ legacy.retired_children = remaining;
39656
+ const excess = scoped.retired_children.length - RETIRED_CHILDREN_LIMIT;
39657
+ if (excess > 0)
39658
+ scoped.retired_children.splice(0, excess);
39659
+ this.db.prepare(`INSERT INTO schema_migrations_meta (key, value) VALUES (?, ?)
39660
+ ON CONFLICT(key) DO UPDATE SET value = excluded.value`).run(this.key, JSON.stringify(scoped));
39661
+ if (Object.keys(legacy.active).length === 0 && legacy.retired_children.length === 0) {
39662
+ this.db.prepare("DELETE FROM schema_migrations_meta WHERE key = ?").run(this.legacyKey);
39663
+ } else {
39664
+ this.db.prepare("UPDATE schema_migrations_meta SET value = ? WHERE key = ?").run(JSON.stringify(legacy), this.legacyKey);
39665
+ }
39666
+ }).immediate();
39437
39667
  }
39438
39668
  read() {
39439
39669
  const row = this.db.prepare("SELECT value FROM schema_migrations_meta WHERE key = ?").get(this.key);
@@ -39660,6 +39890,12 @@ async function sleepUntilPoll(signal, deadline) {
39660
39890
  }, delay);
39661
39891
  });
39662
39892
  }
39893
+ function isProviderFailure(error) {
39894
+ if (!error || typeof error !== "object")
39895
+ return false;
39896
+ const type = error.type;
39897
+ return typeof type === "string" && (type.startsWith("provider.") || type.toLowerCase().includes("provider"));
39898
+ }
39663
39899
  async function awaitAssistantRow(openReader, readSessionError, stepLimit, childID, afterSeq, deadline, signal) {
39664
39900
  for (;; ) {
39665
39901
  const { assistant, idle } = withReader(openReader, (reader) => ({
@@ -39680,7 +39916,7 @@ async function awaitAssistantRow(openReader, readSessionError, stepLimit, childI
39680
39916
  `terminal_row=${errorText(newIdle)}`,
39681
39917
  `session_error=${sessionError === undefined ? "unavailable" : errorText(sessionError)}`
39682
39918
  ];
39683
- throw sessionError === undefined ? new Error(`Hidden completion failed without a provider error: ${details.join("; ")}`) : new HiddenProviderError(details.join("; "));
39919
+ throw sessionError === undefined || !isProviderFailure(sessionError) ? new Error(`Hidden completion failed: ${details.join("; ")}`) : new HiddenProviderError(details.join("; "));
39684
39920
  }
39685
39921
  if (outcome === "succeeded" && newAssistant)
39686
39922
  return newAssistant;
@@ -39694,7 +39930,7 @@ async function awaitAssistantRow(openReader, readSessionError, stepLimit, childI
39694
39930
  `terminal_row=${errorText(newAssistant)}`,
39695
39931
  `session_error=${sessionError === undefined ? "unavailable" : errorText(sessionError)}`
39696
39932
  ];
39697
- throw sessionError === undefined ? new Error(`Hidden completion failed without a provider error: ${details.join("; ")}`) : new HiddenProviderError(details.join("; "));
39933
+ throw sessionError === undefined || !isProviderFailure(sessionError) ? new Error(`Hidden completion failed: ${details.join("; ")}`) : new HiddenProviderError(details.join("; "));
39698
39934
  }
39699
39935
  if (newAssistant.data.error !== undefined) {
39700
39936
  throw new HiddenProviderError(errorText(newAssistant.data.error), {
@@ -39734,9 +39970,35 @@ function createLateHiddenExecutor(current) {
39734
39970
  }
39735
39971
  async function createV2HiddenCompletionExecutor(host, options) {
39736
39972
  const runs = new WeakMap;
39737
- const store = new HiddenChildStateStore(options.db, options.projectIdentity);
39973
+ const store = new HiddenChildStateStore(options.db, options.projectIdentity, options.directory);
39738
39974
  const generation = options.generation ?? "opencode2";
39739
39975
  const roleTails = new Map;
39976
+ const legacy = options.db.prepare("SELECT value FROM schema_migrations_meta WHERE key = ?").get(hiddenChildrenMetaKey(options.projectIdentity));
39977
+ if (legacy) {
39978
+ const children = parseMeta(legacy.value);
39979
+ const statuses = new Map;
39980
+ for (const child of [...Object.values(children.active), ...children.retired_children]) {
39981
+ if (!child || !host.status)
39982
+ continue;
39983
+ const directory = child.directory ?? options.directory;
39984
+ if (!statuses.has(directory)) {
39985
+ try {
39986
+ statuses.set(directory, await host.status({ directory }));
39987
+ } catch {
39988
+ statuses.set(directory, undefined);
39989
+ }
39990
+ }
39991
+ }
39992
+ store.migrateStale((child) => {
39993
+ const directory = child.directory ?? options.directory;
39994
+ const state = statuses.get(directory);
39995
+ if (host.status && (!state || state[child.id]?.type === "busy" || state[child.id]?.type === "retry"))
39996
+ return false;
39997
+ const last = Math.max(child.created_at, withReader(options.openReader, (reader) => Math.max(reader.latestAssistant(child.id)?.data.time?.created ?? 0, reader.latestIdle(child.id)?.data.time?.created ?? 0)));
39998
+ const staleMs = child.role === "historian" ? historianOrphanStaleMs(20 * 60000, 3) : retrospectiveOrphanStaleMs(undefined);
39999
+ return Date.now() - last > staleMs;
40000
+ });
40001
+ }
39740
40002
  const persisted = store.read();
39741
40003
  for (const child of [...Object.values(persisted.active), ...persisted.retired_children]) {
39742
40004
  if (child)
@@ -40106,6 +40368,7 @@ async function createV2HiddenCompletionExecutor(host, options) {
40106
40368
  }
40107
40369
  run.completion = {
40108
40370
  text,
40371
+ tokenLog: runTokenLog(tokens, run.identity.maxOutputTokens, row.data.finish),
40109
40372
  ...hiddenToolLoop(run.identity) ? { messages: toolLoopMessages(attempt) } : {},
40110
40373
  reasoning: text ? null : assistantReasoning(row),
40111
40374
  usage: reportedInput !== undefined || reportedOutput !== undefined ? {
@@ -40479,10 +40742,19 @@ function startDreamTrigger(context, args) {
40479
40742
  };
40480
40743
  }
40481
40744
 
40745
+ // src/v2/hooks/hidden-terminal-error.ts
40746
+ function hiddenTerminalError(event) {
40747
+ if (event.type === "session.execution.failed")
40748
+ return event.data?.error;
40749
+ if (event.type === "session.error")
40750
+ return getSessionErrorInfo(event.data)?.error;
40751
+ return;
40752
+ }
40753
+
40482
40754
  // src/v2/hooks/lkg-system.ts
40483
- import { createHash as createHash16 } from "node:crypto";
40755
+ import { createHash as createHash17 } from "node:crypto";
40484
40756
  function identity(slot) {
40485
- return createHash16("sha256").update(JSON.stringify({
40757
+ return createHash17("sha256").update(JSON.stringify({
40486
40758
  capturedAt: slot.capturedAt,
40487
40759
  captureSequence: slot.captureSequence,
40488
40760
  rowVersion: slot.rowVersion,
@@ -40719,6 +40991,7 @@ function adaptPayload(draft, admittedIDs = new Set) {
40719
40991
  input: structuredClone(call?.input ?? {}),
40720
40992
  status: result ? "completed" : "running",
40721
40993
  ...result ? { output } : {},
40994
+ ...result && (call?.name ?? result.part.name) === "question" ? { metadata: { userAnswer: true } } : {},
40722
40995
  ...files ? { attachments: contentValueAttachments(files) } : {}
40723
40996
  }
40724
40997
  };
@@ -41258,10 +41531,10 @@ function* readV2RawMessagePagesForConversion(openReader, sessionID, pageRows = C
41258
41531
  function createV2RawMessageReader(openReader) {
41259
41532
  const servedBoundaryCache = new Map;
41260
41533
  return {
41261
- readPage: (sessionID, afterOrdinal, limit, finalWatermark) => {
41534
+ readPage: (sessionID, afterOrdinal, limit, finalWatermark, after) => {
41262
41535
  const reader = openReader();
41263
41536
  try {
41264
- return rawMessagePage(reader.messagePage(sessionID, afterOrdinal, limit, finalWatermark), afterOrdinal);
41537
+ return rawMessagePage(reader.messagePage(sessionID, afterOrdinal, limit, finalWatermark, after), afterOrdinal);
41265
41538
  } finally {
41266
41539
  reader.close();
41267
41540
  }
@@ -41355,7 +41628,7 @@ function createV2RawMessageReader(openReader) {
41355
41628
  }
41356
41629
  function createV2RawMessageProvider(reader, sessionID) {
41357
41630
  return {
41358
- readMessagePage: (afterOrdinal, limit, finalWatermark) => reader.readPage(sessionID, afterOrdinal, limit, finalWatermark),
41631
+ readMessagePage: (afterOrdinal, limit, finalWatermark, after) => reader.readPage(sessionID, afterOrdinal, limit, finalWatermark, after),
41359
41632
  readMessageById: (messageID) => reader.findById(sessionID, messageID),
41360
41633
  readMessagePartsById: (messageID) => reader.findPartsById(sessionID, messageID),
41361
41634
  hasMessageById: (messageID) => reader.hasById(sessionID, messageID),
@@ -41413,6 +41686,10 @@ async function registerTools(context, db, config, rustToolBackends) {
41413
41686
  input: tool7.schema.toJSONSchema(tool7.schema.object(definition.args)),
41414
41687
  options: { codemode: false },
41415
41688
  async execute(input, call) {
41689
+ if (name === "ctx_memory" || name === "ctx_note" || name === "ctx_reduce")
41690
+ await withAsyncPrivilegedWriter(db, () => {
41691
+ return;
41692
+ });
41416
41693
  const result = await definition.execute(tool7.schema.object(definition.args).parse(input), {
41417
41694
  sessionID: call.sessionID,
41418
41695
  messageID: call.messageID,
@@ -41645,6 +41922,7 @@ async function applyV2SystemPrompt(systemPrompt, draft) {
41645
41922
  async function registerContext(context) {
41646
41923
  const directory = context.location.directory;
41647
41924
  const config = loadPluginConfigDetailed(directory).config;
41925
+ setHomeProjectPermission(config.allow_home_project);
41648
41926
  if (!config.enabled)
41649
41927
  return;
41650
41928
  const liveConfigReader = pluginConfigReader(directory, config);
@@ -41753,6 +42031,7 @@ async function registerContext(context) {
41753
42031
  }, {
41754
42032
  db: database,
41755
42033
  projectIdentity: resolveProjectIdentityForSession(directory, config.allow_home_project) ?? "",
42034
+ directory,
41756
42035
  hook: hiddenChildHook,
41757
42036
  keepSubagents: config.keep_subagents === true,
41758
42037
  ensureAgent: () => hiddenAgentsReady ??= context.agent.reload(),
@@ -41955,8 +42234,8 @@ async function registerContext(context) {
41955
42234
  if (!event.data?.sessionID)
41956
42235
  continue;
41957
42236
  const sessionID = event.data.sessionID;
41958
- if (event.type === "session.error") {
41959
- const error = getSessionErrorInfo(event.data)?.error;
42237
+ if (event.type === "session.error" || event.type === "session.execution.failed") {
42238
+ const error = hiddenTerminalError(event);
41960
42239
  if (error !== undefined)
41961
42240
  hiddenSessionErrors.set(sessionID, error);
41962
42241
  continue;
@@ -42079,7 +42358,7 @@ async function registerContext(context) {
42079
42358
  try {
42080
42359
  const admissionDb = db ?? storage.current();
42081
42360
  if (!compactionOff && admissionDb)
42082
- withPrivilegedWriter(admissionDb, () => {
42361
+ await withAsyncPrivilegedWriter(admissionDb, () => {
42083
42362
  return;
42084
42363
  });
42085
42364
  recordV2ToolDefinitions(draft);
@@ -42465,14 +42744,14 @@ ${baseline}
42465
42744
  }
42466
42745
 
42467
42746
  // src/v2/hooks/update-check.ts
42468
- import { existsSync as existsSync12, readFileSync as readFileSync9 } from "node:fs";
42747
+ import { existsSync as existsSync12, readFileSync as readFileSync10 } from "node:fs";
42469
42748
  import { dirname as dirname6, join as join12 } from "node:path";
42470
42749
  import { fileURLToPath as fileURLToPath3 } from "node:url";
42471
42750
  function packageInfo() {
42472
42751
  let directory = dirname6(fileURLToPath3(import.meta.url));
42473
42752
  for (;; ) {
42474
42753
  try {
42475
- const pkg = JSON.parse(readFileSync9(join12(directory, "package.json"), "utf8"));
42754
+ const pkg = JSON.parse(readFileSync10(join12(directory, "package.json"), "utf8"));
42476
42755
  if (pkg.name === "@cortexkit/opencode-magic-context" && typeof pkg.version === "string") {
42477
42756
  return {
42478
42757
  version: pkg.version,
@@ -42570,6 +42849,7 @@ var server = async (ctx) => {
42570
42849
  });
42571
42850
  const loadedPluginConfig = loadPluginConfigDetailed(ctx.directory);
42572
42851
  const pluginConfig = loadedPluginConfig.config;
42852
+ setHomeProjectPermission(pluginConfig.allow_home_project);
42573
42853
  const liveConfigReader = pluginConfigReader(ctx.directory, pluginConfig);
42574
42854
  const dreamerCap = createDreamerOutputCapSampler(pluginConfig, () => liveConfigReader.poll().effective);
42575
42855
  reloadWindowOverlay(pluginConfig.models?.window_overlay_path);
@@ -42603,7 +42883,7 @@ var server = async (ctx) => {
42603
42883
  if (hasBannerEntries)
42604
42884
  setTimeout(async () => {
42605
42885
  try {
42606
- const { sendStatusNotification } = await import("./send-session-notification-6xsrcxnp.js");
42886
+ const { sendStatusNotification } = await import("./send-session-notification-04hvd54c.js");
42607
42887
  const clientWithSessions = ctx.client;
42608
42888
  const sessions = await Promise.resolve(clientWithSessions.session?.list?.()).catch(() => null);
42609
42889
  const sessionList = Array.isArray(sessions) ? sessions : sessions?.data;
@@ -42620,7 +42900,7 @@ var server = async (ctx) => {
42620
42900
  log(`[magic-context] opencode_db_missing path=${openCodeDbResolution.path} source=${openCodeDbResolution.source}`);
42621
42901
  setTimeout(async () => {
42622
42902
  try {
42623
- const { sendStatusNotification } = await import("./send-session-notification-6xsrcxnp.js");
42903
+ const { sendStatusNotification } = await import("./send-session-notification-04hvd54c.js");
42624
42904
  const clientWithSessions = ctx.client;
42625
42905
  const sessions = await Promise.resolve(clientWithSessions.session?.list?.()).catch(() => null);
42626
42906
  const sessionList = Array.isArray(sessions) ? sessions : sessions?.data;
@@ -42894,12 +43174,12 @@ var server = async (ctx) => {
42894
43174
  {
42895
43175
  const fence = getSchemaFenceRejection();
42896
43176
  if (fence) {
42897
- import("./conflict-warning-hook-1msyvb51.js").then(({ sendSchemaFenceWarning }) => sendSchemaFenceWarning(ctx.client, ctx.directory, fence));
43177
+ import("./conflict-warning-hook-hmpzxep6.js").then(({ sendSchemaFenceWarning }) => sendSchemaFenceWarning(ctx.client, ctx.directory, fence));
42898
43178
  }
42899
43179
  }
42900
43180
  const serverUrl = ctx.serverUrl;
42901
43181
  const serverUrlStr = serverUrl instanceof URL ? serverUrl.toString().replace(/\/$/, "") : typeof serverUrl === "string" ? serverUrl.replace(/\/$/, "") : undefined;
42902
- import("./send-session-notification-6xsrcxnp.js").then(({ setNotificationServerUrl }) => {
43182
+ import("./send-session-notification-04hvd54c.js").then(({ setNotificationServerUrl }) => {
42903
43183
  setNotificationServerUrl(serverUrlStr);
42904
43184
  });
42905
43185
  if (conflictResult?.hasConflict) {
@@ -42922,7 +43202,7 @@ var server = async (ctx) => {
42922
43202
  }) => {
42923
43203
  if (!shouldShowAnnouncement())
42924
43204
  return;
42925
- return import("./conflict-warning-hook-1msyvb51.js").then(({ sendStartupAnnouncement }) => sendStartupAnnouncement(ctx.client, ctx.directory, ANNOUNCEMENT_VERSION, ANNOUNCEMENT_FEATURES, ANNOUNCEMENT_FOOTER, markAnnouncementSeen));
43205
+ return import("./conflict-warning-hook-hmpzxep6.js").then(({ sendStartupAnnouncement }) => sendStartupAnnouncement(ctx.client, ctx.directory, ANNOUNCEMENT_VERSION, ANNOUNCEMENT_FEATURES, ANNOUNCEMENT_FOOTER, markAnnouncementSeen));
42926
43206
  }).catch(() => {});
42927
43207
  }, 8000);
42928
43208
  }
@@ -42991,8 +43271,8 @@ var server = async (ctx) => {
42991
43271
  internalChildSessions: liveSessionState.internalChildSessions,
42992
43272
  tryReopenStorage,
42993
43273
  onStorageBusyRefusal: async (sessionId, message) => {
42994
- const { sendStatusNotification } = await import("./send-session-notification-6xsrcxnp.js");
42995
- const { abortSessionFailClosed } = await import("./transform-postprocess-phase-t7xgdhdf.js");
43274
+ const { sendStatusNotification } = await import("./send-session-notification-04hvd54c.js");
43275
+ const { abortSessionFailClosed } = await import("./transform-postprocess-phase-ttdkrm6r.js");
42996
43276
  await sendStatusNotification(ctx.client, sessionId, message, {
42997
43277
  toastDurationMs: 15000
42998
43278
  });