openclaw-cortex-memory 0.1.0-Alpha.32 → 0.1.0-Alpha.34

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 (42) hide show
  1. package/README.md +35 -19
  2. package/SKILL.md +2 -2
  3. package/dist/index.d.ts +12 -1
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +51 -5
  6. package/dist/index.js.map +1 -1
  7. package/dist/openclaw.plugin.json +14 -3
  8. package/dist/src/engine/ts_engine.d.ts +2 -0
  9. package/dist/src/engine/ts_engine.d.ts.map +1 -1
  10. package/dist/src/engine/ts_engine.js +19 -8
  11. package/dist/src/engine/ts_engine.js.map +1 -1
  12. package/dist/src/quality/llm_output_validator.d.ts +0 -1
  13. package/dist/src/quality/llm_output_validator.d.ts.map +1 -1
  14. package/dist/src/quality/llm_output_validator.js +0 -1
  15. package/dist/src/quality/llm_output_validator.js.map +1 -1
  16. package/dist/src/store/archive_store.d.ts.map +1 -1
  17. package/dist/src/store/archive_store.js +9 -5
  18. package/dist/src/store/archive_store.js.map +1 -1
  19. package/dist/src/store/graph_memory_store.d.ts.map +1 -1
  20. package/dist/src/store/graph_memory_store.js +146 -0
  21. package/dist/src/store/graph_memory_store.js.map +1 -1
  22. package/dist/src/store/read_store.d.ts.map +1 -1
  23. package/dist/src/store/read_store.js +22 -7
  24. package/dist/src/store/read_store.js.map +1 -1
  25. package/dist/src/store/write_store.d.ts +2 -0
  26. package/dist/src/store/write_store.d.ts.map +1 -1
  27. package/dist/src/store/write_store.js +10 -7
  28. package/dist/src/store/write_store.js.map +1 -1
  29. package/dist/src/sync/session_sync.d.ts +2 -1
  30. package/dist/src/sync/session_sync.d.ts.map +1 -1
  31. package/dist/src/sync/session_sync.js +137 -131
  32. package/dist/src/sync/session_sync.js.map +1 -1
  33. package/dist/src/wiki/wiki_maintainer.d.ts +3 -0
  34. package/dist/src/wiki/wiki_maintainer.d.ts.map +1 -1
  35. package/dist/src/wiki/wiki_maintainer.js +1 -1
  36. package/dist/src/wiki/wiki_maintainer.js.map +1 -1
  37. package/dist/src/wiki/wiki_projector.d.ts +2 -0
  38. package/dist/src/wiki/wiki_projector.d.ts.map +1 -1
  39. package/dist/src/wiki/wiki_projector.js +246 -13
  40. package/dist/src/wiki/wiki_projector.js.map +1 -1
  41. package/openclaw.plugin.json +14 -3
  42. package/package.json +4 -3
@@ -273,9 +273,12 @@ function tailByCharLimit(text, maxChars) {
273
273
  }
274
274
  return source.slice(-Math.floor(maxChars)).trim();
275
275
  }
276
+ function normalizeOneLineText(value) {
277
+ return String(value || "").replace(/\s+/g, " ").trim();
278
+ }
276
279
  const LOW_INFORMATION_LINE = /^(ok|okay|got it|roger|noted|sure|thanks|thank you|received|copy that|understood)\b/i;
