@remnic/core 9.3.735 → 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.
- package/dist/access-boundary.d.ts +17 -6
- package/dist/access-cli.js +1 -1
- package/dist/access-http.d.ts +17 -6
- package/dist/access-mcp.d.ts +17 -6
- package/dist/access-operations.d.ts +17 -6
- package/dist/access-schema.d.ts +4 -4
- package/dist/{access-service-CVx7mmvK.d.ts → access-service-DwQ6BIQw.d.ts} +3 -3
- package/dist/access-service.d.ts +16 -5
- package/dist/access-surface-catalog.d.ts +17 -6
- package/dist/action-confidence.d.ts +1 -1
- package/dist/active-memory-bridge.d.ts +1 -1
- package/dist/active-recall.d.ts +1 -1
- package/dist/behavior-learner.d.ts +1 -1
- package/dist/behavior-signals.d.ts +1 -1
- package/dist/bootstrap.d.ts +16 -4
- package/dist/briefing.d.ts +1 -1
- package/dist/buffer-surprise-report.d.ts +1 -1
- package/dist/buffer.d.ts +1 -1
- package/dist/calibration.d.ts +1 -1
- package/dist/capabilities.d.ts +1 -1
- package/dist/{catalog-BVhDEUhT.d.ts → catalog-_Bap6vfD.d.ts} +1 -1
- package/dist/causal-behavior.d.ts +1 -1
- package/dist/causal-consolidation.d.ts +1 -1
- package/dist/causal-trajectory-graph.d.ts +1 -1
- package/dist/{chunk-FLCYY5JX.js → chunk-PB5YON2G.js} +559 -481
- package/dist/chunk-PB5YON2G.js.map +1 -0
- package/dist/{cli-Cx5Mxwk7.d.ts → cli-BlEIWDQw.d.ts} +3 -3
- package/dist/cli.d.ts +9 -7
- package/dist/compounding/engine.d.ts +1 -1
- package/dist/compounding/preference-consolidator.d.ts +1 -1
- package/dist/compression-optimizer.d.ts +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/connectors/codex-materialize-runner.d.ts +1 -1
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/consolidation-provenance-check.d.ts +1 -1
- package/dist/consolidation-undo.d.ts +1 -1
- package/dist/contradiction/index.d.ts +1 -1
- package/dist/conversation-index/backend.d.ts +1 -1
- package/dist/conversation-index/chunker.d.ts +1 -1
- package/dist/conversation-index/faiss-adapter.d.ts +1 -1
- package/dist/conversation-index/indexer.d.ts +1 -1
- package/dist/conversation-index/search.d.ts +1 -1
- package/dist/day-summary.d.ts +1 -1
- package/dist/delinearize.d.ts +1 -1
- package/dist/direct-answer-wiring.d.ts +1 -1
- package/dist/direct-answer.d.ts +1 -1
- package/dist/embedding-fallback.d.ts +1 -1
- package/dist/enrichment/index.d.ts +1 -1
- package/dist/entity-retrieval.d.ts +1 -1
- package/dist/entity-schema.d.ts +1 -1
- package/dist/explicit-capture.d.ts +16 -4
- package/dist/extraction-faithfulness.d.ts +1 -1
- package/dist/extraction-judge-telemetry.d.ts +1 -1
- package/dist/extraction-judge-training.d.ts +1 -1
- package/dist/extraction-judge.d.ts +1 -1
- package/dist/extraction.d.ts +1 -1
- package/dist/fallback-llm.d.ts +1 -1
- package/dist/graph-dashboard-diff.d.ts +1 -1
- package/dist/graph-dashboard-key.d.ts +1 -1
- package/dist/graph-dashboard-parser.d.ts +1 -1
- package/dist/graph-edge-reinforcement.d.ts +1 -1
- package/dist/graph-snapshot.d.ts +1 -1
- package/dist/graph.d.ts +1 -1
- package/dist/identity-continuity.d.ts +1 -1
- package/dist/importance.d.ts +1 -1
- package/dist/index.d.ts +20 -18
- package/dist/index.js +1 -1
- package/dist/intent.d.ts +1 -1
- package/dist/lcm/engine.d.ts +1 -1
- package/dist/lcm/index.d.ts +1 -1
- package/dist/lcm/tools.d.ts +1 -1
- package/dist/lifecycle.d.ts +1 -1
- package/dist/live-connectors-runner.d.ts +1 -1
- package/dist/local-llm.d.ts +1 -1
- package/dist/local-model-endpoint.d.ts +1 -1
- package/dist/maintenance/memory-governance.d.ts +1 -1
- package/dist/mcp-memory-inspector-app.d.ts +17 -6
- package/dist/memory-action-policy.d.ts +1 -1
- package/dist/memory-cache.d.ts +1 -1
- package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
- package/dist/memory-projection-store.d.ts +1 -1
- package/dist/memory-provenance.d.ts +1 -1
- package/dist/memory-worth-outcomes.d.ts +1 -1
- package/dist/models-json.d.ts +1 -1
- package/dist/namespaces/migrate.d.ts +2 -2
- package/dist/namespaces/principal.d.ts +1 -1
- package/dist/namespaces/search.d.ts +1 -1
- package/dist/namespaces/storage.d.ts +2 -2
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +1 -1
- package/dist/orchestration/compression-guideline-coordinator.d.ts +1 -1
- package/dist/orchestration/maintenance.d.ts +2 -2
- package/dist/{orchestrator-oF0cceBX.d.ts → orchestrator-CJZ21ZiB.d.ts} +139 -14
- package/dist/orchestrator.d.ts +16 -4
- package/dist/orchestrator.js +1 -3
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/policy-runtime.d.ts +1 -1
- package/dist/provenance.d.ts +1 -1
- package/dist/qmd-recall-cache.d.ts +1 -1
- package/dist/qmd.d.ts +1 -1
- package/dist/recall-disclosure-escalation.d.ts +1 -1
- package/dist/recall-explain-renderer.d.ts +1 -1
- package/dist/recall-planner-llm.d.ts +1 -1
- package/dist/recall-state.d.ts +1 -1
- package/dist/recall-tag-filter.d.ts +1 -1
- package/dist/recall-xray-cli.d.ts +1 -1
- package/dist/recall-xray-renderer.d.ts +1 -1
- package/dist/recall-xray.d.ts +1 -1
- package/dist/resolve-auth-token.d.ts +1 -1
- package/dist/retrieval-agents.d.ts +1 -1
- package/dist/retrieval-tiers.d.ts +1 -1
- package/dist/routing/engine.d.ts +1 -1
- package/dist/routing/store.d.ts +1 -1
- package/dist/schemas.d.ts +24 -24
- package/dist/search/embed-helper.d.ts +1 -1
- package/dist/search/factory.d.ts +1 -1
- package/dist/search/index.d.ts +1 -1
- package/dist/search/lancedb-backend.d.ts +1 -1
- package/dist/search/meilisearch-backend.d.ts +1 -1
- package/dist/search/noop-backend.d.ts +1 -1
- package/dist/search/orama-backend.d.ts +1 -1
- package/dist/search/port.d.ts +1 -1
- package/dist/search/remote-backend.d.ts +1 -1
- package/dist/{semantic-consolidation-DKGbufYO.d.ts → semantic-consolidation-DsIEiCka.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/session-observer-bands.d.ts +1 -1
- package/dist/session-observer-state.d.ts +1 -1
- package/dist/shared-context/manager.d.ts +3 -3
- package/dist/signal.d.ts +1 -1
- package/dist/storage.d.ts +1 -1
- package/dist/summarizer.d.ts +1 -1
- package/dist/summary-snapshot.d.ts +1 -1
- package/dist/temporal-supersession.d.ts +1 -1
- package/dist/temporal-validity.d.ts +1 -1
- package/dist/threading.d.ts +1 -1
- package/dist/tier-migration.d.ts +1 -1
- package/dist/tier-routing.d.ts +1 -1
- package/dist/topics.d.ts +1 -1
- package/dist/transcript.d.ts +1 -1
- package/dist/transfer/types.d.ts +42 -42
- package/dist/trust-score-stage.d.ts +2 -2
- package/dist/trust-score.d.ts +1 -1
- package/dist/{types-C7UCxpuO.d.ts → types-CglNn2V-.d.ts} +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/utility-runtime.d.ts +1 -1
- package/package.json +2 -2
- package/src/orchestration/entity-synthesis-coordinator.ts +319 -0
- package/src/orchestration/recall-result-formatter.ts +438 -0
- package/src/orchestrator.ts +34 -540
- package/dist/chunk-FLCYY5JX.js.map +0 -1
package/src/orchestrator.ts
CHANGED
|
@@ -79,12 +79,9 @@ import {
|
|
|
79
79
|
} from "./search/factory.js";
|
|
80
80
|
import { NoopSearchBackend } from "./search/noop-backend.js";
|
|
81
81
|
import {
|
|
82
|
-
compareEntityTimestamps,
|
|
83
82
|
StorageManager,
|
|
84
83
|
ContentHashIndex,
|
|
85
|
-
fingerprintEntityStructuredFacts,
|
|
86
84
|
normalizeAttributePairs,
|
|
87
|
-
parseEntityFile,
|
|
88
85
|
} from "./storage.js";
|
|
89
86
|
import { sanitizeMemoryContent } from "./sanitize.js";
|
|
90
87
|
import { ThreadingManager } from "./threading.js";
|
|
@@ -103,6 +100,9 @@ import { ExtractionQueueCoordinator } from "./orchestration/extraction-queue-coo
|
|
|
103
100
|
import { CompressionGuidelineCoordinator } from "./orchestration/compression-guideline-coordinator.js";
|
|
104
101
|
import { SemanticConsolidationCoordinator } from "./orchestration/semantic-consolidation-coordinator.js";
|
|
105
102
|
import { LifecyclePolicyCoordinator } from "./orchestration/lifecycle-policy-coordinator.js";
|
|
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";
|
|
106
106
|
import {
|
|
107
107
|
runLiveConnectorsOnce,
|
|
108
108
|
type LiveConnectorsRunSummary,
|
|
@@ -451,8 +451,6 @@ import type {
|
|
|
451
451
|
RecallPlanMode,
|
|
452
452
|
RecallSectionConfig,
|
|
453
453
|
RecallTierExplain,
|
|
454
|
-
EntityStructuredSection,
|
|
455
|
-
EntityTimelineEntry,
|
|
456
454
|
} from "./types.js";
|
|
457
455
|
import { disposeDefaultArchiveScoring, getDefaultArchiveScoring, memoryFileToScoreItem } from "./recall/archive-scoring.js";
|
|
458
456
|
|
|
@@ -492,92 +490,6 @@ interface ExtractionRunResult {
|
|
|
492
490
|
postPersistMetadataFailed?: boolean;
|
|
493
491
|
}
|
|
494
492
|
|
|
495
|
-
export function dedupeEntitySynthesisEvidenceEntries(
|
|
496
|
-
entries: EntityTimelineEntry[],
|
|
497
|
-
): EntityTimelineEntry[] {
|
|
498
|
-
const dedupedEvidenceEntries: EntityTimelineEntry[] = [];
|
|
499
|
-
const evidenceByFact = new Map<string, {
|
|
500
|
-
newest: EntityTimelineEntry;
|
|
501
|
-
oldest: EntityTimelineEntry;
|
|
502
|
-
}>();
|
|
503
|
-
|
|
504
|
-
for (const entry of entries) {
|
|
505
|
-
const normalizedFact = entry.text.trim();
|
|
506
|
-
if (!normalizedFact) continue;
|
|
507
|
-
const existing = evidenceByFact.get(normalizedFact);
|
|
508
|
-
if (!existing) {
|
|
509
|
-
evidenceByFact.set(normalizedFact, { newest: entry, oldest: entry });
|
|
510
|
-
continue;
|
|
511
|
-
}
|
|
512
|
-
if (compareEntityTimestamps(entry.timestamp, existing.newest.timestamp) > 0) {
|
|
513
|
-
existing.newest = entry;
|
|
514
|
-
}
|
|
515
|
-
if (compareEntityTimestamps(entry.timestamp, existing.oldest.timestamp) < 0) {
|
|
516
|
-
existing.oldest = entry;
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
for (const { newest, oldest } of evidenceByFact.values()) {
|
|
521
|
-
dedupedEvidenceEntries.push(newest);
|
|
522
|
-
const newestKey = [
|
|
523
|
-
newest.timestamp,
|
|
524
|
-
newest.source ?? "",
|
|
525
|
-
newest.sessionKey ?? "",
|
|
526
|
-
newest.principal ?? "",
|
|
527
|
-
newest.text,
|
|
528
|
-
].join("\u0000");
|
|
529
|
-
const oldestKey = [
|
|
530
|
-
oldest.timestamp,
|
|
531
|
-
oldest.source ?? "",
|
|
532
|
-
oldest.sessionKey ?? "",
|
|
533
|
-
oldest.principal ?? "",
|
|
534
|
-
oldest.text,
|
|
535
|
-
].join("\u0000");
|
|
536
|
-
if (oldestKey !== newestKey) {
|
|
537
|
-
dedupedEvidenceEntries.push(oldest);
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
return dedupedEvidenceEntries;
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
function flattenStructuredSectionEvidence(
|
|
545
|
-
sections: EntityStructuredSection[] | undefined,
|
|
546
|
-
): EntityTimelineEntry[] {
|
|
547
|
-
return (sections ?? []).flatMap((section) =>
|
|
548
|
-
section.facts
|
|
549
|
-
.map((fact) => fact.trim())
|
|
550
|
-
.filter((fact) => fact.length > 0)
|
|
551
|
-
.map((fact) => ({
|
|
552
|
-
timestamp: "",
|
|
553
|
-
text: fact,
|
|
554
|
-
source: `section:${section.title}`,
|
|
555
|
-
})),
|
|
556
|
-
);
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
function fingerprintEntitySynthesisEvidence(entity: {
|
|
560
|
-
timeline: EntityTimelineEntry[];
|
|
561
|
-
structuredSections?: EntityStructuredSection[];
|
|
562
|
-
}): string {
|
|
563
|
-
const fingerprint = createHash("sha256");
|
|
564
|
-
const timelineEntries = entity.timeline
|
|
565
|
-
.map((entry) => [
|
|
566
|
-
entry.timestamp,
|
|
567
|
-
entry.source ?? "",
|
|
568
|
-
entry.sessionKey ?? "",
|
|
569
|
-
entry.principal ?? "",
|
|
570
|
-
entry.text,
|
|
571
|
-
].join("\u0000"))
|
|
572
|
-
.sort();
|
|
573
|
-
const timelineEntrySeparator = String.fromCharCode(1);
|
|
574
|
-
const structuredFactsSeparator = String.fromCharCode(2);
|
|
575
|
-
fingerprint.update(timelineEntries.join(timelineEntrySeparator));
|
|
576
|
-
fingerprint.update(structuredFactsSeparator);
|
|
577
|
-
fingerprint.update(fingerprintEntityStructuredFacts(entity) ?? "");
|
|
578
|
-
return fingerprint.digest("hex");
|
|
579
|
-
}
|
|
580
|
-
|
|
581
493
|
export interface GraphRecallSnapshot {
|
|
582
494
|
recordedAt: string;
|
|
583
495
|
mode: RecallPlanMode | string;
|
|
@@ -1458,31 +1370,6 @@ export async function resolveRecallModeDecisionAsync(
|
|
|
1458
1370
|
};
|
|
1459
1371
|
}
|
|
1460
1372
|
|
|
1461
|
-
export function hasIdentityRecoveryIntent(prompt: string): boolean {
|
|
1462
|
-
const text = typeof prompt === "string" ? prompt.toLowerCase() : "";
|
|
1463
|
-
if (!text) return false;
|
|
1464
|
-
return /\b(identity|continuity|recover(?:y|ing|ed)?|incident|drift|restore|regress(?:ion|ed|ing)?)\b/i.test(
|
|
1465
|
-
text,
|
|
1466
|
-
);
|
|
1467
|
-
}
|
|
1468
|
-
|
|
1469
|
-
export function resolveEffectiveIdentityInjectionMode(options: {
|
|
1470
|
-
configuredMode: IdentityInjectionMode;
|
|
1471
|
-
recallMode: RecallPlanMode;
|
|
1472
|
-
prompt: string;
|
|
1473
|
-
}): { mode: IdentityInjectionMode; shouldInject: boolean } {
|
|
1474
|
-
if (
|
|
1475
|
-
options.configuredMode === "recovery_only" &&
|
|
1476
|
-
!hasIdentityRecoveryIntent(options.prompt)
|
|
1477
|
-
) {
|
|
1478
|
-
return { mode: "recovery_only", shouldInject: false };
|
|
1479
|
-
}
|
|
1480
|
-
if (options.recallMode === "minimal" && options.configuredMode === "full") {
|
|
1481
|
-
return { mode: "minimal", shouldInject: true };
|
|
1482
|
-
}
|
|
1483
|
-
return { mode: options.configuredMode, shouldInject: true };
|
|
1484
|
-
}
|
|
1485
|
-
|
|
1486
1373
|
export function computeArtifactCandidateFetchLimit(
|
|
1487
1374
|
targetCount: number,
|
|
1488
1375
|
): number {
|
|
@@ -1904,6 +1791,7 @@ export class Orchestrator {
|
|
|
1904
1791
|
readonly compressionGuidelineCoordinator: CompressionGuidelineCoordinator;
|
|
1905
1792
|
readonly semanticConsolidationCoordinator: SemanticConsolidationCoordinator;
|
|
1906
1793
|
readonly lifecyclePolicyCoordinator: LifecyclePolicyCoordinator;
|
|
1794
|
+
readonly entitySynthesisCoordinator: EntitySynthesisCoordinator;
|
|
1907
1795
|
/**
|
|
1908
1796
|
* In-memory X-ray snapshot from the most recent `recall()` call that
|
|
1909
1797
|
* was invoked with `xrayCapture: true` (issue #570 PR 1). Scope is
|
|
@@ -2017,6 +1905,11 @@ export class Orchestrator {
|
|
|
2017
1905
|
* hands it to `enqueue`.
|
|
2018
1906
|
*/
|
|
2019
1907
|
readonly extractionQueueCoordinator: ExtractionQueueCoordinator;
|
|
1908
|
+
/**
|
|
1909
|
+
* Issue #1526: recall result formatting + identity continuity section moved
|
|
1910
|
+
* to RecallResultFormatter.
|
|
1911
|
+
*/
|
|
1912
|
+
readonly recallResultFormatter: RecallResultFormatter;
|
|
2020
1913
|
private heartbeatObserverChains = new Map<string, Promise<void>>();
|
|
2021
1914
|
private recentExtractionFingerprints = new Map<string, number>();
|
|
2022
1915
|
private readonly consolidationObservers = new Set<
|
|
@@ -2985,6 +2878,7 @@ export class Orchestrator {
|
|
|
2985
2878
|
});
|
|
2986
2879
|
// Issue #1526: background extraction queue lives on its own coordinator.
|
|
2987
2880
|
this.extractionQueueCoordinator = new ExtractionQueueCoordinator();
|
|
2881
|
+
this.recallResultFormatter = new RecallResultFormatter(this.config);
|
|
2988
2882
|
const conversationIndexRuntime = createConversationIndexRuntime(config, {
|
|
2989
2883
|
getQmd: () => this.conversationQmd,
|
|
2990
2884
|
getFaiss: () => this.conversationFaiss,
|
|
@@ -3027,6 +2921,12 @@ export class Orchestrator {
|
|
|
3027
2921
|
fastChatCompletion: (messages, options) =>
|
|
3028
2922
|
this.fastChatCompletion(messages, options),
|
|
3029
2923
|
});
|
|
2924
|
+
this.entitySynthesisCoordinator = new EntitySynthesisCoordinator({
|
|
2925
|
+
config,
|
|
2926
|
+
getStorage: (namespace) => this.getStorage(namespace),
|
|
2927
|
+
fastChatCompletion: (messages, options) =>
|
|
2928
|
+
this.fastChatCompletion(messages, options),
|
|
2929
|
+
});
|
|
3030
2930
|
|
|
3031
2931
|
this.sessionObserver = new SessionObserverState({
|
|
3032
2932
|
memoryDir: config.memoryDir,
|
|
@@ -4444,150 +4344,10 @@ export class Orchestrator {
|
|
|
4444
4344
|
namespace?: string,
|
|
4445
4345
|
maxEntities: number = 5,
|
|
4446
4346
|
): Promise<number> {
|
|
4447
|
-
|
|
4448
|
-
|
|
4449
|
-
|
|
4450
|
-
|
|
4451
|
-
) return 0;
|
|
4452
|
-
const storage = await this.getStorage(namespace);
|
|
4453
|
-
const queued = await storage.refreshEntitySynthesisQueue();
|
|
4454
|
-
let processed = 0;
|
|
4455
|
-
let attempted = 0;
|
|
4456
|
-
|
|
4457
|
-
for (const entityName of queued) {
|
|
4458
|
-
if (attempted >= maxEntities) break;
|
|
4459
|
-
attempted += 1;
|
|
4460
|
-
try {
|
|
4461
|
-
const raw = await storage.readEntity(entityName);
|
|
4462
|
-
if (!raw) continue;
|
|
4463
|
-
const entity = parseEntityFile(raw, this.config.entitySchemas);
|
|
4464
|
-
const previousSynthesis = entity.synthesis || entity.summary || "";
|
|
4465
|
-
const sortedTimelineEntries = entity.timeline
|
|
4466
|
-
.slice()
|
|
4467
|
-
.sort((left, right) => compareEntityTimestamps(right.timestamp, left.timestamp));
|
|
4468
|
-
const newerTimelineEntries = sortedTimelineEntries.filter(
|
|
4469
|
-
(entry) =>
|
|
4470
|
-
!entity.synthesisUpdatedAt
|
|
4471
|
-
|| compareEntityTimestamps(entry.timestamp, entity.synthesisUpdatedAt) > 0,
|
|
4472
|
-
);
|
|
4473
|
-
const appendedTimelineEntries = entity.synthesisTimelineCount === undefined
|
|
4474
|
-
? []
|
|
4475
|
-
: entity.timeline.slice(Math.max(0, entity.synthesisTimelineCount));
|
|
4476
|
-
const structuredEvidenceEntries = flattenStructuredSectionEvidence(entity.structuredSections);
|
|
4477
|
-
const structuredEvidenceCount = structuredEvidenceEntries.length;
|
|
4478
|
-
const structuredEvidenceDigest = fingerprintEntityStructuredFacts(entity);
|
|
4479
|
-
const structuredEvidenceDrifted = structuredEvidenceDigest !== (entity.synthesisStructuredFactDigest?.trim() || undefined);
|
|
4480
|
-
const appendedStructuredEvidenceEntries = entity.synthesisStructuredFactCount === undefined
|
|
4481
|
-
|| structuredEvidenceDrifted
|
|
4482
|
-
? structuredEvidenceEntries
|
|
4483
|
-
: structuredEvidenceEntries.slice(Math.max(0, entity.synthesisStructuredFactCount));
|
|
4484
|
-
const candidateEvidenceEntries = [
|
|
4485
|
-
...newerTimelineEntries,
|
|
4486
|
-
...appendedTimelineEntries,
|
|
4487
|
-
...appendedStructuredEvidenceEntries,
|
|
4488
|
-
]
|
|
4489
|
-
.slice()
|
|
4490
|
-
.sort((left, right) => compareEntityTimestamps(right.timestamp, left.timestamp));
|
|
4491
|
-
const dedupedEvidenceEntries = dedupeEntitySynthesisEvidenceEntries(
|
|
4492
|
-
candidateEvidenceEntries.length > 0
|
|
4493
|
-
? candidateEvidenceEntries
|
|
4494
|
-
: [...sortedTimelineEntries, ...structuredEvidenceEntries],
|
|
4495
|
-
);
|
|
4496
|
-
const chronologicalEvidenceEntries = dedupedEvidenceEntries
|
|
4497
|
-
.slice()
|
|
4498
|
-
.sort((left, right) => compareEntityTimestamps(left.timestamp, right.timestamp));
|
|
4499
|
-
if (chronologicalEvidenceEntries.length === 0) continue;
|
|
4500
|
-
const latestEvidenceTimestamp = chronologicalEvidenceEntries
|
|
4501
|
-
.slice()
|
|
4502
|
-
.reverse()
|
|
4503
|
-
.map((entry) => entry.timestamp?.trim() || undefined)
|
|
4504
|
-
.find((timestamp) => Boolean(timestamp));
|
|
4505
|
-
const previousSynthesisUpdatedAt = entity.synthesisUpdatedAt?.trim() || undefined;
|
|
4506
|
-
const nextSynthesisUpdatedAt = compareEntityTimestamps(
|
|
4507
|
-
latestEvidenceTimestamp,
|
|
4508
|
-
previousSynthesisUpdatedAt,
|
|
4509
|
-
) >= 0
|
|
4510
|
-
? latestEvidenceTimestamp
|
|
4511
|
-
: previousSynthesisUpdatedAt;
|
|
4512
|
-
const evidenceBatches: typeof chronologicalEvidenceEntries[] = [];
|
|
4513
|
-
for (let index = 0; index < chronologicalEvidenceEntries.length; index += 8) {
|
|
4514
|
-
evidenceBatches.push(chronologicalEvidenceEntries.slice(index, index + 8));
|
|
4515
|
-
}
|
|
4516
|
-
|
|
4517
|
-
let nextSynthesis = previousSynthesis;
|
|
4518
|
-
let batchFailed = false;
|
|
4519
|
-
for (const evidenceEntries of evidenceBatches) {
|
|
4520
|
-
const evidenceText = evidenceEntries
|
|
4521
|
-
.map((entry) => {
|
|
4522
|
-
const sectionTitle = entry.source?.startsWith("section:")
|
|
4523
|
-
? entry.source.slice("section:".length)
|
|
4524
|
-
: "";
|
|
4525
|
-
const metadata = [
|
|
4526
|
-
`timestamp=${entry.timestamp}`,
|
|
4527
|
-
sectionTitle ? `section=${sectionTitle}` : entry.source ? `source=${entry.source}` : "",
|
|
4528
|
-
entry.sessionKey ? `session=${entry.sessionKey}` : "",
|
|
4529
|
-
entry.principal ? `principal=${entry.principal}` : "",
|
|
4530
|
-
]
|
|
4531
|
-
.filter(Boolean)
|
|
4532
|
-
.join(", ");
|
|
4533
|
-
return `- ${metadata}: ${entry.text}`;
|
|
4534
|
-
})
|
|
4535
|
-
.join("\n");
|
|
4536
|
-
const response = await this.fastChatCompletion(
|
|
4537
|
-
[
|
|
4538
|
-
{
|
|
4539
|
-
role: "system",
|
|
4540
|
-
content:
|
|
4541
|
-
"Rewrite the entity synthesis as compact current truth. Preserve uncertainty when evidence conflicts. Return plain text only.",
|
|
4542
|
-
},
|
|
4543
|
-
{
|
|
4544
|
-
role: "user",
|
|
4545
|
-
content: [
|
|
4546
|
-
`Entity: ${entity.name} (${entity.type})`,
|
|
4547
|
-
nextSynthesis ? `Previous synthesis:\n${nextSynthesis}` : "Previous synthesis: none",
|
|
4548
|
-
`New evidence:\n${evidenceText}`,
|
|
4549
|
-
].join("\n\n"),
|
|
4550
|
-
},
|
|
4551
|
-
],
|
|
4552
|
-
{
|
|
4553
|
-
temperature: 0.2,
|
|
4554
|
-
maxTokens: this.config.entitySynthesisMaxTokens,
|
|
4555
|
-
operation: "entity_summary",
|
|
4556
|
-
priority: "background",
|
|
4557
|
-
},
|
|
4558
|
-
);
|
|
4559
|
-
const synthesis = response?.content?.trim().replace(/^["']|["']$/g, "");
|
|
4560
|
-
const maxSynthesisChars = Math.max(2_000, this.config.entitySynthesisMaxTokens * 8);
|
|
4561
|
-
if (!synthesis || synthesis.length < 10 || synthesis.length > maxSynthesisChars) {
|
|
4562
|
-
batchFailed = true;
|
|
4563
|
-
break;
|
|
4564
|
-
}
|
|
4565
|
-
nextSynthesis = synthesis;
|
|
4566
|
-
}
|
|
4567
|
-
if (batchFailed || nextSynthesis.length === 0) continue;
|
|
4568
|
-
const latestRaw = await storage.readEntity(entityName);
|
|
4569
|
-
if (!latestRaw) continue;
|
|
4570
|
-
const latestEntity = parseEntityFile(latestRaw, this.config.entitySchemas);
|
|
4571
|
-
if (
|
|
4572
|
-
fingerprintEntitySynthesisEvidence(latestEntity)
|
|
4573
|
-
!== fingerprintEntitySynthesisEvidence(entity)
|
|
4574
|
-
) {
|
|
4575
|
-
continue;
|
|
4576
|
-
}
|
|
4577
|
-
await storage.updateEntitySynthesis(entityName, nextSynthesis, {
|
|
4578
|
-
entityUpdatedAt: new Date().toISOString(),
|
|
4579
|
-
synthesisStructuredFactDigest: structuredEvidenceDigest,
|
|
4580
|
-
synthesisStructuredFactCount: structuredEvidenceCount,
|
|
4581
|
-
synthesisTimelineCount: entity.timeline.length,
|
|
4582
|
-
updatedAt: nextSynthesisUpdatedAt,
|
|
4583
|
-
});
|
|
4584
|
-
processed += 1;
|
|
4585
|
-
} catch (err) {
|
|
4586
|
-
log.debug(`entity synthesis refresh failed for ${entityName}: ${err}`);
|
|
4587
|
-
}
|
|
4588
|
-
}
|
|
4589
|
-
|
|
4590
|
-
return processed;
|
|
4347
|
+
// Issue #1526: entity synthesis lifecycle moved to EntitySynthesisCoordinator.
|
|
4348
|
+
// Thin delegation keeps all call sites (consolidation pass, access-service)
|
|
4349
|
+
// and tests that exercise the public API working unchanged.
|
|
4350
|
+
return this.entitySynthesisCoordinator.processQueue(namespace, maxEntities);
|
|
4591
4351
|
}
|
|
4592
4352
|
|
|
4593
4353
|
async generateDaySummary(
|
|
@@ -17169,226 +16929,55 @@ export class Orchestrator {
|
|
|
17169
16929
|
}
|
|
17170
16930
|
}
|
|
17171
16931
|
|
|
16932
|
+
// Issue #1526: recall result formatting moved to RecallResultFormatter. Thin
|
|
16933
|
+
// delegation keeps the private API stable for callers + tests.
|
|
17172
16934
|
private formatQmdResults(
|
|
17173
16935
|
title: string,
|
|
17174
16936
|
results: QmdSearchResult[],
|
|
17175
16937
|
sessionKey?: string,
|
|
17176
16938
|
trustByPath?: Map<string, TrustStageResultItem> | null,
|
|
17177
16939
|
): string {
|
|
17178
|
-
|
|
17179
|
-
// resolution requires the handle history to have been recorded for this
|
|
17180
|
-
// session, which only happens when sessionKey is present. Rendering handles
|
|
17181
|
-
// without recording would show tokens a user can never resolve (cursor
|
|
17182
|
-
// review). The rendering logic itself lives in the pure handles module.
|
|
17183
|
-
const handleByIndex = buildHandleIndexForResults(
|
|
17184
|
-
results,
|
|
17185
|
-
this.config.recallMemoryHandles === true && sessionKey != null,
|
|
17186
|
-
);
|
|
17187
|
-
// Issue #1577 — epistemic hedge. Append a deterministic, component-derived
|
|
17188
|
-
// suffix so the downstream model knows each memory's trust status (the
|
|
17189
|
-
// cheap lever against confident-stale-answer failures). Gated separately
|
|
17190
|
-
// from scoring so rendering can ship after the stage is stable. High-band
|
|
17191
|
-
// and neutral items get no suffix (don't waste tokens on the common case).
|
|
17192
|
-
const renderHedge = this.config.trustScoreEpistemicRendering && trustByPath !== null && trustByPath !== undefined;
|
|
17193
|
-
const hedgeMap = renderHedge ? trustByPath : null;
|
|
17194
|
-
const lines = results.map((r, i) => {
|
|
17195
|
-
const snippet = r.snippet
|
|
17196
|
-
? r.snippet.slice(0, 500).replace(/\n/g, " ")
|
|
17197
|
-
: "(no preview)";
|
|
17198
|
-
const source = typeof r.line === "number" ? `${r.path}:${r.line}` : r.path;
|
|
17199
|
-
const head = `[${i + 1}] ${source} (score: ${r.score.toFixed(3)})\n${snippet}`;
|
|
17200
|
-
const handle = handleByIndex.get(i);
|
|
17201
|
-
const hedged = head.replace(/\s+$/, "");
|
|
17202
|
-
const withHandle = handle ? `${hedged} ${handle}` : hedged;
|
|
17203
|
-
if (hedgeMap) {
|
|
17204
|
-
const item = hedgeMap.get(r.path);
|
|
17205
|
-
if (item) {
|
|
17206
|
-
const hedge = renderEpistemicHedge(item.trust);
|
|
17207
|
-
if (hedge.length > 0) return `${withHandle} ${hedge}`;
|
|
17208
|
-
}
|
|
17209
|
-
}
|
|
17210
|
-
return withHandle;
|
|
17211
|
-
});
|
|
17212
|
-
return `## ${title}\n\n${lines.join("\n\n")}`;
|
|
16940
|
+
return this.recallResultFormatter.formatQmdResults(title, results, sessionKey, trustByPath);
|
|
17213
16941
|
}
|
|
17214
16942
|
|
|
17215
16943
|
private formatObjectiveStateResults(
|
|
17216
16944
|
results: ObjectiveStateSearchResult[],
|
|
17217
16945
|
): string {
|
|
17218
|
-
|
|
17219
|
-
const parts = [
|
|
17220
|
-
snapshot.recordedAt.replace("T", " ").slice(0, 16),
|
|
17221
|
-
`${snapshot.kind}/${snapshot.changeKind}`,
|
|
17222
|
-
];
|
|
17223
|
-
if (snapshot.outcome) parts.push(snapshot.outcome);
|
|
17224
|
-
const header = `[${index + 1}] ${parts.join(" | ")} | ${snapshot.scope}`;
|
|
17225
|
-
const detailParts = [snapshot.summary];
|
|
17226
|
-
if (snapshot.command) detailParts.push(`command: ${snapshot.command}`);
|
|
17227
|
-
else if (snapshot.toolName)
|
|
17228
|
-
detailParts.push(`tool: ${snapshot.toolName}`);
|
|
17229
|
-
return `${header}\n${detailParts.join(" | ")}`;
|
|
17230
|
-
});
|
|
17231
|
-
return `## Objective State\n\n${lines.join("\n\n")}`;
|
|
16946
|
+
return this.recallResultFormatter.formatObjectiveStateResults(results);
|
|
17232
16947
|
}
|
|
17233
16948
|
|
|
17234
16949
|
private formatCausalTrajectoryResults(
|
|
17235
16950
|
results: CausalTrajectorySearchResult[],
|
|
17236
16951
|
): string {
|
|
17237
|
-
|
|
17238
|
-
const header = [
|
|
17239
|
-
`[${index + 1}] ${record.recordedAt.replace("T", " ").slice(0, 16)}`,
|
|
17240
|
-
record.outcomeKind,
|
|
17241
|
-
].join(" | ");
|
|
17242
|
-
const details = [
|
|
17243
|
-
`goal: ${record.goal}`,
|
|
17244
|
-
`action: ${record.actionSummary}`,
|
|
17245
|
-
`observation: ${record.observationSummary}`,
|
|
17246
|
-
`outcome: ${record.outcomeSummary}`,
|
|
17247
|
-
];
|
|
17248
|
-
if (record.followUpSummary)
|
|
17249
|
-
details.push(`follow-up: ${record.followUpSummary}`);
|
|
17250
|
-
if (matchedFields.length > 0)
|
|
17251
|
-
details.push(`matched: ${matchedFields.join(", ")}`);
|
|
17252
|
-
return `${header}\n${details.join("\n")}`;
|
|
17253
|
-
});
|
|
17254
|
-
|
|
17255
|
-
return `## Causal Trajectories\n\n${lines.join("\n\n")}`;
|
|
16952
|
+
return this.recallResultFormatter.formatCausalTrajectoryResults(results);
|
|
17256
16953
|
}
|
|
17257
16954
|
|
|
17258
16955
|
private formatTrustZoneResults(results: TrustZoneSearchResult[]): string {
|
|
17259
|
-
|
|
17260
|
-
const header = [
|
|
17261
|
-
`[${index + 1}] ${record.recordedAt.replace("T", " ").slice(0, 16)}`,
|
|
17262
|
-
record.zone,
|
|
17263
|
-
record.kind,
|
|
17264
|
-
].join(" | ");
|
|
17265
|
-
const details = [
|
|
17266
|
-
record.summary,
|
|
17267
|
-
`provenance: ${record.provenance.sourceClass}`,
|
|
17268
|
-
];
|
|
17269
|
-
if (record.entityRefs && record.entityRefs.length > 0) {
|
|
17270
|
-
details.push(`entities: ${record.entityRefs.join(", ")}`);
|
|
17271
|
-
}
|
|
17272
|
-
if (record.tags && record.tags.length > 0) {
|
|
17273
|
-
details.push(`tags: ${record.tags.join(", ")}`);
|
|
17274
|
-
}
|
|
17275
|
-
if (matchedFields.length > 0) {
|
|
17276
|
-
details.push(`matched: ${matchedFields.join(", ")}`);
|
|
17277
|
-
}
|
|
17278
|
-
return `${header}\n${details.join("\n")}`;
|
|
17279
|
-
});
|
|
17280
|
-
|
|
17281
|
-
return `## Trust Zones\n\n${lines.join("\n\n")}`;
|
|
16956
|
+
return this.recallResultFormatter.formatTrustZoneResults(results);
|
|
17282
16957
|
}
|
|
17283
16958
|
|
|
17284
16959
|
private formatHarmonicRetrievalResults(
|
|
17285
16960
|
results: HarmonicRetrievalResult[],
|
|
17286
16961
|
): string {
|
|
17287
|
-
|
|
17288
|
-
(
|
|
17289
|
-
{ node, matchedAnchors, matchedFields, nodeScore, anchorScore },
|
|
17290
|
-
index,
|
|
17291
|
-
) => {
|
|
17292
|
-
const header = [
|
|
17293
|
-
`[${index + 1}] ${node.recordedAt.replace("T", " ").slice(0, 16)}`,
|
|
17294
|
-
`${node.kind}/${node.abstractionLevel}`,
|
|
17295
|
-
node.sessionKey,
|
|
17296
|
-
].join(" | ");
|
|
17297
|
-
const details = [
|
|
17298
|
-
node.title,
|
|
17299
|
-
node.summary,
|
|
17300
|
-
`scores: node=${nodeScore.toFixed(1)} anchor=${anchorScore.toFixed(1)}`,
|
|
17301
|
-
];
|
|
17302
|
-
if (matchedAnchors.length > 0) {
|
|
17303
|
-
details.push(
|
|
17304
|
-
`anchors: ${matchedAnchors.map((anchor) => `${anchor.anchorType}:${anchor.anchorValue}`).join("; ")}`,
|
|
17305
|
-
);
|
|
17306
|
-
}
|
|
17307
|
-
if (matchedFields.length > 0) {
|
|
17308
|
-
details.push(`matched: ${matchedFields.join(", ")}`);
|
|
17309
|
-
}
|
|
17310
|
-
return `${header}\n${details.join("\n")}`;
|
|
17311
|
-
},
|
|
17312
|
-
);
|
|
17313
|
-
|
|
17314
|
-
return `## Harmonic Retrieval\n\n${lines.join("\n\n")}`;
|
|
16962
|
+
return this.recallResultFormatter.formatHarmonicRetrievalResults(results);
|
|
17315
16963
|
}
|
|
17316
16964
|
|
|
17317
16965
|
private formatWorkProductResults(
|
|
17318
16966
|
results: WorkProductLedgerSearchResult[],
|
|
17319
16967
|
): string {
|
|
17320
|
-
|
|
17321
|
-
const header = [
|
|
17322
|
-
`[${index + 1}] ${entry.recordedAt.replace("T", " ").slice(0, 16)}`,
|
|
17323
|
-
`${entry.kind}/${entry.action}`,
|
|
17324
|
-
entry.sessionKey,
|
|
17325
|
-
].join(" | ");
|
|
17326
|
-
const details = [entry.summary, `scope: ${entry.scope}`];
|
|
17327
|
-
if (entry.artifactPath) details.push(`artifact: ${entry.artifactPath}`);
|
|
17328
|
-
if (entry.tags && entry.tags.length > 0)
|
|
17329
|
-
details.push(`tags: ${entry.tags.join(", ")}`);
|
|
17330
|
-
if (matchedFields.length > 0)
|
|
17331
|
-
details.push(`matched: ${matchedFields.join(", ")}`);
|
|
17332
|
-
return `${header}\n${details.join("\n")}`;
|
|
17333
|
-
});
|
|
17334
|
-
|
|
17335
|
-
return `## Work Products\n\n${lines.join("\n\n")}`;
|
|
16968
|
+
return this.recallResultFormatter.formatWorkProductResults(results);
|
|
17336
16969
|
}
|
|
17337
16970
|
|
|
17338
16971
|
private formatVerifiedEpisodeResults(
|
|
17339
16972
|
results: VerifiedEpisodeResult[],
|
|
17340
16973
|
): string {
|
|
17341
|
-
|
|
17342
|
-
({ box, verifiedEpisodeCount, matchedFields }, index) => {
|
|
17343
|
-
const header = [
|
|
17344
|
-
`[${index + 1}] ${box.sealedAt.replace("T", " ").slice(0, 16)}`,
|
|
17345
|
-
box.traceId ? `trace:${box.traceId.slice(0, 12)}` : "trace:none",
|
|
17346
|
-
].join(" | ");
|
|
17347
|
-
const details = [
|
|
17348
|
-
box.goal ?? `topics: ${box.topics.join(", ")}`,
|
|
17349
|
-
`verified episodes: ${verifiedEpisodeCount}`,
|
|
17350
|
-
];
|
|
17351
|
-
if (box.toolsUsed && box.toolsUsed.length > 0) {
|
|
17352
|
-
details.push(`tools: ${box.toolsUsed.join(", ")}`);
|
|
17353
|
-
}
|
|
17354
|
-
if (matchedFields.length > 0) {
|
|
17355
|
-
details.push(`matched: ${matchedFields.join(", ")}`);
|
|
17356
|
-
}
|
|
17357
|
-
return `${header}\n${details.join("\n")}`;
|
|
17358
|
-
},
|
|
17359
|
-
);
|
|
17360
|
-
|
|
17361
|
-
return `## Verified Episodes\n\n${lines.join("\n\n")}`;
|
|
16974
|
+
return this.recallResultFormatter.formatVerifiedEpisodeResults(results);
|
|
17362
16975
|
}
|
|
17363
16976
|
|
|
17364
16977
|
private formatVerifiedSemanticRuleResults(
|
|
17365
16978
|
results: VerifiedSemanticRuleResult[],
|
|
17366
16979
|
): string {
|
|
17367
|
-
|
|
17368
|
-
(
|
|
17369
|
-
{
|
|
17370
|
-
rule,
|
|
17371
|
-
sourceMemoryId,
|
|
17372
|
-
verificationStatus,
|
|
17373
|
-
effectiveConfidence,
|
|
17374
|
-
matchedFields,
|
|
17375
|
-
},
|
|
17376
|
-
index,
|
|
17377
|
-
) => {
|
|
17378
|
-
const header = [
|
|
17379
|
-
`[${index + 1}] ${rule.frontmatter.updated.replace("T", " ").slice(0, 16)}`,
|
|
17380
|
-
verificationStatus,
|
|
17381
|
-
`confidence:${effectiveConfidence.toFixed(2)}`,
|
|
17382
|
-
].join(" | ");
|
|
17383
|
-
const details = [rule.content, `source memory: ${sourceMemoryId}`];
|
|
17384
|
-
if (matchedFields.length > 0) {
|
|
17385
|
-
details.push(`matched: ${matchedFields.join(", ")}`);
|
|
17386
|
-
}
|
|
17387
|
-
return `${header}\n${details.join("\n")}`;
|
|
17388
|
-
},
|
|
17389
|
-
);
|
|
17390
|
-
|
|
17391
|
-
return `## Verified Rules\n\n${lines.join("\n\n")}`;
|
|
16980
|
+
return this.recallResultFormatter.formatVerifiedSemanticRuleResults(results);
|
|
17392
16981
|
}
|
|
17393
16982
|
|
|
17394
16983
|
private summarizeIdentityText(
|
|
@@ -17396,42 +16985,21 @@ export class Orchestrator {
|
|
|
17396
16985
|
maxLines: number,
|
|
17397
16986
|
maxChars: number,
|
|
17398
16987
|
): string {
|
|
17399
|
-
|
|
17400
|
-
.replace(/\r/g, "")
|
|
17401
|
-
.split("\n")
|
|
17402
|
-
.map((line) => line.trim())
|
|
17403
|
-
.filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
17404
|
-
const compact = lines.slice(0, Math.max(1, maxLines)).join(" ");
|
|
17405
|
-
if (compact.length <= maxChars) return compact;
|
|
17406
|
-
return `${compact.slice(0, Math.max(0, maxChars - 1))}…`;
|
|
16988
|
+
return this.recallResultFormatter.summarizeIdentityText(raw, maxLines, maxChars);
|
|
17407
16989
|
}
|
|
17408
16990
|
|
|
17409
16991
|
private formatOpenIncidentLine(
|
|
17410
16992
|
incident: ContinuityIncidentRecord,
|
|
17411
16993
|
includeDetails: boolean,
|
|
17412
16994
|
): string {
|
|
17413
|
-
|
|
17414
|
-
if (!includeDetails) return `- ${base}`;
|
|
17415
|
-
const parts = [base];
|
|
17416
|
-
if (incident.suspectedCause)
|
|
17417
|
-
parts.push(`cause: ${incident.suspectedCause.trim()}`);
|
|
17418
|
-
if (incident.triggerWindow)
|
|
17419
|
-
parts.push(`window: ${incident.triggerWindow.trim()}`);
|
|
17420
|
-
return `- ${parts.join(" | ")}`;
|
|
16995
|
+
return this.recallResultFormatter.formatOpenIncidentLine(incident, includeDetails);
|
|
17421
16996
|
}
|
|
17422
16997
|
|
|
17423
16998
|
private trimIdentitySection(
|
|
17424
16999
|
content: string,
|
|
17425
17000
|
maxChars: number,
|
|
17426
17001
|
): { text: string; truncated: boolean } {
|
|
17427
|
-
|
|
17428
|
-
if (content.length <= maxChars) return { text: content, truncated: false };
|
|
17429
|
-
const suffix = "\n\n...(identity continuity trimmed)";
|
|
17430
|
-
if (maxChars <= suffix.length) {
|
|
17431
|
-
return { text: content.slice(0, maxChars), truncated: true };
|
|
17432
|
-
}
|
|
17433
|
-
const headroom = Math.max(0, maxChars - suffix.length);
|
|
17434
|
-
return { text: `${content.slice(0, headroom)}${suffix}`, truncated: true };
|
|
17002
|
+
return this.recallResultFormatter.trimIdentitySection(content, maxChars);
|
|
17435
17003
|
}
|
|
17436
17004
|
|
|
17437
17005
|
private async buildIdentityContinuitySection(options: {
|
|
@@ -17444,81 +17012,7 @@ export class Orchestrator {
|
|
|
17444
17012
|
injectedChars: number;
|
|
17445
17013
|
truncated: boolean;
|
|
17446
17014
|
} | null> {
|
|
17447
|
-
|
|
17448
|
-
if (this.config.identityMaxInjectChars <= 0) return null;
|
|
17449
|
-
|
|
17450
|
-
const resolved = resolveEffectiveIdentityInjectionMode({
|
|
17451
|
-
configuredMode: this.config.identityInjectionMode,
|
|
17452
|
-
recallMode: options.recallMode,
|
|
17453
|
-
prompt: options.prompt,
|
|
17454
|
-
});
|
|
17455
|
-
if (!resolved.shouldInject) return null;
|
|
17456
|
-
|
|
17457
|
-
const [anchorRaw, loopsRaw, incidents] = await Promise.all([
|
|
17458
|
-
options.storage.readIdentityAnchor(),
|
|
17459
|
-
options.storage.readIdentityImprovementLoops(),
|
|
17460
|
-
options.storage.readContinuityIncidents(200),
|
|
17461
|
-
]);
|
|
17462
|
-
const openIncidents = incidents.filter(
|
|
17463
|
-
(incident) => incident.state === "open",
|
|
17464
|
-
);
|
|
17465
|
-
|
|
17466
|
-
const lines: string[] = [];
|
|
17467
|
-
if (resolved.mode === "full") {
|
|
17468
|
-
lines.push("## Identity Continuity");
|
|
17469
|
-
if (anchorRaw && anchorRaw.trim().length > 0) {
|
|
17470
|
-
lines.push("", "### Anchor", "", anchorRaw.trim());
|
|
17471
|
-
}
|
|
17472
|
-
if (loopsRaw && loopsRaw.trim().length > 0) {
|
|
17473
|
-
lines.push("", "### Improvement Loops", "", loopsRaw.trim());
|
|
17474
|
-
}
|
|
17475
|
-
lines.push("", "### Open Incidents", "");
|
|
17476
|
-
if (openIncidents.length === 0) {
|
|
17477
|
-
lines.push("- none");
|
|
17478
|
-
} else {
|
|
17479
|
-
lines.push(
|
|
17480
|
-
...openIncidents
|
|
17481
|
-
.slice(0, 5)
|
|
17482
|
-
.map((incident) => this.formatOpenIncidentLine(incident, true)),
|
|
17483
|
-
);
|
|
17484
|
-
}
|
|
17485
|
-
} else {
|
|
17486
|
-
const anchorSummary = anchorRaw
|
|
17487
|
-
? this.summarizeIdentityText(anchorRaw, 3, 320)
|
|
17488
|
-
: "";
|
|
17489
|
-
const loopsSummary = loopsRaw
|
|
17490
|
-
? this.summarizeIdentityText(loopsRaw, 2, 240)
|
|
17491
|
-
: "";
|
|
17492
|
-
lines.push("## Identity Continuity Signals", "");
|
|
17493
|
-
if (anchorSummary) lines.push(`- anchor: ${anchorSummary}`);
|
|
17494
|
-
if (loopsSummary) lines.push(`- loops: ${loopsSummary}`);
|
|
17495
|
-
if (openIncidents.length === 0) {
|
|
17496
|
-
lines.push("- incidents: 0 open");
|
|
17497
|
-
} else {
|
|
17498
|
-
lines.push(`- incidents: ${openIncidents.length} open`);
|
|
17499
|
-
lines.push(
|
|
17500
|
-
...openIncidents
|
|
17501
|
-
.slice(0, 2)
|
|
17502
|
-
.map((incident) => this.formatOpenIncidentLine(incident, false)),
|
|
17503
|
-
);
|
|
17504
|
-
}
|
|
17505
|
-
}
|
|
17506
|
-
|
|
17507
|
-
const body = lines.join("\n").trim();
|
|
17508
|
-
if (!body) return null;
|
|
17509
|
-
|
|
17510
|
-
const { text, truncated } = this.trimIdentitySection(
|
|
17511
|
-
body,
|
|
17512
|
-
this.config.identityMaxInjectChars,
|
|
17513
|
-
);
|
|
17514
|
-
if (!text) return null;
|
|
17515
|
-
|
|
17516
|
-
return {
|
|
17517
|
-
section: text,
|
|
17518
|
-
mode: resolved.mode,
|
|
17519
|
-
injectedChars: text.length,
|
|
17520
|
-
truncated,
|
|
17521
|
-
};
|
|
17015
|
+
return this.recallResultFormatter.buildIdentityContinuitySection(options);
|
|
17522
17016
|
}
|
|
17523
17017
|
|
|
17524
17018
|
private emitTrace(event: EngramTraceEvent): void {
|