@anuma/sdk 3.12.0 → 3.12.1

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.
@@ -1,3 +1,7 @@
1
+ import {
2
+ getLogger
3
+ } from "./chunk-ILAWDQDE.mjs";
4
+
1
5
  // src/lib/pii/patterns.ts
2
6
  function luhnCheck(digits) {
3
7
  let sum = 0;
@@ -637,10 +641,24 @@ function createStreamingDeAnonymizer(redactor, emit) {
637
641
  };
638
642
  }
639
643
 
644
+ // src/lib/memory/consolidationFallback.ts
645
+ function notifyConsolidationFallback(reason, onFallback, detail) {
646
+ if (detail !== void 0) {
647
+ getLogger().warn(`memory/consolidate: degraded to create (${reason})`, detail);
648
+ } else {
649
+ getLogger().warn(`memory/consolidate: degraded to create (${reason})`);
650
+ }
651
+ try {
652
+ onFallback?.(reason);
653
+ } catch {
654
+ }
655
+ }
656
+
640
657
  export {
641
658
  PII_PATTERNS,
642
659
  PiiRedactor,
643
660
  isPiiRedactor,
644
661
  resolvePiiRedactor,
645
- createStreamingDeAnonymizer
662
+ createStreamingDeAnonymizer,
663
+ notifyConsolidationFallback
646
664
  };
@@ -1,9 +1,9 @@
1
1
  import {
2
+ notifyConsolidationFallback,
2
3
  resolvePiiRedactor
3
- } from "./chunk-Y7XT2VNQ.mjs";
4
+ } from "./chunk-WV7C7VHF.mjs";
4
5
  import {
5
- callPortalJsonCompletion,
6
- getLogger
6
+ callPortalJsonCompletion
7
7
  } from "./chunk-ILAWDQDE.mjs";
8
8
  import "./chunk-GYKJOWEO.mjs";
9
9
 
@@ -102,15 +102,7 @@ ${candidateText}`;
102
102
  return result;
103
103
  }
104
104
  function degrade(reason, fallback, options, detail) {
105
- if (detail !== void 0) {
106
- getLogger().warn(`memory/consolidate: degraded to create (${reason})`, detail);
107
- } else {
108
- getLogger().warn(`memory/consolidate: degraded to create (${reason})`);
109
- }
110
- try {
111
- options.onFallback?.(reason);
112
- } catch {
113
- }
105
+ notifyConsolidationFallback(reason, options.onFallback, detail);
114
106
  return { ...fallback, fallbackReason: reason };
115
107
  }
116
108
  function validate(parsed, newContent, validIds) {
@@ -8170,6 +8170,25 @@ var init_searchTool = __esm({
8170
8170
  }
8171
8171
  });
8172
8172
 
8173
+ // src/lib/memory/consolidationFallback.ts
8174
+ function notifyConsolidationFallback(reason, onFallback, detail) {
8175
+ if (detail !== void 0) {
8176
+ getLogger().warn(`memory/consolidate: degraded to create (${reason})`, detail);
8177
+ } else {
8178
+ getLogger().warn(`memory/consolidate: degraded to create (${reason})`);
8179
+ }
8180
+ try {
8181
+ onFallback?.(reason);
8182
+ } catch {
8183
+ }
8184
+ }
8185
+ var init_consolidationFallback = __esm({
8186
+ "src/lib/memory/consolidationFallback.ts"() {
8187
+ "use strict";
8188
+ init_logger();
8189
+ }
8190
+ });
8191
+
8173
8192
  // src/lib/memory/consolidate.ts
8174
8193
  var consolidate_exports = {};
8175
8194
  __export(consolidate_exports, {
@@ -8234,15 +8253,7 @@ ${candidateText}`;
8234
8253
  return result;
8235
8254
  }
8236
8255
  function degrade(reason, fallback, options, detail) {
8237
- if (detail !== void 0) {
8238
- getLogger().warn(`memory/consolidate: degraded to create (${reason})`, detail);
8239
- } else {
8240
- getLogger().warn(`memory/consolidate: degraded to create (${reason})`);
8241
- }
8242
- try {
8243
- options.onFallback?.(reason);
8244
- } catch {
8245
- }
8256
+ notifyConsolidationFallback(reason, options.onFallback, detail);
8246
8257
  return { ...fallback, fallbackReason: reason };
8247
8258
  }
8248
8259
  function validate2(parsed, newContent, validIds) {
@@ -8282,8 +8293,8 @@ var DEFAULT_CONSOLIDATION_MODEL, DEFAULT_CONSOLIDATE_ATTEMPTS, DEFAULT_CONSOLIDA
8282
8293
  var init_consolidate = __esm({
8283
8294
  "src/lib/memory/consolidate.ts"() {
8284
8295
  "use strict";
8285
- init_logger();
8286
8296
  init_redactor();
8297
+ init_consolidationFallback();
8287
8298
  init_portalLlm();
8288
8299
  DEFAULT_CONSOLIDATION_MODEL = "inclusionai/ling-2.6-flash";
8289
8300
  DEFAULT_CONSOLIDATE_ATTEMPTS = 3;
@@ -14848,6 +14859,7 @@ init_constants();
14848
14859
  init_embeddings();
14849
14860
  init_vector();
14850
14861
  init_searchTool();
14862
+ init_consolidationFallback();
14851
14863
  var DEFAULT_AUTO_MERGE_THRESHOLD = 0.8;
14852
14864
  var DEFAULT_SCOPE = "private";
14853
14865
  var DEFAULT_CONSOLIDATE_THRESHOLD = 0.55;
@@ -15027,6 +15039,11 @@ async function retain(content, ctx, options = {}) {
15027
15039
  proofCount: 1
15028
15040
  };
15029
15041
  }
15042
+ notifyConsolidationFallback(
15043
+ "target_vanished",
15044
+ options.consolidateOptions?.onFallback,
15045
+ `supersede: primary target ${primaryTargetId} retired or deleted inside the atomic write`
15046
+ );
15030
15047
  }
15031
15048
  const created = await createVaultMemoryOp(ctx.vaultCtx, createOpts);
15032
15049
  ctx.vaultCache.set(created.uniqueId, Float32Array.from(embedding));
@@ -15078,6 +15095,10 @@ function pickFactTypeUpdate(existing, incoming) {
15078
15095
  function resurrectFields(existing) {
15079
15096
  return typeof existing.archivedAt === "number" ? { restore: true } : { preserveUpdatedAt: true };
15080
15097
  }
15098
+ function abandonToRace(options, detail) {
15099
+ notifyConsolidationFallback("target_vanished", options.consolidateOptions?.onFallback, detail);
15100
+ return null;
15101
+ }
15081
15102
  async function tryConsolidate(trimmed, ctx, options, prepared) {
15082
15103
  const consolidateOptions = options.consolidateOptions;
15083
15104
  if (!consolidateOptions) return null;
@@ -15110,12 +15131,22 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
15110
15131
  const existing = await getVaultMemoryOp(ctx.vaultCtx, id);
15111
15132
  if (existing && !existing.supersededBy) valid.push(id);
15112
15133
  }
15113
- if (valid.length === 0) return null;
15134
+ if (valid.length === 0) {
15135
+ return abandonToRace(
15136
+ options,
15137
+ `supersede: all ${requestedIds.length} target(s) deleted or already superseded`
15138
+ );
15139
+ }
15114
15140
  return { supersede: valid, content: decision.content };
15115
15141
  }
15116
15142
  if (decision.action === "noop" && decision.targetId) {
15117
15143
  const existing = await getVaultMemoryOp(ctx.vaultCtx, decision.targetId);
15118
- if (!existing || existing.supersededBy) return null;
15144
+ if (!existing || existing.supersededBy) {
15145
+ return abandonToRace(
15146
+ options,
15147
+ `noop: target ${decision.targetId} ${existing ? "superseded" : "deleted"} before the write`
15148
+ );
15149
+ }
15119
15150
  const mergedSourceIds = unionStrings(
15120
15151
  existing.sourceChunkIds ?? [],
15121
15152
  options.sourceChunkIds ?? []
@@ -15140,7 +15171,10 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
15140
15171
  });
15141
15172
  if (!updated) {
15142
15173
  await assertMergeTargetGoneOrThrow(ctx, decision.targetId);
15143
- return null;
15174
+ return abandonToRace(
15175
+ options,
15176
+ `noop: target ${decision.targetId} deleted mid-write (proof-count bump lost)`
15177
+ );
15144
15178
  }
15145
15179
  return {
15146
15180
  done: {
@@ -15153,7 +15187,12 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
15153
15187
  }
15154
15188
  if (decision.action === "update" && decision.targetId && decision.content) {
15155
15189
  const existing = await getVaultMemoryOp(ctx.vaultCtx, decision.targetId);
15156
- if (!existing || existing.supersededBy) return null;
15190
+ if (!existing || existing.supersededBy) {
15191
+ return abandonToRace(
15192
+ options,
15193
+ `update: target ${decision.targetId} ${existing ? "superseded" : "deleted"} before the write`
15194
+ );
15195
+ }
15157
15196
  const mergedSourceIds = unionStrings(
15158
15197
  existing.sourceChunkIds ?? [],
15159
15198
  options.sourceChunkIds ?? []
@@ -15184,7 +15223,10 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
15184
15223
  });
15185
15224
  if (!updated) {
15186
15225
  await assertMergeTargetGoneOrThrow(ctx, decision.targetId);
15187
- return null;
15226
+ return abandonToRace(
15227
+ options,
15228
+ `update: target ${decision.targetId} deleted mid-write (consolidated rewrite lost)`
15229
+ );
15188
15230
  }
15189
15231
  ctx.vaultCache.set(decision.targetId, Float32Array.from(newEmbedding));
15190
15232
  return {
@@ -15196,6 +15238,11 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
15196
15238
  }
15197
15239
  };
15198
15240
  }
15241
+ notifyConsolidationFallback(
15242
+ "invalid_response",
15243
+ options.consolidateOptions?.onFallback,
15244
+ `unapplicable ${decision.action} decision reached the applier \u2014 validate() should have rejected it`
15245
+ );
15199
15246
  return null;
15200
15247
  }
