@remnic/core 1.1.0 → 1.1.2
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-audit.d.ts +56 -0
- package/dist/access-audit.js +9 -0
- package/dist/access-cli.js +70 -53
- package/dist/access-cli.js.map +1 -1
- package/dist/access-http.d.ts +16 -9
- package/dist/access-http.js +26 -18
- package/dist/access-mcp.d.ts +16 -9
- package/dist/access-mcp.js +30 -8
- package/dist/access-schema.d.ts +124 -33
- package/dist/access-schema.js +5 -1
- package/dist/{access-service-HmO1Trrx.d.ts → access-service-Br8ZydTK.d.ts} +158 -63
- package/dist/access-service.d.ts +13 -6
- package/dist/access-service.js +23 -14
- package/dist/bootstrap.d.ts +6 -3
- package/dist/briefing.d.ts +1 -0
- package/dist/briefing.js +8 -6
- package/dist/buffer-surprise-report.d.ts +70 -0
- package/dist/buffer-surprise-report.js +7 -0
- package/dist/buffer-surprise-report.js.map +1 -0
- package/dist/buffer-surprise.d.ts +98 -0
- package/dist/buffer-surprise.js +11 -0
- package/dist/buffer-surprise.js.map +1 -0
- package/dist/buffer.d.ts +100 -2
- package/dist/buffer.js +1 -1
- package/dist/calibration.js +6 -6
- package/dist/causal-behavior.js +4 -4
- package/dist/causal-chain.js +2 -2
- package/dist/causal-consolidation.js +19 -18
- package/dist/causal-consolidation.js.map +1 -1
- package/dist/causal-retrieval.js +4 -4
- package/dist/causal-trajectory.js +1 -1
- package/dist/{chunk-QNJMBKFK.js → chunk-2LGMW3DJ.js} +3 -2
- package/dist/chunk-2LGMW3DJ.js.map +1 -0
- package/dist/{chunk-QDYXG4CS.js → chunk-3FPTCC3Z.js} +4 -3
- package/dist/chunk-3FPTCC3Z.js.map +1 -0
- package/dist/chunk-3GPTTA4J.js +57 -0
- package/dist/chunk-3GPTTA4J.js.map +1 -0
- package/dist/{chunk-ITRLGI2T.js → chunk-3OGMS3PE.js} +2 -2
- package/dist/{chunk-DEPL3635.js → chunk-3YGHKTBF.js} +1446 -196
- package/dist/chunk-3YGHKTBF.js.map +1 -0
- package/dist/{chunk-BLKTA7MM.js → chunk-4HQS2HPX.js} +54 -21
- package/dist/chunk-4HQS2HPX.js.map +1 -0
- package/dist/chunk-54V4BZWP.js +139 -0
- package/dist/chunk-54V4BZWP.js.map +1 -0
- package/dist/chunk-5JRF2PZA.js +67 -0
- package/dist/chunk-5JRF2PZA.js.map +1 -0
- package/dist/chunk-64NJRYU2.js +332 -0
- package/dist/chunk-64NJRYU2.js.map +1 -0
- package/dist/{chunk-OIT5QGG4.js → chunk-6AUUAZEX.js} +72 -2
- package/dist/chunk-6AUUAZEX.js.map +1 -0
- package/dist/{chunk-3QHL5ABG.js → chunk-6YJHX2DL.js} +191 -10
- package/dist/chunk-6YJHX2DL.js.map +1 -0
- package/dist/chunk-AJU4PJGY.js +126 -0
- package/dist/chunk-AJU4PJGY.js.map +1 -0
- package/dist/chunk-ASAITVLA.js +64 -0
- package/dist/chunk-ASAITVLA.js.map +1 -0
- package/dist/{chunk-44ICJRF3.js → chunk-AYXIPSZO.js} +5 -5
- package/dist/{chunk-MBJHSA7F.js → chunk-BECYBZLX.js} +265 -20
- package/dist/chunk-BECYBZLX.js.map +1 -0
- package/dist/chunk-C4SQJZAF.js +486 -0
- package/dist/chunk-C4SQJZAF.js.map +1 -0
- package/dist/{chunk-6UJ47TVX.js → chunk-CUPFXL3J.js} +2 -2
- package/dist/chunk-DF3RVK3X.js +119 -0
- package/dist/chunk-DF3RVK3X.js.map +1 -0
- package/dist/{chunk-N42IWANG.js → chunk-DG6YMRDC.js} +3 -3
- package/dist/chunk-DGVM5SFL.js +69 -0
- package/dist/chunk-DGVM5SFL.js.map +1 -0
- package/dist/{chunk-3SV6CQHO.js → chunk-DIXB44VE.js} +102 -66
- package/dist/chunk-DIXB44VE.js.map +1 -0
- package/dist/chunk-EIR5VLIH.js +90 -0
- package/dist/chunk-EIR5VLIH.js.map +1 -0
- package/dist/{chunk-GV6NLQ4X.js → chunk-F5VP6YCB.js} +374 -16
- package/dist/chunk-F5VP6YCB.js.map +1 -0
- package/dist/{chunk-6ZH4TU6I.js → chunk-FAAFWE4G.js} +2 -1
- package/dist/chunk-FAAFWE4G.js.map +1 -0
- package/dist/{chunk-7WQ6SLIE.js → chunk-FVA6TGI3.js} +2 -2
- package/dist/{chunk-PAORGQRI.js → chunk-GA5P7RST.js} +37 -23
- package/dist/chunk-GA5P7RST.js.map +1 -0
- package/dist/chunk-GDFS42HT.js +206 -0
- package/dist/chunk-GDFS42HT.js.map +1 -0
- package/dist/chunk-IISBCCWR.js +52 -0
- package/dist/chunk-IISBCCWR.js.map +1 -0
- package/dist/chunk-JBMSGZEQ.js +441 -0
- package/dist/chunk-JBMSGZEQ.js.map +1 -0
- package/dist/{chunk-J4IYOZZ5.js → chunk-JXS5PDQ7.js} +3 -1
- package/dist/chunk-JXS5PDQ7.js.map +1 -0
- package/dist/chunk-KVBLZUKV.js +173 -0
- package/dist/chunk-KVBLZUKV.js.map +1 -0
- package/dist/{chunk-4LACOVZX.js → chunk-L7IXWRYE.js} +10 -5
- package/dist/chunk-L7IXWRYE.js.map +1 -0
- package/dist/chunk-LBLXEFWK.js +51 -0
- package/dist/chunk-LBLXEFWK.js.map +1 -0
- package/dist/{chunk-WBSAYXVI.js → chunk-LOIMBRDE.js} +201 -45
- package/dist/chunk-LOIMBRDE.js.map +1 -0
- package/dist/{chunk-3WHVNEN7.js → chunk-LTCGGW2D.js} +1 -1
- package/dist/chunk-LTCGGW2D.js.map +1 -0
- package/dist/{chunk-ZVBB3T7V.js → chunk-NBVAS5MT.js} +25 -23
- package/dist/chunk-NBVAS5MT.js.map +1 -0
- package/dist/{chunk-UEYA6UC7.js → chunk-NZLQTHS5.js} +25 -2
- package/dist/chunk-NZLQTHS5.js.map +1 -0
- package/dist/{chunk-NQEVYWX6.js → chunk-OC5OXUQ4.js} +211 -7
- package/dist/chunk-OC5OXUQ4.js.map +1 -0
- package/dist/{chunk-LK6SGL53.js → chunk-OR64ZGRZ.js} +3 -2
- package/dist/chunk-OR64ZGRZ.js.map +1 -0
- package/dist/{chunk-SYUK3VLY.js → chunk-PVICZTKG.js} +117 -5
- package/dist/chunk-PVICZTKG.js.map +1 -0
- package/dist/chunk-PVPWZSSI.js +37 -0
- package/dist/chunk-PVPWZSSI.js.map +1 -0
- package/dist/{chunk-JL2PU6AI.js → chunk-R2XRID2N.js} +2 -2
- package/dist/{chunk-4NRAJUDS.js → chunk-RBBWYEFJ.js} +1 -1
- package/dist/chunk-RFYAYKTD.js +146 -0
- package/dist/chunk-RFYAYKTD.js.map +1 -0
- package/dist/chunk-SOBJ6NEY.js +18 -0
- package/dist/chunk-SOBJ6NEY.js.map +1 -0
- package/dist/{chunk-JIU55F3X.js → chunk-SPI27QT6.js} +2 -2
- package/dist/{chunk-MVTHXUBX.js → chunk-STGWEHYR.js} +479 -20
- package/dist/chunk-STGWEHYR.js.map +1 -0
- package/dist/{chunk-6LX5ORAS.js → chunk-TMYO7B5P.js} +4 -4
- package/dist/chunk-TVVEYCNW.js +65 -0
- package/dist/chunk-TVVEYCNW.js.map +1 -0
- package/dist/chunk-ULYOGL6R.js +322 -0
- package/dist/chunk-ULYOGL6R.js.map +1 -0
- package/dist/{chunk-37UIFYWO.js → chunk-UWB5LMWY.js} +108 -9
- package/dist/chunk-UWB5LMWY.js.map +1 -0
- package/dist/{chunk-47UU5PU2.js → chunk-VBVG2M5G.js} +18 -3
- package/dist/chunk-VBVG2M5G.js.map +1 -0
- package/dist/{chunk-7ECD5ATE.js → chunk-VDX363PS.js} +2 -2
- package/dist/{chunk-O5ETUNBT.js → chunk-VTU2B4VF.js} +7 -3
- package/dist/chunk-VTU2B4VF.js.map +1 -0
- package/dist/{chunk-MTLYEMJB.js → chunk-WCLICCGB.js} +18 -3
- package/dist/chunk-WCLICCGB.js.map +1 -0
- package/dist/chunk-X6GF3FX2.js +26 -0
- package/dist/chunk-X6GF3FX2.js.map +1 -0
- package/dist/{chunk-3QFQGRHO.js → chunk-XMHBH5H6.js} +4 -4
- package/dist/{chunk-DHHP2Z4X.js → chunk-XXVWLXSG.js} +2 -2
- package/dist/{chunk-XZ2TIKGC.js → chunk-Y7R2XJ5Q.js} +25 -9
- package/dist/chunk-Y7R2XJ5Q.js.map +1 -0
- package/dist/{chunk-ALXMCZEU.js → chunk-Z2E7VW55.js} +6 -3
- package/dist/chunk-Z2E7VW55.js.map +1 -0
- package/dist/chunk-ZAIM4TUE.js +488 -0
- package/dist/chunk-ZAIM4TUE.js.map +1 -0
- package/dist/chunk-ZZTOURJI.js +91 -0
- package/dist/chunk-ZZTOURJI.js.map +1 -0
- package/dist/{cli-BneVIEvh.d.ts → cli-BkeRaYfk.d.ts} +2 -2
- package/dist/cli.d.ts +13 -6
- package/dist/cli.js +42 -31
- package/dist/config.js +2 -2
- package/dist/consolidation-operator.d.ts +41 -0
- package/dist/consolidation-operator.js +11 -0
- package/dist/consolidation-operator.js.map +1 -0
- package/dist/consolidation-provenance-check.d.ts +68 -0
- package/dist/consolidation-provenance-check.js +9 -0
- package/dist/consolidation-provenance-check.js.map +1 -0
- package/dist/consolidation-undo.d.ts +123 -0
- package/dist/consolidation-undo.js +426 -0
- package/dist/consolidation-undo.js.map +1 -0
- package/dist/{contradiction-scan-GR33PONM.js → contradiction-scan-E3GJTI4F.js} +43 -7
- package/dist/contradiction-scan-E3GJTI4F.js.map +1 -0
- package/dist/cross-namespace-budget.d.ts +133 -0
- package/dist/cross-namespace-budget.js +9 -0
- package/dist/cross-namespace-budget.js.map +1 -0
- package/dist/direct-answer-wiring.js +5 -70
- package/dist/direct-answer-wiring.js.map +1 -1
- package/dist/embedding-fallback.js +2 -1
- package/dist/{engine-5TIQBYZR.js → engine-72LSIWQP.js} +8 -7
- package/dist/engine-72LSIWQP.js.map +1 -0
- package/dist/entity-retrieval.d.ts +1 -0
- package/dist/entity-retrieval.js +7 -6
- package/dist/explicit-capture.d.ts +6 -3
- package/dist/explicit-capture.js +2 -2
- package/dist/extraction-judge-telemetry.d.ts +113 -0
- package/dist/extraction-judge-telemetry.js +14 -0
- package/dist/extraction-judge-telemetry.js.map +1 -0
- package/dist/extraction-judge-training.d.ts +85 -0
- package/dist/extraction-judge-training.js +16 -0
- package/dist/extraction-judge-training.js.map +1 -0
- package/dist/extraction-judge.d.ts +124 -2
- package/dist/extraction-judge.js +11 -1
- package/dist/extraction.js +10 -9
- package/dist/fallback-llm.js +3 -3
- package/dist/graph-recall.d.ts +100 -0
- package/dist/graph-recall.js +8 -0
- package/dist/graph-recall.js.map +1 -0
- package/dist/graph-retrieval.d.ts +271 -0
- package/dist/graph-retrieval.js +21 -0
- package/dist/graph-retrieval.js.map +1 -0
- package/dist/importance.js +1 -1
- package/dist/index.d.ts +585 -20
- package/dist/index.js +542 -344
- package/dist/index.js.map +1 -1
- package/dist/local-llm.js +2 -2
- package/dist/memory-worth-bench.d.ts +51 -0
- package/dist/memory-worth-bench.js +131 -0
- package/dist/memory-worth-bench.js.map +1 -0
- package/dist/memory-worth-filter.d.ts +128 -0
- package/dist/memory-worth-filter.js +10 -0
- package/dist/memory-worth-filter.js.map +1 -0
- package/dist/memory-worth-outcomes.d.ts +118 -0
- package/dist/memory-worth-outcomes.js +9 -0
- package/dist/memory-worth-outcomes.js.map +1 -0
- package/dist/memory-worth.d.ts +102 -0
- package/dist/memory-worth.js +7 -0
- package/dist/memory-worth.js.map +1 -0
- package/dist/operator-toolkit.d.ts +40 -1
- package/dist/operator-toolkit.js +25 -16
- package/dist/{orchestrator-DRYA6_lW.d.ts → orchestrator-CmJ-NTdJ.d.ts} +233 -8
- package/dist/orchestrator.d.ts +6 -3
- package/dist/orchestrator.js +54 -44
- package/dist/page-versioning.d.ts +12 -1
- package/dist/page-versioning.js +5 -3
- package/dist/{port-C1GZFv8h.d.ts → port-BADbLZU5.d.ts} +2 -2
- package/dist/qmd-recall-cache.d.ts +1 -1
- package/dist/qmd.d.ts +5 -3
- package/dist/qmd.js +3 -3
- package/dist/reasoning-trace-recall.d.ts +90 -0
- package/dist/reasoning-trace-recall.js +13 -0
- package/dist/reasoning-trace-recall.js.map +1 -0
- package/dist/reasoning-trace-types.d.ts +54 -0
- package/dist/reasoning-trace-types.js +17 -0
- package/dist/reasoning-trace-types.js.map +1 -0
- package/dist/recall-audit-anomaly.d.ts +112 -0
- package/dist/recall-audit-anomaly.js +11 -0
- package/dist/recall-audit-anomaly.js.map +1 -0
- package/dist/recall-audit.js +5 -44
- package/dist/recall-audit.js.map +1 -1
- package/dist/recall-explain-renderer.d.ts +49 -0
- package/dist/recall-explain-renderer.js +18 -0
- package/dist/recall-explain-renderer.js.map +1 -0
- package/dist/recall-state.d.ts +12 -1
- package/dist/recall-state.js +1 -1
- package/dist/recall-xray-cli.d.ts +40 -0
- package/dist/recall-xray-cli.js +11 -0
- package/dist/recall-xray-cli.js.map +1 -0
- package/dist/recall-xray-renderer.d.ts +44 -0
- package/dist/recall-xray-renderer.js +18 -0
- package/dist/recall-xray-renderer.js.map +1 -0
- package/dist/recall-xray.d.ts +179 -0
- package/dist/recall-xray.js +13 -0
- package/dist/recall-xray.js.map +1 -0
- package/dist/resolve-provider-secret.d.ts +5 -1
- package/dist/resolve-provider-secret.js +3 -1
- package/dist/resume-bundles.js +6 -6
- package/dist/retrieval-agents.d.ts +1 -1
- package/dist/retrieval-tiers.d.ts +17 -0
- package/dist/retrieval-tiers.js +9 -0
- package/dist/retrieval-tiers.js.map +1 -0
- package/dist/schemas.d.ts +309 -53
- package/dist/schemas.js +1 -1
- package/dist/{semantic-consolidation-DrvSYRdB.d.ts → semantic-consolidation-CxJU6MJk.d.ts} +62 -1
- package/dist/semantic-consolidation.d.ts +2 -1
- package/dist/semantic-consolidation.js +22 -7
- package/dist/semantic-rule-promotion.js +7 -6
- package/dist/semantic-rule-verifier.js +7 -6
- package/dist/storage.d.ts +82 -1
- package/dist/storage.js +6 -5
- package/dist/summarizer.js +6 -6
- package/dist/temporal-supersession.d.ts +1 -0
- package/dist/tier-migration.d.ts +2 -1
- package/dist/tokens.js +2 -1
- package/dist/types.d.ts +276 -2
- package/dist/types.js +1 -1
- package/dist/verified-recall.js +7 -6
- package/package.json +1 -1
- package/dist/chunk-37UIFYWO.js.map +0 -1
- package/dist/chunk-3QHL5ABG.js.map +0 -1
- package/dist/chunk-3SV6CQHO.js.map +0 -1
- package/dist/chunk-3WHVNEN7.js.map +0 -1
- package/dist/chunk-47UU5PU2.js.map +0 -1
- package/dist/chunk-4LACOVZX.js.map +0 -1
- package/dist/chunk-6ZH4TU6I.js.map +0 -1
- package/dist/chunk-ALXMCZEU.js.map +0 -1
- package/dist/chunk-BLKTA7MM.js.map +0 -1
- package/dist/chunk-DEPL3635.js.map +0 -1
- package/dist/chunk-GV6NLQ4X.js.map +0 -1
- package/dist/chunk-J4IYOZZ5.js.map +0 -1
- package/dist/chunk-LAYN4LDC.js +0 -267
- package/dist/chunk-LAYN4LDC.js.map +0 -1
- package/dist/chunk-LK6SGL53.js.map +0 -1
- package/dist/chunk-MBJHSA7F.js.map +0 -1
- package/dist/chunk-MTLYEMJB.js.map +0 -1
- package/dist/chunk-MVTHXUBX.js.map +0 -1
- package/dist/chunk-NQEVYWX6.js.map +0 -1
- package/dist/chunk-O5ETUNBT.js.map +0 -1
- package/dist/chunk-OIT5QGG4.js.map +0 -1
- package/dist/chunk-PAORGQRI.js.map +0 -1
- package/dist/chunk-QDYXG4CS.js.map +0 -1
- package/dist/chunk-QNJMBKFK.js.map +0 -1
- package/dist/chunk-SYUK3VLY.js.map +0 -1
- package/dist/chunk-UEYA6UC7.js.map +0 -1
- package/dist/chunk-UVJFDP7P.js +0 -202
- package/dist/chunk-UVJFDP7P.js.map +0 -1
- package/dist/chunk-WBSAYXVI.js.map +0 -1
- package/dist/chunk-XZ2TIKGC.js.map +0 -1
- package/dist/chunk-ZVBB3T7V.js.map +0 -1
- package/dist/contradiction-scan-GR33PONM.js.map +0 -1
- /package/dist/{engine-5TIQBYZR.js.map → access-audit.js.map} +0 -0
- /package/dist/{chunk-ITRLGI2T.js.map → chunk-3OGMS3PE.js.map} +0 -0
- /package/dist/{chunk-44ICJRF3.js.map → chunk-AYXIPSZO.js.map} +0 -0
- /package/dist/{chunk-6UJ47TVX.js.map → chunk-CUPFXL3J.js.map} +0 -0
- /package/dist/{chunk-N42IWANG.js.map → chunk-DG6YMRDC.js.map} +0 -0
- /package/dist/{chunk-7WQ6SLIE.js.map → chunk-FVA6TGI3.js.map} +0 -0
- /package/dist/{chunk-JL2PU6AI.js.map → chunk-R2XRID2N.js.map} +0 -0
- /package/dist/{chunk-4NRAJUDS.js.map → chunk-RBBWYEFJ.js.map} +0 -0
- /package/dist/{chunk-JIU55F3X.js.map → chunk-SPI27QT6.js.map} +0 -0
- /package/dist/{chunk-6LX5ORAS.js.map → chunk-TMYO7B5P.js.map} +0 -0
- /package/dist/{chunk-7ECD5ATE.js.map → chunk-VDX363PS.js.map} +0 -0
- /package/dist/{chunk-3QFQGRHO.js.map → chunk-XMHBH5H6.js.map} +0 -0
- /package/dist/{chunk-DHHP2Z4X.js.map → chunk-XXVWLXSG.js.map} +0 -0
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
CompoundingEngine,
|
|
3
3
|
SharedContextManager,
|
|
4
4
|
defaultTierMigrationCycleBudget
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-XXVWLXSG.js";
|
|
6
6
|
import {
|
|
7
7
|
extractTopics
|
|
8
8
|
} from "./chunk-UHGBNIOS.js";
|
|
@@ -11,9 +11,6 @@ import {
|
|
|
11
11
|
applyUtilityRankingRuntimeDelta,
|
|
12
12
|
loadUtilityRuntimeValues
|
|
13
13
|
} from "./chunk-FSFEQI74.js";
|
|
14
|
-
import {
|
|
15
|
-
HourlySummarizer
|
|
16
|
-
} from "./chunk-N42IWANG.js";
|
|
17
14
|
import {
|
|
18
15
|
applyTemporalSupersession,
|
|
19
16
|
normalizeSupersessionKey,
|
|
@@ -32,11 +29,8 @@ import {
|
|
|
32
29
|
SessionObserverState
|
|
33
30
|
} from "./chunk-JR4ZC3G4.js";
|
|
34
31
|
import {
|
|
35
|
-
|
|
36
|
-
} from "./chunk-
|
|
37
|
-
import {
|
|
38
|
-
findUnresolvedEntityRefs
|
|
39
|
-
} from "./chunk-X7XN6YU4.js";
|
|
32
|
+
HourlySummarizer
|
|
33
|
+
} from "./chunk-DG6YMRDC.js";
|
|
40
34
|
import {
|
|
41
35
|
RelevanceStore
|
|
42
36
|
} from "./chunk-5NPGSAVB.js";
|
|
@@ -66,10 +60,19 @@ import {
|
|
|
66
60
|
applyRuntimeRetrievalPolicy
|
|
67
61
|
} from "./chunk-5IZL4DCV.js";
|
|
68
62
|
import {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
} from "./chunk-
|
|
63
|
+
LastRecallStore,
|
|
64
|
+
TierMigrationStatusStore,
|
|
65
|
+
clampGraphRecallExpandedEntries
|
|
66
|
+
} from "./chunk-VBVG2M5G.js";
|
|
67
|
+
import {
|
|
68
|
+
buildXraySnapshot
|
|
69
|
+
} from "./chunk-KVBLZUKV.js";
|
|
70
|
+
import {
|
|
71
|
+
findUnresolvedEntityRefs
|
|
72
|
+
} from "./chunk-X7XN6YU4.js";
|
|
73
|
+
import {
|
|
74
|
+
applyReasoningTraceBoost
|
|
75
|
+
} from "./chunk-ZZTOURJI.js";
|
|
73
76
|
import {
|
|
74
77
|
reorderRecallResultsWithMmr
|
|
75
78
|
} from "./chunk-YDBIWGNI.js";
|
|
@@ -77,10 +80,10 @@ import {
|
|
|
77
80
|
createRecallSectionMetricRecorder
|
|
78
81
|
} from "./chunk-7DHTMOND.js";
|
|
79
82
|
import {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
} from "./chunk-
|
|
83
|
+
buildQmdRecallCacheKey,
|
|
84
|
+
getCachedQmdRecall,
|
|
85
|
+
setCachedQmdRecall
|
|
86
|
+
} from "./chunk-YCN4BVDK.js";
|
|
84
87
|
import {
|
|
85
88
|
NegativeExampleStore
|
|
86
89
|
} from "./chunk-D654IBA6.js";
|
|
@@ -88,8 +91,9 @@ import {
|
|
|
88
91
|
evaluateMemoryActionPolicy
|
|
89
92
|
} from "./chunk-H63EDPFJ.js";
|
|
90
93
|
import {
|
|
91
|
-
|
|
92
|
-
|
|
94
|
+
applyMemoryWorthFilter,
|
|
95
|
+
buildMemoryWorthCounterMap
|
|
96
|
+
} from "./chunk-3GPTTA4J.js";
|
|
93
97
|
import {
|
|
94
98
|
hasBroadGraphIntent,
|
|
95
99
|
inferIntentFromText,
|
|
@@ -98,16 +102,28 @@ import {
|
|
|
98
102
|
planRecallMode
|
|
99
103
|
} from "./chunk-GGD5W7TB.js";
|
|
100
104
|
import {
|
|
105
|
+
classifyMemoryKind
|
|
106
|
+
} from "./chunk-YAZNBMNF.js";
|
|
107
|
+
import {
|
|
108
|
+
EXTRACTION_JUDGE_VERDICT_CATEGORY,
|
|
109
|
+
recordJudgeVerdict
|
|
110
|
+
} from "./chunk-AJU4PJGY.js";
|
|
111
|
+
import {
|
|
112
|
+
recordJudgeTrainingPair
|
|
113
|
+
} from "./chunk-DF3RVK3X.js";
|
|
114
|
+
import {
|
|
115
|
+
createDeferCountMap,
|
|
101
116
|
createVerdictCache,
|
|
117
|
+
getVerdictKind,
|
|
102
118
|
judgeFactDurability,
|
|
103
119
|
validateProcedureExtraction
|
|
104
|
-
} from "./chunk-
|
|
120
|
+
} from "./chunk-C4SQJZAF.js";
|
|
105
121
|
import {
|
|
106
122
|
ExtractionEngine
|
|
107
|
-
} from "./chunk-
|
|
123
|
+
} from "./chunk-DIXB44VE.js";
|
|
108
124
|
import {
|
|
109
125
|
parseMemoryActionEligibilityContext
|
|
110
|
-
} from "./chunk-
|
|
126
|
+
} from "./chunk-NZLQTHS5.js";
|
|
111
127
|
import {
|
|
112
128
|
ProfilingCollector
|
|
113
129
|
} from "./chunk-NBNN5GOB.js";
|
|
@@ -116,31 +132,35 @@ import {
|
|
|
116
132
|
} from "./chunk-FEMOX5AD.js";
|
|
117
133
|
import {
|
|
118
134
|
LocalLlmClient
|
|
119
|
-
} from "./chunk-
|
|
135
|
+
} from "./chunk-R2XRID2N.js";
|
|
120
136
|
import {
|
|
121
|
-
|
|
122
|
-
} from "./chunk-
|
|
137
|
+
tryDirectAnswer
|
|
138
|
+
} from "./chunk-6AUUAZEX.js";
|
|
123
139
|
import {
|
|
124
140
|
EmbeddingFallback
|
|
125
|
-
} from "./chunk-
|
|
141
|
+
} from "./chunk-Z2E7VW55.js";
|
|
126
142
|
import {
|
|
127
143
|
buildEntityRecallSection,
|
|
128
144
|
entityRecentTranscriptLookbackHours,
|
|
129
145
|
readRecentEntityTranscriptEntries
|
|
130
|
-
} from "./chunk-
|
|
146
|
+
} from "./chunk-FVA6TGI3.js";
|
|
147
|
+
import {
|
|
148
|
+
formatDaySummaryMemories
|
|
149
|
+
} from "./chunk-GZCUW5IC.js";
|
|
131
150
|
import {
|
|
132
151
|
RoutingRulesStore,
|
|
152
|
+
expandTildePath,
|
|
133
153
|
normalizeReplaySessionKey
|
|
134
|
-
} from "./chunk-
|
|
154
|
+
} from "./chunk-GA5P7RST.js";
|
|
135
155
|
import {
|
|
136
156
|
searchVerifiedEpisodes
|
|
137
|
-
} from "./chunk-
|
|
157
|
+
} from "./chunk-CUPFXL3J.js";
|
|
138
158
|
import {
|
|
139
159
|
ThreadingManager
|
|
140
160
|
} from "./chunk-JRNQ3RNA.js";
|
|
141
161
|
import {
|
|
142
162
|
searchVerifiedSemanticRules
|
|
143
|
-
} from "./chunk-
|
|
163
|
+
} from "./chunk-SPI27QT6.js";
|
|
144
164
|
import {
|
|
145
165
|
searchWorkProductLedgerEntries
|
|
146
166
|
} from "./chunk-CULXMQJH.js";
|
|
@@ -154,10 +174,10 @@ import {
|
|
|
154
174
|
createConversationIndexRuntime,
|
|
155
175
|
createSearchBackend,
|
|
156
176
|
writeConversationChunks
|
|
157
|
-
} from "./chunk-
|
|
177
|
+
} from "./chunk-NBVAS5MT.js";
|
|
158
178
|
import {
|
|
159
179
|
parseQmdExplain
|
|
160
|
-
} from "./chunk-
|
|
180
|
+
} from "./chunk-4HQS2HPX.js";
|
|
161
181
|
import {
|
|
162
182
|
PolicyRuntimeManager
|
|
163
183
|
} from "./chunk-EABGC2TL.js";
|
|
@@ -170,7 +190,10 @@ import {
|
|
|
170
190
|
import {
|
|
171
191
|
isAboveImportanceThreshold,
|
|
172
192
|
scoreImportance
|
|
173
|
-
} from "./chunk-
|
|
193
|
+
} from "./chunk-JXS5PDQ7.js";
|
|
194
|
+
import {
|
|
195
|
+
launchProcessSync
|
|
196
|
+
} from "./chunk-OR64ZGRZ.js";
|
|
174
197
|
import {
|
|
175
198
|
collectNativeKnowledgeChunks,
|
|
176
199
|
formatNativeKnowledgeSection,
|
|
@@ -179,6 +202,9 @@ import {
|
|
|
179
202
|
import {
|
|
180
203
|
recordEvalShadowRecall
|
|
181
204
|
} from "./chunk-K6WK37A6.js";
|
|
205
|
+
import {
|
|
206
|
+
GraphIndex
|
|
207
|
+
} from "./chunk-C2EFFULQ.js";
|
|
182
208
|
import {
|
|
183
209
|
CODEX_THREAD_KEY_PREFIX
|
|
184
210
|
} from "./chunk-3PG3H5TD.js";
|
|
@@ -191,22 +217,28 @@ import {
|
|
|
191
217
|
refineCompressionGuidelineCandidateSemantically,
|
|
192
218
|
renderCompressionGuidelinesMarkdown
|
|
193
219
|
} from "./chunk-2NMMFZ5T.js";
|
|
220
|
+
import {
|
|
221
|
+
semanticChunkContent
|
|
222
|
+
} from "./chunk-KVE7R4CG.js";
|
|
223
|
+
import {
|
|
224
|
+
chunkContent
|
|
225
|
+
} from "./chunk-4WMCPJWX.js";
|
|
226
|
+
import {
|
|
227
|
+
SmartBuffer
|
|
228
|
+
} from "./chunk-JBMSGZEQ.js";
|
|
194
229
|
import {
|
|
195
230
|
buildConsolidationPrompt,
|
|
196
231
|
buildExtensionsBlockForConsolidation,
|
|
232
|
+
buildOperatorAwareConsolidationPrompt,
|
|
233
|
+
chooseConsolidationOperator,
|
|
197
234
|
findSimilarClusters,
|
|
198
235
|
materializeAfterSemanticConsolidation,
|
|
199
|
-
parseConsolidationResponse
|
|
200
|
-
|
|
236
|
+
parseConsolidationResponse,
|
|
237
|
+
parseOperatorAwareConsolidationResponse
|
|
238
|
+
} from "./chunk-PVICZTKG.js";
|
|
201
239
|
import {
|
|
202
240
|
FallbackLlmClient
|
|
203
|
-
} from "./chunk-
|
|
204
|
-
import {
|
|
205
|
-
GraphIndex
|
|
206
|
-
} from "./chunk-C2EFFULQ.js";
|
|
207
|
-
import {
|
|
208
|
-
chunkContent
|
|
209
|
-
} from "./chunk-4WMCPJWX.js";
|
|
241
|
+
} from "./chunk-AYXIPSZO.js";
|
|
210
242
|
import {
|
|
211
243
|
buildRecallQueryPolicy
|
|
212
244
|
} from "./chunk-6HZ6AO2P.js";
|
|
@@ -217,38 +249,33 @@ import {
|
|
|
217
249
|
import {
|
|
218
250
|
BootstrapEngine
|
|
219
251
|
} from "./chunk-N53K2EXC.js";
|
|
220
|
-
import {
|
|
221
|
-
BoxBuilder
|
|
222
|
-
} from "./chunk-URB2WSKZ.js";
|
|
223
|
-
import {
|
|
224
|
-
SmartBuffer
|
|
225
|
-
} from "./chunk-UVJFDP7P.js";
|
|
226
252
|
import {
|
|
227
253
|
isDisagreementPrompt
|
|
228
254
|
} from "./chunk-XYIK4LF6.js";
|
|
255
|
+
import {
|
|
256
|
+
BoxBuilder
|
|
257
|
+
} from "./chunk-URB2WSKZ.js";
|
|
229
258
|
import {
|
|
230
259
|
abortError,
|
|
231
260
|
isAbortError,
|
|
232
261
|
throwIfAborted
|
|
233
262
|
} from "./chunk-PVGDJXVK.js";
|
|
234
263
|
import {
|
|
235
|
-
|
|
236
|
-
} from "./chunk-MARWOCVP.js";
|
|
237
|
-
import {
|
|
264
|
+
listTrustZoneRecords,
|
|
238
265
|
searchTrustZoneRecords
|
|
239
266
|
} from "./chunk-EQINRHYR.js";
|
|
267
|
+
import {
|
|
268
|
+
buildProcedurePersistBody
|
|
269
|
+
} from "./chunk-QDW3E4RD.js";
|
|
240
270
|
import {
|
|
241
271
|
shouldSkipImplicitExtraction
|
|
242
|
-
} from "./chunk-
|
|
272
|
+
} from "./chunk-3FPTCC3Z.js";
|
|
243
273
|
import {
|
|
244
274
|
selectRouteRule
|
|
245
|
-
} from "./chunk-
|
|
246
|
-
import {
|
|
247
|
-
buildProcedurePersistBody
|
|
248
|
-
} from "./chunk-QDW3E4RD.js";
|
|
275
|
+
} from "./chunk-2LGMW3DJ.js";
|
|
249
276
|
import {
|
|
250
277
|
searchCausalTrajectories
|
|
251
|
-
} from "./chunk-
|
|
278
|
+
} from "./chunk-RBBWYEFJ.js";
|
|
252
279
|
import {
|
|
253
280
|
canReadNamespace,
|
|
254
281
|
defaultNamespaceForPrincipal,
|
|
@@ -267,10 +294,10 @@ import {
|
|
|
267
294
|
normalizeAttributePairs,
|
|
268
295
|
normalizeEntityName,
|
|
269
296
|
parseEntityFile
|
|
270
|
-
} from "./chunk-
|
|
297
|
+
} from "./chunk-F5VP6YCB.js";
|
|
271
298
|
import {
|
|
272
299
|
confidenceTier
|
|
273
|
-
} from "./chunk-
|
|
300
|
+
} from "./chunk-LTCGGW2D.js";
|
|
274
301
|
import {
|
|
275
302
|
attachCitation,
|
|
276
303
|
hasCitationForTemplate,
|
|
@@ -286,26 +313,28 @@ import {
|
|
|
286
313
|
import {
|
|
287
314
|
sanitizeMemoryContent
|
|
288
315
|
} from "./chunk-M62O4P4T.js";
|
|
316
|
+
import {
|
|
317
|
+
resolveHomeDir
|
|
318
|
+
} from "./chunk-MARWOCVP.js";
|
|
289
319
|
import {
|
|
290
320
|
log
|
|
291
321
|
} from "./chunk-2ODBA7MQ.js";
|
|
292
322
|
|
|
293
323
|
// src/orchestrator.ts
|
|
294
|
-
import
|
|
324
|
+
import path7 from "path";
|
|
295
325
|
import os from "os";
|
|
296
326
|
import { createHash as createHash2, randomBytes } from "crypto";
|
|
297
327
|
import { existsSync as existsSync2 } from "fs";
|
|
298
328
|
import {
|
|
299
|
-
mkdir as
|
|
329
|
+
mkdir as mkdir5,
|
|
300
330
|
readdir as readdir3,
|
|
301
|
-
readFile as
|
|
331
|
+
readFile as readFile4,
|
|
302
332
|
stat as stat3,
|
|
303
333
|
unlink as unlink2,
|
|
304
|
-
writeFile as
|
|
334
|
+
writeFile as writeFile4
|
|
305
335
|
} from "fs/promises";
|
|
306
336
|
|
|
307
337
|
// src/migrate/from-engram.ts
|
|
308
|
-
import { execFileSync } from "child_process";
|
|
309
338
|
import { createHash } from "crypto";
|
|
310
339
|
import path from "path";
|
|
311
340
|
import {
|
|
@@ -341,7 +370,14 @@ function resolveLogger(options) {
|
|
|
341
370
|
}
|
|
342
371
|
function resolveExec(options) {
|
|
343
372
|
return options?.execCommand ?? ((command, args) => {
|
|
344
|
-
|
|
373
|
+
const result = launchProcessSync(command, args, { stdio: "ignore" });
|
|
374
|
+
if (result.error) {
|
|
375
|
+
throw result.error;
|
|
376
|
+
}
|
|
377
|
+
if (result.status !== 0) {
|
|
378
|
+
const reason = result.status === null ? `signal ${result.signal ?? "unknown"}` : `exit code ${result.status}`;
|
|
379
|
+
throw new Error(`migration command failed: ${command} ${args.join(" ")} (${reason})`);
|
|
380
|
+
}
|
|
345
381
|
});
|
|
346
382
|
}
|
|
347
383
|
function remnicRoot(homeDir) {
|
|
@@ -878,7 +914,7 @@ async function buildProcedureRecallSection(storage, prompt, config) {
|
|
|
878
914
|
10,
|
|
879
915
|
Math.max(
|
|
880
916
|
1,
|
|
881
|
-
typeof config.procedural.recallMaxProcedures === "number" && Number.isFinite(config.procedural.recallMaxProcedures) ? Math.floor(config.procedural.recallMaxProcedures) :
|
|
917
|
+
typeof config.procedural.recallMaxProcedures === "number" && Number.isFinite(config.procedural.recallMaxProcedures) ? Math.floor(config.procedural.recallMaxProcedures) : 2
|
|
882
918
|
)
|
|
883
919
|
);
|
|
884
920
|
const all = await storage.readAllMemories();
|
|
@@ -1119,12 +1155,253 @@ async function decideSemanticDedup(content, lookup, options) {
|
|
|
1119
1155
|
};
|
|
1120
1156
|
}
|
|
1121
1157
|
|
|
1122
|
-
// src/
|
|
1158
|
+
// src/taxonomy/default-taxonomy.ts
|
|
1159
|
+
var DEFAULT_TAXONOMY = {
|
|
1160
|
+
version: 1,
|
|
1161
|
+
categories: [
|
|
1162
|
+
{
|
|
1163
|
+
id: "corrections",
|
|
1164
|
+
name: "Corrections",
|
|
1165
|
+
description: "Corrections to previously stored information",
|
|
1166
|
+
filingRules: ["Any update that supersedes a prior fact"],
|
|
1167
|
+
priority: 10,
|
|
1168
|
+
memoryCategories: ["correction"]
|
|
1169
|
+
},
|
|
1170
|
+
{
|
|
1171
|
+
id: "principles",
|
|
1172
|
+
name: "Principles",
|
|
1173
|
+
description: "Rules, guidelines, and recurring patterns",
|
|
1174
|
+
filingRules: ["A guiding principle, rule, or skill"],
|
|
1175
|
+
priority: 20,
|
|
1176
|
+
memoryCategories: ["principle", "rule", "skill"]
|
|
1177
|
+
},
|
|
1178
|
+
{
|
|
1179
|
+
id: "procedures",
|
|
1180
|
+
name: "Procedures",
|
|
1181
|
+
description: "Ordered multi-step workflows the user repeats",
|
|
1182
|
+
filingRules: ["A repeatable sequence of steps or commands for a task"],
|
|
1183
|
+
priority: 25,
|
|
1184
|
+
memoryCategories: ["procedure"]
|
|
1185
|
+
},
|
|
1186
|
+
{
|
|
1187
|
+
id: "entities",
|
|
1188
|
+
name: "Entities",
|
|
1189
|
+
description: "People, organizations, places, projects",
|
|
1190
|
+
filingRules: ["Named entity with attributes"],
|
|
1191
|
+
priority: 30,
|
|
1192
|
+
memoryCategories: ["entity", "relationship"]
|
|
1193
|
+
},
|
|
1194
|
+
{
|
|
1195
|
+
id: "decisions",
|
|
1196
|
+
name: "Decisions",
|
|
1197
|
+
description: "Choices made and their rationale",
|
|
1198
|
+
filingRules: ["A decision or commitment with reasoning"],
|
|
1199
|
+
priority: 35,
|
|
1200
|
+
memoryCategories: ["decision", "commitment"]
|
|
1201
|
+
},
|
|
1202
|
+
{
|
|
1203
|
+
id: "preferences",
|
|
1204
|
+
name: "Preferences",
|
|
1205
|
+
description: "User likes, dislikes, and style choices",
|
|
1206
|
+
filingRules: ["Anything expressing a preference or taste"],
|
|
1207
|
+
priority: 40,
|
|
1208
|
+
memoryCategories: ["preference"]
|
|
1209
|
+
},
|
|
1210
|
+
{
|
|
1211
|
+
id: "facts",
|
|
1212
|
+
name: "Facts",
|
|
1213
|
+
description: "Objective statements about the world",
|
|
1214
|
+
filingRules: ["Any factual claim or piece of information"],
|
|
1215
|
+
priority: 50,
|
|
1216
|
+
memoryCategories: ["fact"]
|
|
1217
|
+
},
|
|
1218
|
+
{
|
|
1219
|
+
id: "moments",
|
|
1220
|
+
name: "Moments",
|
|
1221
|
+
description: "Significant events or experiences",
|
|
1222
|
+
filingRules: ["A specific event worth remembering"],
|
|
1223
|
+
priority: 60,
|
|
1224
|
+
memoryCategories: ["moment"]
|
|
1225
|
+
},
|
|
1226
|
+
{
|
|
1227
|
+
id: "reasoning-traces",
|
|
1228
|
+
name: "Reasoning Traces",
|
|
1229
|
+
description: "Stored intermediate reasoning / solution chains for a problem the agent previously solved",
|
|
1230
|
+
filingRules: [
|
|
1231
|
+
"A multi-step reasoning chain or solution walkthrough the agent can replay for a similar problem"
|
|
1232
|
+
],
|
|
1233
|
+
priority: 55,
|
|
1234
|
+
memoryCategories: ["reasoning_trace"]
|
|
1235
|
+
}
|
|
1236
|
+
]
|
|
1237
|
+
};
|
|
1238
|
+
|
|
1239
|
+
// src/taxonomy/resolver-doc-generator.ts
|
|
1240
|
+
function generateResolverDocument(taxonomy) {
|
|
1241
|
+
const sorted = [...taxonomy.categories].sort((a, b) => {
|
|
1242
|
+
if (a.priority !== b.priority) return a.priority - b.priority;
|
|
1243
|
+
return a.id.localeCompare(b.id);
|
|
1244
|
+
});
|
|
1245
|
+
const lines = [
|
|
1246
|
+
"# Memory Filing Resolver",
|
|
1247
|
+
"",
|
|
1248
|
+
"Given a new piece of knowledge, follow this tree to determine where it belongs.",
|
|
1249
|
+
""
|
|
1250
|
+
];
|
|
1251
|
+
let step = 1;
|
|
1252
|
+
for (const cat of sorted) {
|
|
1253
|
+
lines.push(`## Step ${step}: ${cat.description}?`);
|
|
1254
|
+
lines.push("");
|
|
1255
|
+
for (const rule of cat.filingRules) {
|
|
1256
|
+
lines.push(`- ${rule}`);
|
|
1257
|
+
}
|
|
1258
|
+
lines.push("");
|
|
1259
|
+
lines.push(
|
|
1260
|
+
`> YES: File under **${cat.id}/** (priority ${cat.priority})`
|
|
1261
|
+
);
|
|
1262
|
+
lines.push("");
|
|
1263
|
+
step++;
|
|
1264
|
+
}
|
|
1265
|
+
lines.push("## Tie-breaking");
|
|
1266
|
+
lines.push("");
|
|
1267
|
+
lines.push(
|
|
1268
|
+
"If a fact could go in multiple categories, file under the one with the **lowest priority number**."
|
|
1269
|
+
);
|
|
1270
|
+
lines.push("");
|
|
1271
|
+
lines.push(`---`);
|
|
1272
|
+
lines.push(`*Generated from taxonomy v${taxonomy.version}*`);
|
|
1273
|
+
lines.push("");
|
|
1274
|
+
return lines.join("\n");
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1277
|
+
// src/taxonomy/taxonomy-loader.ts
|
|
1278
|
+
import { readFile as readFile3, mkdir as mkdir3, writeFile as writeFile3 } from "fs/promises";
|
|
1123
1279
|
import path3 from "path";
|
|
1124
|
-
|
|
1280
|
+
var TAXONOMY_DIR = ".taxonomy";
|
|
1281
|
+
var TAXONOMY_FILE = "taxonomy.json";
|
|
1282
|
+
var MAX_SLUG_LENGTH = 32;
|
|
1283
|
+
var SLUG_RE = /^[a-z][a-z0-9-]*$/;
|
|
1284
|
+
function validateSlug(slug) {
|
|
1285
|
+
if (slug.length === 0) {
|
|
1286
|
+
throw new Error("Taxonomy category ID must not be empty");
|
|
1287
|
+
}
|
|
1288
|
+
if (slug.length > MAX_SLUG_LENGTH) {
|
|
1289
|
+
throw new Error(
|
|
1290
|
+
`Taxonomy category ID "${slug}" exceeds ${MAX_SLUG_LENGTH} characters`
|
|
1291
|
+
);
|
|
1292
|
+
}
|
|
1293
|
+
if (!SLUG_RE.test(slug)) {
|
|
1294
|
+
throw new Error(
|
|
1295
|
+
`Taxonomy category ID "${slug}" is invalid: must be lowercase letters, digits, and hyphens, starting with a letter`
|
|
1296
|
+
);
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
function validateTaxonomy(taxonomy) {
|
|
1300
|
+
if (typeof taxonomy.version !== "number" || taxonomy.version < 1) {
|
|
1301
|
+
throw new Error("Taxonomy version must be a positive integer");
|
|
1302
|
+
}
|
|
1303
|
+
if (!Array.isArray(taxonomy.categories)) {
|
|
1304
|
+
throw new Error("Taxonomy categories must be an array");
|
|
1305
|
+
}
|
|
1306
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
1307
|
+
for (const cat of taxonomy.categories) {
|
|
1308
|
+
validateSlug(cat.id);
|
|
1309
|
+
if (seenIds.has(cat.id)) {
|
|
1310
|
+
throw new Error(`Duplicate taxonomy category ID: "${cat.id}"`);
|
|
1311
|
+
}
|
|
1312
|
+
seenIds.add(cat.id);
|
|
1313
|
+
if (typeof cat.name !== "string" || cat.name.trim().length === 0) {
|
|
1314
|
+
throw new Error(`Taxonomy category "${cat.id}" must have a non-empty name`);
|
|
1315
|
+
}
|
|
1316
|
+
if (typeof cat.description !== "string" || cat.description.trim().length === 0) {
|
|
1317
|
+
throw new Error(`Taxonomy category "${cat.id}" must have a non-empty description`);
|
|
1318
|
+
}
|
|
1319
|
+
if (!Array.isArray(cat.filingRules)) {
|
|
1320
|
+
throw new Error(`Taxonomy category "${cat.id}" filingRules must be an array`);
|
|
1321
|
+
}
|
|
1322
|
+
if (typeof cat.priority !== "number" || !Number.isFinite(cat.priority)) {
|
|
1323
|
+
throw new Error(`Taxonomy category "${cat.id}" must have a finite numeric priority`);
|
|
1324
|
+
}
|
|
1325
|
+
if (!Array.isArray(cat.memoryCategories)) {
|
|
1326
|
+
throw new Error(`Taxonomy category "${cat.id}" memoryCategories must be an array`);
|
|
1327
|
+
}
|
|
1328
|
+
if (cat.parentId !== void 0) {
|
|
1329
|
+
if (typeof cat.parentId !== "string") {
|
|
1330
|
+
throw new Error(`Taxonomy category "${cat.id}" parentId must be a string if set`);
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
for (const cat of taxonomy.categories) {
|
|
1335
|
+
if (cat.parentId !== void 0 && !seenIds.has(cat.parentId)) {
|
|
1336
|
+
throw new Error(
|
|
1337
|
+
`Taxonomy category "${cat.id}" references unknown parentId "${cat.parentId}"`
|
|
1338
|
+
);
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
async function loadTaxonomy(memoryDir) {
|
|
1343
|
+
const taxonomyPath = path3.join(memoryDir, TAXONOMY_DIR, TAXONOMY_FILE);
|
|
1344
|
+
let raw;
|
|
1345
|
+
try {
|
|
1346
|
+
raw = await readFile3(taxonomyPath, "utf-8");
|
|
1347
|
+
} catch (err) {
|
|
1348
|
+
if (err instanceof Error && err.code === "ENOENT") {
|
|
1349
|
+
return structuredClone(DEFAULT_TAXONOMY);
|
|
1350
|
+
}
|
|
1351
|
+
throw err;
|
|
1352
|
+
}
|
|
1353
|
+
const parsed = JSON.parse(raw);
|
|
1354
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
1355
|
+
throw new Error("taxonomy.json must be a JSON object");
|
|
1356
|
+
}
|
|
1357
|
+
const obj = parsed;
|
|
1358
|
+
const userVersion = typeof obj.version === "number" ? obj.version : DEFAULT_TAXONOMY.version;
|
|
1359
|
+
const userCategories = Array.isArray(obj.categories) ? obj.categories : [];
|
|
1360
|
+
const userIdCounts = /* @__PURE__ */ new Map();
|
|
1361
|
+
for (const cat of userCategories) {
|
|
1362
|
+
const id = typeof cat.id === "string" ? cat.id : String(cat.id);
|
|
1363
|
+
userIdCounts.set(id, (userIdCounts.get(id) ?? 0) + 1);
|
|
1364
|
+
}
|
|
1365
|
+
const duplicateIds = [...userIdCounts.entries()].filter(([, count]) => count > 1).map(([id]) => id);
|
|
1366
|
+
if (duplicateIds.length > 0) {
|
|
1367
|
+
throw new Error(
|
|
1368
|
+
`Duplicate category IDs in taxonomy.json: ${duplicateIds.map((id) => `"${id}"`).join(", ")}`
|
|
1369
|
+
);
|
|
1370
|
+
}
|
|
1371
|
+
const mergedMap = /* @__PURE__ */ new Map();
|
|
1372
|
+
for (const cat of DEFAULT_TAXONOMY.categories) {
|
|
1373
|
+
mergedMap.set(cat.id, { ...cat });
|
|
1374
|
+
}
|
|
1375
|
+
for (const cat of userCategories) {
|
|
1376
|
+
mergedMap.set(cat.id, cat);
|
|
1377
|
+
}
|
|
1378
|
+
const merged = {
|
|
1379
|
+
version: userVersion,
|
|
1380
|
+
categories: [...mergedMap.values()]
|
|
1381
|
+
};
|
|
1382
|
+
validateTaxonomy(merged);
|
|
1383
|
+
return merged;
|
|
1384
|
+
}
|
|
1385
|
+
async function saveTaxonomy(memoryDir, taxonomy) {
|
|
1386
|
+
validateTaxonomy(taxonomy);
|
|
1387
|
+
const dir = path3.join(memoryDir, TAXONOMY_DIR);
|
|
1388
|
+
await mkdir3(dir, { recursive: true });
|
|
1389
|
+
const filePath = path3.join(dir, TAXONOMY_FILE);
|
|
1390
|
+
await writeFile3(filePath, JSON.stringify(taxonomy, null, 2) + "\n", "utf-8");
|
|
1391
|
+
}
|
|
1392
|
+
function getTaxonomyDir(memoryDir) {
|
|
1393
|
+
return path3.join(memoryDir, TAXONOMY_DIR);
|
|
1394
|
+
}
|
|
1395
|
+
function getTaxonomyFilePath(memoryDir) {
|
|
1396
|
+
return path3.join(memoryDir, TAXONOMY_DIR, TAXONOMY_FILE);
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1399
|
+
// src/lcm/schema.ts
|
|
1400
|
+
import path4 from "path";
|
|
1401
|
+
import { mkdir as mkdir4 } from "fs/promises";
|
|
1125
1402
|
var LCM_SCHEMA_VERSION = 1;
|
|
1126
1403
|
function openLcmDatabase(memoryDir) {
|
|
1127
|
-
const dbPath =
|
|
1404
|
+
const dbPath = path4.join(memoryDir, "state", "lcm.sqlite");
|
|
1128
1405
|
const db = openBetterSqlite3(dbPath);
|
|
1129
1406
|
db.pragma("journal_mode = WAL");
|
|
1130
1407
|
db.pragma("busy_timeout = 5000");
|
|
@@ -1133,7 +1410,7 @@ function openLcmDatabase(memoryDir) {
|
|
|
1133
1410
|
return db;
|
|
1134
1411
|
}
|
|
1135
1412
|
async function ensureLcmStateDir(memoryDir) {
|
|
1136
|
-
await
|
|
1413
|
+
await mkdir4(path4.join(memoryDir, "state"), { recursive: true });
|
|
1137
1414
|
}
|
|
1138
1415
|
function applySchema(db) {
|
|
1139
1416
|
const versionRow = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='lcm_meta'").get();
|
|
@@ -2397,7 +2674,7 @@ function chunkTranscriptEntries(sessionKey, entries, opts) {
|
|
|
2397
2674
|
|
|
2398
2675
|
// src/conversation-index/cleanup.ts
|
|
2399
2676
|
import { readdir as readdir2, rm as rm3 } from "fs/promises";
|
|
2400
|
-
import
|
|
2677
|
+
import path5 from "path";
|
|
2401
2678
|
async function cleanupConversationChunks(rootDir, retentionDays) {
|
|
2402
2679
|
if (!Number.isFinite(retentionDays) || retentionDays <= 0) return;
|
|
2403
2680
|
const cutoffMs = Date.now() - retentionDays * 24 * 60 * 60 * 1e3;
|
|
@@ -2405,7 +2682,7 @@ async function cleanupConversationChunks(rootDir, retentionDays) {
|
|
|
2405
2682
|
const sessions = await readdir2(rootDir, { withFileTypes: true });
|
|
2406
2683
|
for (const s of sessions) {
|
|
2407
2684
|
if (!s.isDirectory()) continue;
|
|
2408
|
-
const sessionDir =
|
|
2685
|
+
const sessionDir = path5.join(rootDir, s.name);
|
|
2409
2686
|
const dayDirs = await readdir2(sessionDir, { withFileTypes: true });
|
|
2410
2687
|
for (const d of dayDirs) {
|
|
2411
2688
|
if (!d.isDirectory()) continue;
|
|
@@ -2413,7 +2690,7 @@ async function cleanupConversationChunks(rootDir, retentionDays) {
|
|
|
2413
2690
|
const dayMs = (/* @__PURE__ */ new Date(d.name + "T00:00:00.000Z")).getTime();
|
|
2414
2691
|
if (!Number.isFinite(dayMs)) continue;
|
|
2415
2692
|
if (dayMs < cutoffMs) {
|
|
2416
|
-
await rm3(
|
|
2693
|
+
await rm3(path5.join(sessionDir, d.name), { recursive: true, force: true });
|
|
2417
2694
|
}
|
|
2418
2695
|
}
|
|
2419
2696
|
try {
|
|
@@ -2429,6 +2706,264 @@ async function cleanupConversationChunks(rootDir, retentionDays) {
|
|
|
2429
2706
|
}
|
|
2430
2707
|
}
|
|
2431
2708
|
|
|
2709
|
+
// src/coding/git-context.ts
|
|
2710
|
+
import path6 from "path";
|
|
2711
|
+
var DEFAULT_GIT_TIMEOUT_MS = 2e3;
|
|
2712
|
+
function defaultGitInvoker() {
|
|
2713
|
+
return (cwd, args) => {
|
|
2714
|
+
const result = launchProcessSync("git", args, {
|
|
2715
|
+
cwd,
|
|
2716
|
+
encoding: "utf-8",
|
|
2717
|
+
timeout: DEFAULT_GIT_TIMEOUT_MS,
|
|
2718
|
+
shell: false
|
|
2719
|
+
});
|
|
2720
|
+
if (result.error) {
|
|
2721
|
+
return { stdout: "", exitCode: 127 };
|
|
2722
|
+
}
|
|
2723
|
+
return {
|
|
2724
|
+
stdout: typeof result.stdout === "string" ? result.stdout : "",
|
|
2725
|
+
exitCode: typeof result.status === "number" ? result.status : 1
|
|
2726
|
+
};
|
|
2727
|
+
};
|
|
2728
|
+
}
|
|
2729
|
+
function stableHash(input) {
|
|
2730
|
+
let hash = 2166136261;
|
|
2731
|
+
for (let i = 0; i < input.length; i++) {
|
|
2732
|
+
hash ^= input.charCodeAt(i);
|
|
2733
|
+
hash = Math.imul(hash, 16777619) >>> 0;
|
|
2734
|
+
}
|
|
2735
|
+
return hash.toString(16).padStart(8, "0");
|
|
2736
|
+
}
|
|
2737
|
+
function normalizeOriginUrl(rawUrl) {
|
|
2738
|
+
let url = rawUrl.trim();
|
|
2739
|
+
if (!url) return "";
|
|
2740
|
+
if (/\.git$/i.test(url)) url = url.slice(0, -4);
|
|
2741
|
+
if (/^[A-Za-z]:[\\/]/.test(url)) {
|
|
2742
|
+
return url.toLowerCase();
|
|
2743
|
+
}
|
|
2744
|
+
const protoMatch = /^[a-z][a-z0-9+.-]*:\/\/(?:[^@/]+@)?(\[[^\]]+\]|[^/:]*)(?::(\d+))?(\/.*)?$/i.exec(url);
|
|
2745
|
+
if (protoMatch) {
|
|
2746
|
+
let host = protoMatch[1] ?? "";
|
|
2747
|
+
const wasBracketed = host.startsWith("[") && host.endsWith("]");
|
|
2748
|
+
if (wasBracketed) host = host.slice(1, -1);
|
|
2749
|
+
const port = protoMatch[2];
|
|
2750
|
+
const repoPath = (protoMatch[3] ?? "").replace(/^\/+/, "");
|
|
2751
|
+
const hostPort = port ? wasBracketed ? `[${host}]:${port}` : `${host}:${port}` : host;
|
|
2752
|
+
const prefix = hostPort.length > 0 ? hostPort : "localhost";
|
|
2753
|
+
return `${prefix}/${repoPath}`.toLowerCase();
|
|
2754
|
+
}
|
|
2755
|
+
const scpMatch = /^(?:([^@\s/]+)@)?(\[[^\]]+\]|[^:@\s/]+):(.+)$/.exec(url);
|
|
2756
|
+
if (scpMatch) {
|
|
2757
|
+
let host = scpMatch[2] ?? "";
|
|
2758
|
+
if (host.startsWith("[") && host.endsWith("]")) host = host.slice(1, -1);
|
|
2759
|
+
const repoPath = scpMatch[3] ?? "";
|
|
2760
|
+
if (repoPath.startsWith("//")) {
|
|
2761
|
+
return url.toLowerCase();
|
|
2762
|
+
}
|
|
2763
|
+
return `${host}/${repoPath.replace(/^\/+/, "")}`.toLowerCase();
|
|
2764
|
+
}
|
|
2765
|
+
return url.toLowerCase();
|
|
2766
|
+
}
|
|
2767
|
+
async function resolveGitContext(cwd, options = {}) {
|
|
2768
|
+
try {
|
|
2769
|
+
if (typeof cwd !== "string" || cwd.length === 0) return null;
|
|
2770
|
+
const expanded = expandTildePath(cwd);
|
|
2771
|
+
if (!path6.isAbsolute(expanded)) return null;
|
|
2772
|
+
const invoker = options.invoker ?? defaultGitInvoker();
|
|
2773
|
+
const topLevel = invoker(expanded, ["rev-parse", "--show-toplevel"]);
|
|
2774
|
+
if (topLevel.exitCode !== 0) return null;
|
|
2775
|
+
const rootPath = topLevel.stdout.trim();
|
|
2776
|
+
if (!rootPath) return null;
|
|
2777
|
+
const branchResult = invoker(rootPath, ["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
2778
|
+
let branch = null;
|
|
2779
|
+
if (branchResult.exitCode === 0) {
|
|
2780
|
+
const raw = branchResult.stdout.trim();
|
|
2781
|
+
branch = raw && raw !== "HEAD" ? raw : null;
|
|
2782
|
+
} else {
|
|
2783
|
+
const unbornRef = invoker(rootPath, ["symbolic-ref", "--quiet", "HEAD"]);
|
|
2784
|
+
if (unbornRef.exitCode === 0) {
|
|
2785
|
+
const raw = unbornRef.stdout.trim();
|
|
2786
|
+
const prefix = "refs/heads/";
|
|
2787
|
+
if (raw.startsWith(prefix)) {
|
|
2788
|
+
const candidate = raw.slice(prefix.length);
|
|
2789
|
+
if (candidate) branch = candidate;
|
|
2790
|
+
}
|
|
2791
|
+
}
|
|
2792
|
+
}
|
|
2793
|
+
const originResult = invoker(rootPath, ["remote", "get-url", "origin"]);
|
|
2794
|
+
let projectId;
|
|
2795
|
+
if (originResult.exitCode === 0) {
|
|
2796
|
+
const normalized = normalizeOriginUrl(originResult.stdout);
|
|
2797
|
+
projectId = normalized ? `origin:${stableHash(normalized)}` : `root:${stableHash(rootPath)}`;
|
|
2798
|
+
} else {
|
|
2799
|
+
projectId = `root:${stableHash(rootPath)}`;
|
|
2800
|
+
}
|
|
2801
|
+
const headRef = invoker(rootPath, ["symbolic-ref", "--quiet", "refs/remotes/origin/HEAD"]);
|
|
2802
|
+
let defaultBranch = null;
|
|
2803
|
+
if (headRef.exitCode === 0) {
|
|
2804
|
+
const raw = headRef.stdout.trim();
|
|
2805
|
+
const prefix = "refs/remotes/origin/";
|
|
2806
|
+
if (raw.startsWith(prefix)) {
|
|
2807
|
+
const candidate = raw.slice(prefix.length);
|
|
2808
|
+
if (candidate) defaultBranch = candidate;
|
|
2809
|
+
}
|
|
2810
|
+
}
|
|
2811
|
+
return {
|
|
2812
|
+
projectId,
|
|
2813
|
+
branch,
|
|
2814
|
+
rootPath,
|
|
2815
|
+
defaultBranch
|
|
2816
|
+
};
|
|
2817
|
+
} catch {
|
|
2818
|
+
return null;
|
|
2819
|
+
}
|
|
2820
|
+
}
|
|
2821
|
+
|
|
2822
|
+
// src/coding/coding-namespace.ts
|
|
2823
|
+
function sanitizeFragment(input) {
|
|
2824
|
+
if (typeof input !== "string") return "";
|
|
2825
|
+
const trimmed = input.trim().toLowerCase();
|
|
2826
|
+
let out = "";
|
|
2827
|
+
let prevIsDash = true;
|
|
2828
|
+
for (let i = 0; i < trimmed.length; i += 1) {
|
|
2829
|
+
const c = trimmed[i];
|
|
2830
|
+
const cc = trimmed.charCodeAt(i);
|
|
2831
|
+
const isSafe = cc >= 48 && cc <= 57 || cc >= 97 && cc <= 122 || cc === 46 || cc === 95;
|
|
2832
|
+
if (isSafe) {
|
|
2833
|
+
out += c;
|
|
2834
|
+
prevIsDash = false;
|
|
2835
|
+
} else if (!prevIsDash) {
|
|
2836
|
+
out += "-";
|
|
2837
|
+
prevIsDash = true;
|
|
2838
|
+
}
|
|
2839
|
+
}
|
|
2840
|
+
if (out.endsWith("-")) out = out.slice(0, -1);
|
|
2841
|
+
return out;
|
|
2842
|
+
}
|
|
2843
|
+
var MAX_NAMESPACE_LEN = 64;
|
|
2844
|
+
var HASH_SUFFIX_LEN = 9;
|
|
2845
|
+
function capLength(value) {
|
|
2846
|
+
if (value.length <= MAX_NAMESPACE_LEN) return value;
|
|
2847
|
+
const hash = stableHash(value);
|
|
2848
|
+
let end = MAX_NAMESPACE_LEN - HASH_SUFFIX_LEN;
|
|
2849
|
+
while (end > 0 && value.charCodeAt(end - 1) === 45) end -= 1;
|
|
2850
|
+
return `${value.slice(0, end)}-${hash}`;
|
|
2851
|
+
}
|
|
2852
|
+
function projectNamespaceName(projectId) {
|
|
2853
|
+
const frag = sanitizeFragment(projectId);
|
|
2854
|
+
return capLength(`project-${frag || "unknown"}`);
|
|
2855
|
+
}
|
|
2856
|
+
function sanitizeBaseFragment(input) {
|
|
2857
|
+
if (typeof input !== "string") return "";
|
|
2858
|
+
const trimmed = input.trim();
|
|
2859
|
+
let out = "";
|
|
2860
|
+
let prevIsDash = true;
|
|
2861
|
+
for (let i = 0; i < trimmed.length; i += 1) {
|
|
2862
|
+
const c = trimmed[i];
|
|
2863
|
+
const cc = trimmed.charCodeAt(i);
|
|
2864
|
+
const isSafe = cc >= 48 && cc <= 57 || cc >= 65 && cc <= 90 || cc >= 97 && cc <= 122 || cc === 46 || cc === 95;
|
|
2865
|
+
if (isSafe) {
|
|
2866
|
+
out += c;
|
|
2867
|
+
prevIsDash = false;
|
|
2868
|
+
} else if (!prevIsDash) {
|
|
2869
|
+
out += "-";
|
|
2870
|
+
prevIsDash = true;
|
|
2871
|
+
}
|
|
2872
|
+
}
|
|
2873
|
+
if (out.endsWith("-")) out = out.slice(0, -1);
|
|
2874
|
+
return out;
|
|
2875
|
+
}
|
|
2876
|
+
function combineNamespaces(base, overlay) {
|
|
2877
|
+
const baseFrag = sanitizeBaseFragment(base);
|
|
2878
|
+
const overlayFrag = sanitizeFragment(overlay);
|
|
2879
|
+
if (!baseFrag) return capLength(overlayFrag || "unknown");
|
|
2880
|
+
if (!overlayFrag) return capLength(baseFrag);
|
|
2881
|
+
return capLength(`${baseFrag}-${overlayFrag}`);
|
|
2882
|
+
}
|
|
2883
|
+
function branchNamespaceName(projectId, branch) {
|
|
2884
|
+
const projectFrag = sanitizeFragment(projectId);
|
|
2885
|
+
const trimmedBranch = branch.trim();
|
|
2886
|
+
const branchFrag = sanitizeFragment(trimmedBranch);
|
|
2887
|
+
const disambig = trimmedBranch.length > 0 && branchFrag !== trimmedBranch;
|
|
2888
|
+
const base = `project-${projectFrag || "unknown"}-branch-${branchFrag || "unknown"}`;
|
|
2889
|
+
const suffixed = disambig ? `${base}-${stableHash(trimmedBranch)}` : base;
|
|
2890
|
+
return capLength(suffixed);
|
|
2891
|
+
}
|
|
2892
|
+
function resolveCodingNamespaceOverlay(codingContext, config) {
|
|
2893
|
+
if (!codingContext) return null;
|
|
2894
|
+
if (!config.projectScope) return null;
|
|
2895
|
+
const projectId = typeof codingContext.projectId === "string" ? codingContext.projectId.trim() : "";
|
|
2896
|
+
if (!projectId) return null;
|
|
2897
|
+
const projectNs = projectNamespaceName(projectId);
|
|
2898
|
+
if (config.branchScope && typeof codingContext.branch === "string" && codingContext.branch.length > 0) {
|
|
2899
|
+
const branchNs = branchNamespaceName(projectId, codingContext.branch);
|
|
2900
|
+
return {
|
|
2901
|
+
namespace: branchNs,
|
|
2902
|
+
readFallbacks: [projectNs],
|
|
2903
|
+
scope: "branch"
|
|
2904
|
+
};
|
|
2905
|
+
}
|
|
2906
|
+
return {
|
|
2907
|
+
namespace: projectNs,
|
|
2908
|
+
readFallbacks: [],
|
|
2909
|
+
scope: "project"
|
|
2910
|
+
};
|
|
2911
|
+
}
|
|
2912
|
+
function describeCodingScope(codingContext, config) {
|
|
2913
|
+
const projectId = codingContext?.projectId ?? null;
|
|
2914
|
+
const branch = codingContext?.branch ?? null;
|
|
2915
|
+
if (!codingContext) {
|
|
2916
|
+
return {
|
|
2917
|
+
scope: "none",
|
|
2918
|
+
projectId: null,
|
|
2919
|
+
branch: null,
|
|
2920
|
+
effectiveNamespace: null,
|
|
2921
|
+
readFallbacks: [],
|
|
2922
|
+
disabledReason: "no-context"
|
|
2923
|
+
};
|
|
2924
|
+
}
|
|
2925
|
+
if (!config.projectScope) {
|
|
2926
|
+
return {
|
|
2927
|
+
scope: "none",
|
|
2928
|
+
projectId,
|
|
2929
|
+
branch,
|
|
2930
|
+
effectiveNamespace: null,
|
|
2931
|
+
readFallbacks: [],
|
|
2932
|
+
disabledReason: "disabled"
|
|
2933
|
+
};
|
|
2934
|
+
}
|
|
2935
|
+
const trimmedId = typeof projectId === "string" ? projectId.trim() : "";
|
|
2936
|
+
if (!trimmedId) {
|
|
2937
|
+
return {
|
|
2938
|
+
scope: "none",
|
|
2939
|
+
projectId,
|
|
2940
|
+
branch,
|
|
2941
|
+
effectiveNamespace: null,
|
|
2942
|
+
readFallbacks: [],
|
|
2943
|
+
disabledReason: "empty-project"
|
|
2944
|
+
};
|
|
2945
|
+
}
|
|
2946
|
+
const overlay = resolveCodingNamespaceOverlay(codingContext, config);
|
|
2947
|
+
if (!overlay) {
|
|
2948
|
+
return {
|
|
2949
|
+
scope: "none",
|
|
2950
|
+
projectId,
|
|
2951
|
+
branch,
|
|
2952
|
+
effectiveNamespace: null,
|
|
2953
|
+
readFallbacks: [],
|
|
2954
|
+
disabledReason: "disabled"
|
|
2955
|
+
};
|
|
2956
|
+
}
|
|
2957
|
+
return {
|
|
2958
|
+
scope: overlay.scope,
|
|
2959
|
+
projectId,
|
|
2960
|
+
branch,
|
|
2961
|
+
effectiveNamespace: overlay.namespace,
|
|
2962
|
+
readFallbacks: overlay.readFallbacks,
|
|
2963
|
+
disabledReason: null
|
|
2964
|
+
};
|
|
2965
|
+
}
|
|
2966
|
+
|
|
2432
2967
|
// src/orchestrator.ts
|
|
2433
2968
|
function dedupeEntitySynthesisEvidenceEntries(entries) {
|
|
2434
2969
|
const dedupedEvidenceEntries = [];
|
|
@@ -2493,6 +3028,20 @@ function fingerprintEntitySynthesisEvidence(entity) {
|
|
|
2493
3028
|
fingerprint.update(fingerprintEntityStructuredFacts(entity) ?? "");
|
|
2494
3029
|
return fingerprint.digest("hex");
|
|
2495
3030
|
}
|
|
3031
|
+
function mapRecallSourceToXrayServedBy(source) {
|
|
3032
|
+
switch (source) {
|
|
3033
|
+
case "recent_scan":
|
|
3034
|
+
return "recent-scan";
|
|
3035
|
+
case "hot_qmd":
|
|
3036
|
+
case "hot_embedding":
|
|
3037
|
+
case "cold_fallback":
|
|
3038
|
+
case "none":
|
|
3039
|
+
return "hybrid";
|
|
3040
|
+
}
|
|
3041
|
+
const _exhaustive = source;
|
|
3042
|
+
void _exhaustive;
|
|
3043
|
+
return "hybrid";
|
|
3044
|
+
}
|
|
2496
3045
|
var abortRecallError = abortError;
|
|
2497
3046
|
function throwIfRecallAborted(signal, message = "recall aborted") {
|
|
2498
3047
|
throwIfAborted(signal, message);
|
|
@@ -2515,7 +3064,7 @@ async function raceRecallAbort(promise, signal, message = "recall aborted") {
|
|
|
2515
3064
|
}
|
|
2516
3065
|
var COMPACTION_SIGNAL_MAX_AGE_MS = 60 * 60 * 1e3;
|
|
2517
3066
|
function defaultWorkspaceDir() {
|
|
2518
|
-
return
|
|
3067
|
+
return path7.join(os.homedir(), ".openclaw", "workspace");
|
|
2519
3068
|
}
|
|
2520
3069
|
function sanitizeSessionKeyForFilename(sessionKey) {
|
|
2521
3070
|
const readable = sessionKey.replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
@@ -2683,11 +3232,11 @@ function mergeGraphExpandedResults(primary, expanded) {
|
|
|
2683
3232
|
return Array.from(mergedByPath.values());
|
|
2684
3233
|
}
|
|
2685
3234
|
function graphPathRelativeToStorage(storageDir, candidatePath) {
|
|
2686
|
-
const absolutePath =
|
|
2687
|
-
const rel =
|
|
3235
|
+
const absolutePath = path7.isAbsolute(candidatePath) ? candidatePath : path7.resolve(storageDir, candidatePath);
|
|
3236
|
+
const rel = path7.relative(storageDir, absolutePath);
|
|
2688
3237
|
if (!rel || rel === ".") return null;
|
|
2689
3238
|
if (rel.startsWith("..")) return null;
|
|
2690
|
-
return rel.split(
|
|
3239
|
+
return rel.split(path7.sep).join("/");
|
|
2691
3240
|
}
|
|
2692
3241
|
function normalizeGraphActivationScore(score) {
|
|
2693
3242
|
const bounded = Number.isFinite(score) && score > 0 ? score : 0;
|
|
@@ -2829,7 +3378,7 @@ function buildMemoryPathById(allMemsForGraph, storageDir) {
|
|
|
2829
3378
|
for (const mem of allMemsForGraph ?? []) {
|
|
2830
3379
|
const id = mem.frontmatter.id;
|
|
2831
3380
|
if (!id) continue;
|
|
2832
|
-
pathById.set(id,
|
|
3381
|
+
pathById.set(id, path7.relative(storageDir, mem.path));
|
|
2833
3382
|
}
|
|
2834
3383
|
return pathById;
|
|
2835
3384
|
}
|
|
@@ -2837,7 +3386,7 @@ function appendMemoryToGraphContext(options) {
|
|
|
2837
3386
|
if (!Array.isArray(options.allMemsForGraph)) return;
|
|
2838
3387
|
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
2839
3388
|
options.allMemsForGraph.push({
|
|
2840
|
-
path:
|
|
3389
|
+
path: path7.join(options.storageDir, options.memoryRelPath),
|
|
2841
3390
|
content: options.content,
|
|
2842
3391
|
frontmatter: {
|
|
2843
3392
|
id: options.memoryId,
|
|
@@ -2857,15 +3406,16 @@ function resolvePersistedMemoryRelativePath(options) {
|
|
|
2857
3406
|
const persisted = options.pathById.get(options.memoryId);
|
|
2858
3407
|
if (persisted) return persisted;
|
|
2859
3408
|
if (options.category === "correction") {
|
|
2860
|
-
return
|
|
3409
|
+
return path7.join("corrections", `${options.memoryId}.md`);
|
|
2861
3410
|
}
|
|
3411
|
+
const subtree = options.category === "procedure" ? "procedures" : options.category === "reasoning_trace" ? "reasoning-traces" : "facts";
|
|
2862
3412
|
const idParts = options.memoryId.split("-");
|
|
2863
3413
|
const maybeTimestamp = Number(idParts[1]);
|
|
2864
3414
|
if (Number.isFinite(maybeTimestamp) && maybeTimestamp > 0) {
|
|
2865
3415
|
const day = new Date(maybeTimestamp).toISOString().slice(0, 10);
|
|
2866
|
-
return
|
|
3416
|
+
return path7.join(subtree, day, `${options.memoryId}.md`);
|
|
2867
3417
|
}
|
|
2868
|
-
return
|
|
3418
|
+
return path7.join(subtree, `${options.memoryId}.md`);
|
|
2869
3419
|
}
|
|
2870
3420
|
var Orchestrator = class _Orchestrator {
|
|
2871
3421
|
storage;
|
|
@@ -2884,12 +3434,39 @@ var Orchestrator = class _Orchestrator {
|
|
|
2884
3434
|
localLlm;
|
|
2885
3435
|
fastLlm;
|
|
2886
3436
|
judgeVerdictCache;
|
|
2887
|
-
|
|
3437
|
+
/**
|
|
3438
|
+
* Per-orchestrator defer-counter map (issue #562, PR 2). Tracks how many
|
|
3439
|
+
* times the judge has returned `"defer"` for a given candidate content
|
|
3440
|
+
* hash so the defer cap can be enforced.
|
|
3441
|
+
*/
|
|
3442
|
+
judgeDeferCounts;
|
|
3443
|
+
/**
|
|
3444
|
+
* Side-channel: number of facts deferred in the most recent
|
|
3445
|
+
* `persistExtraction` call (issue #562, PR 2). The caller reads this after
|
|
3446
|
+
* `persistExtraction` returns to decide whether to retain buffer turns for
|
|
3447
|
+
* the next extraction pass. Not part of the return signature because many
|
|
3448
|
+
* callers already destructure `persistedIds` by position.
|
|
3449
|
+
*/
|
|
3450
|
+
lastPersistExtractionDeferredCount = 0;
|
|
3451
|
+
_fastGatewayLlm;
|
|
3452
|
+
get fastGatewayLlm() {
|
|
3453
|
+
return this._fastGatewayLlm;
|
|
3454
|
+
}
|
|
2888
3455
|
modelRegistry;
|
|
2889
3456
|
relevance;
|
|
2890
3457
|
negatives;
|
|
2891
3458
|
lastRecall;
|
|
2892
3459
|
tierMigrationStatus;
|
|
3460
|
+
/**
|
|
3461
|
+
* In-memory X-ray snapshot from the most recent `recall()` call that
|
|
3462
|
+
* was invoked with `xrayCapture: true` (issue #570 PR 1). Scope is
|
|
3463
|
+
* per-process; later slices add CLI/HTTP/MCP surfaces that consume
|
|
3464
|
+
* this via the shared renderer. `null` until the first capture, and
|
|
3465
|
+
* NEVER overwritten by a recall that did not request capture —
|
|
3466
|
+
* requests without the flag leave prior captures intact so the
|
|
3467
|
+
* capturing caller can still read their snapshot back.
|
|
3468
|
+
*/
|
|
3469
|
+
lastXraySnapshot = null;
|
|
2893
3470
|
embeddingFallback;
|
|
2894
3471
|
conversationIndexDir;
|
|
2895
3472
|
extraction;
|
|
@@ -2905,6 +3482,16 @@ var Orchestrator = class _Orchestrator {
|
|
|
2905
3482
|
/** Lossless Context Management engine — proactive session archive + DAG summarization. */
|
|
2906
3483
|
lcmEngine = null;
|
|
2907
3484
|
rerankCache = new RerankCache();
|
|
3485
|
+
/**
|
|
3486
|
+
* Short-TTL cache for Memory Worth counter lookups so interactive recall
|
|
3487
|
+
* doesn't trigger a full `readAllMemories` scan per query. Keyed by
|
|
3488
|
+
* namespace; the filter unions across namespaces at query time. The TTL
|
|
3489
|
+
* is intentionally short (seconds, not minutes) because counters are
|
|
3490
|
+
* mutated by `recordMemoryOutcome` asynchronously and we'd rather serve
|
|
3491
|
+
* a 30-second-stale worth score than a stable-but-wrong one.
|
|
3492
|
+
*/
|
|
3493
|
+
memoryWorthCounterCache = /* @__PURE__ */ new Map();
|
|
3494
|
+
static MEMORY_WORTH_CACHE_TTL_MS = 3e4;
|
|
2908
3495
|
/**
|
|
2909
3496
|
* Per-session workspace overrides keyed by sessionKey.
|
|
2910
3497
|
* Set by the before_agent_start hook so recall() uses the correct
|
|
@@ -2912,6 +3499,14 @@ var Orchestrator = class _Orchestrator {
|
|
|
2912
3499
|
* Using a Map prevents concurrent sessions from overwriting each other.
|
|
2913
3500
|
*/
|
|
2914
3501
|
_recallWorkspaceOverrides = /* @__PURE__ */ new Map();
|
|
3502
|
+
/**
|
|
3503
|
+
* Per-session coding-agent context (issue #569). Populated by connectors at
|
|
3504
|
+
* session-start (PRs 5/6/7) via `setCodingContextForSession`. Used by both
|
|
3505
|
+
* the recall path and the write path so that memory routing respects the
|
|
3506
|
+
* project/branch scope a session is operating in (rule 42 — read + write
|
|
3507
|
+
* through the same namespace layer).
|
|
3508
|
+
*/
|
|
3509
|
+
_codingContextBySession = /* @__PURE__ */ new Map();
|
|
2915
3510
|
routingRulesStore = null;
|
|
2916
3511
|
contentHashIndex = null;
|
|
2917
3512
|
artifactSourceStatusCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -2945,6 +3540,10 @@ var Orchestrator = class _Orchestrator {
|
|
|
2945
3540
|
runtimePolicyValues = null;
|
|
2946
3541
|
utilityRuntimeValues = null;
|
|
2947
3542
|
evalShadowWriteChain = Promise.resolve();
|
|
3543
|
+
// Pending background observation-mode direct-answer annotations (#518).
|
|
3544
|
+
// Tracks fire-and-forget `annotateDirectAnswerTier` calls so callers (tests,
|
|
3545
|
+
// waitForDirectAnswerObservationIdle) can await settlement.
|
|
3546
|
+
directAnswerObservationChain = Promise.resolve();
|
|
2948
3547
|
// Initialization gate: recall() awaits this before proceeding
|
|
2949
3548
|
initPromise = null;
|
|
2950
3549
|
resolveInit = null;
|
|
@@ -2983,6 +3582,9 @@ var Orchestrator = class _Orchestrator {
|
|
|
2983
3582
|
this.deferredInitAbort = null;
|
|
2984
3583
|
}
|
|
2985
3584
|
}
|
|
3585
|
+
async disposeSearchBackendIfNeeded() {
|
|
3586
|
+
await this.qmd.dispose?.();
|
|
3587
|
+
}
|
|
2986
3588
|
/** Set per-session workspace for the next recall() call (compaction reset). @internal */
|
|
2987
3589
|
setRecallWorkspaceOverride(sessionKey, dir) {
|
|
2988
3590
|
this._recallWorkspaceOverrides.set(sessionKey, dir);
|
|
@@ -2995,10 +3597,96 @@ var Orchestrator = class _Orchestrator {
|
|
|
2995
3597
|
return resolvePrincipal(sessionKey, this.config);
|
|
2996
3598
|
}
|
|
2997
3599
|
resolveSelfNamespace(sessionKey) {
|
|
2998
|
-
|
|
3600
|
+
const base = defaultNamespaceForPrincipal(
|
|
2999
3601
|
this.resolvePrincipal(sessionKey),
|
|
3000
3602
|
this.config
|
|
3001
3603
|
);
|
|
3604
|
+
return this.applyCodingNamespaceOverlay(sessionKey, base);
|
|
3605
|
+
}
|
|
3606
|
+
/**
|
|
3607
|
+
* Attach a coding-agent context to a session (issue #569). Called by the
|
|
3608
|
+
* Claude Code / Codex / Cursor connectors at session start after
|
|
3609
|
+
* `resolveGitContext(cwd)`. The context is consulted by the recall path
|
|
3610
|
+
* and the write path so that memories route to a project- (and optionally
|
|
3611
|
+
* branch-) scoped namespace.
|
|
3612
|
+
*
|
|
3613
|
+
* Pass `null` to clear.
|
|
3614
|
+
*/
|
|
3615
|
+
setCodingContextForSession(sessionKey, codingContext) {
|
|
3616
|
+
if (typeof sessionKey !== "string" || sessionKey.length === 0) return;
|
|
3617
|
+
if (!this._codingContextBySession) {
|
|
3618
|
+
this._codingContextBySession = /* @__PURE__ */ new Map();
|
|
3619
|
+
}
|
|
3620
|
+
if (codingContext === null) {
|
|
3621
|
+
this._codingContextBySession.delete(sessionKey);
|
|
3622
|
+
return;
|
|
3623
|
+
}
|
|
3624
|
+
this._codingContextBySession.set(sessionKey, codingContext);
|
|
3625
|
+
}
|
|
3626
|
+
/**
|
|
3627
|
+
* Read-only accessor for the coding context attached to a session. Returns
|
|
3628
|
+
* `null` when none is set. Used by `remnic doctor` and by tests.
|
|
3629
|
+
*
|
|
3630
|
+
* Defensive `_codingContextBySession` lookup — legacy orchestrator-flush
|
|
3631
|
+
* tests use `Object.create(Orchestrator.prototype)` which does not run
|
|
3632
|
+
* class-field initializers, so the Map may be undefined on stubs.
|
|
3633
|
+
*/
|
|
3634
|
+
getCodingContextForSession(sessionKey) {
|
|
3635
|
+
if (typeof sessionKey !== "string" || sessionKey.length === 0) return null;
|
|
3636
|
+
return this._codingContextBySession?.get(sessionKey) ?? null;
|
|
3637
|
+
}
|
|
3638
|
+
/**
|
|
3639
|
+
* Shared helper used by both the recall path and the write path (rule 42).
|
|
3640
|
+
*
|
|
3641
|
+
* Given a base namespace computed from the principal, returns the overlaid
|
|
3642
|
+
* coding namespace when the session has a coding context AND
|
|
3643
|
+
* `codingMode.projectScope` is true AND `namespacesEnabled` is true.
|
|
3644
|
+
* Otherwise returns `baseNamespace` unchanged — CLAUDE.md #30 escape hatch.
|
|
3645
|
+
*
|
|
3646
|
+
* Principal isolation (CLAUDE.md rule 42): the overlay is COMBINED with
|
|
3647
|
+
* the principal-derived `baseNamespace` rather than replacing it, so two
|
|
3648
|
+
* principals working in the same repository do not share memories through
|
|
3649
|
+
* a common `project-*` namespace.
|
|
3650
|
+
*
|
|
3651
|
+
* Namespaces-disabled gate: when `namespacesEnabled` is false, the
|
|
3652
|
+
* storage router maps every namespace to the same `memoryDir`. Returning
|
|
3653
|
+
* `project-*` in that mode would create apparent route separation with
|
|
3654
|
+
* no actual storage isolation — a false-isolation trap. In that mode we
|
|
3655
|
+
* return `baseNamespace` unchanged so coding mode degrades to the existing
|
|
3656
|
+
* unscoped behavior.
|
|
3657
|
+
*
|
|
3658
|
+
* @internal
|
|
3659
|
+
*/
|
|
3660
|
+
applyCodingNamespaceOverlay(sessionKey, baseNamespace) {
|
|
3661
|
+
if (!this.config.namespacesEnabled) return baseNamespace;
|
|
3662
|
+
const codingContext = this.getCodingContextForSession(sessionKey);
|
|
3663
|
+
const overlay = resolveCodingNamespaceOverlay(codingContext, this.config.codingMode);
|
|
3664
|
+
if (!overlay) return baseNamespace;
|
|
3665
|
+
return combineNamespaces(baseNamespace, overlay.namespace);
|
|
3666
|
+
}
|
|
3667
|
+
/**
|
|
3668
|
+
* Read-side overlay: returns the list of namespaces a session should read
|
|
3669
|
+
* from, including any read fallbacks (branch → project asymmetry lands in
|
|
3670
|
+
* PR 3; PR 2 returns an empty fallbacks list).
|
|
3671
|
+
*
|
|
3672
|
+
* Returns `null` when:
|
|
3673
|
+
* - `namespacesEnabled` is false (overlay would create false isolation)
|
|
3674
|
+
* - no context attached to the session
|
|
3675
|
+
* - `codingMode.projectScope` is false (CLAUDE.md #30 escape hatch)
|
|
3676
|
+
*
|
|
3677
|
+
* The returned `namespace` / `readFallbacks` are RAW overlay fragments
|
|
3678
|
+
* (e.g. `project-origin-ab12`). Callers MUST combine them with the
|
|
3679
|
+
* principal-derived base through `combineNamespaces()` before passing to
|
|
3680
|
+
* storage, so principal isolation is preserved (rule 42).
|
|
3681
|
+
*
|
|
3682
|
+
* @internal
|
|
3683
|
+
*/
|
|
3684
|
+
applyCodingRecallOverlay(sessionKey) {
|
|
3685
|
+
if (!this.config.namespacesEnabled) return null;
|
|
3686
|
+
const codingContext = this.getCodingContextForSession(sessionKey);
|
|
3687
|
+
const overlay = resolveCodingNamespaceOverlay(codingContext, this.config.codingMode);
|
|
3688
|
+
if (!overlay) return null;
|
|
3689
|
+
return { namespace: overlay.namespace, readFallbacks: overlay.readFallbacks };
|
|
3002
3690
|
}
|
|
3003
3691
|
async getStorageForNamespace(namespace) {
|
|
3004
3692
|
const ns = typeof namespace === "string" && namespace.trim().length > 0 ? namespace.trim() : this.config.defaultNamespace;
|
|
@@ -3083,7 +3771,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
3083
3771
|
this.config = config;
|
|
3084
3772
|
this.profiler = new ProfilingCollector({
|
|
3085
3773
|
enabled: config.profilingEnabled,
|
|
3086
|
-
storageDir: config.profilingStorageDir ||
|
|
3774
|
+
storageDir: config.profilingStorageDir || path7.join(config.memoryDir, "profiling"),
|
|
3087
3775
|
maxTraces: config.profilingMaxTraces
|
|
3088
3776
|
});
|
|
3089
3777
|
this.storageRouter = new NamespaceStorageRouter(config);
|
|
@@ -3110,7 +3798,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
3110
3798
|
this.compounding = config.compoundingEnabled ? new CompoundingEngine(config) : void 0;
|
|
3111
3799
|
this.buffer = new SmartBuffer(config, this.storage);
|
|
3112
3800
|
this.transcript = new TranscriptManager(config);
|
|
3113
|
-
this.conversationIndexDir =
|
|
3801
|
+
this.conversationIndexDir = path7.join(
|
|
3114
3802
|
config.memoryDir,
|
|
3115
3803
|
"conversation-index",
|
|
3116
3804
|
"chunks"
|
|
@@ -3134,6 +3822,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
3134
3822
|
this.transcript
|
|
3135
3823
|
);
|
|
3136
3824
|
this.judgeVerdictCache = createVerdictCache();
|
|
3825
|
+
this.judgeDeferCounts = createDeferCountMap();
|
|
3137
3826
|
this.localLlm = new LocalLlmClient(config, this.modelRegistry);
|
|
3138
3827
|
this.localLlm.disableThinking = config.localLlmDisableThinking;
|
|
3139
3828
|
this.fastLlm = config.localLlmFastEnabled ? (() => {
|
|
@@ -3149,7 +3838,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
3149
3838
|
client.disableThinking = true;
|
|
3150
3839
|
return client;
|
|
3151
3840
|
})() : this.localLlm;
|
|
3152
|
-
this.
|
|
3841
|
+
this._fastGatewayLlm = config.modelSource === "gateway" ? new FallbackLlmClient(config.gatewayConfig) : null;
|
|
3153
3842
|
if (config.modelSource === "gateway") {
|
|
3154
3843
|
log.debug(
|
|
3155
3844
|
`orchestrator: gateway model source active` + (config.gatewayAgentId ? ` (primary: ${config.gatewayAgentId})` : "") + (config.fastGatewayAgentId ? ` (fast: ${config.fastGatewayAgentId})` : "")
|
|
@@ -3163,7 +3852,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
3163
3852
|
this.modelRegistry
|
|
3164
3853
|
);
|
|
3165
3854
|
this.threading = new ThreadingManager(
|
|
3166
|
-
|
|
3855
|
+
path7.join(config.memoryDir, "threads"),
|
|
3167
3856
|
config.threadingGapMinutes
|
|
3168
3857
|
);
|
|
3169
3858
|
this.tmtBuilder = new TmtBuilder(config.memoryDir, {
|
|
@@ -3349,9 +4038,9 @@ var Orchestrator = class _Orchestrator {
|
|
|
3349
4038
|
* routes through the gateway chain. Otherwise uses the local fast LLM.
|
|
3350
4039
|
*/
|
|
3351
4040
|
async fastChatCompletion(messages, options) {
|
|
3352
|
-
if (this.
|
|
4041
|
+
if (this._fastGatewayLlm && this.config.modelSource === "gateway") {
|
|
3353
4042
|
const agentId = this.config.fastGatewayAgentId || this.config.gatewayAgentId || void 0;
|
|
3354
|
-
const result2 = await this.
|
|
4043
|
+
const result2 = await this._fastGatewayLlm.chatCompletion(
|
|
3355
4044
|
messages,
|
|
3356
4045
|
{ temperature: options.temperature, maxTokens: options.maxTokens, timeoutMs: options.timeoutMs, agentId }
|
|
3357
4046
|
);
|
|
@@ -3366,7 +4055,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
3366
4055
|
* Otherwise returns the local fast LLM directly.
|
|
3367
4056
|
*/
|
|
3368
4057
|
get fastLlmForRerank() {
|
|
3369
|
-
if (this.
|
|
4058
|
+
if (this._fastGatewayLlm && this.config.modelSource === "gateway") {
|
|
3370
4059
|
return {
|
|
3371
4060
|
chatCompletion: (messages, options) => this.fastChatCompletion(messages, options ?? {})
|
|
3372
4061
|
};
|
|
@@ -3408,7 +4097,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
3408
4097
|
promotionByOutcomeEnabled: this.config.promotionByOutcomeEnabled
|
|
3409
4098
|
});
|
|
3410
4099
|
if (this.config.factDeduplicationEnabled) {
|
|
3411
|
-
const stateDir =
|
|
4100
|
+
const stateDir = path7.join(this.config.memoryDir, "state");
|
|
3412
4101
|
this.contentHashIndex = new ContentHashIndex(stateDir);
|
|
3413
4102
|
await this.contentHashIndex.load();
|
|
3414
4103
|
log.info(
|
|
@@ -3437,7 +4126,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
3437
4126
|
const files = await readdir3(wsDir).catch(() => []);
|
|
3438
4127
|
for (const f of files) {
|
|
3439
4128
|
if (!f.startsWith(".compaction-reset-signal-")) continue;
|
|
3440
|
-
const fp =
|
|
4129
|
+
const fp = path7.join(wsDir, f);
|
|
3441
4130
|
const s = await stat3(fp).catch(() => null);
|
|
3442
4131
|
if (s && Date.now() - s.mtimeMs >= COMPACTION_SIGNAL_MAX_AGE_MS) {
|
|
3443
4132
|
await unlink2(fp).catch(() => {
|
|
@@ -3466,6 +4155,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
3466
4155
|
(entry) => entry.namespace === this.config.defaultNamespace
|
|
3467
4156
|
)?.state ?? "unknown";
|
|
3468
4157
|
if (defaultState === "missing") {
|
|
4158
|
+
await this.disposeSearchBackendIfNeeded();
|
|
3469
4159
|
this.qmd = new NoopSearchBackend();
|
|
3470
4160
|
log.warn(
|
|
3471
4161
|
"Search collection missing for Remnic memory store; disabling search retrieval for this runtime (fallback retrieval remains enabled)"
|
|
@@ -3526,10 +4216,11 @@ var Orchestrator = class _Orchestrator {
|
|
|
3526
4216
|
log.info("QMD startup sync: updating index to match current disk state");
|
|
3527
4217
|
if (this.config.namespacesEnabled) {
|
|
3528
4218
|
await this.namespaceSearchRouter.updateNamespaces(
|
|
3529
|
-
this.configuredNamespaces()
|
|
4219
|
+
this.configuredNamespaces(),
|
|
4220
|
+
{ signal }
|
|
3530
4221
|
);
|
|
3531
4222
|
} else {
|
|
3532
|
-
await this.qmd.update();
|
|
4223
|
+
await this.qmd.update({ signal });
|
|
3533
4224
|
}
|
|
3534
4225
|
log.info("QMD startup sync: complete");
|
|
3535
4226
|
this.deferredSyncSucceeded = true;
|
|
@@ -3546,7 +4237,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
3546
4237
|
const warmupNs = this.config.defaultNamespace;
|
|
3547
4238
|
log.info("QMD warmup: pre-loading models with a test search");
|
|
3548
4239
|
warmupPromises.push(
|
|
3549
|
-
this.qmd.search("warmup", warmupNs, 1).then(() => {
|
|
4240
|
+
this.qmd.search("warmup", warmupNs, 1, void 0, { signal }).then(() => {
|
|
3550
4241
|
log.info("QMD warmup: complete");
|
|
3551
4242
|
}).catch((err) => {
|
|
3552
4243
|
log.debug(`QMD warmup search failed (non-fatal): ${err}`);
|
|
@@ -3686,6 +4377,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
3686
4377
|
if ("available" in this.qmd) {
|
|
3687
4378
|
this.qmd.available = false;
|
|
3688
4379
|
}
|
|
4380
|
+
await this.disposeSearchBackendIfNeeded();
|
|
3689
4381
|
this.qmd = new NoopSearchBackend();
|
|
3690
4382
|
log.warn("startupSearchSync: search collection missing; disabling search (fallback retrieval remains enabled)");
|
|
3691
4383
|
return false;
|
|
@@ -3700,9 +4392,12 @@ var Orchestrator = class _Orchestrator {
|
|
|
3700
4392
|
log.info("startupSearchSync: updating index to match current disk state");
|
|
3701
4393
|
let namespacesUpdated = 0;
|
|
3702
4394
|
if (this.config.namespacesEnabled) {
|
|
3703
|
-
namespacesUpdated = await this.namespaceSearchRouter.updateNamespaces(
|
|
4395
|
+
namespacesUpdated = await this.namespaceSearchRouter.updateNamespaces(
|
|
4396
|
+
namespaces,
|
|
4397
|
+
{ signal }
|
|
4398
|
+
);
|
|
3704
4399
|
} else {
|
|
3705
|
-
await this.qmd.update(signal);
|
|
4400
|
+
await this.qmd.update({ signal });
|
|
3706
4401
|
}
|
|
3707
4402
|
if (signal?.aborted) {
|
|
3708
4403
|
log.debug("startupSearchSync: aborted after update");
|
|
@@ -3746,7 +4441,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
3746
4441
|
*/
|
|
3747
4442
|
async autoRegisterDaySummaryCron() {
|
|
3748
4443
|
const home = resolveHomeDir();
|
|
3749
|
-
const jobsPath =
|
|
4444
|
+
const jobsPath = path7.join(home, ".openclaw", "cron", "jobs.json");
|
|
3750
4445
|
try {
|
|
3751
4446
|
if (!existsSync2(jobsPath)) {
|
|
3752
4447
|
log.debug(
|
|
@@ -3769,8 +4464,8 @@ var Orchestrator = class _Orchestrator {
|
|
|
3769
4464
|
}
|
|
3770
4465
|
}
|
|
3771
4466
|
async autoRegisterNightlyGovernanceCron() {
|
|
3772
|
-
const home =
|
|
3773
|
-
const jobsPath =
|
|
4467
|
+
const home = resolveHomeDir();
|
|
4468
|
+
const jobsPath = path7.join(home, ".openclaw", "cron", "jobs.json");
|
|
3774
4469
|
try {
|
|
3775
4470
|
if (!existsSync2(jobsPath)) {
|
|
3776
4471
|
log.debug("nightly governance cron: jobs.json not found, skipping auto-register");
|
|
@@ -3792,7 +4487,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
3792
4487
|
}
|
|
3793
4488
|
async autoRegisterProceduralMiningCron() {
|
|
3794
4489
|
const home = resolveHomeDir();
|
|
3795
|
-
const jobsPath =
|
|
4490
|
+
const jobsPath = path7.join(home, ".openclaw", "cron", "jobs.json");
|
|
3796
4491
|
try {
|
|
3797
4492
|
if (!existsSync2(jobsPath)) {
|
|
3798
4493
|
log.debug("procedural mining cron: jobs.json not found, skipping auto-register");
|
|
@@ -3812,7 +4507,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
3812
4507
|
}
|
|
3813
4508
|
async autoRegisterContradictionScanCron() {
|
|
3814
4509
|
const home = resolveHomeDir();
|
|
3815
|
-
const jobsPath =
|
|
4510
|
+
const jobsPath = path7.join(home, ".openclaw", "cron", "jobs.json");
|
|
3816
4511
|
try {
|
|
3817
4512
|
if (!existsSync2(jobsPath)) {
|
|
3818
4513
|
log.debug("contradiction scan cron: jobs.json not found, skipping auto-register");
|
|
@@ -3848,15 +4543,15 @@ var Orchestrator = class _Orchestrator {
|
|
|
3848
4543
|
this.lastFileHygieneRunAtMs = now;
|
|
3849
4544
|
if (hygiene.rotateEnabled) {
|
|
3850
4545
|
for (const rel of hygiene.rotatePaths) {
|
|
3851
|
-
const abs =
|
|
4546
|
+
const abs = path7.isAbsolute(rel) ? rel : path7.join(this.config.workspaceDir, rel);
|
|
3852
4547
|
try {
|
|
3853
|
-
const raw = await
|
|
4548
|
+
const raw = await readFile4(abs, "utf-8");
|
|
3854
4549
|
if (raw.length > hygiene.rotateMaxBytes) {
|
|
3855
|
-
const archiveDir =
|
|
4550
|
+
const archiveDir = path7.join(
|
|
3856
4551
|
this.config.workspaceDir,
|
|
3857
4552
|
hygiene.archiveDir
|
|
3858
4553
|
);
|
|
3859
|
-
const base =
|
|
4554
|
+
const base = path7.basename(abs);
|
|
3860
4555
|
const prefix = base.toUpperCase().replace(/\.MD$/i, "").replace(/[^A-Z0-9]+/g, "-") || "FILE";
|
|
3861
4556
|
const { newContent } = await rotateMarkdownFileToArchive({
|
|
3862
4557
|
filePath: abs,
|
|
@@ -3864,7 +4559,7 @@ var Orchestrator = class _Orchestrator {
|
|
|
3864
4559
|
archivePrefix: prefix,
|
|
3865
4560
|
keepTailChars: hygiene.rotateKeepTailChars
|
|
3866
4561
|
});
|
|
3867
|
-
await
|
|
4562
|
+
await writeFile4(abs, newContent, "utf-8");
|
|
3868
4563
|
}
|
|
3869
4564
|
} catch {
|
|
3870
4565
|
}
|
|
@@ -3881,8 +4576,8 @@ var Orchestrator = class _Orchestrator {
|
|
|
3881
4576
|
log.warn(w.message);
|
|
3882
4577
|
}
|
|
3883
4578
|
if (hygiene.warningsLogEnabled && warnings.length > 0) {
|
|
3884
|
-
const fp =
|
|
3885
|
-
await
|
|
4579
|
+
const fp = path7.join(this.config.memoryDir, hygiene.warningsLogPath);
|
|
4580
|
+
await mkdir5(path7.dirname(fp), { recursive: true });
|
|
3886
4581
|
const stamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
3887
4582
|
const block = `
|
|
3888
4583
|
|
|
@@ -3891,11 +4586,11 @@ var Orchestrator = class _Orchestrator {
|
|
|
3891
4586
|
` + warnings.map((w) => `- ${w.message}`).join("\n") + "\n";
|
|
3892
4587
|
let existing = "";
|
|
3893
4588
|
try {
|
|
3894
|
-
existing = await
|
|
4589
|
+
existing = await readFile4(fp, "utf-8");
|
|
3895
4590
|
} catch {
|
|
3896
4591
|
existing = "# Engram File Hygiene Warnings\n";
|
|
3897
4592
|
}
|
|
3898
|
-
await
|
|
4593
|
+
await writeFile4(fp, existing + block, "utf-8");
|
|
3899
4594
|
}
|
|
3900
4595
|
}
|
|
3901
4596
|
}
|
|
@@ -3979,14 +4674,15 @@ var Orchestrator = class _Orchestrator {
|
|
|
3979
4674
|
}
|
|
3980
4675
|
for (const cluster of clusters) {
|
|
3981
4676
|
try {
|
|
3982
|
-
|
|
4677
|
+
const operatorAwareEnabled = this.config.operatorAwareConsolidationEnabled === true;
|
|
4678
|
+
let prompt = operatorAwareEnabled ? buildOperatorAwareConsolidationPrompt(cluster) : buildConsolidationPrompt(cluster);
|
|
3983
4679
|
if (extensionsBlock.length > 0) {
|
|
3984
4680
|
prompt += "\n\n" + extensionsBlock;
|
|
3985
4681
|
}
|
|
3986
4682
|
const messages = [
|
|
3987
4683
|
{
|
|
3988
4684
|
role: "system",
|
|
3989
|
-
content: "You are a memory consolidation system. Output only the consolidated memory text."
|
|
4685
|
+
content: operatorAwareEnabled ? 'You are a memory consolidation system. Return ONLY a JSON object with two keys, "operator" and "output". The "operator" value MUST be one of the exact strings "merge", "update", or "split" \u2014 never a pipe-separated placeholder, never prose. The "output" value is the canonical memory text.' : "You are a memory consolidation system. Output only the consolidated memory text."
|
|
3990
4686
|
},
|
|
3991
4687
|
{ role: "user", content: prompt }
|
|
3992
4688
|
];
|
|
@@ -4012,13 +4708,31 @@ var Orchestrator = class _Orchestrator {
|
|
|
4012
4708
|
result.errors++;
|
|
4013
4709
|
continue;
|
|
4014
4710
|
}
|
|
4015
|
-
|
|
4711
|
+
let canonicalContent;
|
|
4712
|
+
let operator;
|
|
4713
|
+
if (operatorAwareEnabled) {
|
|
4714
|
+
const parsed = parseOperatorAwareConsolidationResponse(
|
|
4715
|
+
response.content,
|
|
4716
|
+
cluster
|
|
4717
|
+
);
|
|
4718
|
+
canonicalContent = parsed.output;
|
|
4719
|
+
operator = parsed.operator;
|
|
4720
|
+
} else {
|
|
4721
|
+
canonicalContent = parseConsolidationResponse(response.content);
|
|
4722
|
+
operator = chooseConsolidationOperator(cluster);
|
|
4723
|
+
}
|
|
4016
4724
|
cluster.canonicalContent = canonicalContent;
|
|
4017
4725
|
const sorted = [...cluster.memories].sort(
|
|
4018
4726
|
(a, b) => new Date(b.frontmatter.created).getTime() - new Date(a.frontmatter.created).getTime()
|
|
4019
4727
|
);
|
|
4020
4728
|
const newest = sorted[0];
|
|
4021
4729
|
const lineageIds = cluster.memories.map((m) => m.frontmatter.id);
|
|
4730
|
+
const derivedFromEntries = [];
|
|
4731
|
+
for (const m of cluster.memories) {
|
|
4732
|
+
if (!m.path) continue;
|
|
4733
|
+
const entry = await this.storage.snapshotForProvenance(m.path);
|
|
4734
|
+
if (entry) derivedFromEntries.push(entry);
|
|
4735
|
+
}
|
|
4022
4736
|
const canonicalId = await this.storage.writeMemory(
|
|
4023
4737
|
newest.frontmatter.category,
|
|
4024
4738
|
canonicalContent,
|
|
@@ -4031,7 +4745,9 @@ var Orchestrator = class _Orchestrator {
|
|
|
4031
4745
|
)
|
|
4032
4746
|
],
|
|
4033
4747
|
source: "semantic-consolidation",
|
|
4034
|
-
lineage: lineageIds
|
|
4748
|
+
lineage: lineageIds,
|
|
4749
|
+
derivedFrom: derivedFromEntries.length > 0 ? derivedFromEntries : void 0,
|
|
4750
|
+
derivedVia: operator
|
|
4035
4751
|
}
|
|
4036
4752
|
);
|
|
4037
4753
|
result.memoriesConsolidated++;
|
|
@@ -4273,18 +4989,18 @@ ${evidenceText}`
|
|
|
4273
4989
|
const datesToScan = [yesterday, utcToday].filter(
|
|
4274
4990
|
(v, i, a) => a.indexOf(v) === i
|
|
4275
4991
|
);
|
|
4276
|
-
const factsBaseDir =
|
|
4992
|
+
const factsBaseDir = path7.join(storage.dir, "facts");
|
|
4277
4993
|
const MAX_CHARS = 1e5;
|
|
4278
4994
|
const facts = [];
|
|
4279
4995
|
for (const date of datesToScan) {
|
|
4280
|
-
const factsDir =
|
|
4996
|
+
const factsDir = path7.join(factsBaseDir, date);
|
|
4281
4997
|
try {
|
|
4282
4998
|
const entries = await readdir3(factsDir, { withFileTypes: true });
|
|
4283
4999
|
for (const entry of entries) {
|
|
4284
5000
|
if (!entry.name.endsWith(".md")) continue;
|
|
4285
|
-
const fullPath =
|
|
5001
|
+
const fullPath = path7.join(factsDir, entry.name);
|
|
4286
5002
|
try {
|
|
4287
|
-
const raw = await
|
|
5003
|
+
const raw = await readFile4(fullPath, "utf-8");
|
|
4288
5004
|
const fmMatch = raw.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
|
|
4289
5005
|
if (!fmMatch) continue;
|
|
4290
5006
|
const fmBlock = fmMatch[1];
|
|
@@ -4298,7 +5014,7 @@ ${evidenceText}`
|
|
|
4298
5014
|
facts.push({
|
|
4299
5015
|
path: fullPath,
|
|
4300
5016
|
frontmatter: {
|
|
4301
|
-
id: fm.id ||
|
|
5017
|
+
id: fm.id || path7.basename(entry.name, ".md"),
|
|
4302
5018
|
category: fm.category || "fact",
|
|
4303
5019
|
created: fm.created || "unknown",
|
|
4304
5020
|
updated: fm.updated || fm.created || "unknown",
|
|
@@ -4319,15 +5035,15 @@ ${evidenceText}`
|
|
|
4319
5035
|
(a, b) => a.frontmatter.created < b.frontmatter.created ? -1 : 1
|
|
4320
5036
|
);
|
|
4321
5037
|
const hourlySummaries = [];
|
|
4322
|
-
const hourlyBaseDir =
|
|
5038
|
+
const hourlyBaseDir = path7.join(storage.dir, "summaries", "hourly");
|
|
4323
5039
|
try {
|
|
4324
5040
|
const sessionKeys = await readdir3(hourlyBaseDir, { withFileTypes: true });
|
|
4325
5041
|
for (const sk of sessionKeys) {
|
|
4326
5042
|
if (!sk.isDirectory()) continue;
|
|
4327
5043
|
for (const date of datesToScan) {
|
|
4328
|
-
const summaryFile =
|
|
5044
|
+
const summaryFile = path7.join(hourlyBaseDir, sk.name, `${date}.md`);
|
|
4329
5045
|
try {
|
|
4330
|
-
const raw = await
|
|
5046
|
+
const raw = await readFile4(summaryFile, "utf-8");
|
|
4331
5047
|
if (raw.trim().length > 0) {
|
|
4332
5048
|
hourlySummaries.push(raw.trim());
|
|
4333
5049
|
}
|
|
@@ -4423,13 +5139,13 @@ ${evidenceText}`
|
|
|
4423
5139
|
}
|
|
4424
5140
|
async getLastGraphRecallSnapshot(namespace) {
|
|
4425
5141
|
const storage = await this.getStorage(namespace);
|
|
4426
|
-
const snapshotPath =
|
|
5142
|
+
const snapshotPath = path7.join(
|
|
4427
5143
|
storage.dir,
|
|
4428
5144
|
"state",
|
|
4429
5145
|
"last_graph_recall.json"
|
|
4430
5146
|
);
|
|
4431
5147
|
try {
|
|
4432
|
-
const raw = await
|
|
5148
|
+
const raw = await readFile4(snapshotPath, "utf-8");
|
|
4433
5149
|
const parsed = JSON.parse(raw);
|
|
4434
5150
|
if (!parsed || typeof parsed !== "object") return null;
|
|
4435
5151
|
return {
|
|
@@ -4462,9 +5178,9 @@ ${evidenceText}`
|
|
|
4462
5178
|
}
|
|
4463
5179
|
async getLastIntentSnapshot(namespace) {
|
|
4464
5180
|
const storage = await this.getStorage(namespace);
|
|
4465
|
-
const snapshotPath =
|
|
5181
|
+
const snapshotPath = path7.join(storage.dir, "state", "last_intent.json");
|
|
4466
5182
|
try {
|
|
4467
|
-
const raw = await
|
|
5183
|
+
const raw = await readFile4(snapshotPath, "utf-8");
|
|
4468
5184
|
const parsed = JSON.parse(raw);
|
|
4469
5185
|
if (!parsed || typeof parsed !== "object") return null;
|
|
4470
5186
|
const graphDecision = parsed.graphDecision && typeof parsed.graphDecision === "object" ? parsed.graphDecision : void 0;
|
|
@@ -4495,13 +5211,13 @@ ${evidenceText}`
|
|
|
4495
5211
|
}
|
|
4496
5212
|
async getLastQmdRecallSnapshot(namespace) {
|
|
4497
5213
|
const storage = await this.getStorage(namespace);
|
|
4498
|
-
const snapshotPath =
|
|
5214
|
+
const snapshotPath = path7.join(
|
|
4499
5215
|
storage.dir,
|
|
4500
5216
|
"state",
|
|
4501
5217
|
"last_qmd_recall.json"
|
|
4502
5218
|
);
|
|
4503
5219
|
try {
|
|
4504
|
-
const raw = await
|
|
5220
|
+
const raw = await readFile4(snapshotPath, "utf-8");
|
|
4505
5221
|
const parsed = JSON.parse(raw);
|
|
4506
5222
|
if (!parsed || typeof parsed !== "object") return null;
|
|
4507
5223
|
return {
|
|
@@ -4647,7 +5363,7 @@ ${r.snippet.trim()}
|
|
|
4647
5363
|
const entries = await readdir3(dir, { withFileTypes: true });
|
|
4648
5364
|
let total = 0;
|
|
4649
5365
|
for (const entry of entries) {
|
|
4650
|
-
const fullPath =
|
|
5366
|
+
const fullPath = path7.join(dir, entry.name);
|
|
4651
5367
|
if (entry.isDirectory()) {
|
|
4652
5368
|
total += await this.countConversationChunkDocs(fullPath);
|
|
4653
5369
|
continue;
|
|
@@ -4918,11 +5634,24 @@ ${r.snippet.trim()}
|
|
|
4918
5634
|
reject(new Error("recall timeout"));
|
|
4919
5635
|
}, RECALL_TIMEOUT_MS);
|
|
4920
5636
|
});
|
|
5637
|
+
let recallResult;
|
|
4921
5638
|
try {
|
|
4922
|
-
|
|
5639
|
+
recallResult = await Promise.race([recallPromise, timeoutPromise]);
|
|
4923
5640
|
} finally {
|
|
4924
5641
|
if (timeoutHandle) clearTimeout(timeoutHandle);
|
|
4925
5642
|
}
|
|
5643
|
+
if (this.config.recallDirectAnswerEnabled && sessionKey) {
|
|
5644
|
+
try {
|
|
5645
|
+
this.enqueueDirectAnswerObservation(
|
|
5646
|
+
prompt,
|
|
5647
|
+
sessionKey,
|
|
5648
|
+
options.namespace?.trim() || void 0
|
|
5649
|
+
);
|
|
5650
|
+
} catch (err) {
|
|
5651
|
+
log.debug(`direct-answer observation setup failed: ${err}`);
|
|
5652
|
+
}
|
|
5653
|
+
}
|
|
5654
|
+
return recallResult;
|
|
4926
5655
|
} catch (err) {
|
|
4927
5656
|
this.logRecallFailure(err);
|
|
4928
5657
|
this.profiler.endTrace();
|
|
@@ -4931,6 +5660,183 @@ ${r.snippet.trim()}
|
|
|
4931
5660
|
options.abortSignal?.removeEventListener("abort", onAbort);
|
|
4932
5661
|
}
|
|
4933
5662
|
}
|
|
5663
|
+
/**
|
|
5664
|
+
* Return the most recent X-ray snapshot captured during a
|
|
5665
|
+
* `recall()` call that passed `xrayCapture: true` (issue #570 PR 1).
|
|
5666
|
+
* Returns `null` when no such capture has occurred on this
|
|
5667
|
+
* orchestrator instance. Returned snapshot is a deep copy so
|
|
5668
|
+
* caller mutation cannot tear the stored value.
|
|
5669
|
+
*/
|
|
5670
|
+
getLastXraySnapshot() {
|
|
5671
|
+
if (!this.lastXraySnapshot) return null;
|
|
5672
|
+
return structuredClone(this.lastXraySnapshot);
|
|
5673
|
+
}
|
|
5674
|
+
/** Clear the captured X-ray snapshot. Exposed for tests / explicit reset. */
|
|
5675
|
+
clearLastXraySnapshot() {
|
|
5676
|
+
this.lastXraySnapshot = null;
|
|
5677
|
+
}
|
|
5678
|
+
/**
|
|
5679
|
+
* Await the in-flight observation-mode direct-answer annotation chain.
|
|
5680
|
+
* Resolves to true when settled, false on timeout.
|
|
5681
|
+
*/
|
|
5682
|
+
async waitForDirectAnswerObservationIdle(timeoutMs = 6e4) {
|
|
5683
|
+
let timeoutHandle = null;
|
|
5684
|
+
try {
|
|
5685
|
+
const timeoutPromise = new Promise((resolve) => {
|
|
5686
|
+
timeoutHandle = setTimeout(() => resolve("timeout"), timeoutMs);
|
|
5687
|
+
});
|
|
5688
|
+
const result = await Promise.race([
|
|
5689
|
+
this.directAnswerObservationChain.then(() => "ok"),
|
|
5690
|
+
timeoutPromise
|
|
5691
|
+
]);
|
|
5692
|
+
if (result === "timeout") {
|
|
5693
|
+
log.warn(
|
|
5694
|
+
`waitForDirectAnswerObservationIdle timed out after ${timeoutMs}ms`
|
|
5695
|
+
);
|
|
5696
|
+
return false;
|
|
5697
|
+
}
|
|
5698
|
+
return true;
|
|
5699
|
+
} finally {
|
|
5700
|
+
if (timeoutHandle) clearTimeout(timeoutHandle);
|
|
5701
|
+
}
|
|
5702
|
+
}
|
|
5703
|
+
enqueueDirectAnswerObservation(prompt, sessionKey, namespaceOverride) {
|
|
5704
|
+
const expectedSnapshot = this.lastRecall.get(sessionKey);
|
|
5705
|
+
if (expectedSnapshot === null) return;
|
|
5706
|
+
if (expectedSnapshot.plannerMode === "no_recall") return;
|
|
5707
|
+
const principal = resolvePrincipal(sessionKey, this.config);
|
|
5708
|
+
const observationCodingOverlay = namespaceOverride && canReadNamespace(principal, namespaceOverride, this.config) ? null : this.applyCodingRecallOverlay(sessionKey);
|
|
5709
|
+
const observationPrincipalSelf = defaultNamespaceForPrincipal(principal, this.config);
|
|
5710
|
+
const observationCodingSelf = observationCodingOverlay ? combineNamespaces(observationPrincipalSelf, observationCodingOverlay.namespace) : null;
|
|
5711
|
+
let observationNamespaces;
|
|
5712
|
+
if (namespaceOverride && canReadNamespace(principal, namespaceOverride, this.config)) {
|
|
5713
|
+
observationNamespaces = [namespaceOverride];
|
|
5714
|
+
} else if (observationCodingOverlay && observationCodingSelf) {
|
|
5715
|
+
const base = recallNamespacesForPrincipal(principal, this.config);
|
|
5716
|
+
const mapped = base.map(
|
|
5717
|
+
(ns) => ns === observationPrincipalSelf ? observationCodingSelf : ns
|
|
5718
|
+
);
|
|
5719
|
+
const fallbackNs = observationCodingOverlay.readFallbacks.map(
|
|
5720
|
+
(fallback) => combineNamespaces(observationPrincipalSelf, fallback)
|
|
5721
|
+
);
|
|
5722
|
+
observationNamespaces = Array.from(/* @__PURE__ */ new Set([...mapped, ...fallbackNs]));
|
|
5723
|
+
} else {
|
|
5724
|
+
observationNamespaces = recallNamespacesForPrincipal(principal, this.config);
|
|
5725
|
+
}
|
|
5726
|
+
const observationQueryPolicy = buildRecallQueryPolicy(prompt, sessionKey, {
|
|
5727
|
+
cronRecallPolicyEnabled: this.config.cronRecallPolicyEnabled,
|
|
5728
|
+
cronRecallNormalizedQueryMaxChars: this.config.cronRecallNormalizedQueryMaxChars,
|
|
5729
|
+
cronRecallInstructionHeavyTokenCap: this.effectiveCronRecallInstructionHeavyTokenCap(),
|
|
5730
|
+
cronConversationRecallMode: this.config.cronConversationRecallMode
|
|
5731
|
+
});
|
|
5732
|
+
const observationQuery = observationQueryPolicy.retrievalQuery || prompt;
|
|
5733
|
+
const expectedIdentity = {
|
|
5734
|
+
writeNonce: expectedSnapshot.writeNonce,
|
|
5735
|
+
traceId: expectedSnapshot.traceId,
|
|
5736
|
+
recordedAt: expectedSnapshot.recordedAt
|
|
5737
|
+
};
|
|
5738
|
+
const previous = this.directAnswerObservationChain;
|
|
5739
|
+
this.directAnswerObservationChain = previous.catch(() => void 0).then(async () => {
|
|
5740
|
+
try {
|
|
5741
|
+
await this.annotateDirectAnswerTier(
|
|
5742
|
+
observationQuery,
|
|
5743
|
+
sessionKey,
|
|
5744
|
+
observationNamespaces,
|
|
5745
|
+
expectedIdentity,
|
|
5746
|
+
void 0
|
|
5747
|
+
);
|
|
5748
|
+
} catch (err) {
|
|
5749
|
+
log.debug(`direct-answer observation chain error: ${err}`);
|
|
5750
|
+
}
|
|
5751
|
+
});
|
|
5752
|
+
}
|
|
5753
|
+
async annotateDirectAnswerTier(prompt, sessionKey, namespaces, expectedIdentity, _parentAbortSignal) {
|
|
5754
|
+
const tierStart = Date.now();
|
|
5755
|
+
try {
|
|
5756
|
+
if (namespaces.length === 0) return;
|
|
5757
|
+
const trustZoneByNsAndRecordId = /* @__PURE__ */ new Map();
|
|
5758
|
+
const trustZoneKey = (ns, recordId) => `${ns}\0${recordId}`;
|
|
5759
|
+
const scopedStorages = /* @__PURE__ */ new Map();
|
|
5760
|
+
for (const ns of namespaces) {
|
|
5761
|
+
const storage = await this.storageRouter.storageFor(ns);
|
|
5762
|
+
scopedStorages.set(ns, storage);
|
|
5763
|
+
const trustZones = await listTrustZoneRecords({
|
|
5764
|
+
memoryDir: storage.dir,
|
|
5765
|
+
trustZoneStoreDir: this.config.trustZoneStoreDir,
|
|
5766
|
+
limit: 200
|
|
5767
|
+
}).catch(() => ({
|
|
5768
|
+
allRecords: []
|
|
5769
|
+
}));
|
|
5770
|
+
for (const record of trustZones.allRecords ?? []) {
|
|
5771
|
+
trustZoneByNsAndRecordId.set(
|
|
5772
|
+
trustZoneKey(ns, record.recordId),
|
|
5773
|
+
record.zone
|
|
5774
|
+
);
|
|
5775
|
+
}
|
|
5776
|
+
}
|
|
5777
|
+
const memoryNamespaceByPath = /* @__PURE__ */ new Map();
|
|
5778
|
+
const memoryNamespaceById = /* @__PURE__ */ new Map();
|
|
5779
|
+
let candidatesConsidered = 0;
|
|
5780
|
+
const sources = {
|
|
5781
|
+
taxonomy: DEFAULT_TAXONOMY,
|
|
5782
|
+
listCandidateMemories: async (options) => {
|
|
5783
|
+
const targetNs = options.namespace;
|
|
5784
|
+
const storage = scopedStorages.get(targetNs) ?? await this.storageRouter.storageFor(targetNs);
|
|
5785
|
+
const all = await storage.readAllMemories();
|
|
5786
|
+
const active = [];
|
|
5787
|
+
for (const m of all) {
|
|
5788
|
+
if ((m.frontmatter.status ?? "active") === "active") {
|
|
5789
|
+
active.push(m);
|
|
5790
|
+
memoryNamespaceByPath.set(m.path, targetNs);
|
|
5791
|
+
if (m.frontmatter.id) {
|
|
5792
|
+
memoryNamespaceById.set(m.frontmatter.id, targetNs);
|
|
5793
|
+
}
|
|
5794
|
+
}
|
|
5795
|
+
}
|
|
5796
|
+
candidatesConsidered += active.length;
|
|
5797
|
+
return active;
|
|
5798
|
+
},
|
|
5799
|
+
trustZoneFor: async (memoryId) => {
|
|
5800
|
+
const ns = memoryNamespaceById.get(memoryId);
|
|
5801
|
+
if (!ns) return null;
|
|
5802
|
+
return trustZoneByNsAndRecordId.get(
|
|
5803
|
+
trustZoneKey(ns, memoryId)
|
|
5804
|
+
) ?? null;
|
|
5805
|
+
},
|
|
5806
|
+
importanceFor: (memory) => typeof memory.frontmatter.importance?.score === "number" ? memory.frontmatter.importance.score : 0
|
|
5807
|
+
};
|
|
5808
|
+
let result;
|
|
5809
|
+
for (const ns of namespaces) {
|
|
5810
|
+
const r = await tryDirectAnswer({
|
|
5811
|
+
query: prompt,
|
|
5812
|
+
namespace: ns,
|
|
5813
|
+
config: this.config,
|
|
5814
|
+
sources
|
|
5815
|
+
});
|
|
5816
|
+
if (r.eligible && r.winner) {
|
|
5817
|
+
result = r;
|
|
5818
|
+
break;
|
|
5819
|
+
}
|
|
5820
|
+
}
|
|
5821
|
+
if (!result?.eligible || !result?.winner) return;
|
|
5822
|
+
const explain = {
|
|
5823
|
+
tier: "direct-answer",
|
|
5824
|
+
tierReason: result.narrative,
|
|
5825
|
+
filteredBy: result.filteredBy,
|
|
5826
|
+
candidatesConsidered,
|
|
5827
|
+
latencyMs: Date.now() - tierStart,
|
|
5828
|
+
sourceAnchors: [{ path: result.winner.memory.path }]
|
|
5829
|
+
};
|
|
5830
|
+
await this.lastRecall.annotateTierExplain(
|
|
5831
|
+
sessionKey,
|
|
5832
|
+
explain,
|
|
5833
|
+
expectedIdentity
|
|
5834
|
+
);
|
|
5835
|
+
} catch (err) {
|
|
5836
|
+
if (err instanceof Error && err.name === "AbortError") return;
|
|
5837
|
+
log.debug(`direct-answer observation failed: ${err}`);
|
|
5838
|
+
}
|
|
5839
|
+
}
|
|
4934
5840
|
logRecallFailure(err) {
|
|
4935
5841
|
const now = Date.now();
|
|
4936
5842
|
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
@@ -5334,7 +6240,7 @@ ${r.snippet.trim()}
|
|
|
5334
6240
|
0
|
|
5335
6241
|
);
|
|
5336
6242
|
seedPaths.push(
|
|
5337
|
-
...seedRelativePaths.map((rel) =>
|
|
6243
|
+
...seedRelativePaths.map((rel) => path7.join(storage.dir, rel))
|
|
5338
6244
|
);
|
|
5339
6245
|
const seedSet = new Set(seedRelativePaths);
|
|
5340
6246
|
const expanded = await this.graphIndexFor(storage).spreadingActivation(
|
|
@@ -5344,7 +6250,7 @@ ${r.snippet.trim()}
|
|
|
5344
6250
|
if (expanded.length === 0) continue;
|
|
5345
6251
|
for (const candidate of expanded.slice(0, perNamespaceExpandedCap)) {
|
|
5346
6252
|
if (seedSet.has(candidate.path)) continue;
|
|
5347
|
-
const memoryPath =
|
|
6253
|
+
const memoryPath = path7.resolve(storage.dir, candidate.path);
|
|
5348
6254
|
const memory = await storage.readMemoryByPath(memoryPath);
|
|
5349
6255
|
if (!memory) continue;
|
|
5350
6256
|
if (isArtifactMemoryPath(memory.path)) continue;
|
|
@@ -5368,7 +6274,7 @@ ${r.snippet.trim()}
|
|
|
5368
6274
|
path: memory.path,
|
|
5369
6275
|
score,
|
|
5370
6276
|
namespace,
|
|
5371
|
-
seed:
|
|
6277
|
+
seed: path7.resolve(storage.dir, candidate.seed),
|
|
5372
6278
|
hopDepth: candidate.hopDepth,
|
|
5373
6279
|
decayedWeight: candidate.decayedWeight,
|
|
5374
6280
|
graphType: candidate.graphType
|
|
@@ -5384,12 +6290,12 @@ ${r.snippet.trim()}
|
|
|
5384
6290
|
}
|
|
5385
6291
|
async recordLastGraphRecallSnapshot(options) {
|
|
5386
6292
|
try {
|
|
5387
|
-
const snapshotPath =
|
|
6293
|
+
const snapshotPath = path7.join(
|
|
5388
6294
|
options.storage.dir,
|
|
5389
6295
|
"state",
|
|
5390
6296
|
"last_graph_recall.json"
|
|
5391
6297
|
);
|
|
5392
|
-
await
|
|
6298
|
+
await mkdir5(path7.dirname(snapshotPath), { recursive: true });
|
|
5393
6299
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
5394
6300
|
const totalSeedCount = options.seedPaths.length;
|
|
5395
6301
|
const totalExpandedCount = options.expandedPaths.length;
|
|
@@ -5416,20 +6322,20 @@ ${r.snippet.trim()}
|
|
|
5416
6322
|
finalResults: (options.finalResults ?? []).slice(0, 64),
|
|
5417
6323
|
shadowComparison: options.shadowComparison
|
|
5418
6324
|
};
|
|
5419
|
-
await
|
|
6325
|
+
await writeFile4(snapshotPath, JSON.stringify(payload, null, 2), "utf-8");
|
|
5420
6326
|
} catch (err) {
|
|
5421
6327
|
log.debug(`last graph recall write failed: ${err}`);
|
|
5422
6328
|
}
|
|
5423
6329
|
}
|
|
5424
6330
|
async recordLastIntentSnapshot(options) {
|
|
5425
6331
|
try {
|
|
5426
|
-
const snapshotPath =
|
|
6332
|
+
const snapshotPath = path7.join(
|
|
5427
6333
|
options.storage.dir,
|
|
5428
6334
|
"state",
|
|
5429
6335
|
"last_intent.json"
|
|
5430
6336
|
);
|
|
5431
|
-
await
|
|
5432
|
-
await
|
|
6337
|
+
await mkdir5(path7.dirname(snapshotPath), { recursive: true });
|
|
6338
|
+
await writeFile4(
|
|
5433
6339
|
snapshotPath,
|
|
5434
6340
|
JSON.stringify(options.snapshot, null, 2),
|
|
5435
6341
|
"utf-8"
|
|
@@ -5440,13 +6346,13 @@ ${r.snippet.trim()}
|
|
|
5440
6346
|
}
|
|
5441
6347
|
async recordLastQmdRecallSnapshot(options) {
|
|
5442
6348
|
try {
|
|
5443
|
-
const snapshotPath =
|
|
6349
|
+
const snapshotPath = path7.join(
|
|
5444
6350
|
options.storage.dir,
|
|
5445
6351
|
"state",
|
|
5446
6352
|
"last_qmd_recall.json"
|
|
5447
6353
|
);
|
|
5448
|
-
await
|
|
5449
|
-
await
|
|
6354
|
+
await mkdir5(path7.dirname(snapshotPath), { recursive: true });
|
|
6355
|
+
await writeFile4(
|
|
5450
6356
|
snapshotPath,
|
|
5451
6357
|
JSON.stringify(options.snapshot, null, 2),
|
|
5452
6358
|
"utf-8"
|
|
@@ -5460,9 +6366,9 @@ ${r.snippet.trim()}
|
|
|
5460
6366
|
const stateDir = await this.resolveStateDirForNamespace(
|
|
5461
6367
|
options.namespace
|
|
5462
6368
|
);
|
|
5463
|
-
const snapshotPath =
|
|
5464
|
-
await
|
|
5465
|
-
await
|
|
6369
|
+
const snapshotPath = path7.join(stateDir, "last_intent.json");
|
|
6370
|
+
await mkdir5(path7.dirname(snapshotPath), { recursive: true });
|
|
6371
|
+
await writeFile4(
|
|
5466
6372
|
snapshotPath,
|
|
5467
6373
|
JSON.stringify(options.snapshot, null, 2),
|
|
5468
6374
|
"utf-8"
|
|
@@ -5473,12 +6379,12 @@ ${r.snippet.trim()}
|
|
|
5473
6379
|
}
|
|
5474
6380
|
async resolveStateDirForNamespace(namespace) {
|
|
5475
6381
|
if (!this.config.namespacesEnabled) {
|
|
5476
|
-
return
|
|
6382
|
+
return path7.join(this.config.memoryDir, "state");
|
|
5477
6383
|
}
|
|
5478
6384
|
if (namespace !== this.config.defaultNamespace) {
|
|
5479
|
-
return
|
|
6385
|
+
return path7.join(this.config.memoryDir, "namespaces", namespace, "state");
|
|
5480
6386
|
}
|
|
5481
|
-
const candidate =
|
|
6387
|
+
const candidate = path7.join(
|
|
5482
6388
|
this.config.memoryDir,
|
|
5483
6389
|
"namespaces",
|
|
5484
6390
|
this.config.defaultNamespace
|
|
@@ -5486,11 +6392,11 @@ ${r.snippet.trim()}
|
|
|
5486
6392
|
try {
|
|
5487
6393
|
const candidateStat = await stat3(candidate);
|
|
5488
6394
|
if (candidateStat.isDirectory()) {
|
|
5489
|
-
return
|
|
6395
|
+
return path7.join(candidate, "state");
|
|
5490
6396
|
}
|
|
5491
6397
|
} catch {
|
|
5492
6398
|
}
|
|
5493
|
-
return
|
|
6399
|
+
return path7.join(this.config.memoryDir, "state");
|
|
5494
6400
|
}
|
|
5495
6401
|
buildGraphRecallRankedResults(results, sourceLabelResolver, limit = 64) {
|
|
5496
6402
|
return results.slice(0, limit).map((result) => ({
|
|
@@ -5576,7 +6482,10 @@ ${r.snippet.trim()}
|
|
|
5576
6482
|
}
|
|
5577
6483
|
return reserved;
|
|
5578
6484
|
}
|
|
5579
|
-
getRecallBudgetChars() {
|
|
6485
|
+
getRecallBudgetChars(override) {
|
|
6486
|
+
if (typeof override === "number" && Number.isFinite(override) && override >= 0) {
|
|
6487
|
+
return Math.floor(override);
|
|
6488
|
+
}
|
|
5580
6489
|
const configuredBudget = this.config.recallBudgetChars;
|
|
5581
6490
|
if (typeof configuredBudget === "number" && Number.isFinite(configuredBudget) && configuredBudget >= 0) {
|
|
5582
6491
|
return Math.floor(configuredBudget);
|
|
@@ -5587,7 +6496,7 @@ ${r.snippet.trim()}
|
|
|
5587
6496
|
}
|
|
5588
6497
|
return 0;
|
|
5589
6498
|
}
|
|
5590
|
-
assembleRecallSections(sectionBuckets) {
|
|
6499
|
+
assembleRecallSections(sectionBuckets, budgetOverride) {
|
|
5591
6500
|
const orderedEntries = [];
|
|
5592
6501
|
const pipeline = Array.isArray(this.config.recallPipeline) ? this.config.recallPipeline : [];
|
|
5593
6502
|
const orderedIds = pipeline.filter((entry) => entry.enabled !== false).map((entry) => entry.id);
|
|
@@ -5603,7 +6512,7 @@ ${r.snippet.trim()}
|
|
|
5603
6512
|
if (chunks.length === 0) continue;
|
|
5604
6513
|
orderedEntries.push({ id, content: chunks.join("\n\n") });
|
|
5605
6514
|
}
|
|
5606
|
-
const budget = this.getRecallBudgetChars();
|
|
6515
|
+
const budget = this.getRecallBudgetChars(budgetOverride);
|
|
5607
6516
|
if (budget === 0) {
|
|
5608
6517
|
return {
|
|
5609
6518
|
sections: [],
|
|
@@ -5735,6 +6644,13 @@ ${r.snippet.trim()}
|
|
|
5735
6644
|
let recalledMemoryCount = 0;
|
|
5736
6645
|
let recalledMemoryIds = [];
|
|
5737
6646
|
let recalledMemoryPaths = [];
|
|
6647
|
+
const xrayBranchPoolSize = {
|
|
6648
|
+
hot_qmd: 0,
|
|
6649
|
+
hot_embedding: 0,
|
|
6650
|
+
cold_fallback: 0,
|
|
6651
|
+
recent_scan: 0
|
|
6652
|
+
};
|
|
6653
|
+
const xrayColdPoolSink = { size: 0 };
|
|
5738
6654
|
let identityInjectionModeUsed = "none";
|
|
5739
6655
|
let identityInjectedChars = 0;
|
|
5740
6656
|
let identityInjectionTruncated = false;
|
|
@@ -5795,7 +6711,7 @@ ${r.snippet.trim()}
|
|
|
5795
6711
|
this.config.verbatimArtifactsMaxRecall
|
|
5796
6712
|
);
|
|
5797
6713
|
const embeddingFetchLimit = computedFetchLimit;
|
|
5798
|
-
const principal = resolvePrincipal(sessionKey, this.config);
|
|
6714
|
+
const principal = typeof options.principalOverride === "string" && options.principalOverride.length > 0 ? options.principalOverride : resolvePrincipal(sessionKey, this.config);
|
|
5799
6715
|
const namespaceOverride = options.namespace?.trim() || void 0;
|
|
5800
6716
|
const readableRecallNamespaces = recallNamespacesForPrincipal(
|
|
5801
6717
|
principal,
|
|
@@ -5806,8 +6722,24 @@ ${r.snippet.trim()}
|
|
|
5806
6722
|
`namespace override is not readable: ${namespaceOverride}`
|
|
5807
6723
|
);
|
|
5808
6724
|
}
|
|
5809
|
-
const
|
|
5810
|
-
const
|
|
6725
|
+
const codingOverlay = namespaceOverride ? null : this.applyCodingRecallOverlay(sessionKey);
|
|
6726
|
+
const principalSelfNamespace = defaultNamespaceForPrincipal(principal, this.config);
|
|
6727
|
+
const codingSelfNamespace = codingOverlay ? combineNamespaces(principalSelfNamespace, codingOverlay.namespace) : null;
|
|
6728
|
+
const selfNamespace = namespaceOverride ?? codingSelfNamespace ?? principalSelfNamespace;
|
|
6729
|
+
let recallNamespaces;
|
|
6730
|
+
if (namespaceOverride) {
|
|
6731
|
+
recallNamespaces = [namespaceOverride];
|
|
6732
|
+
} else if (codingOverlay && codingSelfNamespace) {
|
|
6733
|
+
const mapped = readableRecallNamespaces.map(
|
|
6734
|
+
(ns) => ns === principalSelfNamespace ? codingSelfNamespace : ns
|
|
6735
|
+
);
|
|
6736
|
+
const fallbackNs = codingOverlay.readFallbacks.map(
|
|
6737
|
+
(fallback) => combineNamespaces(principalSelfNamespace, fallback)
|
|
6738
|
+
);
|
|
6739
|
+
recallNamespaces = Array.from(/* @__PURE__ */ new Set([...mapped, ...fallbackNs]));
|
|
6740
|
+
} else {
|
|
6741
|
+
recallNamespaces = readableRecallNamespaces;
|
|
6742
|
+
}
|
|
5811
6743
|
const qmdAvailable = this.qmd.isAvailable();
|
|
5812
6744
|
let graphDecisionStatus = recallDecision.plannedMode === "graph_mode" ? "skipped" : "not_requested";
|
|
5813
6745
|
let graphDecisionReason = recallDecision.graphReason;
|
|
@@ -5824,7 +6756,7 @@ ${r.snippet.trim()}
|
|
|
5824
6756
|
const graphExpandedResultPaths = /* @__PURE__ */ new Set();
|
|
5825
6757
|
const graphSourceLabelsForPath = (resultPath) => {
|
|
5826
6758
|
const labels = [];
|
|
5827
|
-
const normalizedPath = resultPath.split(
|
|
6759
|
+
const normalizedPath = resultPath.split(path7.sep).join("/");
|
|
5828
6760
|
const isEntityPath = normalizedPath.startsWith("entities/") || normalizedPath.includes("/entities/");
|
|
5829
6761
|
if (graphBaselinePaths.has(resultPath)) labels.push("baseline");
|
|
5830
6762
|
if (graphExpandedResultPaths.has(resultPath))
|
|
@@ -5862,6 +6794,32 @@ ${r.snippet.trim()}
|
|
|
5862
6794
|
const earlySessionKey = sessionKey ?? "default";
|
|
5863
6795
|
this._recallWorkspaceOverrides.delete(earlySessionKey);
|
|
5864
6796
|
timings.total = `${Date.now() - recallStart}ms`;
|
|
6797
|
+
if (options.xrayCapture === true && !options.abortSignal?.aborted) {
|
|
6798
|
+
try {
|
|
6799
|
+
this.lastXraySnapshot = buildXraySnapshot({
|
|
6800
|
+
query: retrievalQuery,
|
|
6801
|
+
tierExplain: null,
|
|
6802
|
+
results: [],
|
|
6803
|
+
filters: [
|
|
6804
|
+
{
|
|
6805
|
+
name: "planner-mode",
|
|
6806
|
+
considered: 0,
|
|
6807
|
+
admitted: 0,
|
|
6808
|
+
reason: "no_recall"
|
|
6809
|
+
}
|
|
6810
|
+
],
|
|
6811
|
+
budget: {
|
|
6812
|
+
chars: this.getRecallBudgetChars(options.budgetCharsOverride),
|
|
6813
|
+
used: 0
|
|
6814
|
+
},
|
|
6815
|
+
sessionKey,
|
|
6816
|
+
namespace: selfNamespace,
|
|
6817
|
+
traceId
|
|
6818
|
+
});
|
|
6819
|
+
} catch (err) {
|
|
6820
|
+
log.debug(`x-ray capture (no_recall) failed: ${err}`);
|
|
6821
|
+
}
|
|
6822
|
+
}
|
|
5865
6823
|
if (sessionKey) {
|
|
5866
6824
|
this.lastRecall.record({
|
|
5867
6825
|
sessionKey,
|
|
@@ -7011,16 +7969,16 @@ ${formatted}`;
|
|
|
7011
7969
|
if (!this.config.compactionResetEnabled) return null;
|
|
7012
7970
|
const workspaceDir = compactionWorkspaceDir || this.config.workspaceDir || defaultWorkspaceDir();
|
|
7013
7971
|
const safeSessionKey = sanitizeSessionKeyForFilename(effectiveSessionKey);
|
|
7014
|
-
const signalPath =
|
|
7972
|
+
const signalPath = path7.join(
|
|
7015
7973
|
workspaceDir,
|
|
7016
7974
|
`.compaction-reset-signal-${safeSessionKey}`
|
|
7017
7975
|
);
|
|
7018
|
-
const bootPath =
|
|
7976
|
+
const bootPath = path7.join(workspaceDir, "BOOT.md");
|
|
7019
7977
|
try {
|
|
7020
7978
|
const signalStat = await stat3(signalPath).catch(() => null);
|
|
7021
7979
|
if (!signalStat) return null;
|
|
7022
7980
|
const signalAge = Date.now() - signalStat.mtimeMs;
|
|
7023
|
-
const signalData = JSON.parse(await
|
|
7981
|
+
const signalData = JSON.parse(await readFile4(signalPath, "utf-8"));
|
|
7024
7982
|
if (signalData.sessionKey !== effectiveSessionKey) {
|
|
7025
7983
|
log.debug(
|
|
7026
7984
|
`recall: compaction signal is for ${signalData.sessionKey}, not ${effectiveSessionKey} \u2014 skipping`
|
|
@@ -7040,7 +7998,7 @@ ${formatted}`;
|
|
|
7040
7998
|
|
|
7041
7999
|
`;
|
|
7042
8000
|
try {
|
|
7043
|
-
const bootContent = await
|
|
8001
|
+
const bootContent = await readFile4(bootPath, "utf-8");
|
|
7044
8002
|
section += "### BOOT.md (working state before compaction)\n\n";
|
|
7045
8003
|
section += bootContent + "\n";
|
|
7046
8004
|
} catch {
|
|
@@ -7747,7 +8705,18 @@ ${tmtNode.summary}`
|
|
|
7747
8705
|
"rerankProvider=cloud is reserved/experimental in v2.2.0; skipping rerank"
|
|
7748
8706
|
);
|
|
7749
8707
|
}
|
|
8708
|
+
if (this.config.recallMemoryWorthFilterEnabled && memoryResults.length > 0) {
|
|
8709
|
+
try {
|
|
8710
|
+
memoryResults = await this.applyMemoryWorthRerank(memoryResults, recallNamespaces);
|
|
8711
|
+
} catch (err) {
|
|
8712
|
+
log.debug("memory-worth filter failed open", { error: err.message });
|
|
8713
|
+
}
|
|
8714
|
+
}
|
|
7750
8715
|
const effectiveGateScore = preAugmentTopScore > 0 ? Math.max(preAugmentTopScore, maxSpecializedScore) : 0;
|
|
8716
|
+
xrayBranchPoolSize.hot_qmd = Math.max(
|
|
8717
|
+
xrayBranchPoolSize.hot_qmd,
|
|
8718
|
+
memoryResults.length
|
|
8719
|
+
);
|
|
7751
8720
|
let confidenceGateRejected = false;
|
|
7752
8721
|
if (this.config.recallConfidenceGateEnabled && effectiveGateScore > 0) {
|
|
7753
8722
|
if (effectiveGateScore < this.config.recallConfidenceGateThreshold) {
|
|
@@ -7761,7 +8730,8 @@ ${tmtNode.summary}`
|
|
|
7761
8730
|
memoryResults = this.diversifyAndLimitRecallResults(
|
|
7762
8731
|
"memories",
|
|
7763
8732
|
memoryResults,
|
|
7764
|
-
recallResultLimit
|
|
8733
|
+
recallResultLimit,
|
|
8734
|
+
retrievalQuery
|
|
7765
8735
|
);
|
|
7766
8736
|
if (this.config.memoryReconstructionEnabled && memoryResults.length > 0) {
|
|
7767
8737
|
try {
|
|
@@ -7846,10 +8816,15 @@ ${tmtNode.summary}`
|
|
|
7846
8816
|
recallNamespaces,
|
|
7847
8817
|
retrievalQuery
|
|
7848
8818
|
);
|
|
8819
|
+
xrayBranchPoolSize.hot_embedding = Math.max(
|
|
8820
|
+
xrayBranchPoolSize.hot_embedding,
|
|
8821
|
+
boostedScoped.length
|
|
8822
|
+
);
|
|
7849
8823
|
const scoped = this.diversifyAndLimitRecallResults(
|
|
7850
8824
|
"memories",
|
|
7851
8825
|
boostedScoped,
|
|
7852
|
-
recallResultLimit
|
|
8826
|
+
recallResultLimit,
|
|
8827
|
+
retrievalQuery
|
|
7853
8828
|
);
|
|
7854
8829
|
if (scoped.length > 0) {
|
|
7855
8830
|
if (shouldPersistGraphSnapshot) {
|
|
@@ -7882,7 +8857,8 @@ ${tmtNode.summary}`
|
|
|
7882
8857
|
recallResultLimit,
|
|
7883
8858
|
recallMode,
|
|
7884
8859
|
queryAwarePrefilter,
|
|
7885
|
-
abortSignal: options.abortSignal
|
|
8860
|
+
abortSignal: options.abortSignal,
|
|
8861
|
+
xrayPoolSizeSink: xrayColdPoolSink
|
|
7886
8862
|
});
|
|
7887
8863
|
if (longTerm.length > 0) {
|
|
7888
8864
|
if (shouldPersistGraphSnapshot) {
|
|
@@ -7966,10 +8942,15 @@ ${tmtNode.summary}`
|
|
|
7966
8942
|
recallNamespaces,
|
|
7967
8943
|
retrievalQuery
|
|
7968
8944
|
);
|
|
8945
|
+
xrayBranchPoolSize.hot_embedding = Math.max(
|
|
8946
|
+
xrayBranchPoolSize.hot_embedding,
|
|
8947
|
+
boostedScoped.length
|
|
8948
|
+
);
|
|
7969
8949
|
const scoped = this.diversifyAndLimitRecallResults(
|
|
7970
8950
|
"memories",
|
|
7971
8951
|
boostedScoped,
|
|
7972
|
-
recallResultLimit
|
|
8952
|
+
recallResultLimit,
|
|
8953
|
+
retrievalQuery
|
|
7973
8954
|
);
|
|
7974
8955
|
if (scoped.length > 0) {
|
|
7975
8956
|
if (shouldPersistGraphSnapshot) {
|
|
@@ -8023,7 +9004,8 @@ ${tmtNode.summary}`
|
|
|
8023
9004
|
recallResultLimit,
|
|
8024
9005
|
recallMode,
|
|
8025
9006
|
queryAwarePrefilter,
|
|
8026
|
-
abortSignal: options.abortSignal
|
|
9007
|
+
abortSignal: options.abortSignal,
|
|
9008
|
+
xrayPoolSizeSink: xrayColdPoolSink
|
|
8027
9009
|
});
|
|
8028
9010
|
if (longTerm.length > 0) {
|
|
8029
9011
|
recallSource = "cold_fallback";
|
|
@@ -8065,10 +9047,15 @@ ${tmtNode.summary}`
|
|
|
8065
9047
|
retrievalQuery,
|
|
8066
9048
|
preloadedMap
|
|
8067
9049
|
)).sort((a, b) => b.score - a.score);
|
|
9050
|
+
xrayBranchPoolSize.recent_scan = Math.max(
|
|
9051
|
+
xrayBranchPoolSize.recent_scan,
|
|
9052
|
+
boostedRecent.length
|
|
9053
|
+
);
|
|
8068
9054
|
const recent = this.diversifyAndLimitRecallResults(
|
|
8069
9055
|
"memories",
|
|
8070
9056
|
boostedRecent,
|
|
8071
|
-
recallResultLimit
|
|
9057
|
+
recallResultLimit,
|
|
9058
|
+
retrievalQuery
|
|
8072
9059
|
);
|
|
8073
9060
|
if (recent.length > 0) {
|
|
8074
9061
|
if (shouldPersistGraphSnapshot) {
|
|
@@ -8101,7 +9088,8 @@ ${tmtNode.summary}`
|
|
|
8101
9088
|
recallResultLimit,
|
|
8102
9089
|
recallMode,
|
|
8103
9090
|
queryAwarePrefilter,
|
|
8104
|
-
abortSignal: options.abortSignal
|
|
9091
|
+
abortSignal: options.abortSignal,
|
|
9092
|
+
xrayPoolSizeSink: xrayColdPoolSink
|
|
8105
9093
|
});
|
|
8106
9094
|
if (longTerm.length > 0) {
|
|
8107
9095
|
if (shouldPersistGraphSnapshot) {
|
|
@@ -8137,7 +9125,8 @@ ${tmtNode.summary}`
|
|
|
8137
9125
|
recallResultLimit,
|
|
8138
9126
|
recallMode,
|
|
8139
9127
|
queryAwarePrefilter,
|
|
8140
|
-
abortSignal: options.abortSignal
|
|
9128
|
+
abortSignal: options.abortSignal,
|
|
9129
|
+
xrayPoolSizeSink: xrayColdPoolSink
|
|
8141
9130
|
});
|
|
8142
9131
|
if (longTerm.length > 0) {
|
|
8143
9132
|
if (shouldPersistGraphSnapshot) {
|
|
@@ -8296,7 +9285,10 @@ _Context: ${topQuestion.context}_`
|
|
|
8296
9285
|
);
|
|
8297
9286
|
const timingParts = Object.entries(timings).map(([k, v]) => `${k}=${v}`).join(", ");
|
|
8298
9287
|
log.info(`recall timings: ${timingParts}`);
|
|
8299
|
-
const assembledRecall = this.assembleRecallSections(
|
|
9288
|
+
const assembledRecall = this.assembleRecallSections(
|
|
9289
|
+
sectionBuckets,
|
|
9290
|
+
options.budgetCharsOverride
|
|
9291
|
+
);
|
|
8300
9292
|
const context = assembledRecall.sections.length === 0 ? "" : assembledRecall.sections.join("\n\n---\n\n");
|
|
8301
9293
|
const sourcesUsed = this.collectLastRecallSources(
|
|
8302
9294
|
sectionBuckets,
|
|
@@ -8312,6 +9304,73 @@ _Context: ${topQuestion.context}_`
|
|
|
8312
9304
|
includedSections: assembledRecall.includedIds,
|
|
8313
9305
|
omittedSections: assembledRecall.omittedIds
|
|
8314
9306
|
});
|
|
9307
|
+
if (options.xrayCapture === true && !options.abortSignal?.aborted) {
|
|
9308
|
+
try {
|
|
9309
|
+
const servedBy = mapRecallSourceToXrayServedBy(recallSource);
|
|
9310
|
+
const idFromPath = (p) => {
|
|
9311
|
+
const match = p.match(/([^/]+)\.md$/);
|
|
9312
|
+
return match ? match[1] ?? null : null;
|
|
9313
|
+
};
|
|
9314
|
+
const results = [];
|
|
9315
|
+
for (const recalledPath of recalledMemoryPaths) {
|
|
9316
|
+
const derivedId = idFromPath(recalledPath);
|
|
9317
|
+
if (!derivedId) continue;
|
|
9318
|
+
results.push({
|
|
9319
|
+
memoryId: derivedId,
|
|
9320
|
+
path: recalledPath,
|
|
9321
|
+
servedBy,
|
|
9322
|
+
scoreDecomposition: { final: 0 },
|
|
9323
|
+
admittedBy: []
|
|
9324
|
+
});
|
|
9325
|
+
}
|
|
9326
|
+
let xrayConsidered;
|
|
9327
|
+
switch (recallSource) {
|
|
9328
|
+
case "hot_qmd":
|
|
9329
|
+
xrayConsidered = xrayBranchPoolSize.hot_qmd;
|
|
9330
|
+
break;
|
|
9331
|
+
case "hot_embedding":
|
|
9332
|
+
xrayConsidered = xrayBranchPoolSize.hot_embedding;
|
|
9333
|
+
break;
|
|
9334
|
+
case "cold_fallback":
|
|
9335
|
+
xrayConsidered = xrayColdPoolSink.size;
|
|
9336
|
+
break;
|
|
9337
|
+
case "recent_scan":
|
|
9338
|
+
xrayConsidered = xrayBranchPoolSize.recent_scan;
|
|
9339
|
+
break;
|
|
9340
|
+
case "none":
|
|
9341
|
+
xrayConsidered = recalledMemoryCount;
|
|
9342
|
+
break;
|
|
9343
|
+
default: {
|
|
9344
|
+
const _exhaustive = recallSource;
|
|
9345
|
+
void _exhaustive;
|
|
9346
|
+
xrayConsidered = recalledMemoryCount;
|
|
9347
|
+
}
|
|
9348
|
+
}
|
|
9349
|
+
xrayConsidered = Math.max(xrayConsidered, recalledMemoryIds.length);
|
|
9350
|
+
const filters = [
|
|
9351
|
+
{
|
|
9352
|
+
name: "recall-result-limit",
|
|
9353
|
+
considered: xrayConsidered,
|
|
9354
|
+
admitted: recalledMemoryIds.length
|
|
9355
|
+
}
|
|
9356
|
+
];
|
|
9357
|
+
this.lastXraySnapshot = buildXraySnapshot({
|
|
9358
|
+
query: retrievalQuery,
|
|
9359
|
+
tierExplain: null,
|
|
9360
|
+
results,
|
|
9361
|
+
filters,
|
|
9362
|
+
budget: {
|
|
9363
|
+
chars: this.getRecallBudgetChars(options.budgetCharsOverride),
|
|
9364
|
+
used: assembledRecall.finalChars
|
|
9365
|
+
},
|
|
9366
|
+
sessionKey,
|
|
9367
|
+
namespace: selfNamespace,
|
|
9368
|
+
traceId
|
|
9369
|
+
});
|
|
9370
|
+
} catch (err) {
|
|
9371
|
+
log.debug(`x-ray capture failed: ${err}`);
|
|
9372
|
+
}
|
|
9373
|
+
}
|
|
8315
9374
|
if (sessionKey) {
|
|
8316
9375
|
throwIfRecallAborted(options.abortSignal);
|
|
8317
9376
|
this.lastRecall.record({
|
|
@@ -8788,7 +9847,10 @@ ${normalized}`).digest("hex");
|
|
|
8788
9847
|
return;
|
|
8789
9848
|
}
|
|
8790
9849
|
const principal = resolvePrincipal(sessionKey, this.config);
|
|
8791
|
-
const selfNamespace = typeof options.writeNamespaceOverride === "string" && options.writeNamespaceOverride.length > 0 ? options.writeNamespaceOverride :
|
|
9850
|
+
const selfNamespace = typeof options.writeNamespaceOverride === "string" && options.writeNamespaceOverride.length > 0 ? options.writeNamespaceOverride : this.applyCodingNamespaceOverlay(
|
|
9851
|
+
sessionKey,
|
|
9852
|
+
defaultNamespaceForPrincipal(principal, this.config)
|
|
9853
|
+
);
|
|
8792
9854
|
const storage = await this.storageRouter.storageFor(selfNamespace);
|
|
8793
9855
|
const shouldPersistProcessedFingerprint = normalizedTurns.some(
|
|
8794
9856
|
(turn) => turn.persistProcessedFingerprint === true
|
|
@@ -8881,6 +9943,24 @@ ${normalized}`).digest("hex");
|
|
|
8881
9943
|
} catch (error) {
|
|
8882
9944
|
postPersistMetaError = error;
|
|
8883
9945
|
}
|
|
9946
|
+
try {
|
|
9947
|
+
if (clearBufferAfterExtraction && !this.config.extractionJudgeShadow) {
|
|
9948
|
+
const deferredCount = this.lastPersistExtractionDeferredCount;
|
|
9949
|
+
if (deferredCount > 0 && normalizedTurns.length > 0) {
|
|
9950
|
+
await this.buffer.retainDeferredTurns(
|
|
9951
|
+
bufferKey,
|
|
9952
|
+
normalizedTurns,
|
|
9953
|
+
10
|
|
9954
|
+
);
|
|
9955
|
+
} else {
|
|
9956
|
+
await this.buffer.retainDeferredTurns(bufferKey, [], 0);
|
|
9957
|
+
}
|
|
9958
|
+
}
|
|
9959
|
+
} catch (err) {
|
|
9960
|
+
log.debug(
|
|
9961
|
+
`extraction-judge: defer retention failed (non-fatal): ${err instanceof Error ? err.message : String(err)}`
|
|
9962
|
+
);
|
|
9963
|
+
}
|
|
8884
9964
|
await clearBuffer({ ignoreAbort: true });
|
|
8885
9965
|
if (this.config.memoryBoxesEnabled && persistedIds.length > 0) {
|
|
8886
9966
|
const extractionTopics = deriveTopicsFromExtraction(result);
|
|
@@ -9013,7 +10093,7 @@ ${normalized}`).digest("hex");
|
|
|
9013
10093
|
);
|
|
9014
10094
|
this.tierMigrationInFlight = true;
|
|
9015
10095
|
try {
|
|
9016
|
-
const coldStorage = new StorageManager(
|
|
10096
|
+
const coldStorage = new StorageManager(path7.join(storage.dir, "cold"));
|
|
9017
10097
|
const [hotMemories, coldMemories] = await Promise.all([
|
|
9018
10098
|
storage.readAllMemories(),
|
|
9019
10099
|
coldStorage.readAllMemories()
|
|
@@ -9462,6 +10542,7 @@ ${normalized}`).digest("hex");
|
|
|
9462
10542
|
}
|
|
9463
10543
|
let judgeVerdictsByFactIndex = null;
|
|
9464
10544
|
let judgeGatedCount = 0;
|
|
10545
|
+
this.lastPersistExtractionDeferredCount = 0;
|
|
9465
10546
|
if (this.config.extractionJudgeEnabled) {
|
|
9466
10547
|
try {
|
|
9467
10548
|
const judgeCandidates = [];
|
|
@@ -9496,12 +10577,56 @@ ${normalized}`).digest("hex");
|
|
|
9496
10577
|
});
|
|
9497
10578
|
candidateToFactIndex.push(fi);
|
|
9498
10579
|
}
|
|
10580
|
+
const judgeTelemetryOpts = {
|
|
10581
|
+
enabled: this.config.extractionJudgeTelemetryEnabled === true,
|
|
10582
|
+
memoryDir: this.config.memoryDir
|
|
10583
|
+
};
|
|
10584
|
+
const judgeTrainingOpts = {
|
|
10585
|
+
enabled: this.config.collectJudgeTrainingPairs === true,
|
|
10586
|
+
...this.config.judgeTrainingDir ? { directory: this.config.judgeTrainingDir } : {}
|
|
10587
|
+
};
|
|
10588
|
+
const judgeTelemetryHandler = judgeTelemetryOpts.enabled || judgeTrainingOpts.enabled ? (obs) => {
|
|
10589
|
+
const ts = (/* @__PURE__ */ new Date()).toISOString();
|
|
10590
|
+
const verdictKind = getVerdictKind(obs.verdict);
|
|
10591
|
+
if (judgeTelemetryOpts.enabled) {
|
|
10592
|
+
const event = {
|
|
10593
|
+
version: 1,
|
|
10594
|
+
category: EXTRACTION_JUDGE_VERDICT_CATEGORY,
|
|
10595
|
+
ts,
|
|
10596
|
+
verdictKind,
|
|
10597
|
+
reason: obs.verdict.reason,
|
|
10598
|
+
deferrals: obs.priorDeferrals,
|
|
10599
|
+
elapsedMs: obs.elapsedMs,
|
|
10600
|
+
candidateCategory: obs.candidate.category,
|
|
10601
|
+
confidence: obs.candidate.confidence,
|
|
10602
|
+
contentHash: obs.contentHash,
|
|
10603
|
+
fromCache: obs.source === "cache",
|
|
10604
|
+
...obs.source === "llm-cap-rejected" ? { deferCapTriggered: true } : {}
|
|
10605
|
+
};
|
|
10606
|
+
void recordJudgeVerdict(event, judgeTelemetryOpts);
|
|
10607
|
+
}
|
|
10608
|
+
if (judgeTrainingOpts.enabled) {
|
|
10609
|
+
const pair = {
|
|
10610
|
+
version: 1,
|
|
10611
|
+
ts,
|
|
10612
|
+
candidateText: obs.candidate.text,
|
|
10613
|
+
candidateCategory: obs.candidate.category,
|
|
10614
|
+
...typeof obs.candidate.confidence === "number" ? { candidateConfidence: obs.candidate.confidence } : {},
|
|
10615
|
+
verdictKind,
|
|
10616
|
+
reason: obs.verdict.reason,
|
|
10617
|
+
priorDeferrals: obs.priorDeferrals
|
|
10618
|
+
};
|
|
10619
|
+
void recordJudgeTrainingPair(pair, judgeTrainingOpts);
|
|
10620
|
+
}
|
|
10621
|
+
} : void 0;
|
|
9499
10622
|
const judgeResult = await judgeFactDurability(
|
|
9500
10623
|
judgeCandidates,
|
|
9501
10624
|
this.config,
|
|
9502
10625
|
this.localLlm,
|
|
9503
10626
|
new FallbackLlmClient(this.config.gatewayConfig),
|
|
9504
|
-
this.judgeVerdictCache
|
|
10627
|
+
this.judgeVerdictCache,
|
|
10628
|
+
this.judgeDeferCounts,
|
|
10629
|
+
judgeTelemetryHandler
|
|
9505
10630
|
);
|
|
9506
10631
|
judgeVerdictsByFactIndex = /* @__PURE__ */ new Map();
|
|
9507
10632
|
for (const [candidateIdx, verdict] of judgeResult.verdicts) {
|
|
@@ -9511,8 +10636,9 @@ ${normalized}`).digest("hex");
|
|
|
9511
10636
|
}
|
|
9512
10637
|
}
|
|
9513
10638
|
log.info(
|
|
9514
|
-
`extraction-judge: ${judgeResult.verdicts.size}/${judgeCandidates.length} facts evaluated, ${judgeResult.cached} cached, ${judgeResult.judged} judged, ${judgeResult.elapsed}ms`
|
|
10639
|
+
`extraction-judge: ${judgeResult.verdicts.size}/${judgeCandidates.length} facts evaluated, ${judgeResult.cached} cached, ${judgeResult.judged} judged, ${judgeResult.deferred} deferred` + (judgeResult.deferredCappedToReject > 0 ? ` (${judgeResult.deferredCappedToReject} cap-rejected)` : "") + `, ${judgeResult.elapsed}ms`
|
|
9515
10640
|
);
|
|
10641
|
+
this.lastPersistExtractionDeferredCount = judgeResult.deferred;
|
|
9516
10642
|
} catch (err) {
|
|
9517
10643
|
log.warn(
|
|
9518
10644
|
`extraction-judge: pipeline error, proceeding without filtering (fail-open): ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -9587,10 +10713,17 @@ ${normalized}`).digest("hex");
|
|
|
9587
10713
|
if (judgeVerdictsByFactIndex) {
|
|
9588
10714
|
const verdict = judgeVerdictsByFactIndex.get(factLoopIndex);
|
|
9589
10715
|
if (verdict && !verdict.durable) {
|
|
10716
|
+
const verdictKind = getVerdictKind(verdict);
|
|
9590
10717
|
if (this.config.extractionJudgeShadow) {
|
|
9591
10718
|
log.info(
|
|
9592
|
-
`extraction-judge[shadow]: would
|
|
10719
|
+
`extraction-judge[shadow]: would ${verdictKind} "${fact.content.slice(0, 60)}\u2026" reason="${verdict.reason}"`
|
|
10720
|
+
);
|
|
10721
|
+
} else if (verdictKind === "defer") {
|
|
10722
|
+
judgeGatedCount++;
|
|
10723
|
+
log.debug(
|
|
10724
|
+
`extraction-judge: deferred "${fact.content.slice(0, 60)}\u2026" reason="${verdict.reason}"`
|
|
9593
10725
|
);
|
|
10726
|
+
continue;
|
|
9594
10727
|
} else {
|
|
9595
10728
|
judgeGatedCount++;
|
|
9596
10729
|
log.debug(
|
|
@@ -10133,7 +11266,7 @@ ${normalized}`).digest("hex");
|
|
|
10133
11266
|
const allMems = allMemsForGraph ?? [];
|
|
10134
11267
|
for (const m of allMems) {
|
|
10135
11268
|
if (m.frontmatter.entityRef === entityRef) {
|
|
10136
|
-
const rel =
|
|
11269
|
+
const rel = path7.relative(storage.dir, m.path);
|
|
10137
11270
|
if (rel !== memoryRelPath) entitySiblings.push(rel);
|
|
10138
11271
|
}
|
|
10139
11272
|
}
|
|
@@ -10404,14 +11537,14 @@ ${normalized}`).digest("hex");
|
|
|
10404
11537
|
}
|
|
10405
11538
|
if (this.config.semanticConsolidationEnabled) {
|
|
10406
11539
|
try {
|
|
10407
|
-
const stateFilePath =
|
|
11540
|
+
const stateFilePath = path7.join(
|
|
10408
11541
|
this.config.memoryDir,
|
|
10409
11542
|
"state",
|
|
10410
11543
|
"semantic-consolidation-last-run.json"
|
|
10411
11544
|
);
|
|
10412
11545
|
let shouldRun = true;
|
|
10413
11546
|
try {
|
|
10414
|
-
const stateRaw = await
|
|
11547
|
+
const stateRaw = await readFile4(stateFilePath, "utf-8");
|
|
10415
11548
|
const stateData = JSON.parse(stateRaw);
|
|
10416
11549
|
if (stateData.lastRunAt) {
|
|
10417
11550
|
const lastRunMs = new Date(stateData.lastRunAt).getTime();
|
|
@@ -10434,9 +11567,9 @@ ${normalized}`).digest("hex");
|
|
|
10434
11567
|
allMemories = await this.storage.readAllMemories();
|
|
10435
11568
|
}
|
|
10436
11569
|
if (semResult.errors === 0 || semResult.memoriesArchived > 0) {
|
|
10437
|
-
const stateDir =
|
|
10438
|
-
await
|
|
10439
|
-
await
|
|
11570
|
+
const stateDir = path7.join(this.config.memoryDir, "state");
|
|
11571
|
+
await mkdir5(stateDir, { recursive: true });
|
|
11572
|
+
await writeFile4(
|
|
10440
11573
|
stateFilePath,
|
|
10441
11574
|
JSON.stringify({ lastRunAt: (/* @__PURE__ */ new Date()).toISOString() }),
|
|
10442
11575
|
"utf-8"
|
|
@@ -10908,13 +12041,13 @@ ${texts.map((t, i) => `[${i + 1}] ${t}`).join("\n\n")}`;
|
|
|
10908
12041
|
protectedCategories: this.config.lifecycleProtectedCategories
|
|
10909
12042
|
}
|
|
10910
12043
|
};
|
|
10911
|
-
const metricsPath =
|
|
12044
|
+
const metricsPath = path7.join(
|
|
10912
12045
|
this.storage.dir,
|
|
10913
12046
|
"state",
|
|
10914
12047
|
"lifecycle-metrics.json"
|
|
10915
12048
|
);
|
|
10916
|
-
await
|
|
10917
|
-
await
|
|
12049
|
+
await mkdir5(path7.dirname(metricsPath), { recursive: true });
|
|
12050
|
+
await writeFile4(metricsPath, JSON.stringify(metrics, null, 2), "utf-8");
|
|
10918
12051
|
}
|
|
10919
12052
|
/**
|
|
10920
12053
|
* Archive old, low-importance, rarely-accessed facts (v6.0).
|
|
@@ -11417,11 +12550,97 @@ ${lines.join("\n\n")}`;
|
|
|
11417
12550
|
*
|
|
11418
12551
|
* Callers must pass the full candidate pool (post-rerank, pre-slice).
|
|
11419
12552
|
*/
|
|
11420
|
-
|
|
12553
|
+
async applyMemoryWorthRerank(results, namespaces) {
|
|
12554
|
+
const counters = /* @__PURE__ */ new Map();
|
|
12555
|
+
const seenNamespaces = /* @__PURE__ */ new Set();
|
|
12556
|
+
const nowMs = Date.now();
|
|
12557
|
+
for (const [key, entry] of this.memoryWorthCounterCache) {
|
|
12558
|
+
if (nowMs - entry.at >= _Orchestrator.MEMORY_WORTH_CACHE_TTL_MS) {
|
|
12559
|
+
this.memoryWorthCounterCache.delete(key);
|
|
12560
|
+
}
|
|
12561
|
+
}
|
|
12562
|
+
for (const ns of namespaces) {
|
|
12563
|
+
if (seenNamespaces.has(ns)) continue;
|
|
12564
|
+
seenNamespaces.add(ns);
|
|
12565
|
+
try {
|
|
12566
|
+
const cached = this.memoryWorthCounterCache.get(ns);
|
|
12567
|
+
let nsMap;
|
|
12568
|
+
if (cached && nowMs - cached.at < _Orchestrator.MEMORY_WORTH_CACHE_TTL_MS) {
|
|
12569
|
+
nsMap = cached.counters;
|
|
12570
|
+
} else {
|
|
12571
|
+
const storage = await this.getStorage(ns);
|
|
12572
|
+
const memories = await storage.readAllMemories();
|
|
12573
|
+
nsMap = buildMemoryWorthCounterMap(memories);
|
|
12574
|
+
this.memoryWorthCounterCache.set(ns, { at: nowMs, counters: nsMap });
|
|
12575
|
+
}
|
|
12576
|
+
for (const [path8, c] of nsMap) counters.set(path8, c);
|
|
12577
|
+
} catch (err) {
|
|
12578
|
+
log.debug("memory-worth: failed to read namespace, skipping", {
|
|
12579
|
+
namespace: ns,
|
|
12580
|
+
error: err.message
|
|
12581
|
+
});
|
|
12582
|
+
}
|
|
12583
|
+
}
|
|
12584
|
+
const missing = results.filter((r) => !counters.has(r.path));
|
|
12585
|
+
if (missing.length > 0) {
|
|
12586
|
+
let reader = null;
|
|
12587
|
+
for (const ns of namespaces) {
|
|
12588
|
+
try {
|
|
12589
|
+
reader = await this.getStorage(ns);
|
|
12590
|
+
break;
|
|
12591
|
+
} catch {
|
|
12592
|
+
}
|
|
12593
|
+
}
|
|
12594
|
+
if (reader) {
|
|
12595
|
+
for (const r of missing) {
|
|
12596
|
+
try {
|
|
12597
|
+
const memory = await reader.readMemoryByPath(r.path);
|
|
12598
|
+
if (!memory) continue;
|
|
12599
|
+
const fm = memory.frontmatter;
|
|
12600
|
+
if (fm.mw_success === void 0 && fm.mw_fail === void 0) continue;
|
|
12601
|
+
counters.set(r.path, {
|
|
12602
|
+
mw_success: fm.mw_success,
|
|
12603
|
+
mw_fail: fm.mw_fail,
|
|
12604
|
+
lastAccessed: fm.lastAccessed
|
|
12605
|
+
});
|
|
12606
|
+
} catch (err) {
|
|
12607
|
+
log.debug("memory-worth: direct path lookup failed", {
|
|
12608
|
+
path: r.path,
|
|
12609
|
+
error: err.message
|
|
12610
|
+
});
|
|
12611
|
+
}
|
|
12612
|
+
}
|
|
12613
|
+
}
|
|
12614
|
+
}
|
|
12615
|
+
if (counters.size === 0) return results;
|
|
12616
|
+
const rankedInputs = results.map((r, i) => ({
|
|
12617
|
+
path: r.path,
|
|
12618
|
+
// Large positive rank score so multiplier math stays well-scaled and
|
|
12619
|
+
// we never hit zero; descending so earlier items rank higher.
|
|
12620
|
+
score: results.length - i
|
|
12621
|
+
}));
|
|
12622
|
+
const filtered = applyMemoryWorthFilter(rankedInputs, {
|
|
12623
|
+
counters,
|
|
12624
|
+
now: /* @__PURE__ */ new Date(),
|
|
12625
|
+
halfLifeMs: this.config.recallMemoryWorthHalfLifeMs > 0 ? this.config.recallMemoryWorthHalfLifeMs : void 0
|
|
12626
|
+
});
|
|
12627
|
+
const byPath = new Map(results.map((r) => [r.path, r]));
|
|
12628
|
+
const reordered = [];
|
|
12629
|
+
for (const item of filtered) {
|
|
12630
|
+
const original = byPath.get(item.path);
|
|
12631
|
+
if (original) reordered.push(original);
|
|
12632
|
+
}
|
|
12633
|
+
return reordered;
|
|
12634
|
+
}
|
|
12635
|
+
diversifyAndLimitRecallResults(sectionId, results, limit, retrievalQuery) {
|
|
11421
12636
|
const safeLimit = typeof limit === "number" && Number.isFinite(limit) ? Math.max(0, Math.floor(limit)) : 0;
|
|
11422
12637
|
if (!Array.isArray(results) || results.length === 0) return [];
|
|
11423
12638
|
if (safeLimit === 0) return [];
|
|
11424
|
-
const
|
|
12639
|
+
const boosted = this.config.recallReasoningTraceBoostEnabled && typeof retrievalQuery === "string" ? applyReasoningTraceBoost(results, {
|
|
12640
|
+
enabled: true,
|
|
12641
|
+
query: retrievalQuery
|
|
12642
|
+
}) : results;
|
|
12643
|
+
const diversified = this.applyMmrToQmdResults(sectionId, boosted);
|
|
11425
12644
|
return diversified.slice(0, safeLimit);
|
|
11426
12645
|
}
|
|
11427
12646
|
/**
|
|
@@ -11525,12 +12744,12 @@ ${lines.join("\n\n")}`;
|
|
|
11525
12744
|
*/
|
|
11526
12745
|
semanticDedupScopeFor(targetStorage) {
|
|
11527
12746
|
if (!this.config.namespacesEnabled) return {};
|
|
11528
|
-
const memoryDir =
|
|
11529
|
-
const storageDir =
|
|
12747
|
+
const memoryDir = path7.resolve(this.config.memoryDir);
|
|
12748
|
+
const storageDir = path7.resolve(targetStorage.dir);
|
|
11530
12749
|
if (storageDir === memoryDir) {
|
|
11531
12750
|
return { pathExcludePrefixes: ["namespaces/"] };
|
|
11532
12751
|
}
|
|
11533
|
-
let rel =
|
|
12752
|
+
let rel = path7.relative(memoryDir, storageDir);
|
|
11534
12753
|
if (!rel || rel.startsWith("..")) {
|
|
11535
12754
|
log.debug(
|
|
11536
12755
|
`semantic dedup: target storage dir ${storageDir} is outside memoryDir ${memoryDir}; scoping lookup to absolute path prefix`
|
|
@@ -11549,7 +12768,7 @@ ${lines.join("\n\n")}`;
|
|
|
11549
12768
|
if (hits.length === 0) return [];
|
|
11550
12769
|
const results = [];
|
|
11551
12770
|
for (const hit of hits) {
|
|
11552
|
-
const fullPath =
|
|
12771
|
+
const fullPath = path7.isAbsolute(hit.path) ? hit.path : path7.join(this.config.memoryDir, hit.path);
|
|
11553
12772
|
const memory = await this.storage.readMemoryByPath(fullPath);
|
|
11554
12773
|
if (!memory) continue;
|
|
11555
12774
|
results.push({
|
|
@@ -11726,10 +12945,26 @@ ${lines.join("\n\n")}`;
|
|
|
11726
12945
|
"rerankProvider=cloud is reserved/experimental in v2.2.0; skipping rerank"
|
|
11727
12946
|
);
|
|
11728
12947
|
}
|
|
12948
|
+
if (this.config.recallMemoryWorthFilterEnabled && results.length > 0) {
|
|
12949
|
+
try {
|
|
12950
|
+
results = await this.applyMemoryWorthRerank(results, options.recallNamespaces);
|
|
12951
|
+
} catch (err) {
|
|
12952
|
+
log.debug("memory-worth filter (cold) failed open", {
|
|
12953
|
+
error: err.message
|
|
12954
|
+
});
|
|
12955
|
+
}
|
|
12956
|
+
}
|
|
12957
|
+
if (options.xrayPoolSizeSink) {
|
|
12958
|
+
options.xrayPoolSizeSink.size = Math.max(
|
|
12959
|
+
options.xrayPoolSizeSink.size,
|
|
12960
|
+
results.length
|
|
12961
|
+
);
|
|
12962
|
+
}
|
|
11729
12963
|
return this.diversifyAndLimitRecallResults(
|
|
11730
12964
|
"memories",
|
|
11731
12965
|
results,
|
|
11732
|
-
options.recallResultLimit
|
|
12966
|
+
options.recallResultLimit,
|
|
12967
|
+
options.prompt
|
|
11733
12968
|
);
|
|
11734
12969
|
}
|
|
11735
12970
|
// ---------------------------------------------------------------------------
|
|
@@ -12123,8 +13358,8 @@ ${lines.join("\n\n")}`;
|
|
|
12123
13358
|
}
|
|
12124
13359
|
namespaceFromStorageDir(storageDir) {
|
|
12125
13360
|
if (!this.config.namespacesEnabled) return this.config.defaultNamespace;
|
|
12126
|
-
const resolvedStorageDir =
|
|
12127
|
-
const resolvedMemoryDir =
|
|
13361
|
+
const resolvedStorageDir = path7.resolve(storageDir);
|
|
13362
|
+
const resolvedMemoryDir = path7.resolve(this.config.memoryDir);
|
|
12128
13363
|
if (resolvedStorageDir === resolvedMemoryDir)
|
|
12129
13364
|
return this.config.defaultNamespace;
|
|
12130
13365
|
const m = resolvedStorageDir.match(/[\\/]namespaces[\\/]([^\\/]+)$/);
|
|
@@ -12157,6 +13392,21 @@ export {
|
|
|
12157
13392
|
migrateFromEngram,
|
|
12158
13393
|
buildProcedureRecallSection,
|
|
12159
13394
|
decideSemanticDedup,
|
|
13395
|
+
DEFAULT_TAXONOMY,
|
|
13396
|
+
generateResolverDocument,
|
|
13397
|
+
validateSlug,
|
|
13398
|
+
validateTaxonomy,
|
|
13399
|
+
loadTaxonomy,
|
|
13400
|
+
saveTaxonomy,
|
|
13401
|
+
getTaxonomyDir,
|
|
13402
|
+
getTaxonomyFilePath,
|
|
13403
|
+
stableHash,
|
|
13404
|
+
normalizeOriginUrl,
|
|
13405
|
+
resolveGitContext,
|
|
13406
|
+
projectNamespaceName,
|
|
13407
|
+
branchNamespaceName,
|
|
13408
|
+
resolveCodingNamespaceOverlay,
|
|
13409
|
+
describeCodingScope,
|
|
12160
13410
|
dedupeEntitySynthesisEvidenceEntries,
|
|
12161
13411
|
defaultWorkspaceDir,
|
|
12162
13412
|
sanitizeSessionKeyForFilename,
|
|
@@ -12185,4 +13435,4 @@ export {
|
|
|
12185
13435
|
resolvePersistedMemoryRelativePath,
|
|
12186
13436
|
Orchestrator
|
|
12187
13437
|
};
|
|
12188
|
-
//# sourceMappingURL=chunk-
|
|
13438
|
+
//# sourceMappingURL=chunk-3YGHKTBF.js.map
|