@remnic/core 9.3.736 → 9.3.737

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 (148) hide show
  1. package/dist/access-boundary.d.ts +17 -6
  2. package/dist/access-cli.js +1 -1
  3. package/dist/access-http.d.ts +17 -6
  4. package/dist/access-mcp.d.ts +17 -6
  5. package/dist/access-operations.d.ts +17 -6
  6. package/dist/{access-service-CdC0q4pr.d.ts → access-service-DwQ6BIQw.d.ts} +3 -3
  7. package/dist/access-service.d.ts +16 -5
  8. package/dist/access-surface-catalog.d.ts +17 -6
  9. package/dist/action-confidence.d.ts +1 -1
  10. package/dist/active-memory-bridge.d.ts +1 -1
  11. package/dist/active-recall.d.ts +1 -1
  12. package/dist/behavior-learner.d.ts +1 -1
  13. package/dist/behavior-signals.d.ts +1 -1
  14. package/dist/bootstrap.d.ts +16 -4
  15. package/dist/briefing.d.ts +1 -1
  16. package/dist/buffer-surprise-report.d.ts +1 -1
  17. package/dist/buffer.d.ts +1 -1
  18. package/dist/calibration.d.ts +1 -1
  19. package/dist/capabilities.d.ts +1 -1
  20. package/dist/{catalog-D2NLDg4S.d.ts → catalog-_Bap6vfD.d.ts} +1 -1
  21. package/dist/causal-behavior.d.ts +1 -1
  22. package/dist/causal-consolidation.d.ts +1 -1
  23. package/dist/causal-trajectory-graph.d.ts +1 -1
  24. package/dist/{chunk-AE2HPUP7.js → chunk-PB5YON2G.js} +352 -297
  25. package/dist/chunk-PB5YON2G.js.map +1 -0
  26. package/dist/{cli-BHy6Bo6u.d.ts → cli-BlEIWDQw.d.ts} +3 -3
  27. package/dist/cli.d.ts +9 -7
  28. package/dist/compounding/engine.d.ts +1 -1
  29. package/dist/compounding/preference-consolidator.d.ts +1 -1
  30. package/dist/compression-optimizer.d.ts +1 -1
  31. package/dist/config.d.ts +1 -1
  32. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  33. package/dist/connectors/codex-materialize.d.ts +1 -1
  34. package/dist/connectors/index.d.ts +1 -1
  35. package/dist/consolidation-provenance-check.d.ts +1 -1
  36. package/dist/consolidation-undo.d.ts +1 -1
  37. package/dist/contradiction/index.d.ts +1 -1
  38. package/dist/conversation-index/backend.d.ts +1 -1
  39. package/dist/conversation-index/chunker.d.ts +1 -1
  40. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  41. package/dist/conversation-index/indexer.d.ts +1 -1
  42. package/dist/conversation-index/search.d.ts +1 -1
  43. package/dist/day-summary.d.ts +1 -1
  44. package/dist/delinearize.d.ts +1 -1
  45. package/dist/direct-answer-wiring.d.ts +1 -1
  46. package/dist/direct-answer.d.ts +1 -1
  47. package/dist/embedding-fallback.d.ts +1 -1
  48. package/dist/enrichment/index.d.ts +1 -1
  49. package/dist/entity-retrieval.d.ts +1 -1
  50. package/dist/entity-schema.d.ts +1 -1
  51. package/dist/explicit-capture.d.ts +16 -4
  52. package/dist/extraction-faithfulness.d.ts +1 -1
  53. package/dist/extraction-judge-telemetry.d.ts +1 -1
  54. package/dist/extraction-judge-training.d.ts +1 -1
  55. package/dist/extraction-judge.d.ts +1 -1
  56. package/dist/extraction.d.ts +1 -1
  57. package/dist/fallback-llm.d.ts +1 -1
  58. package/dist/graph-dashboard-diff.d.ts +1 -1
  59. package/dist/graph-dashboard-key.d.ts +1 -1
  60. package/dist/graph-dashboard-parser.d.ts +1 -1
  61. package/dist/graph-edge-reinforcement.d.ts +1 -1
  62. package/dist/graph-snapshot.d.ts +1 -1
  63. package/dist/graph.d.ts +1 -1
  64. package/dist/identity-continuity.d.ts +1 -1
  65. package/dist/importance.d.ts +1 -1
  66. package/dist/index.d.ts +20 -18
  67. package/dist/index.js +1 -1
  68. package/dist/intent.d.ts +1 -1
  69. package/dist/lcm/engine.d.ts +1 -1
  70. package/dist/lcm/index.d.ts +1 -1
  71. package/dist/lcm/tools.d.ts +1 -1
  72. package/dist/lifecycle.d.ts +1 -1
  73. package/dist/live-connectors-runner.d.ts +1 -1
  74. package/dist/local-llm.d.ts +1 -1
  75. package/dist/local-model-endpoint.d.ts +1 -1
  76. package/dist/maintenance/memory-governance.d.ts +1 -1
  77. package/dist/mcp-memory-inspector-app.d.ts +17 -6
  78. package/dist/memory-action-policy.d.ts +1 -1
  79. package/dist/memory-cache.d.ts +1 -1
  80. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  81. package/dist/memory-projection-store.d.ts +1 -1
  82. package/dist/memory-provenance.d.ts +1 -1
  83. package/dist/memory-worth-outcomes.d.ts +1 -1
  84. package/dist/models-json.d.ts +1 -1
  85. package/dist/namespaces/migrate.d.ts +2 -2
  86. package/dist/namespaces/principal.d.ts +1 -1
  87. package/dist/namespaces/search.d.ts +1 -1
  88. package/dist/namespaces/storage.d.ts +2 -2
  89. package/dist/native-knowledge.d.ts +1 -1
  90. package/dist/operator-toolkit.d.ts +1 -1
  91. package/dist/orchestration/compression-guideline-coordinator.d.ts +1 -1
  92. package/dist/orchestration/maintenance.d.ts +2 -2
  93. package/dist/{orchestrator-C-xp_rtZ.d.ts → orchestrator-CJZ21ZiB.d.ts} +78 -12
  94. package/dist/orchestrator.d.ts +16 -4
  95. package/dist/orchestrator.js +1 -1
  96. package/dist/patterns-cli.d.ts +1 -1
  97. package/dist/policy-runtime.d.ts +1 -1
  98. package/dist/provenance.d.ts +1 -1
  99. package/dist/qmd-recall-cache.d.ts +1 -1
  100. package/dist/qmd.d.ts +1 -1
  101. package/dist/recall-disclosure-escalation.d.ts +1 -1
  102. package/dist/recall-explain-renderer.d.ts +1 -1
  103. package/dist/recall-planner-llm.d.ts +1 -1
  104. package/dist/recall-state.d.ts +1 -1
  105. package/dist/recall-tag-filter.d.ts +1 -1
  106. package/dist/recall-xray-cli.d.ts +1 -1
  107. package/dist/recall-xray-renderer.d.ts +1 -1
  108. package/dist/recall-xray.d.ts +1 -1
  109. package/dist/resolve-auth-token.d.ts +1 -1
  110. package/dist/retrieval-agents.d.ts +1 -1
  111. package/dist/retrieval-tiers.d.ts +1 -1
  112. package/dist/routing/engine.d.ts +1 -1
  113. package/dist/routing/store.d.ts +1 -1
  114. package/dist/search/embed-helper.d.ts +1 -1
  115. package/dist/search/factory.d.ts +1 -1
  116. package/dist/search/index.d.ts +1 -1
  117. package/dist/search/lancedb-backend.d.ts +1 -1
  118. package/dist/search/meilisearch-backend.d.ts +1 -1
  119. package/dist/search/noop-backend.d.ts +1 -1
  120. package/dist/search/orama-backend.d.ts +1 -1
  121. package/dist/search/port.d.ts +1 -1
  122. package/dist/search/remote-backend.d.ts +1 -1
  123. package/dist/{semantic-consolidation-COdwU-me.d.ts → semantic-consolidation-DsIEiCka.d.ts} +1 -1
  124. package/dist/semantic-consolidation.d.ts +2 -2
  125. package/dist/semantic-rule-verifier.d.ts +1 -1
  126. package/dist/session-observer-bands.d.ts +1 -1
  127. package/dist/session-observer-state.d.ts +1 -1
  128. package/dist/shared-context/manager.d.ts +1 -1
  129. package/dist/signal.d.ts +1 -1
  130. package/dist/storage.d.ts +1 -1
  131. package/dist/summarizer.d.ts +1 -1
  132. package/dist/summary-snapshot.d.ts +1 -1
  133. package/dist/temporal-supersession.d.ts +1 -1
  134. package/dist/temporal-validity.d.ts +1 -1
  135. package/dist/threading.d.ts +1 -1
  136. package/dist/tier-migration.d.ts +1 -1
  137. package/dist/tier-routing.d.ts +1 -1
  138. package/dist/topics.d.ts +1 -1
  139. package/dist/transcript.d.ts +1 -1
  140. package/dist/trust-score-stage.d.ts +2 -2
  141. package/dist/trust-score.d.ts +1 -1
  142. package/dist/{types-w3Y232yi.d.ts → types-CglNn2V-.d.ts} +1 -1
  143. package/dist/types.d.ts +1 -1
  144. package/dist/utility-runtime.d.ts +1 -1
  145. package/package.json +2 -2
  146. package/src/orchestration/recall-result-formatter.ts +438 -0
  147. package/src/orchestrator.ts +22 -305
  148. package/dist/chunk-AE2HPUP7.js.map +0 -1