15201
15248
  async function assertMergeTargetGoneOrThrow(ctx, targetId) {
@@ -5322,8 +5322,26 @@ interface RecallDiagnostics {
5322
5322
  }
5323
5323
  type RetainAction = "create" | "merge" | "update" | "skip" | "suppressed" | "supersede";
5324
5324
  type RetainSource = "manual" | "auto-extracted" | "capsule";
5325
- /** Why the consolidator fell back to "create" instead of a real decision. */
5326
- type ConsolidationFallbackReason = "llm_error" | "invalid_response";
5325
+ /**
5326
+ * Why a retain fell back to "create" instead of applying a consolidation
5327
+ * decision. Each value names a DIFFERENT thing to go fix, which is the point of
5328
+ * keeping them apart:
5329
+ *
5330
+ * - `llm_error` — the consolidation call never produced a response (network,
5331
+ * timeout, 5xx, 429, empty completion, or missing credentials). Look at the
5332
+ * portal and the auth config.
5333
+ * - `invalid_response` — the model answered, but with something unusable: an
5334
+ * unknown action, a targetId that was not in the candidate set, an `update` or
5335
+ * `supersede` with empty content, a `noop` with no target. Look at the prompt
5336
+ * and the model.
5337
+ * - `target_vanished` — the model returned a decision that was valid when it was
5338
+ * made, and the row it named was deleted or superseded by a concurrent writer
5339
+ * before the write landed. Nothing is broken in the consolidator; a sustained
5340
+ * rate points at write contention (for example an auto-extraction worker and a
5341
+ * manual write racing over the same vault), which quietly costs you the
5342
+ * dedup that decision would have performed.
5343
+ */
5344
+ type ConsolidationFallbackReason = "llm_error" | "invalid_response" | "target_vanished";
5327
5345
  interface RetainOptions {
5328
5346
  source?: RetainSource;
5329
5347
  sourceChunkIds?: string[];
@@ -5322,8 +5322,26 @@ interface RecallDiagnostics {
5322
5322
  }
5323
5323
  type RetainAction = "create" | "merge" | "update" | "skip" | "suppressed" | "supersede";
5324
5324
  type RetainSource = "manual" | "auto-extracted" | "capsule";
5325
- /** Why the consolidator fell back to "create" instead of a real decision. */
5326
- type ConsolidationFallbackReason = "llm_error" | "invalid_response";
5325
+ /**
5326
+ * Why a retain fell back to "create" instead of applying a consolidation
5327
+ * decision. Each value names a DIFFERENT thing to go fix, which is the point of
5328
+ * keeping them apart:
5329
+ *
5330
+ * - `llm_error` — the consolidation call never produced a response (network,
5331
+ * timeout, 5xx, 429, empty completion, or missing credentials). Look at the
5332
+ * portal and the auth config.
5333
+ * - `invalid_response` — the model answered, but with something unusable: an
5334
+ * unknown action, a targetId that was not in the candidate set, an `update` or
5335
+ * `supersede` with empty content, a `noop` with no target. Look at the prompt
5336
+ * and the model.
5337
+ * - `target_vanished` — the model returned a decision that was valid when it was
5338
+ * made, and the row it named was deleted or superseded by a concurrent writer
5339
+ * before the write landed. Nothing is broken in the consolidator; a sustained
5340
+ * rate points at write contention (for example an auto-extraction worker and a
5341
+ * manual write racing over the same vault), which quietly costs you the
5342
+ * dedup that decision would have performed.
5343
+ */
5344
+ type ConsolidationFallbackReason = "llm_error" | "invalid_response" | "target_vanished";
5327
5345
  interface RetainOptions {
5328
5346
  source?: RetainSource;
5329
5347
  sourceChunkIds?: string[];
@@ -120,8 +120,9 @@ import {
120
120
  PiiRedactor,
121
121
  createStreamingDeAnonymizer,
122
122
  isPiiRedactor,
123
+ notifyConsolidationFallback,
123
124
  resolvePiiRedactor
124
- } from "./chunk-Y7XT2VNQ.mjs";
125
+ } from "./chunk-WV7C7VHF.mjs";
125
126
  import {
126
127
  callPortalJsonCompletion,
127
128
  consoleLogger,
@@ -6583,6 +6584,11 @@ async function retain(content, ctx, options = {}) {
6583
6584
  proofCount: 1
6584
6585
  };
6585
6586
  }
6587
+ notifyConsolidationFallback(
6588
+ "target_vanished",
6589
+ options.consolidateOptions?.onFallback,
6590
+ `supersede: primary target ${primaryTargetId} retired or deleted inside the atomic write`
6591
+ );
6586
6592
  }
6587
6593
  const created = await createVaultMemoryOp(ctx.vaultCtx, createOpts);
6588
6594
  ctx.vaultCache.set(created.uniqueId, Float32Array.from(embedding));
@@ -6634,6 +6640,10 @@ function pickFactTypeUpdate(existing, incoming) {
6634
6640
  function resurrectFields(existing) {
6635
6641
  return typeof existing.archivedAt === "number" ? { restore: true } : { preserveUpdatedAt: true };
6636
6642
  }
6643
+ function abandonToRace(options, detail) {
6644
+ notifyConsolidationFallback("target_vanished", options.consolidateOptions?.onFallback, detail);
6645
+ return null;
6646
+ }
6637
6647
  async function tryConsolidate(trimmed, ctx, options, prepared) {
6638
6648
  const consolidateOptions = options.consolidateOptions;
6639
6649
  if (!consolidateOptions) return null;
@@ -6655,7 +6665,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
6655
6665
  content: m.content,
6656
6666
  similarity: m.similarity
6657
6667
  }));