277
- const LOW_VALUE_ONLY_LINE = /^(好的|收到|谢谢|辛苦|了解|明白|可以|没问题|嗯|哦|ok|okay|got it|roger|noted|thanks|thank you|copy that|understood|sounds good)[\s.!?,。!?]*$/i;
278
- const ACTIVE_VALUE_SIGNAL_PATTERN = /(决定|结论|方案|权衡|风险|约束|需求|修复|报错|异常|阻塞|排查|回滚|上线|部署|进度|里程碑|行动项|待办|负责人|owner|next step|todo|deadline|eta|issue|bug|fix|decision|trade-?off|constraint|requirement|rollback|deploy|incident|metric|latency|error rate|cost|url|link|路径|文件|配置|参数|版本|commit|pr|ticket)/i;
280
+ const LOW_VALUE_ONLY_LINE = /^(ok|okay|got it|roger|noted|thanks|thank you|received|copy that|understood|sounds good)[\s.!?,]*$/i;
281
+ const ACTIVE_VALUE_SIGNAL_PATTERN = /(decision|trade-?off|constraint|requirement|fix|error|exception|blocked|rollback|deploy|progress|milestone|action item|owner|next step|todo|deadline|eta|issue|bug|metric|latency|error rate|cost|url|link|path|file|config|parameter|version|commit|pr|ticket)/i;
279
282
  const ACTIVE_VALUE_EVIDENCE_PATTERN = /(https?:\/\/|www\.|[`#/:\\]|[A-Za-z]:\\|\/[A-Za-z0-9._\-\/]+|\b\d+(?:\.\d+)?%?\b|#\d{1,8})/;
280
283
  function denoiseTranscriptForWrite(transcript) {
281
284
  const raw = (transcript || "").trim();
@@ -334,33 +337,33 @@ function buildEventSnippet(text) {
334
337
  .map(line => line.trim())
335
338
  .filter(Boolean)
336
339
  .filter(line => line.length >= 8);
337
- const actionPattern = /(决定|完成|修复|阻塞|失败|成功|上线|部署|实现|依赖|owner|blocked|resolved|fixed|depends|decide|complete)/i;
340
+ const actionPattern = /(decision|fix|error|exception|blocked|deploy|progress|action item|owner|resolved|depends|complete)/i;
338
341
  const picked = lines.filter(line => actionPattern.test(line));
339
342
  const use = picked.length > 0 ? picked : lines.slice(-20);
340
343
  return use.slice(-30).join("\n").slice(-8000);
341
344
  }
342
345
  const TASK_INSTRUCTION_PATTERNS = [
343
- /请|帮我|麻烦|需要|任务|需求|实现|修复|排查|优化|上线|部署|整理|编写|启用|查看/i,
346
+ /please|can you|need to|task|implement|fix|investigate|optimi[sz]e|deploy|enable|review/i,
344
347
  /please|can you|need to|task|implement|fix|investigate|optimi[sz]e|deploy|enable|review/i,
345
348
  ];
346
349
  const COMPLETION_REPORT_PATTERNS = [
347
- /已完成|完成了|处理完|搞定|已修复|修复了|已实现|已上线|已部署|结果|汇报|完成情况|报告/i,
350
+ /done|completed|fixed|implemented|deployed|resolved|report|summary|finished/i,
348
351
  /done|completed|fixed|implemented|deployed|resolved|report|summary|finished/i,
349
352
  ];
350
353
  const USER_ACCEPTANCE_PATTERNS = [
351
- /确认|认可|通过|验收|OK|可以|好的|收到|辛苦|谢谢|没问题|就这样/i,
354
+ /approved|accepted|looks good|great|works|thank you|confirmed|ok/i,
352
355
  /approved|accepted|looks good|great|works|thank you|confirmed/i,
353
356
  ];
354
357
  const FAILURE_PATTERNS = [
355
- /失败|报错|错误|异常|阻塞|卡住|不行|超时|回滚|故障/i,
358
+ /failed|error|exception|blocked|timeout|rollback|incident/i,
356
359
  /failed|error|exception|blocked|timeout|rollback|incident/i,
357
360
  ];
358
361
  const SUCCESS_PATTERNS = [
359
- /成功|完成|修复|解决|通过|已上线|稳定|正常|恢复/i,
362
+ /success|completed|fixed|resolved|passed|stable|recovered|works/i,
360
363
  /success|completed|fixed|resolved|passed|stable|recovered|works/i,
361
364
  ];
362
- const USER_ROLE_HINT = /^(user|human|customer|client|用户|客户|需求方|老板)/i;
363
- const AGENT_ROLE_HINT = /^(assistant|agent|ai|system|openclaw|claude|gpt|助手)/i;
365
+ const USER_ROLE_HINT = /^(user|human|customer|client)/i;
366
+ const AGENT_ROLE_HINT = /^(assistant|agent|ai|system|openclaw|claude|gpt)/i;
364
367
  function matchesAnyPattern(text, patterns) {
365
368
  return patterns.some(pattern => pattern.test(text));
366
369
  }
@@ -381,11 +384,9 @@ function parseTranscriptLines(transcript) {
381
384
  }).filter(item => item.text.length > 0);
382
385
  }
383
386
  function summarizeForArchive(text, maxChars) {
387
+ void maxChars;
384
388
  const normalized = text.replace(/\s+/g, " ").trim();
385
- if (normalized.length <= maxChars) {
386
- return normalized;
387
- }
388
- return `${normalized.slice(0, Math.max(40, maxChars - 1)).trim()}…`;
389
+ return normalized;
389
390
  }
390
391
  function evaluateTaskLifecycle(transcript) {
391
392
  const parsed = parseTranscriptLines(transcript);
@@ -477,16 +478,9 @@ function appendLifecycleArchiveDecision(decisions, transcript, logger) {
477
478
  if (!fallbackGraph) {
478
479
  return decisions;
479
480
  }
480
- const summaryParts = [
481
- "Task lifecycle archived: user issued a concrete task, agent reported completion, and user accepted the result.",
482
- lifecycle.taskText ? `Task: ${summarizeForArchive(lifecycle.taskText, 180)}` : "",
483
- lifecycle.reportText ? `Completion: ${summarizeForArchive(lifecycle.reportText, 220)}` : "",
484
- lifecycle.acceptanceText ? `Acceptance: ${summarizeForArchive(lifecycle.acceptanceText, 160)}` : "",
485
- lifecycle.failThenSuccess
486
- ? "The execution included setbacks/errors followed by successful completion, so the reusable experience value is high."
487
- : "",
488
- ].filter(Boolean);
489
- const summary = summaryParts.join(" ");
481
+ const summary = lifecycle.failThenSuccess
482
+ ? "Task lifecycle closed: user request, failure iteration, final completion, and user acceptance."
483
+ : "Task lifecycle closed: user request, completion report, and user acceptance.";
490
484
  const cause = lifecycle.taskText
491
485
  ? summarizeForArchive(lifecycle.taskText, 220)
492
486
  : "User issued a concrete task request.";
@@ -509,9 +503,6 @@ function appendLifecycleArchiveDecision(decisions, transcript, logger) {
509
503
  entities: fallbackGraph.entities,
510
504
  relations: fallbackGraph.relations,
511
505
  entity_types: fallbackGraph.entity_types,
512
- outcome: lifecycle.acceptanceText
513
- ? summarizeForArchive(lifecycle.acceptanceText, 180)
514
- : "User acknowledged and accepted the delivery.",
515
506
  confidence: typeof fallbackGraph.confidence === "number" ? fallbackGraph.confidence : confidence,
516
507
  },
517
508
  reason: "lifecycle_archive_fallback",
@@ -530,13 +521,13 @@ const GRAPH_REWRITE_SCOPE_FIELDS = [
530
521
  const GRAPH_REWRITE_SCOPE_SET = new Set(GRAPH_REWRITE_SCOPE_FIELDS);
531
522
  const WRITE_GATE_PROMPT_VERSION = "write-gate.v1.7.9";
532
523
  const WRITE_GATE_STAGE_AB_PROMPT_VERSION = "write-gate.ab.v1.1.5";
533
- const WRITE_GATE_STAGE_C_PROMPT_VERSION = "write-gate.c.v1.4.1";
524
+ const WRITE_GATE_STAGE_C_PROMPT_VERSION = "write-gate.c.v1.5.0";
534
525
  const WRITE_GATE_STAGE_D_PROMPT_VERSION = "write-gate.d.v1.1.0";
535
526
  const WRITE_GATE_GRAPH_REWRITE_PROMPT_VERSION = "write-gate.graph-rewrite.v1.1.0";
536
527
  const WRITE_GATE_REGRESSION_SAMPLES = [
537
- "样例A: “今天讨论了三种方案,尚未决策” => active_only",
538
- "样例B: “决定采用B方案并完成上线,错误率下降到0.2%” => archive_event",
539
- "样例C: “好的收到谢谢” => skip",
528
+ "Example A: \"Discussed three options today, no final decision yet\" => active_only",
529
+ "Example B: \"Decided to use plan B and completed rollout, error rate dropped to 0.2%\" => archive_event",
530
+ "Example C: \"ok received thanks\" => skip",
540
531
  ];
541
532
  function buildActiveValuePromptHint(schema) {
542
533
  const pick = (source, wanted) => {
@@ -627,18 +618,7 @@ function buildStablePersonalFactGraph(text) {
627
618
  if (!source)
628
619
  return null;
629
620
  const genericTokens = new Set([
630
- "user",
631
- "person",
632
- "people",
633
- "system",
634
- "assistant",
635
- "agent",
636
- "用户",
637
- "系统",
638
- "助手",
639
- "实体",
640
- "问题",
641
- "方案",
621
+ "user", "person", "people", "system", "assistant", "agent",
642
622
  ]);
643
623
  const normalizeToken = (value) => value.trim().toLowerCase();
644
624
  const isConcreteName = (value) => {
@@ -649,47 +629,41 @@ function buildStablePersonalFactGraph(text) {
649
629
  return false;
650
630
  if (/^(wife|husband|spouse|child|kid|children)$/i.test(name))
651
631
  return false;
652
- if (/^(妻子|丈夫|配偶|孩子|儿子|女儿)$/.test(name))
653
- return false;
654
632
  return true;
655
633
  };
656
634
  const extractConcreteName = (candidate) => {
657
- const cleaned = (candidate || "").trim().replace(/[.,;:!?,。;:!?]+$/g, "");
635
+ const cleaned = (candidate || "").trim().replace(/[.,;:!?]+$/g, "");
658
636
  return isConcreteName(cleaned) ? cleaned : "";
659
637
  };
660
638
  const findSubjectName = () => {
661
639
  const patterns = [
662
640
  /([A-Za-z][A-Za-z0-9._-]{1,40})\s*'s\s*(wife|husband|spouse|child|kid|daughter|son)\b/i,
663
- /([\u4e00-\u9fff]{2,12})\s*的\s*(妻子|老婆|配偶|爱人|丈夫|老公|孩子|儿子|女儿)/,
664
641
  /\b([A-Z][a-zA-Z0-9._-]{1,40})\b/,
665
642
  ];
666
643
  for (const pattern of patterns) {
667
644
  const hit = source.match(pattern);
668
645
  const candidate = hit ? extractConcreteName(hit[1] || "") : "";
669
- if (candidate) {
646
+ if (candidate)
670
647
  return candidate;
671
- }
672
648
  }
673
649
  return "";
674
650
  };
675
651
  const subjectName = findSubjectName();
676
- if (!subjectName) {
652
+ if (!subjectName)
677
653
  return null;
678
- }
679
654
  const entities = new Set([subjectName]);
680
655
  const entity_types = { [subjectName]: "Person" };
681
656
  const relations = [];
682
657
  const relationKeys = new Set();
683
658
  const addRelation = (relation) => {
684
659
  const relationKey = `${relation.source}|${relation.type}|${relation.target}`;
685
- if (relationKeys.has(relationKey)) {
660
+ if (relationKeys.has(relationKey))
686
661
  return;
687
- }
688
662
  relationKeys.add(relationKey);
689
663
  relations.push(relation);
690
664
  };
691
- const spouseNameHit = source.match(/(妻子|老婆|配偶|爱人|丈夫|老公|wife|husband|spouse)(?:\s*(?:是|叫|named|:|-)\s*)?([A-Za-z][A-Za-z0-9._-]{1,40}|[\u4e00-\u9fff]{2,12})/i);
692
- const spouseName = spouseNameHit ? extractConcreteName(spouseNameHit[2] || "") : "";
665
+ const spouseNameHit = source.match(/(?:wife|husband|spouse)(?:\s*(?:named|is|:|-)?\s*)?([A-Za-z][A-Za-z0-9._-]{1,40})/i);
666
+ const spouseName = spouseNameHit ? extractConcreteName(spouseNameHit[1] || "") : "";
693
667
  if (spouseName) {
694
668
  entities.add(spouseName);
695
669
  entity_types[spouseName] = "FamilyMember";
@@ -702,8 +676,8 @@ function buildStablePersonalFactGraph(text) {
702
676
  confidence: 0.9,
703
677
  });
704
678
  }
705
- const childNameHit = source.match(/(儿子|女儿|孩子|child|kid|daughter|son)(?:\s*(?:是|叫|named|:|-)\s*)?([A-Za-z][A-Za-z0-9._-]{1,40}|[\u4e00-\u9fff]{2,12})/i);
706
- const childName = childNameHit ? extractConcreteName(childNameHit[2] || "") : "";
679
+ const childNameHit = source.match(/(?:child|kid|daughter|son)(?:\s*(?:named|is|:|-)?\s*)?([A-Za-z][A-Za-z0-9._-]{1,40})/i);
680
+ const childName = childNameHit ? extractConcreteName(childNameHit[1] || "") : "";
707
681
  if (childName) {
708
682
  entities.add(childName);
709
683
  entity_types[childName] = "FamilyMember";
@@ -716,50 +690,49 @@ function buildStablePersonalFactGraph(text) {
716
690
  confidence: 0.88,
717
691
  });
718
692
  }
719
- const birthdayMatch = source.match(/(birthday|生日)[^,。;\n]*?(\d{4}-\d{2}-\d{2}|\d{1,2}月\d{1,2}日|\d{1,2}[/-]\d{1,2})/i);
693
+ const birthdayMatch = source.match(/birthday[^\n]*?(\d{4}-\d{2}-\d{2}|\d{1,2}[/-]\d{1,2})/i);
720
694
  if (birthdayMatch && spouseName) {
721
- const dateEntity = birthdayMatch[2];
695
+ const dateEntity = birthdayMatch[1];
722
696
  entities.add(dateEntity);
723
697
  entity_types[dateEntity] = "Date";
724
698
  addRelation({
725
699
  source: spouseName,
726
700
  target: dateEntity,
727
701
  type: "birthday_on",
728
- evidence_span: birthdayMatch[2],
702
+ evidence_span: birthdayMatch[1],
729
703
  context_chunk: source.slice(0, 160).trim(),
730
704
  confidence: 0.92,
731
705
  });
732
706
  }
733
707
  if (birthdayMatch && childName) {
734
- const dateEntity = birthdayMatch[2];
708
+ const dateEntity = birthdayMatch[1];
735
709
  entities.add(dateEntity);
736
710
  entity_types[dateEntity] = "Date";
737
711
  addRelation({
738
712
  source: childName,
739
713
  target: dateEntity,
740
714
  type: "birthday_on",
741
- evidence_span: birthdayMatch[2],
715
+ evidence_span: birthdayMatch[1],
742
716
  context_chunk: source.slice(0, 160).trim(),
743
717
  confidence: 0.9,
744
718
  });
745
719
  }
746
- const anniversaryMatch = source.match(/(纪念日|结婚纪念日|anniversary)[^,。;\n]*?(\d{4}-\d{2}-\d{2}|\d{1,2}月\d{1,2}日|\d{1,2}[/-]\d{1,2})/i);
720
+ const anniversaryMatch = source.match(/anniversary[^\n]*?(\d{4}-\d{2}-\d{2}|\d{1,2}[/-]\d{1,2})/i);
747
721
  if (anniversaryMatch) {
748
- const dateEntity = anniversaryMatch[2];
722
+ const dateEntity = anniversaryMatch[1];
749
723
  entities.add(dateEntity);
750
724
  entity_types[dateEntity] = "Date";
751
725
  addRelation({
752
726
  source: subjectName,
753
727
  target: dateEntity,
754
728
  type: "anniversary_on",
755
- evidence_span: anniversaryMatch[2],
729
+ evidence_span: anniversaryMatch[1],
756
730
  context_chunk: source.slice(0, 160).trim(),
757
731
  confidence: 0.9,
758
732
  });
759
733
  }
760
- if (relations.length === 0) {
734
+ if (relations.length === 0)
761
735
  return null;
762
- }
763
736
  return {
764
737
  entities: [...entities],
765
738
  entity_types,
@@ -828,7 +801,6 @@ function parseArchiveEventPayload(value) {
828
801
  entities,
829
802
  entity_types,
830
803
  relations,
831
- outcome: typeof obj.outcome === "string" ? obj.outcome.trim() : "",
832
804
  confidence: typeof obj.confidence === "number" ? Math.max(0, Math.min(1, obj.confidence)) : 0.6,
833
805
  };
834
806
  }
@@ -1269,13 +1241,16 @@ function parseWritePlanDecisions(rootObj, logger, schema) {
1269
1241
  if (!candidateId)
1270
1242
  continue;
1271
1243
  trustedCandidateIds.add(candidateId);
1272
- const sourceSlice = firstString([payload.source_slice, payload.source_span, payload.normalized_text, payload.span, payload.candidate_text]) || "";
1244
+ const sourceSlice = firstString([payload.source_slice, payload.sourceSlice]) || "";
1273
1245
  if (sourceSlice && !candidateTextById.has(candidateId)) {
1274
1246
  candidateTextById.set(candidateId, sourceSlice);
1275
1247
  }
1276
- const activeText = firstString([payload.active_text, payload.activeText, payload.text]) || "";
1277
- if (activeText) {
1278
- activePayloadById.set(candidateId, activeText);
1248
+ const activeSummary = normalizeOneLineText(firstString([payload.summary, payload.active_summary, payload.activeSummary]) || "");
1249
+ if (activeSummary || sourceSlice) {
1250
+ activePayloadById.set(candidateId, {
1251
+ summary: activeSummary,
1252
+ source_slice: sourceSlice.trim(),
1253
+ });
1279
1254
  }
1280
1255
  }
1281
1256
  const archivePayloadById = new Map();
@@ -1321,7 +1296,6 @@ function parseWritePlanDecisions(rootObj, logger, schema) {
1321
1296
  entities: eventValidation.cleaned.entities,
1322
1297
  entity_types: eventValidation.cleaned.entity_types,
1323
1298
  relations: eventValidation.cleaned.relations,
1324
- outcome: eventValidation.cleaned.outcome || "",
1325
1299
  confidence: eventValidation.cleaned.confidence,
1326
1300
  });
1327
1301
  }
@@ -1411,12 +1385,15 @@ function parseWritePlanDecisions(rootObj, logger, schema) {
1411
1385
  targetLayer = activePayloadById.has(candidateId) ? "active_only" : "skip";
1412
1386
  event = undefined;
1413
1387
  }
1414
- const activeText = activePayloadById.get(candidateId) || (targetLayer === "active_only" ? candidateTextById.get(candidateId) || "" : "");
1388
+ const activePayload = activePayloadById.get(candidateId);
1389
+ const activeSummary = activePayload?.summary || "";
1390
+ const activeSourceSlice = activePayload?.source_slice || "";
1415
1391
  decisions.push({
1416
1392
  candidate_id: candidateId,
1417
1393
  candidate_text: candidateTextById.get(candidateId),
1418
1394
  target_layer: targetLayer,
1419
- active_text: activeText,
1395
+ active_summary: activeSummary || undefined,
1396
+ active_source_slice: activeSourceSlice || undefined,
1420
1397
  event: targetLayer === "archive_event" ? event : undefined,
1421
1398
  graph: graphPayloadById.get(candidateId),
1422
1399
  merge_hint: mergeHintById.get(candidateId),
@@ -1458,7 +1435,6 @@ function parseLegacyRoutingDecisions(rootObj, logger, schema) {
1458
1435
  entities: eventValidation.cleaned.entities,
1459
1436
  entity_types: eventValidation.cleaned.entity_types,
1460
1437
  relations: eventValidation.cleaned.relations,
1461
- outcome: eventValidation.cleaned.outcome || "",
1462
1438
  confidence: eventValidation.cleaned.confidence,
1463
1439
  };
1464
1440
  }
@@ -1473,7 +1449,15 @@ function parseLegacyRoutingDecisions(rootObj, logger, schema) {
1473
1449
  candidate_id: candidateId,
1474
1450
  candidate_text: candidateTextById.get(candidateId) || undefined,
1475
1451
  target_layer: target,
1476
- active_text: typeof obj.active_text === "string" ? obj.active_text.trim() : "",
1452
+ active_summary: normalizeOneLineText(typeof obj.summary === "string"
1453
+ ? obj.summary
1454
+ : (typeof obj.active_summary === "string"
1455
+ ? obj.active_summary
1456
+ : (typeof obj.active_text === "string" ? obj.active_text : ""))) || undefined,
1457
+ active_source_slice: firstString([
1458
+ obj.source_slice,
1459
+ obj.source_span,
1460
+ ]) || undefined,
1477
1461
  event: event || undefined,
1478
1462
  graph: toAppendableGraphPayload(parseGraphPayload(obj.graph)),
1479
1463
  reason: typeof obj.reason === "string" ? obj.reason.trim() : "",
@@ -1534,7 +1518,7 @@ function parseLlmGateDecisions(raw, logger, schema) {
1534
1518
  const deduped = [];
1535
1519
  const seen = new Set();
1536
1520
  for (const item of legacyOutput) {
1537
- const key = `${item.candidate_id || ""}|${item.target_layer}|${item.event?.summary || item.active_text || item.reason || ""}`;
1521
+ const key = `${item.candidate_id || ""}|${item.target_layer}|${item.event?.summary || item.active_summary || item.reason || ""}`;
1538
1522
  if (seen.has(key))
1539
1523
  continue;
1540
1524
  seen.add(key);
@@ -1629,10 +1613,10 @@ async function extractGateDecisionsWithLlm(args) {
1629
1613
  "Task: execute Stage A+B only (denoise + candidate split + route classification).",
1630
1614
  "Route classes: active_only | archive_event | skip.",
1631
1615
  "Rules:",
1632
- "- Denoise first: remove pure acknowledgements/politeness/chitchat/repeated filler (for example: 好的/收到/谢谢/ok/got it/thanks) when they contain no task facts.",
1616
+ "- Denoise first: remove pure acknowledgements/politeness/chitchat/repeated filler (for example: 婵犻潧鍊婚弲顐⑩枔?闂佽 鍋撻悹鍝勬惈閻?闁荤姴顑冮崹濂告⒓?ok/got it/thanks) when they contain no task facts.",
1633
1617
  `- Keep factual evidence during denoise using dictionary-grounded signals. ${activeValuePromptHint}`,
1634
1618
  `- ${entityDictionaryPromptHint}`,
1635
- "- Concrete entities must be source-grounded names or aliases from the dictionary above; reject generic placeholders (e.g., user/person/system/问题/方案/实体/thing).",
1619
+ "- Concrete entities must be source-grounded names or aliases from the dictionary above; reject generic placeholders (e.g., user/person/system/闂傚倸鍋嗛崳锝夈€?闂佸搫鍊介~澶愩€?闁诲骸婀遍崑妯肩礊?thing).",
1636
1620
  "- Semantic event split rule: one candidate = one principal event with a coherent subject + action/decision + object/outcome in the same phase.",
1637
1621
  "- Split into different candidates when topic/goal/subject changes, or when a new decision/outcome starts.",
1638
1622
  "- Merge sentences into one candidate when they describe the same event progression in one phase.",
@@ -1644,6 +1628,10 @@ async function extractGateDecisionsWithLlm(args) {
1644
1628
  "- skip: noise/repetition/chitchat/no clear business value.",
1645
1629
  "- Archive task-lifecycle by default when all three are present: user instruction -> agent completion report -> user acceptance.",
1646
1630
  "- If failure/iteration then eventual success exists, prefer archive_event.",
1631
+ "Candidate field definitions:",
1632
+ "- span: source text slice for this candidate (verbatim excerpt from transcript snippet, may contain minor noise).",
1633
+ "- normalized_text: denoised and normalized version of span for the same candidate; keep meaning unchanged.",
1634
+ "- When both are available, normalized_text is the canonical text field for downstream stages.",
1647
1635
  "Output schema:",
1648
1636
  "{\"write_plan\":{\"candidates\":[{\"candidate_id\":\"c1\",\"route\":\"archive_event\",\"span\":\"...\",\"normalized_text\":\"...\",\"reason\":\"...\"}]}}",
1649
1637
  ...WRITE_GATE_REGRESSION_SAMPLES,
@@ -1675,51 +1663,60 @@ async function extractGateDecisionsWithLlm(args) {
1675
1663
  "C2) Build archive_payloads[] for archive_event candidates.",
1676
1664
  "C3) Build graph_payloads[] for candidates with stable graph facts (independent from route).",
1677
1665
  "Keep candidate_id exactly equal to input candidates.",
1678
- "- For active_only route, C1 active_text is required and must contain valuable reusable information, not only acknowledgement/politeness.",
1679
1666
  "- For archive_event route, C2 archive payload must include complete cause/process/result; if confidence < 0.35, prefer no archive payload for that candidate.",
1667
+ "- For every candidate routed to active_only or archive_event, C3 graph_payload is REQUIRED (non-optional).",
1668
+ "- For durable personal profile facts (family relation, birthday, anniversary, long-term schedule), C3 graph payload remains REQUIRED as a strict subset of the rule above.",
1680
1669
  "- Preserve key entities/relations/URLs/document paths/exact numbers/timepoints from source text; do NOT over-abstract placeholders.",
1681
1670
  `- ${stableGraphFactHint}`,
1682
1671
  `- ${entityDictionaryPromptHint}`,
1683
1672
  "- Concrete entities in C1/C2/C3 must follow the dictionary above and remain source-grounded; do not output generic placeholders.",
1684
- "- Each C1/C2/C3 item must carry source_slice, which is the denoised segmented source text for that candidate from A+B.",
1685
- "- source_slice is the canonical text passage for executor write path and traceability; do not invent text outside source.",
1673
+ "- Each C1/C2/C3 item must carry source_slice.",
1674
+ "- source_slice must come from the [CANDIDATES] object in this same request: use the denoised source segment text of the same candidate_id (prefer normalized_text, then span).",
1675
+ "- In [CANDIDATES], normalized_text means denoised canonical candidate text, and span means original source slice; keep source_slice semantically consistent with these fields.",
1676
+ "- source_slice is a trace field for executor write path and retrieval backtracking; keep it source-faithful (do not paraphrase, truncate, or invent text).",
1686
1677
  "C1 field requirements (active_payloads[] item):",
1687
1678
  "- candidate_id: required; must match one input candidate_id exactly.",
1688
- "- source_slice: required; denoised segmented source text for this candidate.",
1689
- "- active_text: required; non-empty; must keep factual evidence and valuable progress context; must not be only acknowledgement/politeness.",
1690
- "- active_text should preserve concrete entities, decisions, blockers/risks, next actions, owners, deadlines, metrics, URLs/paths/config/version details when present.",
1679
+ "- source_slice: required; must be the denoised original text from this C1 candidate slice (full candidate text, DO NOT truncate or excerpt).",
1680
+ "- summary: required; preserve key information (cause, subject, object, and important entities grounded in the graph schema dictionary/aliases above), include stage result for process updates, and stay within 100 characters.",
1691
1681
  "C2 field requirements (archive_payloads[] item):",
1692
1682
  "- candidate_id: required; must match one input candidate_id exactly.",
1693
- "- source_slice: required; denoised segmented source text for this candidate.",
1683
+ "- source_slice: required; must be the denoised original text from this C2 candidate slice.",
1694
1684
  "- event_type: required; must be dictionary-grounded to schema eventTypes/eventTypeAliases.",
1695
- "- summary: required; concise but complete, and should mention key entities in the event.",
1685
+ "- summary: required; must explain cause->process->result end-to-end and stay within 100 characters.",
1696
1686
  "- cause: required; explain why the event happened.",
1697
1687
  "- process: required; explain key execution/decision process.",
1698
1688
  "- result: required; explain final result/state.",
1699
1689
  "- entities: recommended; if present, use concrete entity names from source text.",
1700
1690
  "- entity_types: recommended; if entities are present, provide valid schema type for each entity.",
1701
1691
  "- relations: optional; if provided, each relation should be source-grounded and schema-compatible.",
1702
- "- outcome: optional short conclusion.",
1703
1692
  "- confidence: recommended numeric score in [0,1].",
1704
- "- For every candidate routed to active_only or archive_event, C3 graph_payload is REQUIRED (non-optional).",
1705
- "- For durable personal profile facts (family relation, birthday, anniversary, long-term schedule), C3 graph payload remains REQUIRED as a strict subset of the rule above.",
1706
- "C3 graph payload requirements (single authoritative definition):",
1707
- "- Required fields: candidate_id, source_slice, summary, source_text_nav, entities[], entity_types, relations[], confidence.",
1708
- "- summary must cover every entity listed in entities[].",
1709
- "- source_text_nav must include: layer,session_id,source_file,source_memory_id,source_event_id.",
1710
- "- entity_types must provide a valid type for every entity in entities[].",
1693
+ "C3 field requirements (graph_payloads[] item):",
1694
+ "- candidate_id: required; must match one input candidate_id exactly.",
1695
+ "- source_slice: required; must be the denoised original text from this candidate slice.",
1696
+ "- summary: required; must cover every entity listed in entities[] and explain key relations among entities.",
1697
+ "- source_text_nav: required trace object for source-location and replay; it links graph facts to the original memory/event for retrieval, citation, and debugging.",
1698
+ "- source_text_nav.layer: required; active_only or archive_event, and should be consistent with the candidate route/context.",
1699
+ "- source_text_nav.session_id: required; session id where this candidate comes from (copy from current routing context).",
1700
+ "- source_text_nav.source_file: required; source file identifier/path where this candidate comes from (copy from current routing context).",
1701
+ "- source_text_nav.source_memory_id: required; stable memory record id for this candidate in the source layer (use source_event_id when no separate memory id exists).",
1702
+ "- source_text_nav.source_event_id: required; stable event trace id for this candidate used for full-text backtracking.",
1703
+ "- entities: required array of concrete entities from source text.",
1704
+ "- entity_types: required map; every entity in entities[] must have a valid schema type.",
1705
+ "- relations: required array; each relation must be source-grounded and schema-compatible.",
1706
+ "- confidence: required number in [0,1].",
1707
+ "C3 additional requirements:",
1708
+ "- For archive_event candidates, extract richer source-grounded entities/relations from source_slice + cause/process/result when available (archive facts are higher-value).",
1711
1709
  "- Key-entity protection: entities explicitly mentioned in candidate span should not be dropped.",
1712
1710
  "- Normalize alias/cross-language references to one canonical entity when possible.",
1713
1711
  `- ${args.relationPromptHint}`,
1714
1712
  "- Every relation must include: source,target,type,relation_origin,evidence_span,context_chunk,confidence.",
1715
1713
  "- If relation_origin is llm_custom, relation_definition is required.",
1716
- "- If evidence_span/context_chunk/confidence is missing, do not output that relation.",
1717
1714
  "Output structure (C1/C2/C3 are different item schemas):",
1718
- "- write_plan.active_payloads[] item (C1): {candidate_id,source_slice,active_text}",
1719
- "- write_plan.archive_payloads[] item (C2): {candidate_id,source_slice,event_type,summary,cause,process,result,entities,entity_types,relations,outcome,confidence}",
1715
+ "- write_plan.active_payloads[] item (C1): {candidate_id,source_slice,summary}",
1716
+ "- write_plan.archive_payloads[] item (C2): {candidate_id,source_slice,event_type,summary,cause,process,result,entities,entity_types,relations,confidence}",
1720
1717
  "- write_plan.graph_payloads[] item (C3): {candidate_id,source_slice,summary,source_text_nav,entities,entity_types,relations,confidence}",
1721
1718
  "Top-level output schema:",
1722
- "{\"write_plan\":{\"active_payloads\":[{\"candidate_id\":\"c1\",\"source_slice\":\"...\",\"active_text\":\"...\"}],\"archive_payloads\":[{\"candidate_id\":\"c2\",\"source_slice\":\"...\",\"event_type\":\"decision\",\"summary\":\"...\",\"cause\":\"...\",\"process\":\"...\",\"result\":\"...\",\"entities\":[\"A\"],\"entity_types\":{\"A\":\"Project\"},\"relations\":[],\"outcome\":\"...\",\"confidence\":0.82}],\"graph_payloads\":[{\"candidate_id\":\"c1\",\"source_slice\":\"...\",\"summary\":\"...\",\"source_text_nav\":{\"layer\":\"active_only\",\"session_id\":\"s1\",\"source_file\":\"daily_summary:2026-04-03.md\",\"source_memory_id\":\"evt_1\",\"source_event_id\":\"evt_1\"},\"entities\":[\"A\"],\"entity_types\":{\"A\":\"Project\"},\"relations\":[{\"source\":\"A\",\"target\":\"B\",\"type\":\"depends_on\",\"relation_origin\":\"canonical\",\"evidence_span\":\"A 依赖 B\",\"context_chunk\":\"原文上下文...\",\"confidence\":0.9}],\"confidence\":0.8}]}}",
1719
+ "{\"write_plan\":{\"active_payloads\":[{\"candidate_id\":\"c1\",\"source_slice\":\"...\",\"summary\":\"...\"}],\"archive_payloads\":[{\"candidate_id\":\"c2\",\"source_slice\":\"...\",\"event_type\":\"decision\",\"summary\":\"...\",\"cause\":\"...\",\"process\":\"...\",\"result\":\"...\",\"entities\":[\"A\"],\"entity_types\":{\"A\":\"Project\"},\"relations\":[],\"confidence\":0.82}],\"graph_payloads\":[{\"candidate_id\":\"c1\",\"source_slice\":\"...\",\"summary\":\"...\",\"source_text_nav\":{\"layer\":\"active_only\",\"session_id\":\"s1\",\"source_file\":\"daily_summary:2026-04-03.md\",\"source_memory_id\":\"evt_1\",\"source_event_id\":\"evt_1\"},\"entities\":[\"A\"],\"entity_types\":{\"A\":\"Project\"},\"relations\":[{\"source\":\"A\",\"target\":\"B\",\"type\":\"depends_on\",\"relation_origin\":\"canonical\",\"evidence_span\":\"A 婵炴挻纰嶇换鍡欑矉?B\",\"context_chunk\":\"闂佸憡顭囬崰鎰板几閸愨晝鈻斿┑鐘辫兌閻熸捇鏌?..\",\"confidence\":0.9}],\"confidence\":0.8}]}}",
1723
1720
  "Output JSON only. Do NOT output merge_hints/graph_rewrite.",
1724
1721
  "",
1725
1722
  "[CANDIDATES]",
@@ -1766,7 +1763,7 @@ async function extractGateDecisionsWithLlm(args) {
1766
1763
  "- For every Stage C graph_payload candidate, output one merge_hints item and one graph_rewrite item.",
1767
1764
  "- Do not output active_payloads/archive_payloads/graph_payloads in this stage.",
1768
1765
  "Output schema:",
1769
- "{\"write_plan\":{\"merge_hints\":[{\"candidate_id\":\"c1\",\"same_event\":false,\"same_entity_pairs\":[[\"Ava\",\"艾娃\"]],\"suggested_action\":\"merge_aliases\",\"reason\":\"Ava and 艾娃 refer to the same person in this candidate\"}],\"graph_rewrite\":[{\"candidate_id\":\"c1\",\"rewrite_required\":true,\"rewrite_reason\":\"entity canonicalization changed summary and relations\",\"rewrite_scope\":[\"summary\",\"entities\",\"entity_types\",\"relations\"],\"graph_rewrite_payload\":{\"summary\":\"...\",\"entities\":[\"艾娃\",\"Joe\"],\"entity_types\":{\"艾娃\":\"Person\",\"Joe\":\"Person\"},\"relations\":[{\"source\":\"Joe\",\"target\":\"艾娃\",\"type\":\"has_spouse\",\"relation_origin\":\"canonical\",\"evidence_span\":\"Joe 艾娃是夫妻\",\"context_chunk\":\"原文上下文...\",\"confidence\":0.91}],\"confidence\":0.86}}]}}",
1766
+ "{\"write_plan\":{\"merge_hints\":[{\"candidate_id\":\"c1\",\"same_event\":false,\"same_entity_pairs\":[[\"Ava\",\"Ava\"]],\"suggested_action\":\"merge_aliases\",\"reason\":\"Alias pair refers to the same person\"}],\"graph_rewrite\":[{\"candidate_id\":\"c1\",\"rewrite_required\":true,\"rewrite_reason\":\"entity canonicalization changed summary and relations\",\"rewrite_scope\":[\"summary\",\"entities\",\"entity_types\",\"relations\"],\"graph_rewrite_payload\":{\"summary\":\"...\",\"entities\":[\"Ava\",\"Joe\"],\"entity_types\":{\"Ava\":\"Person\",\"Joe\":\"Person\"},\"relations\":[{\"source\":\"Joe\",\"target\":\"Ava\",\"type\":\"has_spouse\",\"relation_origin\":\"canonical\",\"evidence_span\":\"Joe is spouse of Ava\",\"context_chunk\":\"source snippet context\",\"confidence\":0.91}],\"confidence\":0.86}}]}}",
1770
1767
  "Output JSON only.",
1771
1768
  "",
1772
1769
  "[CANDIDATES]",
@@ -1842,7 +1839,9 @@ async function rewriteGraphPayloadWithLlm(args) {
1842
1839
  "- Do not output related_to.",
1843
1840
  `- ${args.relationPromptHint}`,
1844
1841
  "Field contract (required):",
1845
- "- graph_payload.summary: concise stable fact summary; must cover all entities and key relations.",
1842
+ "- graph_payload.summary: must cover all entities and key relations.",
1843
+ "- If source_text_nav.layer is active_only, summary must preserve key information (cause, subject, object and important entities grounded in the graph schema dictionary/aliases), include stage result for process updates, and stay within 100 characters.",
1844
+ "- summary should remain model-authored text; do not apply rule-based hard truncation after generation.",
1846
1845
  "- graph_payload.source_text_nav: required object with layer,session_id,source_file,source_memory_id,source_event_id; fulltext_anchor optional.",
1847
1846
  "- graph_payload.entities: required array of concrete entity names; deduplicated.",
1848
1847
  "- graph_payload.entity_types: required map; every entity in entities should have a type from dictionary.",
@@ -1971,6 +1970,7 @@ function createSessionSync(options) {
1971
1970
  try {
1972
1971
  fallbackWrite = await options.writeStore.writeMemory({
1973
1972
  text: tailByCharLimit(normalizedTranscript, activeTextMaxChars),
1973
+ sourceText: normalizedTranscript,
1974
1974
  role: "system",
1975
1975
  source: `sync_gate_fallback:${args.sourceFile}`,
1976
1976
  sessionId: args.sessionId,
@@ -2015,25 +2015,8 @@ function createSessionSync(options) {
2015
2015
  let graphRewriteApplied = 0;
2016
2016
  let graphRewriteFailed = 0;
2017
2017
  const archiveInputs = [];
2018
- function summaryMentionsAllEntities(summary, entities) {
2019
- const normalizedSummary = summary.toLowerCase();
2020
- return entities.every(entity => normalizedSummary.includes(entity.toLowerCase()));
2021
- }
2022
- function buildAppendSummary(payload) {
2023
- const entities = Array.isArray(payload.entities) ? payload.entities : [];
2024
- const relations = Array.isArray(payload.relations) ? payload.relations : [];
2025
- const current = typeof payload.summary === "string" ? payload.summary.trim() : "";
2026
- const relationText = relations
2027
- .slice(0, 3)
2028
- .map(item => `${item.source} ${item.type} ${item.target}`)
2029
- .join("; ");
2030
- const base = current || (relationText
2031
- ? `Graph extraction captured key relations: ${relationText}.`
2032
- : "Graph extraction captured key entities and relations.");
2033
- if (entities.length === 0 || summaryMentionsAllEntities(base, entities)) {
2034
- return base;
2035
- }
2036
- return `${base} Entities: ${entities.join(", ")}.`;
2018
+ function resolveGraphSummary(payload) {
2019
+ return typeof payload.summary === "string" ? payload.summary.trim() : "";
2037
2020
  }
2038
2021
  function buildAppendSourceTextNav(argsForAppend) {
2039
2022
  const nav = argsForAppend.graphPayload?.source_text_nav;
@@ -2065,7 +2048,12 @@ function createSessionSync(options) {
2065
2048
  if (!appendableGraph) {
2066
2049
  return;
2067
2050
  }
2068
- const summary = buildAppendSummary(appendableGraph);
2051
+ const summary = resolveGraphSummary(appendableGraph);
2052
+ if (!summary) {
2053
+ graphSkipped += 1;
2054
+ options.logger.info(`graph_skip_reason=missing_summary source_event_id=${argsForAppend.sourceEventId}`);
2055
+ return;
2056
+ }
2069
2057
  const sourceTextNav = buildAppendSourceTextNav({
2070
2058
  sourceEventId: argsForAppend.sourceEventId,
2071
2059
  sourceLayer: argsForAppend.sourceLayer,
@@ -2116,10 +2104,15 @@ function createSessionSync(options) {
2116
2104
  }
2117
2105
  for (const decision of routedDecisions) {
2118
2106
  llmDecisions += 1;
2107
+ const decisionActiveSummary = normalizeOneLineText(decision.active_summary || "");
2108
+ const decisionActiveSourceSlice = (decision.active_source_slice || "").trim();
2119
2109
  const fallbackGraphPayload = !decision.graph
2120
- ? buildStablePersonalFactGraph(decision.active_text || decision.candidate_text || normalizedTranscript)
2110
+ ? buildStablePersonalFactGraph(decisionActiveSummary || decision.candidate_text || normalizedTranscript)
2121
2111
  : null;
2122
2112
  let graphPayload = mergeGraphPayload(toAppendableGraphPayload(decision.graph), toAppendableGraphPayload(fallbackGraphPayload || undefined));
2113
+ if (decisionActiveSummary && graphPayload && !normalizeOneLineText(graphPayload.summary || "")) {
2114
+ graphPayload = { ...graphPayload, summary: decisionActiveSummary };
2115
+ }
2123
2116
  const mergeReviewed = applyMergeHintToGraphPayload({
2124
2117
  graphPayload,
2125
2118
  mergeHint: decision.merge_hint,
@@ -2155,7 +2148,7 @@ function createSessionSync(options) {
2155
2148
  const rewritten = await rewriteGraphPayloadWithLlm({
2156
2149
  llm: { model: llmModel, apiKey: llmApiKey, baseUrl: llmBaseUrl },
2157
2150
  transcript: normalizedTranscript,
2158
- candidateText: decision.candidate_text || decision.active_text,
2151
+ candidateText: decision.candidate_text || decisionActiveSummary,
2159
2152
  graphPayload,
2160
2153
  rewritePlan: decision.graph_rewrite,
2161
2154
  mergeHint: decision.merge_hint,
@@ -2199,8 +2192,14 @@ function createSessionSync(options) {
2199
2192
  }
2200
2193
  if (decision.target_layer === "active_only") {
2201
2194
  activeAttempted += 1;
2202
- const activeCandidateText = denoiseTranscriptForWrite(decision.active_text || normalizedTranscript);
2203
- const activeText = tailByCharLimit(activeCandidateText, activeTextMaxChars);
2195
+ const activeSummary = decisionActiveSummary
2196
+ || normalizeOneLineText(graphPayload?.summary || "")
2197
+ || normalizeOneLineText(decision.candidate_text || "");
2198
+ const activeText = tailByCharLimit(activeSummary, activeTextMaxChars);
2199
+ const activeSourceSlice = decisionActiveSourceSlice;
2200
+ if (activeSummary && graphPayload && !normalizeOneLineText(graphPayload.summary || "")) {
2201
+ graphPayload = { ...graphPayload, summary: activeSummary };
2202
+ }
2204
2203
  if (!activeText) {
2205
2204
  if (graphPayload) {
2206
2205
  const graphOnlySourceEventId = buildGraphOnlySourceEventId({
@@ -2212,12 +2211,18 @@ function createSessionSync(options) {
2212
2211
  sourceEventId: graphOnlySourceEventId,
2213
2212
  sourceLayer: "active_only",
2214
2213
  eventType: "insight",
2215
- sourceText: normalizedTranscript,
2214
+ sourceText: decision.candidate_text || normalizedTranscript,
2216
2215
  graphPayload,
2217
2216
  });
2218
2217
  }
2219
2218
  skipped += 1;
2220
- bumpReason("active_only_empty");
2219
+ bumpReason("active_summary_missing");
2220
+ continue;
2221
+ }
2222
+ if (!activeSourceSlice) {
2223
+ skipped += 1;
2224
+ bumpReason("active_source_slice_missing");
2225
+ options.logger.warn(`sync_skip reason=active_source_slice_missing session=${args.sessionId} candidate_id=${decision.candidate_id || "unknown"}`);
2221
2226
  continue;
2222
2227
  }
2223
2228
  if (!hasValuableActiveContent(activeText)) {
@@ -2231,7 +2236,7 @@ function createSessionSync(options) {
2231
2236
  sourceEventId: graphOnlySourceEventId,
2232
2237
  sourceLayer: "active_only",
2233
2238
  eventType: "insight",
2234
- sourceText: activeText,
2239
+ sourceText: activeSourceSlice,
2235
2240
  graphPayload,
2236
2241
  });
2237
2242
  }
@@ -2250,6 +2255,8 @@ function createSessionSync(options) {
2250
2255
  try {
2251
2256
  writeResult = await options.writeStore.writeMemory({
2252
2257
  text: activeText,
2258
+ summary: activeSummary || undefined,
2259
+ sourceText: activeSourceSlice,
2253
2260
  role: "system",
2254
2261
  source: `sync_gate_active:${args.sourceFile}`,
2255
2262
  sessionId: args.sessionId,
@@ -2274,7 +2281,7 @@ function createSessionSync(options) {
2274
2281
  sourceEventId: activeSourceEventId,
2275
2282
  sourceLayer: "active_only",
2276
2283
  eventType: "insight",
2277
- sourceText: activeText,
2284
+ sourceText: activeSourceSlice,
2278
2285
  graphPayload,
2279
2286
  });
2280
2287
  }
@@ -2318,7 +2325,6 @@ function createSessionSync(options) {
2318
2325
  entities: decision.event.entities,
2319
2326
  relations: decision.event.relations,
2320
2327
  entity_types: decision.event.entity_types,
2321
- outcome: decision.event.outcome,
2322
2328
  confidence: decision.event.confidence,
2323
2329
  session_id: args.sessionId,
2324
2330
  source_file: args.sourceFile,