@remnic/core 9.3.723 → 9.3.725
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 +6 -11
- package/dist/access-boundary.js +9 -9
- package/dist/access-cli.js +29 -23
- package/dist/access-cli.js.map +1 -1
- package/dist/access-http.d.ts +5 -5
- package/dist/access-http.js +19 -14
- package/dist/access-mcp.d.ts +5 -5
- package/dist/access-mcp.js +18 -13
- package/dist/access-operations-batch.js +16 -10
- package/dist/access-operations.d.ts +5 -5
- package/dist/access-operations.js +17 -11
- package/dist/{access-service-Dj3I-VBS.d.ts → access-service-B2PlPtxh.d.ts} +3 -3
- package/dist/access-service.d.ts +5 -5
- package/dist/access-service.js +8 -8
- package/dist/access-surface-catalog.d.ts +5 -5
- package/dist/access-surface-catalog.js +82 -82
- package/dist/access-surface-catalog.js.map +1 -1
- 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 +4 -4
- package/dist/briefing.d.ts +1 -1
- package/dist/briefing.js +3 -3
- 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-F-OEVbRQ.d.ts → catalog-CzUb-GyD.d.ts} +1 -1
- package/dist/causal-behavior.d.ts +1 -1
- package/dist/causal-consolidation.d.ts +1 -1
- package/dist/causal-consolidation.js +4 -4
- package/dist/causal-trajectory-graph.d.ts +1 -1
- package/dist/{chunk-EVPNWN7Z.js → chunk-4R3CGCI5.js} +2 -2
- package/dist/{chunk-UO5ZHIIH.js → chunk-4WZ3J7M6.js} +2 -2
- package/dist/{chunk-PD42EYQN.js → chunk-5OPYYPJN.js} +2 -2
- package/dist/{chunk-EEJMD2L2.js → chunk-6CWGS2LY.js} +2 -2
- package/dist/{chunk-7CTNUVHZ.js → chunk-6SQQOJ4U.js} +2 -2
- package/dist/{chunk-ILFSEIRT.js → chunk-7AG54AF3.js} +1 -1
- package/dist/{chunk-ILFSEIRT.js.map → chunk-7AG54AF3.js.map} +1 -1
- package/dist/{chunk-UIXXE6NI.js → chunk-C6BWLYW5.js} +24 -15
- package/dist/chunk-C6BWLYW5.js.map +1 -0
- package/dist/{chunk-A5XNBK2D.js → chunk-DF3I6JGP.js} +6 -6
- package/dist/{chunk-GJSL4WG2.js → chunk-F3XZN24Z.js} +2 -2
- package/dist/{chunk-J3JPB7ZI.js → chunk-FACTVMXQ.js} +2 -2
- package/dist/{chunk-B7WISIAJ.js → chunk-FN6QP7JQ.js} +154 -1067
- package/dist/chunk-FN6QP7JQ.js.map +1 -0
- package/dist/{chunk-EBDA5TYA.js → chunk-FXCIOLRB.js} +2 -2
- package/dist/{chunk-TXQCG6SE.js → chunk-H7HUQIY7.js} +3 -3
- package/dist/{chunk-QD6QP5P6.js → chunk-I2HL5M6T.js} +17 -17
- package/dist/{chunk-M7R5R6OJ.js → chunk-IAIPNEHD.js} +20 -2
- package/dist/{chunk-M7R5R6OJ.js.map → chunk-IAIPNEHD.js.map} +1 -1
- package/dist/{chunk-Z4RU5VPM.js → chunk-J334N6QV.js} +2 -2
- package/dist/{chunk-NXRUUDUF.js → chunk-JJJCVCCQ.js} +2 -2
- package/dist/{chunk-GDUOCHCD.js → chunk-KGZF2VO3.js} +10 -10
- package/dist/{chunk-LA3HZKES.js → chunk-KLFYKC3K.js} +448 -49
- package/dist/chunk-KLFYKC3K.js.map +1 -0
- package/dist/{chunk-LLUGAZ3B.js → chunk-NT36GU6X.js} +30 -4
- package/dist/chunk-NT36GU6X.js.map +1 -0
- package/dist/{chunk-OHTOPFRF.js → chunk-SC2YAWRF.js} +2 -2
- package/dist/{chunk-YEE5KJQQ.js → chunk-T55EGZSJ.js} +2 -2
- package/dist/{chunk-N77ELJ2D.js → chunk-TT5U3UDO.js} +4 -4
- package/dist/{chunk-6FAMMBQ3.js → chunk-UBHVAGO7.js} +2 -2
- package/dist/chunk-VI5SGGXB.js +420 -0
- package/dist/chunk-VI5SGGXB.js.map +1 -0
- package/dist/{chunk-EDOQM4E4.js → chunk-WAFDHKES.js} +2 -2
- package/dist/{chunk-EXUCUPV2.js → chunk-WM7DNKBD.js} +2 -2
- package/dist/{dreams-ledger-3WSCI5V4.js → chunk-YF6FMLBT.js} +5 -6
- package/dist/{dreams-ledger-3WSCI5V4.js.map → chunk-YF6FMLBT.js.map} +1 -1
- package/dist/{chunk-WQYSDPMA.js → chunk-YQMPUYHE.js} +2 -2
- package/dist/{chunk-5O42UKXI.js → chunk-YUYPWJD3.js} +2 -2
- package/dist/{chunk-VCLGUIFM.js → chunk-Z3FGC3QE.js} +2 -2
- package/dist/{chunk-A7TJZLPK.js → chunk-ZK2L72VN.js} +2 -2
- package/dist/{chunk-BXEOHV7K.js → chunk-ZOHMPFOB.js} +3 -3
- package/dist/{graph-edge-decay-QPRJQ7DL.js → chunk-ZQNCHPTZ.js} +4 -5
- package/dist/{graph-edge-decay-QPRJQ7DL.js.map → chunk-ZQNCHPTZ.js.map} +1 -1
- package/dist/{cli-P_GaYcCY.d.ts → cli-IOlDHSBT.d.ts} +3 -3
- package/dist/cli.d.ts +6 -6
- package/dist/cli.js +31 -26
- package/dist/compounding/engine.d.ts +1 -1
- package/dist/compounding/engine.js +3 -3
- 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-runner.js +3 -3
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +3 -3
- 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/dreams-ledger-6UODQOX6.js +22 -0
- package/dist/dreams-ledger-6UODQOX6.js.map +1 -0
- 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-retrieval.js +3 -3
- package/dist/entity-schema.d.ts +1 -1
- package/dist/event-time.d.ts +33 -1
- package/dist/event-time.js +3 -1
- package/dist/explicit-capture.d.ts +4 -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-decay-RXUCJIN4.js +22 -0
- package/dist/graph-edge-decay-RXUCJIN4.js.map +1 -0
- 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 +9 -9
- package/dist/index.js +58 -56
- package/dist/index.js.map +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/maintenance/memory-governance.js +3 -3
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +3 -3
- package/dist/maintenance/rebuild-memory-projection.js +4 -4
- package/dist/mcp-memory-inspector-app.d.ts +5 -5
- 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/migrate.js +4 -4
- 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/namespaces/storage.js +3 -3
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +1 -1
- package/dist/operator-toolkit.js +8 -8
- package/dist/orchestration/maintenance.d.ts +2 -2
- package/dist/orchestration/maintenance.js +5 -5
- package/dist/{orchestrator-f5xv19kp.d.ts → orchestrator-C_OMSIMZ.d.ts} +34 -3
- package/dist/orchestrator.d.ts +4 -4
- package/dist/orchestrator.js +17 -17
- 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-explain-renderer.js +3 -3
- 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-cli.js +4 -4
- package/dist/recall-xray-renderer.d.ts +1 -1
- package/dist/recall-xray-renderer.js +3 -3
- package/dist/recall-xray.d.ts +1 -1
- package/dist/recall-xray.js +2 -2
- 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 +22 -22
- 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-BQm1e1Pn.d.ts → semantic-consolidation-B8LiYtvx.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +4 -4
- package/dist/semantic-rule-promotion.js +3 -3
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/semantic-rule-verifier.js +3 -3
- 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 +1 -1
- package/dist/signal.d.ts +1 -1
- package/dist/storage.d.ts +1 -1
- package/dist/storage.js +2 -2
- 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 +12 -12
- package/dist/trust-score-stage.d.ts +1 -1
- package/dist/trust-score.d.ts +1 -1
- package/dist/{types-DwO1Ot4n.d.ts → types-DmTaqob2.d.ts} +14 -0
- package/dist/types.d.ts +1 -1
- package/dist/types.js +1 -1
- package/dist/utility-runtime.d.ts +1 -1
- package/dist/verified-recall.js +3 -3
- package/package.json +2 -2
- package/src/access-boundary.ts +36 -2
- package/src/access-http.ts +17 -8
- package/src/access-mcp.ts +149 -1189
- package/src/access-operations-batch.ts +227 -1439
- package/src/access-surface-catalog.test.ts +4 -15
- package/src/access-surface-catalog.ts +82 -82
- package/src/bitemporal-dedup-backfill.test.ts +169 -0
- package/src/event-time.ts +57 -0
- package/src/extraction-eventtime-wiring.test.ts +101 -1
- package/src/orchestrator.ts +238 -43
- package/src/recall/archive-scoring.ts +526 -0
- package/src/types.ts +14 -0
- package/dist/chunk-B7WISIAJ.js.map +0 -1
- package/dist/chunk-EM2LDXJ2.js +0 -1315
- package/dist/chunk-EM2LDXJ2.js.map +0 -1
- package/dist/chunk-LA3HZKES.js.map +0 -1
- package/dist/chunk-LLUGAZ3B.js.map +0 -1
- package/dist/chunk-UIXXE6NI.js.map +0 -1
- /package/dist/{chunk-EVPNWN7Z.js.map → chunk-4R3CGCI5.js.map} +0 -0
- /package/dist/{chunk-UO5ZHIIH.js.map → chunk-4WZ3J7M6.js.map} +0 -0
- /package/dist/{chunk-PD42EYQN.js.map → chunk-5OPYYPJN.js.map} +0 -0
- /package/dist/{chunk-EEJMD2L2.js.map → chunk-6CWGS2LY.js.map} +0 -0
- /package/dist/{chunk-7CTNUVHZ.js.map → chunk-6SQQOJ4U.js.map} +0 -0
- /package/dist/{chunk-A5XNBK2D.js.map → chunk-DF3I6JGP.js.map} +0 -0
- /package/dist/{chunk-GJSL4WG2.js.map → chunk-F3XZN24Z.js.map} +0 -0
- /package/dist/{chunk-J3JPB7ZI.js.map → chunk-FACTVMXQ.js.map} +0 -0
- /package/dist/{chunk-EBDA5TYA.js.map → chunk-FXCIOLRB.js.map} +0 -0
- /package/dist/{chunk-TXQCG6SE.js.map → chunk-H7HUQIY7.js.map} +0 -0
- /package/dist/{chunk-QD6QP5P6.js.map → chunk-I2HL5M6T.js.map} +0 -0
- /package/dist/{chunk-Z4RU5VPM.js.map → chunk-J334N6QV.js.map} +0 -0
- /package/dist/{chunk-NXRUUDUF.js.map → chunk-JJJCVCCQ.js.map} +0 -0
- /package/dist/{chunk-GDUOCHCD.js.map → chunk-KGZF2VO3.js.map} +0 -0
- /package/dist/{chunk-OHTOPFRF.js.map → chunk-SC2YAWRF.js.map} +0 -0
- /package/dist/{chunk-YEE5KJQQ.js.map → chunk-T55EGZSJ.js.map} +0 -0
- /package/dist/{chunk-N77ELJ2D.js.map → chunk-TT5U3UDO.js.map} +0 -0
- /package/dist/{chunk-6FAMMBQ3.js.map → chunk-UBHVAGO7.js.map} +0 -0
- /package/dist/{chunk-EDOQM4E4.js.map → chunk-WAFDHKES.js.map} +0 -0
- /package/dist/{chunk-EXUCUPV2.js.map → chunk-WM7DNKBD.js.map} +0 -0
- /package/dist/{chunk-WQYSDPMA.js.map → chunk-YQMPUYHE.js.map} +0 -0
- /package/dist/{chunk-5O42UKXI.js.map → chunk-YUYPWJD3.js.map} +0 -0
- /package/dist/{chunk-VCLGUIFM.js.map → chunk-Z3FGC3QE.js.map} +0 -0
- /package/dist/{chunk-A7TJZLPK.js.map → chunk-ZK2L72VN.js.map} +0 -0
- /package/dist/{chunk-BXEOHV7K.js.map → chunk-ZOHMPFOB.js.map} +0 -0
package/src/orchestrator.ts
CHANGED
|
@@ -129,7 +129,7 @@ import {
|
|
|
129
129
|
shouldFilterSupersededFromRecall,
|
|
130
130
|
} from "./temporal-supersession.js";
|
|
131
131
|
import { isValidAsOf, isValidityExpiredNow } from "./temporal-validity.js";
|
|
132
|
-
import { resolveFactEventTime } from "./event-time.js";
|
|
132
|
+
import { pickFactEventTimeAnchor, resolveFactEventTime } from "./event-time.js";
|
|
133
133
|
import { RelevanceStore } from "./relevance.js";
|
|
134
134
|
import { NegativeExampleStore } from "./negative.js";
|
|
135
135
|
import {
|
|
@@ -438,6 +438,7 @@ import type {
|
|
|
438
438
|
EntityStructuredSection,
|
|
439
439
|
EntityTimelineEntry,
|
|
440
440
|
} from "./types.js";
|
|
441
|
+
import { disposeDefaultArchiveScoring, getDefaultArchiveScoring, memoryFileToScoreItem } from "./recall/archive-scoring.js";
|
|
441
442
|
|
|
442
443
|
export interface BulkImportBatchIngestResult {
|
|
443
444
|
attemptedTurnCount: number;
|
|
@@ -1828,6 +1829,7 @@ export function resolvePersistedMemoryRelativePath(options: {
|
|
|
1828
1829
|
}
|
|
1829
1830
|
|
|
1830
1831
|
export class Orchestrator {
|
|
1832
|
+
|
|
1831
1833
|
readonly storage: StorageManager;
|
|
1832
1834
|
private readonly storageRouter: NamespaceStorageRouter;
|
|
1833
1835
|
/** Rebuildable namespace catalog (issue #1499). Inert unless namespaces enabled. */
|
|
@@ -2111,6 +2113,8 @@ export class Orchestrator {
|
|
|
2111
2113
|
if (this.conversationQmd && this.conversationQmd !== this.qmd) {
|
|
2112
2114
|
await (this.conversationQmd as { dispose?: () => void | Promise<void> }).dispose?.();
|
|
2113
2115
|
}
|
|
2116
|
+
// Issue #1674: terminate archive-scoring worker threads on destroy.
|
|
2117
|
+
await disposeDefaultArchiveScoring();
|
|
2114
2118
|
}
|
|
2115
2119
|
|
|
2116
2120
|
/** Set per-session workspace for the next recall() call (compaction reset). @internal */
|
|
@@ -2727,6 +2731,123 @@ export class Orchestrator {
|
|
|
2727
2731
|
index.remove(memory.content);
|
|
2728
2732
|
}
|
|
2729
2733
|
|
|
2734
|
+
/**
|
|
2735
|
+
* Issue #1671 — backfill bi-temporal bounds onto an existing promoted/deduped
|
|
2736
|
+
* copy that was written BEFORE the source fact carried a resolved
|
|
2737
|
+
* `invalid_at`/`observedAt`/`eventTimeSource`.
|
|
2738
|
+
*
|
|
2739
|
+
* On re-extraction/backfill, a fact may now carry a resolved end bound (e.g.
|
|
2740
|
+
* "until June 2025") that the existing copy lacks because it was promoted
|
|
2741
|
+
* before bi-temporal wiring existed. Without this backfill, recall keeps
|
|
2742
|
+
* surfacing an expired fact even though the source copy now expires correctly.
|
|
2743
|
+
*
|
|
2744
|
+
* Finds the active fact in `targetStorage` matching `dedupContent`, then
|
|
2745
|
+
* patches the temporal frontmatter the existing copy is missing. Best-effort
|
|
2746
|
+
* / fail-open — any I/O error is logged and swallowed so the dedup
|
|
2747
|
+
* short-circuit is never blocked by a backfill failure.
|
|
2748
|
+
*
|
|
2749
|
+
* Matching: the stored `frontmatter.contentHash` is compared against
|
|
2750
|
+
* `ContentHashIndex.computeHash(dedupContent)` first (the exact hash the
|
|
2751
|
+
* content-hash index uses), then falls back to stripping citations and
|
|
2752
|
+
* comparing normalized bodies. This handles inline-attribution deployments
|
|
2753
|
+
* where the persisted body carries a citation marker the dedup key does not.
|
|
2754
|
+
*
|
|
2755
|
+
* I/O gate: only triggers when `invalidAt` is present (the end bound that
|
|
2756
|
+
* actually changes recall behavior by expiring the fact). `observedAt` and
|
|
2757
|
+
* `eventTimeSource` alone don'\''t expire a fact, so backfilling them without
|
|
2758
|
+
* an end bound would cause a full readAllMemories scan on every dedup hit
|
|
2759
|
+
* under biTemporal for no recall benefit.
|
|
2760
|
+
*
|
|
2761
|
+
* Only patches fields the existing copy LACKS — never overwrites a bound the
|
|
2762
|
+
* copy already carries.
|
|
2763
|
+
*/
|
|
2764
|
+
private async backfillTemporalBoundsOnDedupHit(
|
|
2765
|
+
targetStorage: StorageManager,
|
|
2766
|
+
dedupContent: string,
|
|
2767
|
+
bounds: {
|
|
2768
|
+
invalidAt?: string;
|
|
2769
|
+
observedAt?: string;
|
|
2770
|
+
eventTimeSource?: "extracted" | "assumed";
|
|
2771
|
+
},
|
|
2772
|
+
entityRef?: string,
|
|
2773
|
+
): Promise<void> {
|
|
2774
|
+
// I/O gate: only scan when there is an end bound to backfill. Without
|
|
2775
|
+
// invalidAt there is nothing that changes recall behavior — observedAt
|
|
2776
|
+
// and eventTimeSource alone do not expire a fact. This avoids a full
|
|
2777
|
+
// readAllMemories on every dedup short-circuit under biTemporal.
|
|
2778
|
+
if (!bounds.invalidAt) return;
|
|
2779
|
+
try {
|
|
2780
|
+
const incomingHash = ContentHashIndex.computeHash(dedupContent);
|
|
2781
|
+
const normalizedIncoming = ContentHashIndex.normalizeContent(dedupContent);
|
|
2782
|
+
// Normalize the entity for same-entity scoping when provided — two
|
|
2783
|
+
// entities can share identical fact text, and patching a different
|
|
2784
|
+
// entity'\''s fact would corrupt its temporal bounds (cursor review).
|
|
2785
|
+
const incomingEntityNorm = entityRef
|
|
2786
|
+
? normalizeSupersessionKey(entityRef)
|
|
2787
|
+
: undefined;
|
|
2788
|
+
const all = await targetStorage.readAllMemories();
|
|
2789
|
+
const existing = all.find((m) => {
|
|
2790
|
+
if (m.frontmatter.category !== "fact") return false;
|
|
2791
|
+
if ((m.frontmatter.status ?? "active") !== "active") return false;
|
|
2792
|
+
// Same-entity guard: reject only when the stored fact carries a
|
|
2793
|
+
// DIFFERENT entity (two entities can share identical fact text, so
|
|
2794
|
+
// patching the other entity's copy would corrupt its bounds — codex
|
|
2795
|
+
// P2 PRRT_OvB4A). Legacy facts written before entity linkage (no
|
|
2796
|
+
// entityRef) have no entity to conflict with, so they stay eligible
|
|
2797
|
+
// for backfill (cursor PRRT_OvKnV: the guard must NOT silently
|
|
2798
|
+
// no-op for older promoted copies that predate entity linkage).
|
|
2799
|
+
if (
|
|
2800
|
+
incomingEntityNorm &&
|
|
2801
|
+
m.frontmatter.entityRef &&
|
|
2802
|
+
normalizeSupersessionKey(m.frontmatter.entityRef) !== incomingEntityNorm
|
|
2803
|
+
) {
|
|
2804
|
+
return false;
|
|
2805
|
+
}
|
|
2806
|
+
// Prefer the stored contentHash (what the hash index actually keys
|
|
2807
|
+
// on) — it is computed from contentHashSource (the raw/enriched
|
|
2808
|
+
// body before citation), matching the dedupContent the caller passes.
|
|
2809
|
+
if (m.frontmatter.contentHash) {
|
|
2810
|
+
return m.frontmatter.contentHash === incomingHash;
|
|
2811
|
+
}
|
|
2812
|
+
// Legacy facts without a stored hash: strip citations then compare
|
|
2813
|
+
// normalized bodies so inline-attribution markers don'\''t prevent
|
|
2814
|
+
// a match.
|
|
2815
|
+
return (
|
|
2816
|
+
ContentHashIndex.normalizeContent(
|
|
2817
|
+
stripCitationForTemplate(m.content ?? "", this.config.inlineSourceAttributionFormat),
|
|
2818
|
+
) === normalizedIncoming
|
|
2819
|
+
);
|
|
2820
|
+
});
|
|
2821
|
+
if (!existing) return;
|
|
2822
|
+
// Build a patch containing ONLY the fields the existing copy lacks.
|
|
2823
|
+
const patch: Partial<MemoryFrontmatter> = {};
|
|
2824
|
+
const fm = existing.frontmatter;
|
|
2825
|
+
if (bounds.invalidAt && (!fm.invalid_at || fm.invalid_at.length === 0)) {
|
|
2826
|
+
patch.invalid_at = bounds.invalidAt;
|
|
2827
|
+
}
|
|
2828
|
+
if (bounds.observedAt && (!fm.observedAt || fm.observedAt.length === 0)) {
|
|
2829
|
+
patch.observedAt = bounds.observedAt;
|
|
2830
|
+
}
|
|
2831
|
+
if (
|
|
2832
|
+
bounds.eventTimeSource &&
|
|
2833
|
+
(!fm.eventTimeSource || fm.eventTimeSource.length === 0)
|
|
2834
|
+
) {
|
|
2835
|
+
patch.eventTimeSource = bounds.eventTimeSource;
|
|
2836
|
+
}
|
|
2837
|
+
if (Object.keys(patch).length === 0) return;
|
|
2838
|
+
const ok = await targetStorage.writeMemoryFrontmatter(existing, patch);
|
|
2839
|
+
if (ok) {
|
|
2840
|
+
log.debug(
|
|
2841
|
+
`bitemporal-backfill: patched ${Object.keys(patch).join(",")} onto existing fact ${fm.id ?? "(unknown)"} in ${targetStorage.dir}`,
|
|
2842
|
+
);
|
|
2843
|
+
}
|
|
2844
|
+
} catch (err) {
|
|
2845
|
+
log.warn(
|
|
2846
|
+
`bitemporal-backfill: failed open for ${targetStorage.dir}: ${err}`,
|
|
2847
|
+
);
|
|
2848
|
+
}
|
|
2849
|
+
}
|
|
2850
|
+
|
|
2730
2851
|
private async saveContentHashIndexes(): Promise<void> {
|
|
2731
2852
|
const indexes = new Set<ContentHashIndex>();
|
|
2732
2853
|
if (this.contentHashIndex) indexes.add(this.contentHashIndex);
|
|
@@ -14155,6 +14276,22 @@ export class Orchestrator {
|
|
|
14155
14276
|
options.category === "fact" &&
|
|
14156
14277
|
(await targetStorage.hasFactContentHash(dedupContent))
|
|
14157
14278
|
) {
|
|
14279
|
+
// #1671 — backfill bi-temporal bounds the existing promoted copy
|
|
14280
|
+
// lacks (re-extraction with a now-resolved invalidAt). Best-effort,
|
|
14281
|
+
// fail-open; the helper gates on invalidAt to avoid I/O when no
|
|
14282
|
+
// end bound is present.
|
|
14283
|
+
if (options.invalidAt) {
|
|
14284
|
+
await this.backfillTemporalBoundsOnDedupHit(
|
|
14285
|
+
targetStorage,
|
|
14286
|
+
dedupContent,
|
|
14287
|
+
{
|
|
14288
|
+
invalidAt: options.invalidAt,
|
|
14289
|
+
...(options.observedAt ? { observedAt: options.observedAt } : {}),
|
|
14290
|
+
...(options.eventTimeSource ? { eventTimeSource: options.eventTimeSource } : {}),
|
|
14291
|
+
},
|
|
14292
|
+
options.entityRef,
|
|
14293
|
+
);
|
|
14294
|
+
}
|
|
14158
14295
|
continue;
|
|
14159
14296
|
}
|
|
14160
14297
|
const promotedId = await targetStorage.writeMemory(
|
|
@@ -14318,6 +14455,22 @@ export class Orchestrator {
|
|
|
14318
14455
|
options.category === "fact" &&
|
|
14319
14456
|
(await sharedStorage.hasFactContentHash(dedupContent))
|
|
14320
14457
|
) {
|
|
14458
|
+
// #1671 — backfill bi-temporal bounds onto the existing shared copy
|
|
14459
|
+
// before the supersession short-circuit. Covers all return paths below
|
|
14460
|
+
// (supersession-hit, catch-skip, and the no-supersession short-circuit)
|
|
14461
|
+
// in one shot. Best-effort / fail-open; the helper gates on invalidAt.
|
|
14462
|
+
if (options.invalidAt) {
|
|
14463
|
+
await this.backfillTemporalBoundsOnDedupHit(
|
|
14464
|
+
sharedStorage,
|
|
14465
|
+
dedupContent,
|
|
14466
|
+
{
|
|
14467
|
+
invalidAt: options.invalidAt,
|
|
14468
|
+
...(options.observedAt ? { observedAt: options.observedAt } : {}),
|
|
14469
|
+
...(options.eventTimeSource ? { eventTimeSource: options.eventTimeSource } : {}),
|
|
14470
|
+
},
|
|
14471
|
+
options.entityRef,
|
|
14472
|
+
);
|
|
14473
|
+
}
|
|
14321
14474
|
// Uj6H fix: shared-namespace temporal supersession must also run when
|
|
14322
14475
|
// the hash-dedup short-circuit fires. Without this, an existing shared
|
|
14323
14476
|
// fact whose structuredAttributes are stale (or an older conflicting
|
|
@@ -14885,7 +15038,14 @@ export class Orchestrator {
|
|
|
14885
15038
|
typeof (fact as any).confidence === "number"
|
|
14886
15039
|
? (fact as any).confidence
|
|
14887
15040
|
: 0.7;
|
|
14888
|
-
|
|
15041
|
+
// #1670 — anchor each fact's event-time to its SOURCE TURN timestamp,
|
|
15042
|
+
// not the batch-wide latest. When a buffered conversation spans a date
|
|
15043
|
+
// boundary, a relative expression ("yesterday") on an early-turn fact
|
|
15044
|
+
// must resolve against that early turn's date. Prefer the fact's
|
|
15045
|
+
// explicit sourceTurnTimestamp, then the earliest provenance span's
|
|
15046
|
+
// observedAt, then fall back to the batch anchor (legacy extractors).
|
|
15047
|
+
const factAnchor = pickFactEventTimeAnchor(fact, sourceContext?.validAt);
|
|
15048
|
+
const biTemporal = this.config.temporalBiTemporal && factAnchor ? resolveFactEventTime(fact.eventTime, factAnchor) : undefined;
|
|
14889
15049
|
// Content-hash dedup check (v6.0)
|
|
14890
15050
|
//
|
|
14891
15051
|
// Canonicalize pre-tagged facts before hashing (Codex P2 — issue #369).
|
|
@@ -14990,6 +15150,15 @@ export class Orchestrator {
|
|
|
14990
15150
|
writeCategory === "procedure"
|
|
14991
15151
|
? buildProcedurePersistBody(fact.content, fact.procedureSteps)
|
|
14992
15152
|
: canonicalContentForHash;
|
|
15153
|
+
// Importance is scored before the dedup short-circuit so #1671 backfill
|
|
15154
|
+
// can gate on it (cursor PRRT_OvKnS): a low-value duplicate that the
|
|
15155
|
+
// importance write-gate (#372) or the judge pre-filter would drop must
|
|
15156
|
+
// not expire an active fact.
|
|
15157
|
+
const importance = scoreImportance(
|
|
15158
|
+
fact.content,
|
|
15159
|
+
writeCategory,
|
|
15160
|
+
fact.tags,
|
|
15161
|
+
);
|
|
14993
15162
|
let exactDuplicate = false;
|
|
14994
15163
|
try {
|
|
14995
15164
|
exactDuplicate = await this.hasContentHashDedup(
|
|
@@ -15002,6 +15171,47 @@ export class Orchestrator {
|
|
|
15002
15171
|
);
|
|
15003
15172
|
}
|
|
15004
15173
|
if (exactDuplicate) {
|
|
15174
|
+
// #1671 — before short-circuiting, backfill bi-temporal bounds
|
|
15175
|
+
// onto the existing source-namespace copy if it lacks bounds the
|
|
15176
|
+
// incoming fact now carries (re-extraction with a resolved invalidAt).
|
|
15177
|
+
// Skip when the fact would be rejected/deferred/pending by downstream
|
|
15178
|
+
// gates — a non-durable candidate must not expire an active fact
|
|
15179
|
+
// (chatgpt-codex P1: faithfulness, requireSpans, extraction judge).
|
|
15180
|
+
if (biTemporal && biTemporal.validUntil) {
|
|
15181
|
+
const fr = faithfulnessResultsByFactIndex?.get(factLoopIndex);
|
|
15182
|
+
const faithfulnessWouldPending =
|
|
15183
|
+
faithfulnessMode === "enforce" &&
|
|
15184
|
+
fr?.ok === true &&
|
|
15185
|
+
(fr.verdict === "unsupported" || fr.verdict === "contradicted");
|
|
15186
|
+
const requireSpansWouldPending =
|
|
15187
|
+
this.config.provenance?.requireSpans === true &&
|
|
15188
|
+
fact.requireSpansPending === true;
|
|
15189
|
+
const judgeVerdict = judgeVerdictsByFactIndex?.get(factLoopIndex);
|
|
15190
|
+
const judgeWouldGate =
|
|
15191
|
+
!this.config.extractionJudgeShadow &&
|
|
15192
|
+
judgeVerdict !== undefined &&
|
|
15193
|
+
!judgeVerdict.durable;
|
|
15194
|
+
// Importance gate (cursor PRRT_OvKnS): below-threshold duplicates
|
|
15195
|
+
// would never persist (#372) and carry no judge verdict (the
|
|
15196
|
+
// pre-filter skips them), so they must not expire an active fact.
|
|
15197
|
+
if (
|
|
15198
|
+
isAboveImportanceThreshold(importance.level, this.config.extractionMinImportanceLevel) &&
|
|
15199
|
+
!faithfulnessWouldPending &&
|
|
15200
|
+
!requireSpansWouldPending &&
|
|
15201
|
+
!judgeWouldGate
|
|
15202
|
+
) {
|
|
15203
|
+
await this.backfillTemporalBoundsOnDedupHit(
|
|
15204
|
+
targetStorage,
|
|
15205
|
+
contentHashDedupKey,
|
|
15206
|
+
{
|
|
15207
|
+
invalidAt: biTemporal.validUntil,
|
|
15208
|
+
observedAt: biTemporal.observedAt,
|
|
15209
|
+
eventTimeSource: biTemporal.eventTimeSource,
|
|
15210
|
+
},
|
|
15211
|
+
fact.entityRef,
|
|
15212
|
+
);
|
|
15213
|
+
}
|
|
15214
|
+
}
|
|
15005
15215
|
log.debug(
|
|
15006
15216
|
`dedup: skipping duplicate fact "${fact.content.slice(0, 60)}…" in storage ${targetStorage.dir}`,
|
|
15007
15217
|
);
|
|
@@ -15009,14 +15219,6 @@ export class Orchestrator {
|
|
|
15009
15219
|
continue;
|
|
15010
15220
|
}
|
|
15011
15221
|
|
|
15012
|
-
// Score importance using local heuristics (Phase 1B).
|
|
15013
|
-
// writeCategory / targetStorage already reflect routing.
|
|
15014
|
-
const importance = scoreImportance(
|
|
15015
|
-
fact.content,
|
|
15016
|
-
writeCategory,
|
|
15017
|
-
fact.tags,
|
|
15018
|
-
);
|
|
15019
|
-
|
|
15020
15222
|
if (writeCategory === "procedure" && this.config.procedural?.enabled !== true) {
|
|
15021
15223
|
log.debug("persistExtraction: skip procedure memory (procedural.enabled is false)");
|
|
15022
15224
|
continue;
|
|
@@ -18915,29 +19117,22 @@ export class Orchestrator {
|
|
|
18915
19117
|
await this.readArchivedMemoriesForNamespaces(recallNamespaces);
|
|
18916
19118
|
if (archivedMemories.length === 0) return scopedSeedResults;
|
|
18917
19119
|
|
|
18918
|
-
|
|
18919
|
-
|
|
18920
|
-
|
|
18921
|
-
|
|
18922
|
-
|
|
18923
|
-
|
|
18924
|
-
|
|
18925
|
-
|
|
18926
|
-
|
|
18927
|
-
|
|
18928
|
-
|
|
18929
|
-
|
|
18930
|
-
|
|
18931
|
-
|
|
18932
|
-
|
|
18933
|
-
|
|
18934
|
-
scored.push({
|
|
18935
|
-
docid: memory.frontmatter.id,
|
|
18936
|
-
path: memory.path,
|
|
18937
|
-
score: normalized,
|
|
18938
|
-
snippet: memory.content.slice(0, 400).replace(/\n/g, " "),
|
|
18939
|
-
});
|
|
18940
|
-
}
|
|
19120
|
+
// Issue #1674: off-load the CPU-bound archive-scoring loop to a
|
|
19121
|
+
// worker_threads pool so concurrent recall requests run on separate
|
|
19122
|
+
// cores instead of serializing on the main JS thread. The pure scoring
|
|
19123
|
+
// function is identical to the old inline loop — only the execution
|
|
19124
|
+
// context changed. Aborts are checked at the boundaries (before submit
|
|
19125
|
+
// and after result); the worker's work is bounded by the file count.
|
|
19126
|
+
throwIfRecallAborted(abortSignal);
|
|
19127
|
+
const scoring = getDefaultArchiveScoring();
|
|
19128
|
+
const scoredResults = await scoring.score(archivedMemories.map(memoryFileToScoreItem), tokens, abortSignal);
|
|
19129
|
+
throwIfRecallAborted(abortSignal);
|
|
19130
|
+
const scored: QmdSearchResult[] = scoredResults.map((r) => ({
|
|
19131
|
+
docid: r.docid,
|
|
19132
|
+
path: r.path,
|
|
19133
|
+
score: r.score,
|
|
19134
|
+
snippet: r.snippet,
|
|
19135
|
+
}));
|
|
18941
19136
|
|
|
18942
19137
|
const mergedByPath = new Map<string, QmdSearchResult>();
|
|
18943
19138
|
for (const result of [...scopedSeedResults, ...scored]) {
|
|
@@ -19138,17 +19333,17 @@ export class Orchestrator {
|
|
|
19138
19333
|
}
|
|
19139
19334
|
}
|
|
19140
19335
|
if (longTerm.length === 0) {
|
|
19336
|
+
// Deadline-aware abort: terminate the scoring worker when the shared
|
|
19337
|
+
// assembly deadline wins, not just when the caller aborts (#1674).
|
|
19338
|
+
const da = new AbortController();
|
|
19339
|
+
if (options.abortSignal?.aborted) da.abort();
|
|
19340
|
+
else options.abortSignal?.addEventListener("abort", () => da.abort(), { once: true });
|
|
19141
19341
|
longTerm = await runColdStepWithinDeadline(
|
|
19142
|
-
"archive scan",
|
|
19143
|
-
|
|
19144
|
-
|
|
19145
|
-
|
|
19146
|
-
|
|
19147
|
-
options.recallNamespaces,
|
|
19148
|
-
options.recallResultLimit,
|
|
19149
|
-
options.queryAwarePrefilter,
|
|
19150
|
-
options.abortSignal,
|
|
19151
|
-
),
|
|
19342
|
+
"archive scan", [],
|
|
19343
|
+
() => this.searchLongTermArchiveFallback(
|
|
19344
|
+
options.prompt, options.recallNamespaces, options.recallResultLimit,
|
|
19345
|
+
options.queryAwarePrefilter, da.signal),
|
|
19346
|
+
() => da.abort(),
|
|
19152
19347
|
);
|
|
19153
19348
|
if (longTerm.length > 0) {
|
|
19154
19349
|
log.debug("cold-tier recall source=archive-scan");
|