6658
- const { consolidateMemory: doConsolidate } = await import("./consolidate-HYIEFPFA.mjs");
6668
+ const { consolidateMemory: doConsolidate } = await import("./consolidate-AURTG64H.mjs");
6659
6669
  const decision = await doConsolidate(trimmed, candidates, consolidateOptions);
6660
6670
  if (decision.action === "create") return null;
6661
6671
  if (decision.action === "supersede" && decision.content) {
@@ -6666,12 +6676,22 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
6666
6676
  const existing = await getVaultMemoryOp(ctx.vaultCtx, id);
6667
6677
  if (existing && !existing.supersededBy) valid.push(id);
6668
6678
  }
6669
- if (valid.length === 0) return null;
6679
+ if (valid.length === 0) {
6680
+ return abandonToRace(
6681
+ options,
6682
+ `supersede: all ${requestedIds.length} target(s) deleted or already superseded`
6683
+ );
6684
+ }
6670
6685
  return { supersede: valid, content: decision.content };
6671
6686
  }
6672
6687
  if (decision.action === "noop" && decision.targetId) {
6673
6688
  const existing = await getVaultMemoryOp(ctx.vaultCtx, decision.targetId);
6674
- if (!existing || existing.supersededBy) return null;
6689
+ if (!existing || existing.supersededBy) {
6690
+ return abandonToRace(
6691
+ options,
6692
+ `noop: target ${decision.targetId} ${existing ? "superseded" : "deleted"} before the write`
6693
+ );
6694
+ }
6675
6695
  const mergedSourceIds = unionStrings(
6676
6696
  existing.sourceChunkIds ?? [],
6677
6697
  options.sourceChunkIds ?? []
@@ -6696,7 +6716,10 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
6696
6716
  });
6697
6717
  if (!updated) {
6698
6718
  await assertMergeTargetGoneOrThrow(ctx, decision.targetId);
6699
- return null;
6719
+ return abandonToRace(
6720
+ options,
6721
+ `noop: target ${decision.targetId} deleted mid-write (proof-count bump lost)`
6722
+ );
6700
6723
  }
6701
6724
  return {
6702
6725
  done: {
@@ -6709,7 +6732,12 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
6709
6732
  }
6710
6733
  if (decision.action === "update" && decision.targetId && decision.content) {
6711
6734
  const existing = await getVaultMemoryOp(ctx.vaultCtx, decision.targetId);
6712
- if (!existing || existing.supersededBy) return null;
6735
+ if (!existing || existing.supersededBy) {
6736
+ return abandonToRace(
6737
+ options,
6738
+ `update: target ${decision.targetId} ${existing ? "superseded" : "deleted"} before the write`
6739
+ );
6740
+ }
6713
6741
  const mergedSourceIds = unionStrings(
6714
6742
  existing.sourceChunkIds ?? [],
6715
6743
  options.sourceChunkIds ?? []
@@ -6740,7 +6768,10 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
6740
6768
  });
6741
6769
  if (!updated) {
6742
6770
  await assertMergeTargetGoneOrThrow(ctx, decision.targetId);
6743
- return null;
6771
+ return abandonToRace(
6772
+ options,
6773
+ `update: target ${decision.targetId} deleted mid-write (consolidated rewrite lost)`
6774
+ );
6744
6775
  }
6745
6776
  ctx.vaultCache.set(decision.targetId, Float32Array.from(newEmbedding));
6746
6777
  return {
@@ -6752,6 +6783,11 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
6752
6783
  }
6753
6784
  };
6754
6785
  }
6786
+ notifyConsolidationFallback(
6787
+ "invalid_response",
6788
+ options.consolidateOptions?.onFallback,
6789
+ `unapplicable ${decision.action} decision reached the applier \u2014 validate() should have rejected it`
6790
+ );
6755
6791
  return null;
6756
6792
  }
6757
6793
  async function assertMergeTargetGoneOrThrow(ctx, targetId) {
@@ -1,3 +1,7 @@
1
+ import {
2
+ getLogger
3
+ } from "./chunk-ILAWDQDE.mjs";
4
+
1
5
  // src/lib/pii/patterns.ts
2
6
  function luhnCheck(digits) {
3
7
  let sum = 0;
@@ -637,9 +641,23 @@ function createStreamingDeAnonymizer(redactor, emit) {
637
641
  };
638
642
  }
639
643
 
644
+ // src/lib/memory/consolidationFallback.ts
645
+ function notifyConsolidationFallback(reason, onFallback, detail) {
646
+ if (detail !== void 0) {
647
+ getLogger().warn(`memory/consolidate: degraded to create (${reason})`, detail);
648
+ } else {
649
+ getLogger().warn(`memory/consolidate: degraded to create (${reason})`);
650
+ }
651
+ try {
652
+ onFallback?.(reason);
653
+ } catch {
654
+ }
655
+ }
656
+
640
657
  export {
641
658
  PiiRedactor,
642
659
  isPiiRedactor,
643
660
  resolvePiiRedactor,
644
- createStreamingDeAnonymizer
661
+ createStreamingDeAnonymizer,
662
+ notifyConsolidationFallback
645
663
  };
@@ -1,9 +1,9 @@
1
1
  import {
2
+ notifyConsolidationFallback,
2
3
  resolvePiiRedactor
3
- } from "./chunk-TP6CJZ25.mjs";
4
+ } from "./chunk-3NPDZZGO.mjs";
4
5
  import {
5
- callPortalJsonCompletion,
6
- getLogger
6
+ callPortalJsonCompletion
7
7
  } from "./chunk-ILAWDQDE.mjs";
8
8
  import "./chunk-GYKJOWEO.mjs";
9
9
 