@@ -101,6 +101,8 @@ import { CompressionGuidelineCoordinator } from "./orchestration/compression-gui
101
101
  import { SemanticConsolidationCoordinator } from "./orchestration/semantic-consolidation-coordinator.js";
102
102
  import { LifecyclePolicyCoordinator } from "./orchestration/lifecycle-policy-coordinator.js";
103
103
  import { EntitySynthesisCoordinator } from "./orchestration/entity-synthesis-coordinator.js";
104
+ import { RecallResultFormatter } from "./orchestration/recall-result-formatter.js";
105
+ export { hasIdentityRecoveryIntent, resolveEffectiveIdentityInjectionMode } from "./orchestration/recall-result-formatter.js";
104
106
  import {
105
107
  runLiveConnectorsOnce,
106
108
  type LiveConnectorsRunSummary,
@@ -1368,31 +1370,6 @@ export async function resolveRecallModeDecisionAsync(
1368
1370
  };
1369
1371
  }
1370
1372
 
1371
- export function hasIdentityRecoveryIntent(prompt: string): boolean {
1372
- const text = typeof prompt === "string" ? prompt.toLowerCase() : "";
1373
- if (!text) return false;
1374
- return /\b(identity|continuity|recover(?:y|ing|ed)?|incident|drift|restore|regress(?:ion|ed|ing)?)\b/i.test(
1375
- text,
1376
- );
1377
- }
1378
-
1379
- export function resolveEffectiveIdentityInjectionMode(options: {
1380
- configuredMode: IdentityInjectionMode;
1381
- recallMode: RecallPlanMode;
1382
- prompt: string;
1383
- }): { mode: IdentityInjectionMode; shouldInject: boolean } {
1384
- if (
1385
- options.configuredMode === "recovery_only" &&
1386
- !hasIdentityRecoveryIntent(options.prompt)
1387
- ) {
1388
- return { mode: "recovery_only", shouldInject: false };
1389
- }
1390
- if (options.recallMode === "minimal" && options.configuredMode === "full") {
1391
- return { mode: "minimal", shouldInject: true };
1392
- }
1393
- return { mode: options.configuredMode, shouldInject: true };
1394
- }
1395
-
1396
1373
  export function computeArtifactCandidateFetchLimit(
1397
1374
  targetCount: number,
1398
1375
  ): number {
@@ -1928,6 +1905,11 @@ export class Orchestrator {
1928
1905
  * hands it to `enqueue`.
1929
1906
  */
1930
1907
  readonly extractionQueueCoordinator: ExtractionQueueCoordinator;
1908
+ /**
1909
+ * Issue #1526: recall result formatting + identity continuity section moved
1910
+ * to RecallResultFormatter.
1911
+ */
1912
+ readonly recallResultFormatter: RecallResultFormatter;
1931
1913
  private heartbeatObserverChains = new Map<string, Promise<void>>();
1932
1914
  private recentExtractionFingerprints = new Map<string, number>();
1933
1915
  private readonly consolidationObservers = new Set<
@@ -2896,6 +2878,7 @@ export class Orchestrator {
2896
2878
  });
2897
2879
  // Issue #1526: background extraction queue lives on its own coordinator.
2898
2880
  this.extractionQueueCoordinator = new ExtractionQueueCoordinator();
2881
+ this.recallResultFormatter = new RecallResultFormatter(this.config);
2899
2882
  const conversationIndexRuntime = createConversationIndexRuntime(config, {
2900
2883
  getQmd: () => this.conversationQmd,
2901
2884
  getFaiss: () => this.conversationFaiss,
@@ -16946,226 +16929,55 @@ export class Orchestrator {
16946
16929
  }
16947
16930
  }
16948
16931
 
16932
+ // Issue #1526: recall result formatting moved to RecallResultFormatter. Thin
16933
+ // delegation keeps the private API stable for callers + tests.
16949
16934
  private formatQmdResults(
16950
16935
  title: string,
16951
16936
  results: QmdSearchResult[],
16952
16937
  sessionKey?: string,
16953
16938
  trustByPath?: Map<string, TrustStageResultItem> | null,
16954
16939
  ): string {
16955
- // Issue #1582 handles are only rendered when a session key is available:
16956
- // resolution requires the handle history to have been recorded for this
16957
- // session, which only happens when sessionKey is present. Rendering handles
16958
- // without recording would show tokens a user can never resolve (cursor
16959
- // review). The rendering logic itself lives in the pure handles module.
16960
- const handleByIndex = buildHandleIndexForResults(
16961
- results,
16962
- this.config.recallMemoryHandles === true && sessionKey != null,
16963
- );
16964
- // Issue #1577 — epistemic hedge. Append a deterministic, component-derived
16965
- // suffix so the downstream model knows each memory's trust status (the
16966
- // cheap lever against confident-stale-answer failures). Gated separately
16967
- // from scoring so rendering can ship after the stage is stable. High-band
16968
- // and neutral items get no suffix (don't waste tokens on the common case).
16969
- const renderHedge = this.config.trustScoreEpistemicRendering && trustByPath !== null && trustByPath !== undefined;
16970
- const hedgeMap = renderHedge ? trustByPath : null;
16971
- const lines = results.map((r, i) => {
16972
- const snippet = r.snippet
16973
- ? r.snippet.slice(0, 500).replace(/\n/g, " ")
16974
- : "(no preview)";
16975
- const source = typeof r.line === "number" ? `${r.path}:${r.line}` : r.path;
16976
- const head = `[${i + 1}] ${source} (score: ${r.score.toFixed(3)})\n${snippet}`;
16977
- const handle = handleByIndex.get(i);
16978
- const hedged = head.replace(/\s+$/, "");
16979
- const withHandle = handle ? `${hedged} ${handle}` : hedged;
16980
- if (hedgeMap) {
16981
- const item = hedgeMap.get(r.path);
16982
- if (item) {
16983
- const hedge = renderEpistemicHedge(item.trust);
16984
- if (hedge.length > 0) return `${withHandle} ${hedge}`;
16985
- }
16986
- }
16987
- return withHandle;
16988
- });
16989
- return `## ${title}\n\n${lines.join("\n\n")}`;
16940
+ return this.recallResultFormatter.formatQmdResults(title, results, sessionKey, trustByPath);
16990
16941
  }
16991
16942
 
16992
16943
  private formatObjectiveStateResults(
16993
16944
  results: ObjectiveStateSearchResult[],
16994
16945
  ): string {
16995
- const lines = results.map(({ snapshot }, index) => {
16996
- const parts = [
16997
- snapshot.recordedAt.replace("T", " ").slice(0, 16),
16998
- `${snapshot.kind}/${snapshot.changeKind}`,
16999
- ];
17000
- if (snapshot.outcome) parts.push(snapshot.outcome);
17001
- const header = `[${index + 1}] ${parts.join(" | ")} | ${snapshot.scope}`;
17002
- const detailParts = [snapshot.summary];
17003
- if (snapshot.command) detailParts.push(`command: ${snapshot.command}`);
17004
- else if (snapshot.toolName)
17005
- detailParts.push(`tool: ${snapshot.toolName}`);
17006
- return `${header}\n${detailParts.join(" | ")}`;
17007
- });
17008
- return `## Objective State\n\n${lines.join("\n\n")}`;
16946
+ return this.recallResultFormatter.formatObjectiveStateResults(results);
17009
16947
  }
17010
16948
 
17011
16949
  private formatCausalTrajectoryResults(
17012
16950
  results: CausalTrajectorySearchResult[],
17013
16951
  ): string {
17014
- const lines = results.map(({ record, matchedFields }, index) => {
17015
- const header = [
17016
- `[${index + 1}] ${record.recordedAt.replace("T", " ").slice(0, 16)}`,
17017
- record.outcomeKind,
17018
- ].join(" | ");
17019
- const details = [
17020
- `goal: ${record.goal}`,
17021
- `action: ${record.actionSummary}`,
17022
- `observation: ${record.observationSummary}`,
17023
- `outcome: ${record.outcomeSummary}`,
17024
- ];
17025
- if (record.followUpSummary)
17026
- details.push(`follow-up: ${record.followUpSummary}`);
17027
- if (matchedFields.length > 0)
17028
- details.push(`matched: ${matchedFields.join(", ")}`);
17029
- return `${header}\n${details.join("\n")}`;
17030
- });
17031
-
17032
- return `## Causal Trajectories\n\n${lines.join("\n\n")}`;
16952
+ return this.recallResultFormatter.formatCausalTrajectoryResults(results);
17033
16953
  }
17034
16954
 
17035
16955
  private formatTrustZoneResults(results: TrustZoneSearchResult[]): string {
17036
- const lines = results.map(({ record, matchedFields }, index) => {
17037
- const header = [
17038
- `[${index + 1}] ${record.recordedAt.replace("T", " ").slice(0, 16)}`,
17039
- record.zone,
17040
- record.kind,
17041
- ].join(" | ");
17042
- const details = [
17043
- record.summary,
17044
- `provenance: ${record.provenance.sourceClass}`,
17045
- ];
17046
- if (record.entityRefs && record.entityRefs.length > 0) {
17047
- details.push(`entities: ${record.entityRefs.join(", ")}`);
17048
- }
17049
- if (record.tags && record.tags.length > 0) {
17050
- details.push(`tags: ${record.tags.join(", ")}`);
17051
- }
17052
- if (matchedFields.length > 0) {
17053
- details.push(`matched: ${matchedFields.join(", ")}`);
17054
- }
17055
- return `${header}\n${details.join("\n")}`;
17056
- });
17057
-
17058
- return `## Trust Zones\n\n${lines.join("\n\n")}`;
16956
+ return this.recallResultFormatter.formatTrustZoneResults(results);
17059
16957
  }
17060
16958
 
17061
16959
  private formatHarmonicRetrievalResults(
17062
16960
  results: HarmonicRetrievalResult[],
17063
16961
  ): string {
17064
- const lines = results.map(
17065
- (
17066
- { node, matchedAnchors, matchedFields, nodeScore, anchorScore },
17067
- index,
17068
- ) => {
17069
- const header = [
17070
- `[${index + 1}] ${node.recordedAt.replace("T", " ").slice(0, 16)}`,
17071
- `${node.kind}/${node.abstractionLevel}`,
17072
- node.sessionKey,
17073
- ].join(" | ");
17074
- const details = [
17075
- node.title,
17076
- node.summary,
17077
- `scores: node=${nodeScore.toFixed(1)} anchor=${anchorScore.toFixed(1)}`,
17078
- ];
17079
- if (matchedAnchors.length > 0) {
17080
- details.push(
17081
- `anchors: ${matchedAnchors.map((anchor) => `${anchor.anchorType}:${anchor.anchorValue}`).join("; ")}`,
17082
- );
17083
- }
17084
- if (matchedFields.length > 0) {
17085
- details.push(`matched: ${matchedFields.join(", ")}`);
17086
- }
17087
- return `${header}\n${details.join("\n")}`;
17088
- },
17089
- );
17090
-
17091
- return `## Harmonic Retrieval\n\n${lines.join("\n\n")}`;
16962
+ return this.recallResultFormatter.formatHarmonicRetrievalResults(results);
17092
16963
  }
17093
16964
 
17094
16965
  private formatWorkProductResults(
17095
16966
  results: WorkProductLedgerSearchResult[],
17096
16967
  ): string {
17097
- const lines = results.map(({ entry, matchedFields }, index) => {
17098
- const header = [
17099
- `[${index + 1}] ${entry.recordedAt.replace("T", " ").slice(0, 16)}`,
17100
- `${entry.kind}/${entry.action}`,
17101
- entry.sessionKey,
17102
- ].join(" | ");
17103
- const details = [entry.summary, `scope: ${entry.scope}`];
17104
- if (entry.artifactPath) details.push(`artifact: ${entry.artifactPath}`);
17105
- if (entry.tags && entry.tags.length > 0)
17106
- details.push(`tags: ${entry.tags.join(", ")}`);
17107
- if (matchedFields.length > 0)
17108
- details.push(`matched: ${matchedFields.join(", ")}`);
17109
- return `${header}\n${details.join("\n")}`;
17110
- });
17111
-
17112
- return `## Work Products\n\n${lines.join("\n\n")}`;
16968
+ return this.recallResultFormatter.formatWorkProductResults(results);
17113
16969
  }
17114
16970
 
17115
16971
  private formatVerifiedEpisodeResults(
17116
16972
  results: VerifiedEpisodeResult[],
17117
16973
  ): string {
17118
- const lines = results.map(
17119
- ({ box, verifiedEpisodeCount, matchedFields }, index) => {
17120
- const header = [
17121
- `[${index + 1}] ${box.sealedAt.replace("T", " ").slice(0, 16)}`,
17122
- box.traceId ? `trace:${box.traceId.slice(0, 12)}` : "trace:none",
17123
- ].join(" | ");
17124
- const details = [
17125
- box.goal ?? `topics: ${box.topics.join(", ")}`,
17126
- `verified episodes: ${verifiedEpisodeCount}`,
17127
- ];
17128
- if (box.toolsUsed && box.toolsUsed.length > 0) {
17129
- details.push(`tools: ${box.toolsUsed.join(", ")}`);
17130
- }
17131
- if (matchedFields.length > 0) {
17132
- details.push(`matched: ${matchedFields.join(", ")}`);
17133
- }
17134
- return `${header}\n${details.join("\n")}`;
17135
- },
17136
- );
17137
-
17138
- return `## Verified Episodes\n\n${lines.join("\n\n")}`;
16974
+ return this.recallResultFormatter.formatVerifiedEpisodeResults(results);
17139
16975
  }
17140
16976
 
17141
16977
  private formatVerifiedSemanticRuleResults(
17142
16978
  results: VerifiedSemanticRuleResult[],
17143
16979
  ): string {
17144
- const lines = results.map(
17145
- (
17146
- {
17147
- rule,
17148
- sourceMemoryId,
17149
- verificationStatus,
17150
- effectiveConfidence,
17151
- matchedFields,
17152
- },
17153
- index,
17154
- ) => {
17155
- const header = [
17156
- `[${index + 1}] ${rule.frontmatter.updated.replace("T", " ").slice(0, 16)}`,
17157
- verificationStatus,
17158
- `confidence:${effectiveConfidence.toFixed(2)}`,
17159
- ].join(" | ");
17160
- const details = [rule.content, `source memory: ${sourceMemoryId}`];
17161
- if (matchedFields.length > 0) {
17162
- details.push(`matched: ${matchedFields.join(", ")}`);
17163
- }
17164
- return `${header}\n${details.join("\n")}`;
17165
- },
17166
- );
17167
-
17168
- return `## Verified Rules\n\n${lines.join("\n\n")}`;
16980
+ return this.recallResultFormatter.formatVerifiedSemanticRuleResults(results);
17169
16981
  }
17170
16982
 
17171
16983
  private summarizeIdentityText(
@@ -17173,42 +16985,21 @@ export class Orchestrator {
17173
16985
  maxLines: number,
17174
16986
  maxChars: number,
17175
16987
  ): string {
17176
- const lines = raw
17177
- .replace(/\r/g, "")
17178
- .split("\n")
17179
- .map((line) => line.trim())
17180
- .filter((line) => line.length > 0 && !line.startsWith("#"));
17181
- const compact = lines.slice(0, Math.max(1, maxLines)).join(" ");
17182
- if (compact.length <= maxChars) return compact;
17183
- return `${compact.slice(0, Math.max(0, maxChars - 1))}…`;
16988
+ return this.recallResultFormatter.summarizeIdentityText(raw, maxLines, maxChars);
17184
16989
  }
17185
16990
 
17186
16991
  private formatOpenIncidentLine(
17187
16992
  incident: ContinuityIncidentRecord,
17188
16993
  includeDetails: boolean,
17189
16994
  ): string {
17190
- const base = `[${incident.id}] ${incident.symptom.trim()}`;
17191
- if (!includeDetails) return `- ${base}`;
17192
- const parts = [base];
17193
- if (incident.suspectedCause)
17194
- parts.push(`cause: ${incident.suspectedCause.trim()}`);
17195
- if (incident.triggerWindow)
17196
- parts.push(`window: ${incident.triggerWindow.trim()}`);
17197
- return `- ${parts.join(" | ")}`;
16995
+ return this.recallResultFormatter.formatOpenIncidentLine(incident, includeDetails);
17198
16996
  }
17199
16997
 
17200
16998
  private trimIdentitySection(
17201
16999
  content: string,
17202
17000
  maxChars: number,
17203
17001
  ): { text: string; truncated: boolean } {
17204
- if (maxChars <= 0) return { text: "", truncated: false };
17205
- if (content.length <= maxChars) return { text: content, truncated: false };
17206
- const suffix = "\n\n...(identity continuity trimmed)";
17207
- if (maxChars <= suffix.length) {
17208
- return { text: content.slice(0, maxChars), truncated: true };
17209
- }
17210
- const headroom = Math.max(0, maxChars - suffix.length);
17211
- return { text: `${content.slice(0, headroom)}${suffix}`, truncated: true };
17002
+ return this.recallResultFormatter.trimIdentitySection(content, maxChars);
17212
17003
  }
17213
17004
 
17214
17005
  private async buildIdentityContinuitySection(options: {
@@ -17221,81 +17012,7 @@ export class Orchestrator {
17221
17012
  injectedChars: number;
17222
17013
  truncated: boolean;
17223
17014
  } | null> {
17224
- if (!resolveIdentityContinuityCapabilities(this.config).identityContinuity) return null;
17225
- if (this.config.identityMaxInjectChars <= 0) return null;
17226
-
17227
- const resolved = resolveEffectiveIdentityInjectionMode({
17228
- configuredMode: this.config.identityInjectionMode,
17229
- recallMode: options.recallMode,
17230
- prompt: options.prompt,
17231
- });
17232
- if (!resolved.shouldInject) return null;
17233
-
17234
- const [anchorRaw, loopsRaw, incidents] = await Promise.all([
17235
- options.storage.readIdentityAnchor(),
17236
- options.storage.readIdentityImprovementLoops(),
17237
- options.storage.readContinuityIncidents(200),
17238
- ]);
17239
- const openIncidents = incidents.filter(
17240
- (incident) => incident.state === "open",
17241
- );
17242
-
17243
- const lines: string[] = [];
17244
- if (resolved.mode === "full") {
17245
- lines.push("## Identity Continuity");
17246
- if (anchorRaw && anchorRaw.trim().length > 0) {
17247
- lines.push("", "### Anchor", "", anchorRaw.trim());
17248
- }
17249
- if (loopsRaw && loopsRaw.trim().length > 0) {
17250
- lines.push("", "### Improvement Loops", "", loopsRaw.trim());
17251
- }
17252
- lines.push("", "### Open Incidents", "");
17253
- if (openIncidents.length === 0) {
17254
- lines.push("- none");
17255
- } else {
17256
- lines.push(
17257
- ...openIncidents
17258
- .slice(0, 5)
17259
- .map((incident) => this.formatOpenIncidentLine(incident, true)),
17260
- );
17261
- }
17262
- } else {
17263
- const anchorSummary = anchorRaw
17264
- ? this.summarizeIdentityText(anchorRaw, 3, 320)
17265
- : "";
17266
- const loopsSummary = loopsRaw
17267
- ? this.summarizeIdentityText(loopsRaw, 2, 240)
17268
- : "";
17269
- lines.push("## Identity Continuity Signals", "");
17270
- if (anchorSummary) lines.push(`- anchor: ${anchorSummary}`);
17271
- if (loopsSummary) lines.push(`- loops: ${loopsSummary}`);
17272
- if (openIncidents.length === 0) {
17273
- lines.push("- incidents: 0 open");
17274
- } else {
17275
- lines.push(`- incidents: ${openIncidents.length} open`);
17276
- lines.push(
17277
- ...openIncidents
17278
- .slice(0, 2)
17279
- .map((incident) => this.formatOpenIncidentLine(incident, false)),
17280
- );
17281
- }
17282
- }
17283
-
17284
- const body = lines.join("\n").trim();
17285
- if (!body) return null;
17286
-
17287
- const { text, truncated } = this.trimIdentitySection(
17288
- body,
17289
- this.config.identityMaxInjectChars,
17290
- );
17291
- if (!text) return null;
17292
-
17293
- return {
17294
- section: text,
17295
- mode: resolved.mode,
17296
- injectedChars: text.length,
17297
- truncated,
17298
- };
17015
+ return this.recallResultFormatter.buildIdentityContinuitySection(options);
17299
17016
  }
17300
17017
 
17301
17018
  private emitTrace(event: EngramTraceEvent): void {