@@ -102,15 +102,7 @@ ${candidateText}`;
102
102
  return result;
103
103
  }
104
104
  function degrade(reason, fallback, options, detail) {
105
- if (detail !== void 0) {
106
- getLogger().warn(`memory/consolidate: degraded to create (${reason})`, detail);
107
- } else {
108
- getLogger().warn(`memory/consolidate: degraded to create (${reason})`);
109
- }
110
- try {
111
- options.onFallback?.(reason);
112
- } catch {
113
- }
105
+ notifyConsolidationFallback(reason, options.onFallback, detail);
114
106
  return { ...fallback, fallbackReason: reason };
115
107
  }
116
108
  function validate(parsed, newContent, validIds) {
@@ -8471,6 +8471,25 @@ var init_searchTool = __esm({
8471
8471
  }
8472
8472
  });
8473
8473
 
8474
+ // src/lib/memory/consolidationFallback.ts
8475
+ function notifyConsolidationFallback(reason, onFallback, detail) {
8476
+ if (detail !== void 0) {
8477
+ getLogger().warn(`memory/consolidate: degraded to create (${reason})`, detail);
8478
+ } else {
8479
+ getLogger().warn(`memory/consolidate: degraded to create (${reason})`);
8480
+ }
8481
+ try {
8482
+ onFallback?.(reason);
8483
+ } catch {
8484
+ }
8485
+ }
8486
+ var init_consolidationFallback = __esm({
8487
+ "src/lib/memory/consolidationFallback.ts"() {
8488
+ "use strict";
8489
+ init_logger();
8490
+ }
8491
+ });
8492
+
8474
8493
  // src/lib/memory/consolidate.ts
8475
8494
  var consolidate_exports = {};
8476
8495
  __export(consolidate_exports, {
@@ -8535,15 +8554,7 @@ ${candidateText}`;
8535
8554
  return result;
8536
8555
  }
8537
8556
  function degrade(reason, fallback, options, detail) {
8538
- if (detail !== void 0) {
8539
- getLogger().warn(`memory/consolidate: degraded to create (${reason})`, detail);
8540
- } else {
8541
- getLogger().warn(`memory/consolidate: degraded to create (${reason})`);
8542
- }
8543
- try {
8544
- options.onFallback?.(reason);
8545
- } catch {
8546
- }
8557
+ notifyConsolidationFallback(reason, options.onFallback, detail);
8547
8558
  return { ...fallback, fallbackReason: reason };
8548
8559
  }
8549
8560
  function validate2(parsed, newContent, validIds) {
@@ -8583,8 +8594,8 @@ var DEFAULT_CONSOLIDATION_MODEL, DEFAULT_CONSOLIDATE_ATTEMPTS, DEFAULT_CONSOLIDA
8583
8594
  var init_consolidate = __esm({
8584
8595
  "src/lib/memory/consolidate.ts"() {
8585
8596
  "use strict";
8586
- init_logger();
8587
8597
  init_redactor();
8598
+ init_consolidationFallback();
8588
8599
  init_portalLlm();
8589
8600
  DEFAULT_CONSOLIDATION_MODEL = "inclusionai/ling-2.6-flash";
8590
8601
  DEFAULT_CONSOLIDATE_ATTEMPTS = 3;
@@ -16165,6 +16176,7 @@ init_constants();
16165
16176
  init_embeddings();
16166
16177
  init_vector();
16167
16178
  init_searchTool();
16179
+ init_consolidationFallback();
16168
16180
  var DEFAULT_AUTO_MERGE_THRESHOLD = 0.8;
16169
16181
  var DEFAULT_SCOPE = "private";
16170
16182
  var DEFAULT_CONSOLIDATE_THRESHOLD = 0.55;
@@ -16344,6 +16356,11 @@ async function retain(content, ctx, options = {}) {
16344
16356
  proofCount: 1
16345
16357
  };
16346
16358
  }
16359
+ notifyConsolidationFallback(
16360
+ "target_vanished",
16361
+ options.consolidateOptions?.onFallback,
16362
+ `supersede: primary target ${primaryTargetId} retired or deleted inside the atomic write`
16363
+ );
16347
16364
  }
16348
16365
  const created = await createVaultMemoryOp(ctx.vaultCtx, createOpts);
16349
16366
  ctx.vaultCache.set(created.uniqueId, Float32Array.from(embedding));
@@ -16395,6 +16412,10 @@ function pickFactTypeUpdate(existing, incoming) {
16395
16412
  function resurrectFields(existing) {
16396
16413
  return typeof existing.archivedAt === "number" ? { restore: true } : { preserveUpdatedAt: true };
16397
16414
  }
16415
+ function abandonToRace(options, detail) {
16416
+ notifyConsolidationFallback("target_vanished", options.consolidateOptions?.onFallback, detail);
16417
+ return null;
16418
+ }
16398
16419
  async function tryConsolidate(trimmed, ctx, options, prepared) {
16399
16420
  const consolidateOptions = options.consolidateOptions;
16400
16421
  if (!consolidateOptions) return null;
@@ -16427,12 +16448,22 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
16427
16448
  const existing = await getVaultMemoryOp(ctx.vaultCtx, id);
16428
16449
  if (existing && !existing.supersededBy) valid.push(id);
16429
16450
  }
16430
- if (valid.length === 0) return null;
16451
+ if (valid.length === 0) {
16452
+ return abandonToRace(
16453
+ options,
16454
+ `supersede: all ${requestedIds.length} target(s) deleted or already superseded`
16455
+ );
16456
+ }
16431
16457
  return { supersede: valid, content: decision.content };
16432
16458
  }
16433
16459
  if (decision.action === "noop" && decision.targetId) {
16434
16460
  const existing = await getVaultMemoryOp(ctx.vaultCtx, decision.targetId);
16435
- if (!existing || existing.supersededBy) return null;
16461
+ if (!existing || existing.supersededBy) {
16462
+ return abandonToRace(
16463
+ options,
16464
+ `noop: target ${decision.targetId} ${existing ? "superseded" : "deleted"} before the write`
16465
+ );
16466
+ }
16436
16467
  const mergedSourceIds = unionStrings(
16437
16468
  existing.sourceChunkIds ?? [],
16438
16469
  options.sourceChunkIds ?? []
@@ -16457,7 +16488,10 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
16457
16488
  });
16458
16489
  if (!updated) {
16459
16490
  await assertMergeTargetGoneOrThrow(ctx, decision.targetId);
16460
- return null;
16491
+ return abandonToRace(
16492
+ options,
16493
+ `noop: target ${decision.targetId} deleted mid-write (proof-count bump lost)`
16494
+ );
16461
16495
  }
16462
16496
  return {
16463
16497
  done: {
@@ -16470,7 +16504,12 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
16470
16504
  }
16471
16505
  if (decision.action === "update" && decision.targetId && decision.content) {
16472
16506
  const existing = await getVaultMemoryOp(ctx.vaultCtx, decision.targetId);
16473
- if (!existing || existing.supersededBy) return null;
16507
+ if (!existing || existing.supersededBy) {
16508
+ return abandonToRace(
16509
+ options,
16510
+ `update: target ${decision.targetId} ${existing ? "superseded" : "deleted"} before the write`
16511
+ );
16512
+ }
16474
16513
  const mergedSourceIds = unionStrings(
16475
16514
  existing.sourceChunkIds ?? [],
16476
16515
  options.sourceChunkIds ?? []
@@ -16501,7 +16540,10 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
16501
16540
  });
16502
16541
  if (!updated) {
16503
16542
  await assertMergeTargetGoneOrThrow(ctx, decision.targetId);
16504
- return null;
16543
+ return abandonToRace(
16544
+ options,
16545
+ `update: target ${decision.targetId} deleted mid-write (consolidated rewrite lost)`
16546
+ );
16505
16547
  }
16506
16548
  ctx.vaultCache.set(decision.targetId, Float32Array.from(newEmbedding));
16507
16549
  return {
@@ -16513,6 +16555,11 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
16513
16555
  }
16514
16556
  };
16515
16557
  }
16558
+ notifyConsolidationFallback(
16559
+ "invalid_response",
16560
+ options.consolidateOptions?.onFallback,
16561
+ `unapplicable ${decision.action} decision reached the applier \u2014 validate() should have rejected it`
16562
+ );
16516
16563
  return null;
16517
16564
  }
16518
16565
  async function assertMergeTargetGoneOrThrow(ctx, targetId) {
@@ -6595,8 +6595,26 @@ interface RecallDiagnostics {
6595
6595
  }
6596
6596
  type RetainAction = "create" | "merge" | "update" | "skip" | "suppressed" | "supersede";
6597
6597
  type RetainSource = "manual" | "auto-extracted" | "capsule";
6598
- /** Why the consolidator fell back to "create" instead of a real decision. */
6599
- type ConsolidationFallbackReason = "llm_error" | "invalid_response";
6598
+ /**
6599
+ * Why a retain fell back to "create" instead of applying a consolidation
6600
+ * decision. Each value names a DIFFERENT thing to go fix, which is the point of
6601
+ * keeping them apart:
6602
+ *
6603
+ * - `llm_error` — the consolidation call never produced a response (network,
6604
+ * timeout, 5xx, 429, empty completion, or missing credentials). Look at the
6605
+ * portal and the auth config.
6606
+ * - `invalid_response` — the model answered, but with something unusable: an
6607
+ * unknown action, a targetId that was not in the candidate set, an `update` or
6608
+ * `supersede` with empty content, a `noop` with no target. Look at the prompt
6609
+ * and the model.
6610
+ * - `target_vanished` — the model returned a decision that was valid when it was
6611
+ * made, and the row it named was deleted or superseded by a concurrent writer
6612
+ * before the write landed. Nothing is broken in the consolidator; a sustained
6613
+ * rate points at write contention (for example an auto-extraction worker and a
6614
+ * manual write racing over the same vault), which quietly costs you the
6615
+ * dedup that decision would have performed.
6616
+ */
6617
+ type ConsolidationFallbackReason = "llm_error" | "invalid_response" | "target_vanished";
6600
6618
  interface RetainOptions {
6601
6619
  source?: RetainSource;
6602
6620
  sourceChunkIds?: string[];
@@ -6595,8 +6595,26 @@ interface RecallDiagnostics {
6595
6595
  }
6596
6596
  type RetainAction = "create" | "merge" | "update" | "skip" | "suppressed" | "supersede";
6597
6597
  type RetainSource = "manual" | "auto-extracted" | "capsule";
6598
- /** Why the consolidator fell back to "create" instead of a real decision. */
6599
- type ConsolidationFallbackReason = "llm_error" | "invalid_response";
6598
+ /**
6599
+ * Why a retain fell back to "create" instead of applying a consolidation
6600
+ * decision. Each value names a DIFFERENT thing to go fix, which is the point of
6601
+ * keeping them apart:
6602
+ *
6603
+ * - `llm_error` — the consolidation call never produced a response (network,
6604
+ * timeout, 5xx, 429, empty completion, or missing credentials). Look at the
6605
+ * portal and the auth config.
6606
+ * - `invalid_response` — the model answered, but with something unusable: an
6607
+ * unknown action, a targetId that was not in the candidate set, an `update` or
6608
+ * `supersede` with empty content, a `noop` with no target. Look at the prompt
6609
+ * and the model.
6610
+ * - `target_vanished` — the model returned a decision that was valid when it was
6611
+ * made, and the row it named was deleted or superseded by a concurrent writer
6612
+ * before the write landed. Nothing is broken in the consolidator; a sustained
6613
+ * rate points at write contention (for example an auto-extraction worker and a
6614
+ * manual write racing over the same vault), which quietly costs you the
6615
+ * dedup that decision would have performed.
6616
+ */
6617
+ type ConsolidationFallbackReason = "llm_error" | "invalid_response" | "target_vanished";
6600
6618
  interface RetainOptions {
6601
6619
  source?: RetainSource;
6602
6620
  sourceChunkIds?: string[];
@@ -164,8 +164,9 @@ import {
164
164
  PiiRedactor,
165
165
  createStreamingDeAnonymizer,
166
166
  isPiiRedactor,
167
+ notifyConsolidationFallback,
167
168
  resolvePiiRedactor
168
- } from "./chunk-TP6CJZ25.mjs";
169
+ } from "./chunk-3NPDZZGO.mjs";
169
170
  import {
170
171
  callPortalJsonCompletion,
171
172
  consoleLogger,
@@ -7400,6 +7401,11 @@ async function retain(content, ctx, options = {}) {
7400
7401
  proofCount: 1
7401
7402
  };
7402
7403
  }
7404
+ notifyConsolidationFallback(
7405
+ "target_vanished",
7406
+ options.consolidateOptions?.onFallback,
7407
+ `supersede: primary target ${primaryTargetId} retired or deleted inside the atomic write`
7408
+ );
7403
7409
  }
7404
7410
  const created = await createVaultMemoryOp(ctx.vaultCtx, createOpts);
7405
7411
  ctx.vaultCache.set(created.uniqueId, Float32Array.from(embedding));
@@ -7451,6 +7457,10 @@ function pickFactTypeUpdate(existing, incoming) {
7451
7457
  function resurrectFields(existing) {
7452
7458
  return typeof existing.archivedAt === "number" ? { restore: true } : { preserveUpdatedAt: true };
7453
7459
  }
7460
+ function abandonToRace(options, detail) {
7461
+ notifyConsolidationFallback("target_vanished", options.consolidateOptions?.onFallback, detail);
7462
+ return null;
7463
+ }
7454
7464
  async function tryConsolidate(trimmed, ctx, options, prepared) {
7455
7465
  const consolidateOptions = options.consolidateOptions;
7456
7466
  if (!consolidateOptions) return null;
@@ -7472,7 +7482,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
7472
7482
  content: m.content,
7473
7483
  similarity: m.similarity
7474
7484
  }));
7475
- const { consolidateMemory: doConsolidate } = await import("./consolidate-DOY3ZWTE.mjs");
7485
+ const { consolidateMemory: doConsolidate } = await import("./consolidate-R6FH7XMV.mjs");
7476
7486
  const decision = await doConsolidate(trimmed, candidates, consolidateOptions);
7477
7487
  if (decision.action === "create") return null;
7478
7488
  if (decision.action === "supersede" && decision.content) {
@@ -7483,12 +7493,22 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
7483
7493
  const existing = await getVaultMemoryOp(ctx.vaultCtx, id);
7484
7494
  if (existing && !existing.supersededBy) valid.push(id);
7485
7495
  }
7486
- if (valid.length === 0) return null;
7496
+ if (valid.length === 0) {
7497
+ return abandonToRace(
7498
+ options,
7499
+ `supersede: all ${requestedIds.length} target(s) deleted or already superseded`
7500
+ );
7501
+ }
7487
7502
  return { supersede: valid, content: decision.content };
7488
7503
  }
7489
7504
  if (decision.action === "noop" && decision.targetId) {
7490
7505
  const existing = await getVaultMemoryOp(ctx.vaultCtx, decision.targetId);
7491
- if (!existing || existing.supersededBy) return null;
7506
+ if (!existing || existing.supersededBy) {
7507
+ return abandonToRace(
7508
+ options,
7509
+ `noop: target ${decision.targetId} ${existing ? "superseded" : "deleted"} before the write`
7510
+ );
7511
+ }
7492
7512
  const mergedSourceIds = unionStrings(
7493
7513
  existing.sourceChunkIds ?? [],
7494
7514
  options.sourceChunkIds ?? []
@@ -7513,7 +7533,10 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
7513
7533
  });
7514
7534
  if (!updated) {
7515
7535
  await assertMergeTargetGoneOrThrow(ctx, decision.targetId);
7516
- return null;
7536
+ return abandonToRace(
7537
+ options,
7538
+ `noop: target ${decision.targetId} deleted mid-write (proof-count bump lost)`
7539
+ );
7517
7540
  }
7518
7541
  return {
7519
7542
  done: {
@@ -7526,7 +7549,12 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
7526
7549
  }
7527
7550
  if (decision.action === "update" && decision.targetId && decision.content) {
7528
7551
  const existing = await getVaultMemoryOp(ctx.vaultCtx, decision.targetId);
7529
- if (!existing || existing.supersededBy) return null;
7552
+ if (!existing || existing.supersededBy) {
7553
+ return abandonToRace(
7554
+ options,
7555
+ `update: target ${decision.targetId} ${existing ? "superseded" : "deleted"} before the write`
7556
+ );
7557
+ }
7530
7558
  const mergedSourceIds = unionStrings(
7531
7559
  existing.sourceChunkIds ?? [],
7532
7560
  options.sourceChunkIds ?? []
@@ -7557,7 +7585,10 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
7557
7585
  });
7558
7586
  if (!updated) {
7559
7587
  await assertMergeTargetGoneOrThrow(ctx, decision.targetId);
7560
- return null;
7588
+ return abandonToRace(
7589
+ options,
7590
+ `update: target ${decision.targetId} deleted mid-write (consolidated rewrite lost)`
7591
+ );
7561
7592
  }
7562
7593
  ctx.vaultCache.set(decision.targetId, Float32Array.from(newEmbedding));
7563
7594
  return {
@@ -7569,6 +7600,11 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
7569
7600
  }
7570
7601
  };
7571
7602
  }
7603
+ notifyConsolidationFallback(
7604
+ "invalid_response",
7605
+ options.consolidateOptions?.onFallback,
7606
+ `unapplicable ${decision.action} decision reached the applier \u2014 validate() should have rejected it`
7607
+ );
7572
7608
  return null;
7573
7609
  }
7574
7610
  async function assertMergeTargetGoneOrThrow(ctx, targetId) {
@@ -1,3 +1,7 @@
1
+ import {
2
+ getLogger
3
+ } from "./chunk-OBDRKQQI.mjs";
4
+
1
5
  // src/lib/pii/patterns.ts
2
6
  function luhnCheck(digits) {
3
7
  let sum = 0;
@@ -637,7 +641,21 @@ function createStreamingDeAnonymizer(redactor, emit) {
637
641
  };
638
642
  }
639
643
 
644
+ // src/lib/memory/consolidationFallback.ts
645
+ function notifyConsolidationFallback(reason, onFallback, detail) {
646
+ if (detail !== void 0) {
647
+ getLogger().warn(`memory/consolidate: degraded to create (${reason})`, detail);
648
+ } else {
649
+ getLogger().warn(`memory/consolidate: degraded to create (${reason})`);
650
+ }
651
+ try {
652
+ onFallback?.(reason);
653
+ } catch {
654
+ }
655
+ }
656
+
640
657
  export {
641
658
  resolvePiiRedactor,
642
- createStreamingDeAnonymizer
659
+ createStreamingDeAnonymizer,
660
+ notifyConsolidationFallback
643
661
  };
@@ -1,9 +1,9 @@
1
1
  import {
2
+ notifyConsolidationFallback,
2
3
  resolvePiiRedactor
3
- } from "./chunk-PXN5Q3MD.mjs";
4
+ } from "./chunk-RT75PNSJ.mjs";
4
5
  import {
5
- callPortalJsonCompletion,
6
- getLogger
6
+ callPortalJsonCompletion
7
7
  } from "./chunk-OBDRKQQI.mjs";
8
8
  import "./chunk-3RPGXXPZ.mjs";
9
9
 
@@ -102,15 +102,7 @@ ${candidateText}`;
102
102
  return result;
103
103
  }
104
104
  function degrade(reason, fallback, options, detail) {
105
- if (detail !== void 0) {
106
- getLogger().warn(`memory/consolidate: degraded to create (${reason})`, detail);
107
- } else {
108
- getLogger().warn(`memory/consolidate: degraded to create (${reason})`);
109
- }
110
- try {
111
- options.onFallback?.(reason);
112
- } catch {
113
- }
105
+ notifyConsolidationFallback(reason, options.onFallback, detail);
114
106
  return { ...fallback, fallbackReason: reason };
115
107
  }
116
108
  function validate(parsed, newContent, validIds) {
@@ -22995,6 +22995,25 @@ var init_redactor = __esm({
22995
22995
  }
22996
22996
  });
22997
22997
 
22998
+ // src/lib/memory/consolidationFallback.ts
22999
+ function notifyConsolidationFallback(reason, onFallback, detail) {
23000
+ if (detail !== void 0) {
23001
+ getLogger().warn(`memory/consolidate: degraded to create (${reason})`, detail);
23002
+ } else {
23003
+ getLogger().warn(`memory/consolidate: degraded to create (${reason})`);
23004
+ }
23005
+ try {
23006
+ onFallback?.(reason);
23007
+ } catch {
23008
+ }
23009
+ }
23010
+ var init_consolidationFallback = __esm({
23011
+ "src/lib/memory/consolidationFallback.ts"() {
23012
+ "use strict";
23013
+ init_logger();
23014
+ }
23015
+ });
23016
+
22998
23017
  // src/lib/memory/consolidate.ts
22999
23018
  var consolidate_exports = {};
23000
23019
  __export(consolidate_exports, {
@@ -23059,15 +23078,7 @@ ${candidateText}`;
23059
23078
  return result;
23060
23079
  }
23061
23080
  function degrade(reason, fallback, options, detail) {
23062
- if (detail !== void 0) {
23063
- getLogger().warn(`memory/consolidate: degraded to create (${reason})`, detail);
23064
- } else {
23065
- getLogger().warn(`memory/consolidate: degraded to create (${reason})`);
23066
- }
23067
- try {
23068
- options.onFallback?.(reason);
23069
- } catch {
23070
- }
23081
+ notifyConsolidationFallback(reason, options.onFallback, detail);
23071
23082
  return { ...fallback, fallbackReason: reason };
23072
23083
  }
23073
23084
  function validate2(parsed, newContent, validIds) {
@@ -23107,8 +23118,8 @@ var DEFAULT_CONSOLIDATION_MODEL, DEFAULT_CONSOLIDATE_ATTEMPTS, DEFAULT_CONSOLIDA
23107
23118
  var init_consolidate = __esm({
23108
23119
  "src/lib/memory/consolidate.ts"() {
23109
23120
  "use strict";
23110
- init_logger();
23111
23121
  init_redactor();
23122
+ init_consolidationFallback();
23112
23123
  init_portalLlm();
23113
23124
  DEFAULT_CONSOLIDATION_MODEL = "inclusionai/ling-2.6-flash";
23114
23125
  DEFAULT_CONSOLIDATE_ATTEMPTS = 3;
@@ -27822,6 +27833,7 @@ init_constants();
27822
27833
  init_embeddings();
27823
27834
  init_vector();
27824
27835
  init_searchTool();
27836
+ init_consolidationFallback();
27825
27837
  var DEFAULT_AUTO_MERGE_THRESHOLD = 0.8;
27826
27838
  var DEFAULT_SCOPE = "private";
27827
27839
  var DEFAULT_CONSOLIDATE_THRESHOLD = 0.55;
@@ -28001,6 +28013,11 @@ async function retain(content, ctx, options = {}) {
28001
28013
  proofCount: 1
28002
28014
  };
28003
28015
  }
28016
+ notifyConsolidationFallback(
28017
+ "target_vanished",
28018
+ options.consolidateOptions?.onFallback,
28019
+ `supersede: primary target ${primaryTargetId} retired or deleted inside the atomic write`
28020
+ );
28004
28021
  }
28005
28022
  const created = await createVaultMemoryOp(ctx.vaultCtx, createOpts);
28006
28023
  ctx.vaultCache.set(created.uniqueId, Float32Array.from(embedding));
@@ -28052,6 +28069,10 @@ function pickFactTypeUpdate(existing, incoming) {
28052
28069
  function resurrectFields(existing) {
28053
28070
  return typeof existing.archivedAt === "number" ? { restore: true } : { preserveUpdatedAt: true };
28054
28071
  }
28072
+ function abandonToRace(options, detail) {
28073
+ notifyConsolidationFallback("target_vanished", options.consolidateOptions?.onFallback, detail);
28074
+ return null;
28075
+ }
28055
28076
  async function tryConsolidate(trimmed, ctx, options, prepared) {
28056
28077
  const consolidateOptions = options.consolidateOptions;
28057
28078
  if (!consolidateOptions) return null;
@@ -28084,12 +28105,22 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
28084
28105
  const existing = await getVaultMemoryOp(ctx.vaultCtx, id);
28085
28106
  if (existing && !existing.supersededBy) valid.push(id);
28086
28107
  }
28087
- if (valid.length === 0) return null;
28108
+ if (valid.length === 0) {
28109
+ return abandonToRace(
28110
+ options,
28111
+ `supersede: all ${requestedIds.length} target(s) deleted or already superseded`
28112
+ );
28113
+ }
28088
28114
  return { supersede: valid, content: decision.content };
28089
28115
  }
28090
28116
  if (decision.action === "noop" && decision.targetId) {
28091
28117
  const existing = await getVaultMemoryOp(ctx.vaultCtx, decision.targetId);
28092
- if (!existing || existing.supersededBy) return null;
28118
+ if (!existing || existing.supersededBy) {
28119
+ return abandonToRace(
28120
+ options,
28121
+ `noop: target ${decision.targetId} ${existing ? "superseded" : "deleted"} before the write`
28122
+ );
28123
+ }
28093
28124
  const mergedSourceIds = unionStrings(
28094
28125
  existing.sourceChunkIds ?? [],
28095
28126
  options.sourceChunkIds ?? []
@@ -28114,7 +28145,10 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
28114
28145
  });
28115
28146
  if (!updated) {
28116
28147
  await assertMergeTargetGoneOrThrow(ctx, decision.targetId);
28117
- return null;
28148
+ return abandonToRace(
28149
+ options,
28150
+ `noop: target ${decision.targetId} deleted mid-write (proof-count bump lost)`
28151
+ );
28118
28152
  }
28119
28153
  return {
28120
28154
  done: {
@@ -28127,7 +28161,12 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
28127
28161
  }
28128
28162
  if (decision.action === "update" && decision.targetId && decision.content) {
28129
28163
  const existing = await getVaultMemoryOp(ctx.vaultCtx, decision.targetId);
28130
- if (!existing || existing.supersededBy) return null;
28164
+ if (!existing || existing.supersededBy) {
28165
+ return abandonToRace(
28166
+ options,
28167
+ `update: target ${decision.targetId} ${existing ? "superseded" : "deleted"} before the write`
28168
+ );
28169
+ }
28131
28170
  const mergedSourceIds = unionStrings(
28132
28171
  existing.sourceChunkIds ?? [],
28133
28172
  options.sourceChunkIds ?? []
@@ -28158,7 +28197,10 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
28158
28197
  });
28159
28198
  if (!updated) {
28160
28199
  await assertMergeTargetGoneOrThrow(ctx, decision.targetId);
28161
- return null;
28200
+ return abandonToRace(
28201
+ options,
28202
+ `update: target ${decision.targetId} deleted mid-write (consolidated rewrite lost)`
28203
+ );
28162
28204
  }
28163
28205
  ctx.vaultCache.set(decision.targetId, Float32Array.from(newEmbedding));
28164
28206
  return {
@@ -28170,6 +28212,11 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
28170
28212
  }
28171
28213
  };
28172
28214
  }
28215
+ notifyConsolidationFallback(
28216
+ "invalid_response",
28217
+ options.consolidateOptions?.onFallback,
28218
+ `unapplicable ${decision.action} decision reached the applier \u2014 validate() should have rejected it`
28219
+ );
28173
28220
  return null;
28174
28221
  }
28175
28222
  async function assertMergeTargetGoneOrThrow(ctx, targetId) {
@@ -5254,8 +5254,26 @@ interface RecallDiagnostics {
5254
5254
  }
5255
5255
  type RetainAction = "create" | "merge" | "update" | "skip" | "suppressed" | "supersede";
5256
5256
  type RetainSource = "manual" | "auto-extracted" | "capsule";
5257
- /** Why the consolidator fell back to "create" instead of a real decision. */
5258
- type ConsolidationFallbackReason = "llm_error" | "invalid_response";
5257
+ /**
5258
+ * Why a retain fell back to "create" instead of applying a consolidation
5259
+ * decision. Each value names a DIFFERENT thing to go fix, which is the point of
5260
+ * keeping them apart:
5261
+ *
5262
+ * - `llm_error` — the consolidation call never produced a response (network,
5263
+ * timeout, 5xx, 429, empty completion, or missing credentials). Look at the
5264
+ * portal and the auth config.
5265
+ * - `invalid_response` — the model answered, but with something unusable: an
5266
+ * unknown action, a targetId that was not in the candidate set, an `update` or
5267
+ * `supersede` with empty content, a `noop` with no target. Look at the prompt
5268
+ * and the model.
5269
+ * - `target_vanished` — the model returned a decision that was valid when it was
5270
+ * made, and the row it named was deleted or superseded by a concurrent writer
5271
+ * before the write landed. Nothing is broken in the consolidator; a sustained
5272
+ * rate points at write contention (for example an auto-extraction worker and a
5273
+ * manual write racing over the same vault), which quietly costs you the
5274
+ * dedup that decision would have performed.
5275
+ */
5276
+ type ConsolidationFallbackReason = "llm_error" | "invalid_response" | "target_vanished";
5259
5277
  interface RetainOptions {
5260
5278
  source?: RetainSource;
5261
5279
  sourceChunkIds?: string[];
@@ -5254,8 +5254,26 @@ interface RecallDiagnostics {
5254
5254
  }
5255
5255
  type RetainAction = "create" | "merge" | "update" | "skip" | "suppressed" | "supersede";
5256
5256
  type RetainSource = "manual" | "auto-extracted" | "capsule";
5257
- /** Why the consolidator fell back to "create" instead of a real decision. */
5258
- type ConsolidationFallbackReason = "llm_error" | "invalid_response";
5257
+ /**
5258
+ * Why a retain fell back to "create" instead of applying a consolidation
5259
+ * decision. Each value names a DIFFERENT thing to go fix, which is the point of
5260
+ * keeping them apart:
5261
+ *
5262
+ * - `llm_error` — the consolidation call never produced a response (network,
5263
+ * timeout, 5xx, 429, empty completion, or missing credentials). Look at the
5264
+ * portal and the auth config.
5265
+ * - `invalid_response` — the model answered, but with something unusable: an
5266
+ * unknown action, a targetId that was not in the candidate set, an `update` or
5267
+ * `supersede` with empty content, a `noop` with no target. Look at the prompt
5268
+ * and the model.
5269
+ * - `target_vanished` — the model returned a decision that was valid when it was
5270
+ * made, and the row it named was deleted or superseded by a concurrent writer
5271
+ * before the write landed. Nothing is broken in the consolidator; a sustained
5272
+ * rate points at write contention (for example an auto-extraction worker and a
5273
+ * manual write racing over the same vault), which quietly costs you the
5274
+ * dedup that decision would have performed.
5275
+ */
5276
+ type ConsolidationFallbackReason = "llm_error" | "invalid_response" | "target_vanished";
5259
5277
  interface RetainOptions {
5260
5278
  source?: RetainSource;
5261
5279
  sourceChunkIds?: string[];
@@ -134,8 +134,9 @@ import {
134
134
  } from "./chunk-FXGG7JA5.mjs";
135
135
  import {
136
136
  createStreamingDeAnonymizer,
137
+ notifyConsolidationFallback,
137
138
  resolvePiiRedactor
138
- } from "./chunk-PXN5Q3MD.mjs";
139
+ } from "./chunk-RT75PNSJ.mjs";
139
140
  import {
140
141
  callPortalJsonCompletion,
141
142
  extractJsonCandidate,
@@ -5311,6 +5312,11 @@ async function retain(content, ctx, options = {}) {
5311
5312
  proofCount: 1
5312
5313
  };
5313
5314
  }
5315
+ notifyConsolidationFallback(
5316
+ "target_vanished",
5317
+ options.consolidateOptions?.onFallback,
5318
+ `supersede: primary target ${primaryTargetId} retired or deleted inside the atomic write`
5319
+ );
5314
5320
  }
5315
5321
  const created = await createVaultMemoryOp(ctx.vaultCtx, createOpts);
5316
5322
  ctx.vaultCache.set(created.uniqueId, Float32Array.from(embedding));
@@ -5362,6 +5368,10 @@ function pickFactTypeUpdate(existing, incoming) {
5362
5368
  function resurrectFields(existing) {
5363
5369
  return typeof existing.archivedAt === "number" ? { restore: true } : { preserveUpdatedAt: true };
5364
5370
  }
5371
+ function abandonToRace(options, detail) {
5372
+ notifyConsolidationFallback("target_vanished", options.consolidateOptions?.onFallback, detail);
5373
+ return null;
5374
+ }
5365
5375
  async function tryConsolidate(trimmed, ctx, options, prepared) {
5366
5376
  const consolidateOptions = options.consolidateOptions;
5367
5377
  if (!consolidateOptions) return null;
@@ -5383,7 +5393,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
5383
5393
  content: m.content,
5384
5394
  similarity: m.similarity
5385
5395
  }));
5386
- const { consolidateMemory: doConsolidate } = await import("./consolidate-JMGL3MXG.mjs");
5396
+ const { consolidateMemory: doConsolidate } = await import("./consolidate-4VEAS3YN.mjs");
5387
5397
  const decision = await doConsolidate(trimmed, candidates, consolidateOptions);
5388
5398
  if (decision.action === "create") return null;
5389
5399
  if (decision.action === "supersede" && decision.content) {
@@ -5394,12 +5404,22 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
5394
5404
  const existing = await getVaultMemoryOp(ctx.vaultCtx, id);
5395
5405
  if (existing && !existing.supersededBy) valid.push(id);
5396
5406
  }
5397
- if (valid.length === 0) return null;
5407
+ if (valid.length === 0) {
5408
+ return abandonToRace(
5409
+ options,
5410
+ `supersede: all ${requestedIds.length} target(s) deleted or already superseded`
5411
+ );
5412
+ }
5398
5413
  return { supersede: valid, content: decision.content };
5399
5414
  }
5400
5415
  if (decision.action === "noop" && decision.targetId) {
5401
5416
  const existing = await getVaultMemoryOp(ctx.vaultCtx, decision.targetId);
5402
- if (!existing || existing.supersededBy) return null;
5417
+ if (!existing || existing.supersededBy) {
5418
+ return abandonToRace(
5419
+ options,
5420
+ `noop: target ${decision.targetId} ${existing ? "superseded" : "deleted"} before the write`
5421
+ );
5422
+ }
5403
5423
  const mergedSourceIds = unionStrings(
5404
5424
  existing.sourceChunkIds ?? [],
5405
5425
  options.sourceChunkIds ?? []
@@ -5424,7 +5444,10 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
5424
5444
  });
5425
5445
  if (!updated) {
5426
5446
  await assertMergeTargetGoneOrThrow(ctx, decision.targetId);
5427
- return null;
5447
+ return abandonToRace(
5448
+ options,
5449
+ `noop: target ${decision.targetId} deleted mid-write (proof-count bump lost)`
5450
+ );
5428
5451
  }
5429
5452
  return {
5430
5453
  done: {
@@ -5437,7 +5460,12 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
5437
5460
  }
5438
5461
  if (decision.action === "update" && decision.targetId && decision.content) {
5439
5462
  const existing = await getVaultMemoryOp(ctx.vaultCtx, decision.targetId);
5440
- if (!existing || existing.supersededBy) return null;
5463
+ if (!existing || existing.supersededBy) {
5464
+ return abandonToRace(
5465
+ options,
5466
+ `update: target ${decision.targetId} ${existing ? "superseded" : "deleted"} before the write`
5467
+ );
5468
+ }
5441
5469
  const mergedSourceIds = unionStrings(
5442
5470
  existing.sourceChunkIds ?? [],
5443
5471
  options.sourceChunkIds ?? []
@@ -5468,7 +5496,10 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
5468
5496
  });
5469
5497
  if (!updated) {
5470
5498
  await assertMergeTargetGoneOrThrow(ctx, decision.targetId);
5471
- return null;
5499
+ return abandonToRace(
5500
+ options,
5501
+ `update: target ${decision.targetId} deleted mid-write (consolidated rewrite lost)`
5502
+ );
5472
5503
  }
5473
5504
  ctx.vaultCache.set(decision.targetId, Float32Array.from(newEmbedding));
5474
5505
  return {
@@ -5480,6 +5511,11 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
5480
5511
  }
5481
5512
  };
5482
5513
  }
5514
+ notifyConsolidationFallback(
5515
+ "invalid_response",
5516
+ options.consolidateOptions?.onFallback,
5517
+ `unapplicable ${decision.action} decision reached the applier \u2014 validate() should have rejected it`
5518
+ );
5483
5519
  return null;
5484
5520
  }
5485
5521
  async function assertMergeTargetGoneOrThrow(ctx, targetId) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anuma/sdk",
3
- "version": "3.12.0",
3
+ "version": "3.12.1",
4
4
  "description": "",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.mjs",