@remnic/core 9.3.741 → 9.3.743
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/access-boundary.d.ts +5 -5
- package/dist/access-boundary.js +10 -10
- package/dist/access-cli.js +32 -32
- package/dist/access-http.d.ts +5 -5
- package/dist/access-http.js +15 -15
- package/dist/access-mcp.d.ts +5 -5
- package/dist/access-mcp.js +14 -14
- package/dist/access-operations-batch.js +12 -12
- package/dist/access-operations.d.ts +5 -5
- package/dist/access-operations.js +13 -13
- package/dist/{access-service-Cbk-Kv_A.d.ts → access-service-BeW5GOg1.d.ts} +3 -3
- package/dist/access-service.d.ts +5 -5
- package/dist/access-service.js +9 -9
- package/dist/access-surface-catalog.d.ts +5 -5
- package/dist/action-confidence.d.ts +1 -1
- package/dist/active-memory-bridge.d.ts +1 -1
- package/dist/active-memory-bridge.js +3 -3
- package/dist/active-recall.d.ts +1 -1
- package/dist/{auto-sync-G3V5AN4C.js → auto-sync-XHSKKQAH.js} +2 -2
- package/dist/behavior-learner.d.ts +1 -1
- package/dist/behavior-signals.d.ts +1 -1
- package/dist/bootstrap.d.ts +4 -4
- package/dist/briefing.d.ts +1 -1
- package/dist/buffer-surprise-report.d.ts +1 -1
- package/dist/buffer.d.ts +1 -1
- package/dist/buffer.js +2 -2
- package/dist/calibration.d.ts +1 -1
- package/dist/capabilities.d.ts +10 -5
- package/dist/capabilities.js +1 -1
- package/dist/{catalog-_Bap6vfD.d.ts → catalog-CX0CjOaf.d.ts} +1 -1
- package/dist/causal-behavior.d.ts +1 -1
- package/dist/causal-consolidation.d.ts +1 -1
- package/dist/causal-consolidation.js +2 -2
- package/dist/causal-trajectory-graph.d.ts +1 -1
- package/dist/{chunk-X5PMDVY4.js → chunk-3EA5LIFJ.js} +4 -4
- package/dist/{chunk-YNHRWFAP.js → chunk-4DLFJJOQ.js} +2 -2
- package/dist/{chunk-WIMKOTNY.js → chunk-5QANTTY2.js} +2 -2
- package/dist/{chunk-QCO2QFLZ.js → chunk-5UNSGRCR.js} +7 -6
- package/dist/{chunk-QCO2QFLZ.js.map → chunk-5UNSGRCR.js.map} +1 -1
- package/dist/{chunk-Y6PNYJVO.js → chunk-A2KKLCOS.js} +2 -2
- package/dist/{chunk-O4IWVWSW.js → chunk-AVBT5WEW.js} +3 -3
- package/dist/{chunk-M5KLYHHI.js → chunk-BYLC4DKI.js} +2 -2
- package/dist/{chunk-OZECYVGI.js → chunk-C7LDPZJJ.js} +6 -4
- package/dist/{chunk-OZECYVGI.js.map → chunk-C7LDPZJJ.js.map} +1 -1
- package/dist/{chunk-UOVDO6TC.js → chunk-CHELXDTO.js} +3 -3
- package/dist/{chunk-TQQN64J2.js → chunk-DBSMLRTO.js} +2 -2
- package/dist/{chunk-4J53ZVPQ.js → chunk-DYK27X7V.js} +3 -3
- package/dist/{chunk-K2N6WIZM.js → chunk-E7RGJQWP.js} +2 -2
- package/dist/{chunk-M4WI23X3.js → chunk-EEKDRAWX.js} +2 -2
- package/dist/{chunk-H3WSZWHK.js → chunk-G5FP7VSQ.js} +13 -12
- package/dist/chunk-G5FP7VSQ.js.map +1 -0
- package/dist/{chunk-BE6NEQLF.js → chunk-HAZVVOYT.js} +3 -3
- package/dist/{chunk-OT5K26NG.js → chunk-HM6UJPPO.js} +2 -2
- package/dist/{chunk-PI4JHLDD.js → chunk-IP5SANO2.js} +2 -2
- package/dist/{chunk-WHEF76BQ.js → chunk-JRZV3767.js} +2 -2
- package/dist/{chunk-OS5RKJOH.js → chunk-JZ7P26GF.js} +2 -2
- package/dist/{chunk-Y62QPRKV.js → chunk-K5LLP4CY.js} +2 -2
- package/dist/{chunk-C3Z5YJSM.js → chunk-LOPZ2DWR.js} +2 -2
- package/dist/{chunk-BJPL5WAL.js → chunk-MXDG6SRH.js} +3 -3
- package/dist/{chunk-UYYSOMS2.js → chunk-NBP3YHHS.js} +4 -4
- package/dist/{chunk-USHVHI6J.js → chunk-NNL4LJAD.js} +3 -3
- package/dist/{chunk-GPX5E36D.js → chunk-OSMBC3JU.js} +2 -2
- package/dist/{chunk-OUSOMUFV.js → chunk-PE6XR4GG.js} +2 -2
- package/dist/{chunk-DGVM5SFL.js → chunk-PHRLJFWZ.js} +3 -2
- package/dist/{chunk-DGVM5SFL.js.map → chunk-PHRLJFWZ.js.map} +1 -1
- package/dist/{chunk-CMPXLMC3.js → chunk-PI23H7FV.js} +3 -3
- package/dist/{chunk-WGDE2TJP.js → chunk-QOGXUNWL.js} +4 -4
- package/dist/{chunk-ELL5VYXC.js → chunk-RNWWAS5V.js} +3 -3
- package/dist/{chunk-LD6A7XG5.js → chunk-TQPSOTC7.js} +7 -7
- package/dist/{chunk-AX4TRSRE.js → chunk-U5WVRMCA.js} +2 -2
- package/dist/{chunk-773DPI6T.js → chunk-V5RVMULT.js} +11 -8
- package/dist/chunk-V5RVMULT.js.map +1 -0
- package/dist/{chunk-DBVBV2RF.js → chunk-VE54E6RP.js} +4 -4
- package/dist/{chunk-VC7QELR6.js → chunk-VO4VARZL.js} +1054 -869
- package/dist/chunk-VO4VARZL.js.map +1 -0
- package/dist/{chunk-G7Q4D2G3.js → chunk-VSF7AAGE.js} +1 -3
- package/dist/chunk-VSF7AAGE.js.map +1 -0
- package/dist/{chunk-OVYBENIJ.js → chunk-W3M34XT4.js} +3 -3
- package/dist/{chunk-XPOOY35N.js → chunk-W4H5A3TJ.js} +3 -2
- package/dist/chunk-W4H5A3TJ.js.map +1 -0
- package/dist/{chunk-7Y5KKMIP.js → chunk-WPLRJ4XM.js} +9 -8
- package/dist/{chunk-7Y5KKMIP.js.map → chunk-WPLRJ4XM.js.map} +1 -1
- package/dist/{chunk-3TUDKDTQ.js → chunk-XEADGIAA.js} +6 -6
- package/dist/{cli-BQW2xKdb.d.ts → cli-BYad9YYY.d.ts} +3 -3
- package/dist/cli.d.ts +6 -6
- package/dist/cli.js +21 -21
- package/dist/compounding/engine.d.ts +1 -1
- package/dist/compounding/engine.js +3 -3
- package/dist/compounding/preference-consolidator.d.ts +1 -1
- package/dist/compression-optimizer.d.ts +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/connectors/codex-materialize-runner.d.ts +1 -1
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +2 -2
- package/dist/consolidation-provenance-check.d.ts +1 -1
- package/dist/consolidation-undo.d.ts +1 -1
- package/dist/contradiction/index.d.ts +1 -1
- package/dist/contradiction/index.js +2 -2
- package/dist/{contradiction-scan-UERKJESC.js → contradiction-scan-3FJYWS3G.js} +3 -3
- package/dist/conversation-index/backend.d.ts +1 -1
- package/dist/conversation-index/chunker.d.ts +1 -1
- package/dist/conversation-index/faiss-adapter.d.ts +1 -1
- package/dist/conversation-index/indexer.d.ts +1 -1
- package/dist/conversation-index/search.d.ts +1 -1
- package/dist/day-summary.d.ts +1 -1
- package/dist/day-summary.js +2 -2
- package/dist/delinearize.d.ts +1 -1
- package/dist/direct-answer-wiring.d.ts +1 -1
- package/dist/direct-answer.d.ts +1 -1
- package/dist/embedding-fallback.d.ts +1 -1
- package/dist/embedding-fallback.js +2 -2
- package/dist/enrichment/index.d.ts +1 -1
- package/dist/entity-retrieval.d.ts +1 -1
- package/dist/entity-retrieval.js +2 -2
- package/dist/entity-schema.d.ts +1 -1
- package/dist/explicit-capture.d.ts +4 -4
- package/dist/explicit-capture.js +2 -2
- package/dist/extraction-faithfulness.d.ts +1 -1
- package/dist/extraction-judge-telemetry.d.ts +1 -1
- package/dist/extraction-judge-training.d.ts +1 -1
- package/dist/extraction-judge.d.ts +1 -1
- package/dist/extraction.d.ts +1 -1
- package/dist/extraction.js +4 -4
- package/dist/fallback-llm.d.ts +1 -1
- package/dist/{first-start-migration-GQ3UQNIL.js → first-start-migration-4I3VDSYS.js} +2 -2
- package/dist/graph-dashboard-diff.d.ts +1 -1
- package/dist/graph-dashboard-key.d.ts +1 -1
- package/dist/graph-dashboard-parser.d.ts +1 -1
- package/dist/graph-edge-reinforcement.d.ts +1 -1
- package/dist/graph-recall.js +1 -1
- package/dist/graph-snapshot.d.ts +1 -1
- package/dist/graph.d.ts +1 -1
- package/dist/identity-continuity.d.ts +1 -1
- package/dist/importance.d.ts +1 -1
- package/dist/index.d.ts +9 -9
- package/dist/index.js +40 -40
- package/dist/intent.d.ts +1 -1
- package/dist/lcm/engine.d.ts +1 -1
- package/dist/lcm/engine.js +2 -2
- package/dist/lcm/index.d.ts +1 -1
- package/dist/lcm/index.js +2 -2
- package/dist/lcm/summarizer.js +1 -1
- package/dist/lcm/tools.d.ts +1 -1
- package/dist/lifecycle.d.ts +1 -1
- package/dist/live-connectors-runner.d.ts +1 -1
- package/dist/local-llm.d.ts +1 -1
- package/dist/local-llm.js +2 -2
- package/dist/local-model-endpoint.d.ts +1 -1
- package/dist/maintenance/memory-governance.d.ts +1 -1
- package/dist/mcp-memory-inspector-app.d.ts +5 -5
- package/dist/memory-action-policy.d.ts +1 -1
- package/dist/memory-cache.d.ts +1 -1
- package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
- package/dist/memory-projection-store.d.ts +1 -1
- package/dist/memory-provenance.d.ts +1 -1
- package/dist/memory-worth-outcomes.d.ts +1 -1
- package/dist/models-json.d.ts +1 -1
- package/dist/namespaces/migrate.d.ts +2 -2
- package/dist/namespaces/migrate.js +6 -6
- package/dist/namespaces/principal.d.ts +1 -1
- package/dist/namespaces/principal.js +2 -2
- package/dist/namespaces/search.d.ts +1 -1
- package/dist/namespaces/search.js +4 -4
- package/dist/namespaces/storage.d.ts +2 -2
- package/dist/namespaces/storage.js +2 -2
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +1 -1
- package/dist/operator-toolkit.js +11 -11
- package/dist/orchestration/compression-guideline-coordinator.d.ts +1 -1
- package/dist/orchestration/compression-guideline-coordinator.js +2 -2
- package/dist/orchestration/maintenance.d.ts +2 -2
- package/dist/orchestration/maintenance.js +6 -6
- package/dist/{orchestrator-BOAFN_Yr.d.ts → orchestrator-CupigmWu.d.ts} +221 -7
- package/dist/orchestrator.d.ts +4 -4
- package/dist/orchestrator.js +27 -27
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/policy-runtime.d.ts +1 -1
- package/dist/provenance.d.ts +1 -1
- package/dist/qmd-recall-cache.d.ts +1 -1
- package/dist/qmd.d.ts +1 -1
- package/dist/recall-disclosure-escalation.d.ts +1 -1
- package/dist/recall-explain-renderer.d.ts +1 -1
- package/dist/recall-planner-llm.d.ts +1 -1
- package/dist/recall-state.d.ts +1 -1
- package/dist/recall-tag-filter.d.ts +1 -1
- package/dist/recall-xray-cli.d.ts +1 -1
- package/dist/recall-xray-renderer.d.ts +1 -1
- package/dist/recall-xray.d.ts +1 -1
- package/dist/resolve-auth-token.d.ts +1 -1
- package/dist/retrieval-agents.d.ts +1 -1
- package/dist/retrieval-tiers.d.ts +1 -1
- package/dist/routing/engine.d.ts +1 -1
- package/dist/routing/store.d.ts +1 -1
- package/dist/search/embed-helper.d.ts +1 -1
- package/dist/search/embed-helper.js +2 -2
- package/dist/search/factory.d.ts +1 -1
- package/dist/search/factory.js +3 -3
- package/dist/search/index.d.ts +1 -1
- package/dist/search/index.js +3 -3
- package/dist/search/lancedb-backend.d.ts +1 -1
- package/dist/search/meilisearch-backend.d.ts +1 -1
- package/dist/search/noop-backend.d.ts +1 -1
- package/dist/search/orama-backend.d.ts +1 -1
- package/dist/search/port.d.ts +1 -1
- package/dist/search/remote-backend.d.ts +1 -1
- package/dist/{semantic-consolidation-DsIEiCka.d.ts → semantic-consolidation-ByzGwC9c.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +2 -2
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/session-observer-bands.d.ts +1 -1
- package/dist/session-observer-state.d.ts +1 -1
- package/dist/shared-context/manager.d.ts +1 -1
- package/dist/shared-context/manager.js +2 -2
- package/dist/signal.d.ts +1 -1
- package/dist/storage.d.ts +1 -1
- package/dist/summarizer.d.ts +1 -1
- package/dist/summarizer.js +3 -3
- package/dist/summary-snapshot.d.ts +1 -1
- package/dist/temporal-supersession.d.ts +1 -1
- package/dist/temporal-validity.d.ts +1 -1
- package/dist/threading.d.ts +1 -1
- package/dist/tier-migration.d.ts +1 -1
- package/dist/tier-routing.d.ts +1 -1
- package/dist/{tier-stats-CSKL7BDG.js → tier-stats-5XF4UBRQ.js} +2 -2
- package/dist/topics.d.ts +1 -1
- package/dist/transcript.d.ts +1 -1
- package/dist/trust-score-stage.d.ts +1 -1
- package/dist/trust-score.d.ts +1 -1
- package/dist/{types-CglNn2V-.d.ts → types-5Jik3r4G.d.ts} +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/utility-runtime.d.ts +1 -1
- package/package.json +2 -2
- package/src/capabilities.test.ts +0 -2
- package/src/capabilities.ts +7 -6
- package/src/cli.ts +2 -1
- package/src/graph-recall.ts +2 -1
- package/src/lcm/engine.ts +9 -6
- package/src/lcm/summarizer.ts +2 -1
- package/src/operator-toolkit.ts +2 -1
- package/src/orchestration/contradiction-linking-coordinator.ts +336 -0
- package/src/orchestration/qmd-result-resolver.ts +377 -0
- package/src/orchestration/recall-section-coordinator.ts +349 -0
- package/src/orchestrator.ts +81 -679
- package/src/procedural/procedure-stats.ts +2 -1
- package/src/wearables/pipeline.ts +5 -3
- package/dist/chunk-773DPI6T.js.map +0 -1
- package/dist/chunk-G7Q4D2G3.js.map +0 -1
- package/dist/chunk-H3WSZWHK.js.map +0 -1
- package/dist/chunk-VC7QELR6.js.map +0 -1
- package/dist/chunk-XPOOY35N.js.map +0 -1
- /package/dist/{auto-sync-G3V5AN4C.js.map → auto-sync-XHSKKQAH.js.map} +0 -0
- /package/dist/{chunk-X5PMDVY4.js.map → chunk-3EA5LIFJ.js.map} +0 -0
- /package/dist/{chunk-YNHRWFAP.js.map → chunk-4DLFJJOQ.js.map} +0 -0
- /package/dist/{chunk-WIMKOTNY.js.map → chunk-5QANTTY2.js.map} +0 -0
- /package/dist/{chunk-Y6PNYJVO.js.map → chunk-A2KKLCOS.js.map} +0 -0
- /package/dist/{chunk-O4IWVWSW.js.map → chunk-AVBT5WEW.js.map} +0 -0
- /package/dist/{chunk-M5KLYHHI.js.map → chunk-BYLC4DKI.js.map} +0 -0
- /package/dist/{chunk-UOVDO6TC.js.map → chunk-CHELXDTO.js.map} +0 -0
- /package/dist/{chunk-TQQN64J2.js.map → chunk-DBSMLRTO.js.map} +0 -0
- /package/dist/{chunk-4J53ZVPQ.js.map → chunk-DYK27X7V.js.map} +0 -0
- /package/dist/{chunk-K2N6WIZM.js.map → chunk-E7RGJQWP.js.map} +0 -0
- /package/dist/{chunk-M4WI23X3.js.map → chunk-EEKDRAWX.js.map} +0 -0
- /package/dist/{chunk-BE6NEQLF.js.map → chunk-HAZVVOYT.js.map} +0 -0
- /package/dist/{chunk-OT5K26NG.js.map → chunk-HM6UJPPO.js.map} +0 -0
- /package/dist/{chunk-PI4JHLDD.js.map → chunk-IP5SANO2.js.map} +0 -0
- /package/dist/{chunk-WHEF76BQ.js.map → chunk-JRZV3767.js.map} +0 -0
- /package/dist/{chunk-OS5RKJOH.js.map → chunk-JZ7P26GF.js.map} +0 -0
- /package/dist/{chunk-Y62QPRKV.js.map → chunk-K5LLP4CY.js.map} +0 -0
- /package/dist/{chunk-C3Z5YJSM.js.map → chunk-LOPZ2DWR.js.map} +0 -0
- /package/dist/{chunk-BJPL5WAL.js.map → chunk-MXDG6SRH.js.map} +0 -0
- /package/dist/{chunk-UYYSOMS2.js.map → chunk-NBP3YHHS.js.map} +0 -0
- /package/dist/{chunk-USHVHI6J.js.map → chunk-NNL4LJAD.js.map} +0 -0
- /package/dist/{chunk-GPX5E36D.js.map → chunk-OSMBC3JU.js.map} +0 -0
- /package/dist/{chunk-OUSOMUFV.js.map → chunk-PE6XR4GG.js.map} +0 -0
- /package/dist/{chunk-CMPXLMC3.js.map → chunk-PI23H7FV.js.map} +0 -0
- /package/dist/{chunk-WGDE2TJP.js.map → chunk-QOGXUNWL.js.map} +0 -0
- /package/dist/{chunk-ELL5VYXC.js.map → chunk-RNWWAS5V.js.map} +0 -0
- /package/dist/{chunk-LD6A7XG5.js.map → chunk-TQPSOTC7.js.map} +0 -0
- /package/dist/{chunk-AX4TRSRE.js.map → chunk-U5WVRMCA.js.map} +0 -0
- /package/dist/{chunk-DBVBV2RF.js.map → chunk-VE54E6RP.js.map} +0 -0
- /package/dist/{chunk-OVYBENIJ.js.map → chunk-W3M34XT4.js.map} +0 -0
- /package/dist/{chunk-3TUDKDTQ.js.map → chunk-XEADGIAA.js.map} +0 -0
- /package/dist/{contradiction-scan-UERKJESC.js.map → contradiction-scan-3FJYWS3G.js.map} +0 -0
- /package/dist/{first-start-migration-GQ3UQNIL.js.map → first-start-migration-4I3VDSYS.js.map} +0 -0
- /package/dist/{tier-stats-CSKL7BDG.js.map → tier-stats-5XF4UBRQ.js.map} +0 -0
package/src/orchestrator.ts
CHANGED
|
@@ -104,6 +104,9 @@ import { EntitySynthesisCoordinator } from "./orchestration/entity-synthesis-coo
|
|
|
104
104
|
import { RecallResultFormatter } from "./orchestration/recall-result-formatter.js";
|
|
105
105
|
import { ConversationIndexCoordinator } from "./orchestration/conversation-index-coordinator.js";
|
|
106
106
|
import { RecallRerankCoordinator } from "./orchestration/recall-rerank-coordinator.js";
|
|
107
|
+
import { RecallSectionCoordinator } from "./orchestration/recall-section-coordinator.js";
|
|
108
|
+
import { QmdResultResolver, qmdCollectionPathParts, qmdResultPathCandidates } from "./orchestration/qmd-result-resolver.js";
|
|
109
|
+
import { ContradictionLinkingCoordinator } from "./orchestration/contradiction-linking-coordinator.js";
|
|
107
110
|
export { hasIdentityRecoveryIntent, resolveEffectiveIdentityInjectionMode } from "./orchestration/recall-result-formatter.js";
|
|
108
111
|
import {
|
|
109
112
|
runLiveConnectorsOnce,
|
|
@@ -738,52 +741,6 @@ async function raceRecallAbort<T>(
|
|
|
738
741
|
}
|
|
739
742
|
}
|
|
740
743
|
|
|
741
|
-
function qmdCollectionPathParts(resultPath: string): {
|
|
742
|
-
collection: string;
|
|
743
|
-
relativePath: string;
|
|
744
|
-
} | null {
|
|
745
|
-
if (!resultPath || path.isAbsolute(resultPath)) return null;
|
|
746
|
-
const normalized = resultPath.replace(/\\/g, "/").replace(/^\/+/, "");
|
|
747
|
-
const slashIndex = normalized.indexOf("/");
|
|
748
|
-
if (slashIndex <= 0 || slashIndex >= normalized.length - 1) return null;
|
|
749
|
-
const collection = normalized.slice(0, slashIndex);
|
|
750
|
-
if (/^\d{4}-\d{2}-\d{2}$/.test(collection)) return null;
|
|
751
|
-
return {
|
|
752
|
-
collection,
|
|
753
|
-
relativePath: normalized.slice(slashIndex + 1),
|
|
754
|
-
};
|
|
755
|
-
}
|
|
756
|
-
|
|
757
|
-
function qmdResultPathCandidates(
|
|
758
|
-
storageDir: string,
|
|
759
|
-
resultPath: string,
|
|
760
|
-
): string[] {
|
|
761
|
-
const candidates = new Set<string>();
|
|
762
|
-
const storageRoot = path.resolve(storageDir);
|
|
763
|
-
const addCandidate = (candidate: string) => {
|
|
764
|
-
const resolved = path.resolve(candidate);
|
|
765
|
-
if (isPathInsideStorageRoot(storageRoot, resolved)) {
|
|
766
|
-
candidates.add(resolved);
|
|
767
|
-
}
|
|
768
|
-
};
|
|
769
|
-
const addRelativeCandidates = (relativePath: string) => {
|
|
770
|
-
const normalized = relativePath.replace(/\\/g, "/").replace(/^\/+/, "");
|
|
771
|
-
if (!normalized) return;
|
|
772
|
-
addCandidate(path.join(storageRoot, normalized));
|
|
773
|
-
if (/^\d{4}-\d{2}-\d{2}\//.test(normalized)) {
|
|
774
|
-
addCandidate(path.join(storageRoot, "facts", normalized));
|
|
775
|
-
}
|
|
776
|
-
};
|
|
777
|
-
|
|
778
|
-
if (path.isAbsolute(resultPath)) {
|
|
779
|
-
addCandidate(resultPath);
|
|
780
|
-
} else {
|
|
781
|
-
addRelativeCandidates(resultPath);
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
return [...candidates];
|
|
785
|
-
}
|
|
786
|
-
|
|
787
744
|
/** Maximum age (ms) before a compaction-reset signal file is considered stale and removed. */
|
|
788
745
|
const COMPACTION_SIGNAL_MAX_AGE_MS = 60 * 60 * 1000; // 1 hour
|
|
789
746
|
const DEFAULT_QMD_STARTUP_COLLECTION_CHECK_TIMEOUT_MS = 10_000;
|
|
@@ -1885,6 +1842,9 @@ export class Orchestrator {
|
|
|
1885
1842
|
*/
|
|
1886
1843
|
readonly conversationIndexCoordinator: ConversationIndexCoordinator;
|
|
1887
1844
|
readonly recallRerankCoordinator: RecallRerankCoordinator;
|
|
1845
|
+
readonly recallSectionCoordinator: RecallSectionCoordinator;
|
|
1846
|
+
readonly qmdResultResolver: QmdResultResolver;
|
|
1847
|
+
readonly contradictionLinkingCoordinator: ContradictionLinkingCoordinator;
|
|
1888
1848
|
private heartbeatObserverChains = new Map<string, Promise<void>>();
|
|
1889
1849
|
private recentExtractionFingerprints = new Map<string, number>();
|
|
1890
1850
|
private readonly consolidationObservers = new Set<
|
|
@@ -2885,6 +2845,19 @@ export class Orchestrator {
|
|
|
2885
2845
|
readQmdResultMemory: (resultPath, fallbackStorage, recallNamespaces) =>
|
|
2886
2846
|
this.readQmdResultMemory(resultPath, fallbackStorage, recallNamespaces),
|
|
2887
2847
|
});
|
|
2848
|
+
this.recallSectionCoordinator = new RecallSectionCoordinator({
|
|
2849
|
+
getConfig: () => this.config,
|
|
2850
|
+
resolveSectionEnabled: (id, def) => this.isRecallSectionEnabled(id, def),
|
|
2851
|
+
});
|
|
2852
|
+
this.contradictionLinkingCoordinator = new ContradictionLinkingCoordinator({
|
|
2853
|
+
getConfig: () => this.config,
|
|
2854
|
+
isSearchAvailable: () => this.isSearchAvailableForNamespaceRouting(),
|
|
2855
|
+
searchAcrossNamespaces: (options) => this.searchAcrossNamespaces(options),
|
|
2856
|
+
extractMemoryIdsFromResults: (results) => this.extractMemoryIdsFromResults(results),
|
|
2857
|
+
namespaceFromPath: (p) => this.namespaceFromPath(p),
|
|
2858
|
+
storageForNamespace: (namespace) => this.storageRouter.storageFor(namespace),
|
|
2859
|
+
getExtraction: () => this.extraction,
|
|
2860
|
+
});
|
|
2888
2861
|
this.modelRegistry = new ModelRegistry(config.memoryDir);
|
|
2889
2862
|
this.relevance = new RelevanceStore(config.memoryDir);
|
|
2890
2863
|
this.negatives = new NegativeExampleStore(config.memoryDir);
|
|
@@ -2913,6 +2886,13 @@ export class Orchestrator {
|
|
|
2913
2886
|
fastChatCompletion: (messages, options) =>
|
|
2914
2887
|
this.fastChatCompletion(messages, options),
|
|
2915
2888
|
});
|
|
2889
|
+
this.qmdResultResolver = new QmdResultResolver({
|
|
2890
|
+
getConfig: () => this.config,
|
|
2891
|
+
storageFor: (namespace) => this.storageRouter.storageFor(namespace),
|
|
2892
|
+
storageDirNamespace: (storageDir) => this.storageDirNamespace(storageDir),
|
|
2893
|
+
qmdCollectionNamespaceFromPrefix: (prefix) => this.qmdCollectionNamespaceFromPrefix(prefix),
|
|
2894
|
+
namespaceFromPath: (p) => this.namespaceFromPath(p),
|
|
2895
|
+
});
|
|
2916
2896
|
|
|
2917
2897
|
this.sessionObserver = new SessionObserverState({
|
|
2918
2898
|
memoryDir: config.memoryDir,
|
|
@@ -6414,52 +6394,46 @@ export class Orchestrator {
|
|
|
6414
6394
|
}));
|
|
6415
6395
|
}
|
|
6416
6396
|
|
|
6397
|
+
// Issue #1526 (seam 13): recall section budgeting/assembly moved to
|
|
6398
|
+
// RecallSectionCoordinator. Thin delegation keeps the orchestrator's
|
|
6399
|
+
// recallInternal call sites stable.
|
|
6417
6400
|
private getRecallSectionEntry(
|
|
6418
6401
|
sectionId: string,
|
|
6419
6402
|
): RecallSectionConfig | undefined {
|
|
6420
|
-
|
|
6421
|
-
? this.config.recallPipeline
|
|
6422
|
-
: [];
|
|
6423
|
-
return pipeline.find((entry) => entry.id === sectionId);
|
|
6403
|
+
return this.recallSectionCoordinator.getRecallSectionEntry(sectionId);
|
|
6424
6404
|
}
|
|
6425
6405
|
|
|
6426
6406
|
private isRecallSectionEnabled(
|
|
6427
6407
|
sectionId: string,
|
|
6428
6408
|
defaultEnabled: boolean = true,
|
|
6429
6409
|
): boolean {
|
|
6430
|
-
|
|
6431
|
-
|
|
6432
|
-
|
|
6410
|
+
return this.recallSectionCoordinator.isRecallSectionEnabled(
|
|
6411
|
+
sectionId,
|
|
6412
|
+
defaultEnabled,
|
|
6413
|
+
);
|
|
6433
6414
|
}
|
|
6434
6415
|
|
|
6435
6416
|
private isSpecializedRecallSectionEnabled(
|
|
6436
6417
|
sectionId: string,
|
|
6437
6418
|
topLevelEnabled: boolean,
|
|
6438
6419
|
): boolean {
|
|
6439
|
-
|
|
6440
|
-
|
|
6441
|
-
|
|
6420
|
+
return this.recallSectionCoordinator.isSpecializedRecallSectionEnabled(
|
|
6421
|
+
sectionId,
|
|
6422
|
+
topLevelEnabled,
|
|
6423
|
+
);
|
|
6442
6424
|
}
|
|
6443
6425
|
|
|
6444
6426
|
private getRecallSectionMaxChars(
|
|
6445
6427
|
sectionId: string,
|
|
6446
6428
|
): number | null | undefined {
|
|
6447
|
-
|
|
6448
|
-
if (!entry) return undefined;
|
|
6449
|
-
if (entry.maxChars === null) return null;
|
|
6450
|
-
if (typeof entry.maxChars !== "number") return undefined;
|
|
6451
|
-
return Math.max(0, Math.floor(entry.maxChars));
|
|
6429
|
+
return this.recallSectionCoordinator.getRecallSectionMaxChars(sectionId);
|
|
6452
6430
|
}
|
|
6453
6431
|
|
|
6454
6432
|
private getRecallSectionNumber(
|
|
6455
6433
|
sectionId: string,
|
|
6456
6434
|
key: keyof RecallSectionConfig,
|
|
6457
6435
|
): number | undefined {
|
|
6458
|
-
|
|
6459
|
-
if (!entry) return undefined;
|
|
6460
|
-
const value = entry[key];
|
|
6461
|
-
if (typeof value !== "number" || !Number.isFinite(value)) return undefined;
|
|
6462
|
-
return Math.max(0, Math.floor(value));
|
|
6436
|
+
return this.recallSectionCoordinator.getRecallSectionNumber(sectionId, key);
|
|
6463
6437
|
}
|
|
6464
6438
|
|
|
6465
6439
|
private appendRecallSection(
|
|
@@ -6467,104 +6441,25 @@ export class Orchestrator {
|
|
|
6467
6441
|
sectionId: string,
|
|
6468
6442
|
content: string,
|
|
6469
6443
|
): boolean {
|
|
6470
|
-
|
|
6471
|
-
|
|
6472
|
-
|
|
6473
|
-
|
|
6474
|
-
|
|
6475
|
-
if (!this.isRecallSectionEnabled(sectionId)) return false;
|
|
6476
|
-
const trimmed = content.trim();
|
|
6477
|
-
if (trimmed.length === 0) return false;
|
|
6478
|
-
|
|
6479
|
-
const maxChars = this.getRecallSectionMaxChars(sectionId);
|
|
6480
|
-
let finalContent = trimmed;
|
|
6481
|
-
if (maxChars === 0) return false;
|
|
6482
|
-
if (typeof maxChars === "number" && finalContent.length > maxChars) {
|
|
6483
|
-
finalContent = `${finalContent.slice(0, maxChars)}\n\n...(trimmed)\n`;
|
|
6484
|
-
}
|
|
6485
|
-
|
|
6486
|
-
const existing = sectionBuckets.get(sectionId) ?? [];
|
|
6487
|
-
existing.push(finalContent);
|
|
6488
|
-
sectionBuckets.set(sectionId, existing);
|
|
6489
|
-
return true;
|
|
6444
|
+
return this.recallSectionCoordinator.appendRecallSection(
|
|
6445
|
+
sectionBuckets,
|
|
6446
|
+
sectionId,
|
|
6447
|
+
content,
|
|
6448
|
+
);
|
|
6490
6449
|
}
|
|
6491
6450
|
|
|
6492
6451
|
private truncateRecallSectionToBudget(
|
|
6493
6452
|
content: string,
|
|
6494
6453
|
maxChars: number,
|
|
6495
6454
|
): string {
|
|
6496
|
-
|
|
6497
|
-
|
|
6498
|
-
|
|
6499
|
-
|
|
6500
|
-
return content.slice(0, maxChars);
|
|
6501
|
-
}
|
|
6502
|
-
return `${content.slice(0, maxChars - suffix.length)}${suffix}`;
|
|
6503
|
-
}
|
|
6504
|
-
|
|
6505
|
-
private protectedRecallSectionIds(
|
|
6506
|
-
sectionBuckets: Map<string, string[]>,
|
|
6507
|
-
): Set<string> {
|
|
6508
|
-
const protectedIds = new Set<string>();
|
|
6509
|
-
if ((sectionBuckets.get("memories")?.length ?? 0) > 0) {
|
|
6510
|
-
protectedIds.add("memories");
|
|
6511
|
-
}
|
|
6512
|
-
return protectedIds;
|
|
6513
|
-
}
|
|
6514
|
-
|
|
6515
|
-
private protectedRecallReservationChars(content: string): number {
|
|
6516
|
-
const headingBoundary = content.indexOf("\n\n");
|
|
6517
|
-
const headingChars =
|
|
6518
|
-
headingBoundary >= 0 ? headingBoundary + 2 : Math.min(content.length, 24);
|
|
6519
|
-
return Math.min(content.length, Math.max(headingChars, 24));
|
|
6520
|
-
}
|
|
6521
|
-
|
|
6522
|
-
private estimateReservedRecallBudget(
|
|
6523
|
-
entries: Array<{ id: string; content: string }>,
|
|
6524
|
-
startIndex: number,
|
|
6525
|
-
protectedIds: Set<string>,
|
|
6526
|
-
alreadyIncludedCount: number,
|
|
6527
|
-
): number {
|
|
6528
|
-
const separatorLength = "\n\n---\n\n".length;
|
|
6529
|
-
let reserved = 0;
|
|
6530
|
-
let simulatedIncluded = alreadyIncludedCount;
|
|
6531
|
-
for (let i = startIndex; i < entries.length; i += 1) {
|
|
6532
|
-
const entry = entries[i];
|
|
6533
|
-
if (!entry || !protectedIds.has(entry.id)) continue;
|
|
6534
|
-
if (simulatedIncluded > 0) {
|
|
6535
|
-
reserved += separatorLength;
|
|
6536
|
-
}
|
|
6537
|
-
reserved += this.protectedRecallReservationChars(entry.content);
|
|
6538
|
-
simulatedIncluded += 1;
|
|
6539
|
-
}
|
|
6540
|
-
return reserved;
|
|
6455
|
+
return this.recallSectionCoordinator.truncateRecallSectionToBudget(
|
|
6456
|
+
content,
|
|
6457
|
+
maxChars,
|
|
6458
|
+
);
|
|
6541
6459
|
}
|
|
6542
6460
|
|
|
6543
6461
|
private getRecallBudgetChars(override?: number): number {
|
|
6544
|
-
|
|
6545
|
-
typeof override === "number" &&
|
|
6546
|
-
Number.isFinite(override) &&
|
|
6547
|
-
override >= 0
|
|
6548
|
-
) {
|
|
6549
|
-
return Math.floor(override);
|
|
6550
|
-
}
|
|
6551
|
-
const configuredBudget = this.config.recallBudgetChars;
|
|
6552
|
-
if (
|
|
6553
|
-
typeof configuredBudget === "number" &&
|
|
6554
|
-
Number.isFinite(configuredBudget) &&
|
|
6555
|
-
configuredBudget >= 0
|
|
6556
|
-
) {
|
|
6557
|
-
return Math.floor(configuredBudget);
|
|
6558
|
-
}
|
|
6559
|
-
const tokenBudget = this.config.maxMemoryTokens;
|
|
6560
|
-
if (
|
|
6561
|
-
typeof tokenBudget === "number" &&
|
|
6562
|
-
Number.isFinite(tokenBudget) &&
|
|
6563
|
-
tokenBudget >= 0
|
|
6564
|
-
) {
|
|
6565
|
-
return Math.floor(tokenBudget * 4);
|
|
6566
|
-
}
|
|
6567
|
-
return 0;
|
|
6462
|
+
return this.recallSectionCoordinator.getRecallBudgetChars(override);
|
|
6568
6463
|
}
|
|
6569
6464
|
|
|
6570
6465
|
private assembleRecallSections(
|
|
@@ -6577,89 +6472,13 @@ export class Orchestrator {
|
|
|
6577
6472
|
truncated: boolean;
|
|
6578
6473
|
finalChars: number;
|
|
6579
6474
|
} {
|
|
6580
|
-
|
|
6581
|
-
|
|
6582
|
-
|
|
6583
|
-
|
|
6584
|
-
|
|
6585
|
-
.filter((entry) => entry.enabled !== false)
|
|
6586
|
-
.map((entry) => entry.id);
|
|
6587
|
-
const seen = new Set<string>();
|
|
6588
|
-
|
|
6589
|
-
for (const id of orderedIds) {
|
|
6590
|
-
const chunks = sectionBuckets.get(id);
|
|
6591
|
-
if (!chunks || chunks.length === 0) continue;
|
|
6592
|
-
orderedEntries.push({ id, content: chunks.join("\n\n") });
|
|
6593
|
-
seen.add(id);
|
|
6594
|
-
}
|
|
6595
|
-
|
|
6596
|
-
for (const [id, chunks] of sectionBuckets.entries()) {
|
|
6597
|
-
if (seen.has(id)) continue;
|
|
6598
|
-
if (chunks.length === 0) continue;
|
|
6599
|
-
orderedEntries.push({ id, content: chunks.join("\n\n") });
|
|
6600
|
-
}
|
|
6601
|
-
|
|
6602
|
-
const budget = this.getRecallBudgetChars(budgetOverride);
|
|
6603
|
-
if (budget === 0) {
|
|
6604
|
-
return {
|
|
6605
|
-
sections: [],
|
|
6606
|
-
includedIds: [],
|
|
6607
|
-
omittedIds: orderedEntries.map((entry) => entry.id),
|
|
6608
|
-
truncated: orderedEntries.length > 0,
|
|
6609
|
-
finalChars: 0,
|
|
6610
|
-
};
|
|
6611
|
-
}
|
|
6612
|
-
|
|
6613
|
-
const separator = "\n\n---\n\n";
|
|
6614
|
-
const protectedIds = this.protectedRecallSectionIds(sectionBuckets);
|
|
6615
|
-
const sections: string[] = [];
|
|
6616
|
-
const includedIds: string[] = [];
|
|
6617
|
-
const omittedIds: string[] = [];
|
|
6618
|
-
let usedChars = 0;
|
|
6619
|
-
let truncated = false;
|
|
6475
|
+
return this.recallSectionCoordinator.assembleRecallSections(
|
|
6476
|
+
sectionBuckets,
|
|
6477
|
+
budgetOverride,
|
|
6478
|
+
);
|
|
6479
|
+
}
|
|
6620
6480
|
|
|
6621
|
-
for (let index = 0; index < orderedEntries.length; index += 1) {
|
|
6622
|
-
const entry = orderedEntries[index]!;
|
|
6623
|
-
const separatorChars = sections.length > 0 ? separator.length : 0;
|
|
6624
|
-
const reserve = protectedIds.has(entry.id)
|
|
6625
|
-
? 0
|
|
6626
|
-
: this.estimateReservedRecallBudget(
|
|
6627
|
-
orderedEntries,
|
|
6628
|
-
index + 1,
|
|
6629
|
-
protectedIds,
|
|
6630
|
-
sections.length + 1,
|
|
6631
|
-
);
|
|
6632
|
-
const availableForEntry = budget - usedChars - separatorChars - reserve;
|
|
6633
|
-
if (availableForEntry <= 0) {
|
|
6634
|
-
omittedIds.push(entry.id);
|
|
6635
|
-
truncated = true;
|
|
6636
|
-
continue;
|
|
6637
|
-
}
|
|
6638
|
-
const finalContent = this.truncateRecallSectionToBudget(
|
|
6639
|
-
entry.content,
|
|
6640
|
-
availableForEntry,
|
|
6641
|
-
);
|
|
6642
|
-
if (!finalContent) {
|
|
6643
|
-
omittedIds.push(entry.id);
|
|
6644
|
-
truncated = true;
|
|
6645
|
-
continue;
|
|
6646
|
-
}
|
|
6647
|
-
if (finalContent.length < entry.content.length) {
|
|
6648
|
-
truncated = true;
|
|
6649
|
-
}
|
|
6650
|
-
sections.push(finalContent);
|
|
6651
|
-
includedIds.push(entry.id);
|
|
6652
|
-
usedChars += separatorChars + finalContent.length;
|
|
6653
|
-
}
|
|
6654
6481
|
|
|
6655
|
-
return {
|
|
6656
|
-
sections,
|
|
6657
|
-
includedIds,
|
|
6658
|
-
omittedIds,
|
|
6659
|
-
truncated,
|
|
6660
|
-
finalChars: usedChars,
|
|
6661
|
-
};
|
|
6662
|
-
}
|
|
6663
6482
|
|
|
6664
6483
|
/**
|
|
6665
6484
|
* Clock source for the shared post-retrieval assembly/enrichment budget. The
|
|
@@ -16898,143 +16717,14 @@ export class Orchestrator {
|
|
|
16898
16717
|
return null;
|
|
16899
16718
|
}
|
|
16900
16719
|
|
|
16720
|
+
// Issue #1526 seam 11: QMD result-resolution methods moved to QmdResultResolver.
|
|
16721
|
+
// Thin delegation keeps the private API stable for callers + tests.
|
|
16901
16722
|
private async readQmdResultMemory(
|
|
16902
16723
|
resultPath: string,
|
|
16903
16724
|
fallbackStorage: StorageManager,
|
|
16904
16725
|
recallNamespaces: readonly string[] = [],
|
|
16905
16726
|
): Promise<MemoryFile | null> {
|
|
16906
|
-
|
|
16907
|
-
const storageDirFor = (storage: StorageManager): string | null =>
|
|
16908
|
-
typeof (storage as { dir?: unknown }).dir === "string" &&
|
|
16909
|
-
(storage as { dir?: string }).dir
|
|
16910
|
-
? (storage as { dir: string }).dir
|
|
16911
|
-
: null;
|
|
16912
|
-
const fallbackStorageDir = storageDirFor(fallbackStorage);
|
|
16913
|
-
const coldCollection = this.config.qmdColdCollection ?? "openclaw-engram-cold";
|
|
16914
|
-
if (parts && parts.collection === coldCollection) {
|
|
16915
|
-
const storages: StorageManager[] = [];
|
|
16916
|
-
const seenStorageDirs = new Set<string>();
|
|
16917
|
-
const addStorage = (storage: StorageManager): void => {
|
|
16918
|
-
const storageDir = storageDirFor(storage);
|
|
16919
|
-
const storageKey = storageDir
|
|
16920
|
-
? path.resolve(storageDir)
|
|
16921
|
-
: `storage-without-dir-${storages.length}`;
|
|
16922
|
-
if (seenStorageDirs.has(storageKey)) return;
|
|
16923
|
-
seenStorageDirs.add(storageKey);
|
|
16924
|
-
storages.push(storage);
|
|
16925
|
-
};
|
|
16926
|
-
|
|
16927
|
-
const fallbackNamespace =
|
|
16928
|
-
fallbackStorageDir !== null
|
|
16929
|
-
? this.storageDirNamespace(fallbackStorageDir)
|
|
16930
|
-
: this.config.defaultNamespace;
|
|
16931
|
-
if (
|
|
16932
|
-
recallNamespaces.length === 0 ||
|
|
16933
|
-
!resolveNamespaceCapabilities(this.config).namespaces ||
|
|
16934
|
-
recallNamespaces.includes(fallbackNamespace)
|
|
16935
|
-
) {
|
|
16936
|
-
addStorage(fallbackStorage);
|
|
16937
|
-
}
|
|
16938
|
-
|
|
16939
|
-
if (recallNamespaces.length > 0) {
|
|
16940
|
-
for (const namespace of recallNamespaces) {
|
|
16941
|
-
try {
|
|
16942
|
-
addStorage(await this.storageRouter.storageFor(namespace));
|
|
16943
|
-
} catch (err) {
|
|
16944
|
-
log.debug("qmd cold result namespace storage lookup skipped", {
|
|
16945
|
-
path: resultPath,
|
|
16946
|
-
namespace,
|
|
16947
|
-
error: (err as Error).message,
|
|
16948
|
-
});
|
|
16949
|
-
}
|
|
16950
|
-
}
|
|
16951
|
-
}
|
|
16952
|
-
|
|
16953
|
-
for (const storage of storages) {
|
|
16954
|
-
const storageDir = storageDirFor(storage);
|
|
16955
|
-
if (!storageDir) {
|
|
16956
|
-
const memory = await storage.readMemoryByPath(resultPath);
|
|
16957
|
-
if (memory) return memory;
|
|
16958
|
-
continue;
|
|
16959
|
-
}
|
|
16960
|
-
try {
|
|
16961
|
-
const coldRoot = path.join(storageDir, "cold");
|
|
16962
|
-
for (const candidate of qmdResultPathCandidates(
|
|
16963
|
-
coldRoot,
|
|
16964
|
-
parts.relativePath,
|
|
16965
|
-
)) {
|
|
16966
|
-
const memory = await storage.readMemoryByPath(candidate);
|
|
16967
|
-
if (memory) return memory;
|
|
16968
|
-
}
|
|
16969
|
-
} catch (err) {
|
|
16970
|
-
if (err instanceof SecureStoreLockedError) throw err;
|
|
16971
|
-
log.debug("qmd cold result path lookup failed open", {
|
|
16972
|
-
path: resultPath,
|
|
16973
|
-
collection: coldCollection,
|
|
16974
|
-
error: (err as Error).message,
|
|
16975
|
-
});
|
|
16976
|
-
}
|
|
16977
|
-
}
|
|
16978
|
-
return null;
|
|
16979
|
-
}
|
|
16980
|
-
const collectionNamespace = parts
|
|
16981
|
-
? this.qmdCollectionNamespaceFromPrefix(parts.collection)
|
|
16982
|
-
: null;
|
|
16983
|
-
|
|
16984
|
-
if (parts && collectionNamespace) {
|
|
16985
|
-
try {
|
|
16986
|
-
const collectionStorage =
|
|
16987
|
-
await this.storageRouter.storageFor(collectionNamespace);
|
|
16988
|
-
for (const candidate of qmdResultPathCandidates(
|
|
16989
|
-
collectionStorage.dir,
|
|
16990
|
-
parts.relativePath,
|
|
16991
|
-
)) {
|
|
16992
|
-
const memory = await collectionStorage.readMemoryByPath(candidate);
|
|
16993
|
-
if (memory) return memory;
|
|
16994
|
-
}
|
|
16995
|
-
return null;
|
|
16996
|
-
} catch (err) {
|
|
16997
|
-
if (err instanceof SecureStoreLockedError) throw err;
|
|
16998
|
-
log.debug("qmd result namespace path lookup failed open", {
|
|
16999
|
-
path: resultPath,
|
|
17000
|
-
namespace: collectionNamespace,
|
|
17001
|
-
error: (err as Error).message,
|
|
17002
|
-
});
|
|
17003
|
-
return null;
|
|
17004
|
-
}
|
|
17005
|
-
}
|
|
17006
|
-
|
|
17007
|
-
if (path.isAbsolute(resultPath)) {
|
|
17008
|
-
if (!fallbackStorageDir) {
|
|
17009
|
-
return await fallbackStorage.readMemoryByPath(resultPath);
|
|
17010
|
-
}
|
|
17011
|
-
const ownerStorage = await this.storageForAbsoluteQmdResultPath(
|
|
17012
|
-
resultPath,
|
|
17013
|
-
fallbackStorage,
|
|
17014
|
-
recallNamespaces,
|
|
17015
|
-
);
|
|
17016
|
-
if (!ownerStorage) return null;
|
|
17017
|
-
for (const candidate of qmdResultPathCandidates(
|
|
17018
|
-
ownerStorage.dir,
|
|
17019
|
-
resultPath,
|
|
17020
|
-
)) {
|
|
17021
|
-
const memory = await ownerStorage.storage.readMemoryByPath(candidate);
|
|
17022
|
-
if (memory) return memory;
|
|
17023
|
-
}
|
|
17024
|
-
return null;
|
|
17025
|
-
}
|
|
17026
|
-
|
|
17027
|
-
if (!fallbackStorageDir) {
|
|
17028
|
-
return await fallbackStorage.readMemoryByPath(resultPath);
|
|
17029
|
-
}
|
|
17030
|
-
for (const candidate of qmdResultPathCandidates(
|
|
17031
|
-
fallbackStorageDir,
|
|
17032
|
-
resultPath,
|
|
17033
|
-
)) {
|
|
17034
|
-
const memory = await fallbackStorage.readMemoryByPath(candidate);
|
|
17035
|
-
if (memory) return memory;
|
|
17036
|
-
}
|
|
17037
|
-
return null;
|
|
16727
|
+
return this.qmdResultResolver.readQmdResultMemory(resultPath, fallbackStorage, recallNamespaces);
|
|
17038
16728
|
}
|
|
17039
16729
|
|
|
17040
16730
|
private async resolveColdQmdResultForRecall(
|
|
@@ -17042,40 +16732,7 @@ export class Orchestrator {
|
|
|
17042
16732
|
fallbackStorage: StorageManager,
|
|
17043
16733
|
recallNamespaces: readonly string[] = [],
|
|
17044
16734
|
): Promise<{ namespace: string; result: QmdSearchResult } | null> {
|
|
17045
|
-
|
|
17046
|
-
result.path,
|
|
17047
|
-
fallbackStorage,
|
|
17048
|
-
recallNamespaces,
|
|
17049
|
-
);
|
|
17050
|
-
if (!memory) return null;
|
|
17051
|
-
|
|
17052
|
-
let ownerNamespace: string | null = null;
|
|
17053
|
-
if (path.isAbsolute(memory.path)) {
|
|
17054
|
-
const ownerStorage = await this.storageForAbsoluteQmdResultPath(
|
|
17055
|
-
memory.path,
|
|
17056
|
-
fallbackStorage,
|
|
17057
|
-
recallNamespaces,
|
|
17058
|
-
);
|
|
17059
|
-
ownerNamespace = ownerStorage?.namespace ?? null;
|
|
17060
|
-
if (!ownerNamespace && resolveNamespaceCapabilities(this.config).namespaces) return null;
|
|
17061
|
-
}
|
|
17062
|
-
ownerNamespace ??= this.namespaceFromPath(memory.path);
|
|
17063
|
-
if (
|
|
17064
|
-
recallNamespaces.length > 0 &&
|
|
17065
|
-
!recallNamespaces.includes(ownerNamespace)
|
|
17066
|
-
) {
|
|
17067
|
-
return null;
|
|
17068
|
-
}
|
|
17069
|
-
|
|
17070
|
-
return {
|
|
17071
|
-
namespace: ownerNamespace,
|
|
17072
|
-
result: {
|
|
17073
|
-
...result,
|
|
17074
|
-
docid: result.docid || memory.frontmatter.id,
|
|
17075
|
-
path: memory.path,
|
|
17076
|
-
snippet: result.snippet || memory.content.slice(0, 400),
|
|
17077
|
-
},
|
|
17078
|
-
};
|
|
16735
|
+
return this.qmdResultResolver.resolveColdQmdResultForRecall(result, fallbackStorage, recallNamespaces);
|
|
17079
16736
|
}
|
|
17080
16737
|
|
|
17081
16738
|
private async storageForAbsoluteQmdResultPath(
|
|
@@ -17083,73 +16740,7 @@ export class Orchestrator {
|
|
|
17083
16740
|
fallbackStorage: StorageManager,
|
|
17084
16741
|
recallNamespaces: readonly string[] = [],
|
|
17085
16742
|
): Promise<{ storage: StorageManager; dir: string; namespace: string } | null> {
|
|
17086
|
-
|
|
17087
|
-
const memoryRoot = path.resolve(this.config.memoryDir);
|
|
17088
|
-
const namespacesRoot = path.join(memoryRoot, "namespaces");
|
|
17089
|
-
const fallbackStorageDir =
|
|
17090
|
-
typeof (fallbackStorage as { dir?: unknown }).dir === "string" &&
|
|
17091
|
-
(fallbackStorage as { dir?: string }).dir
|
|
17092
|
-
? (fallbackStorage as { dir: string }).dir
|
|
17093
|
-
: null;
|
|
17094
|
-
const matches: Array<{ storage: StorageManager; dir: string; namespace: string }> = [];
|
|
17095
|
-
const seenDirs = new Set<string>();
|
|
17096
|
-
|
|
17097
|
-
const maybeAddStorage = (storage: StorageManager, namespace: string) => {
|
|
17098
|
-
const storageDir =
|
|
17099
|
-
typeof (storage as { dir?: unknown }).dir === "string" &&
|
|
17100
|
-
(storage as { dir?: string }).dir
|
|
17101
|
-
? (storage as { dir: string }).dir
|
|
17102
|
-
: null;
|
|
17103
|
-
if (!storageDir) return;
|
|
17104
|
-
const candidateRoot = path.resolve(storageDir);
|
|
17105
|
-
if (seenDirs.has(candidateRoot)) return;
|
|
17106
|
-
if (!isPathInsideStorageRoot(candidateRoot, resolvedPath)) return;
|
|
17107
|
-
if (
|
|
17108
|
-
candidateRoot === memoryRoot &&
|
|
17109
|
-
isPathInsideStorageRoot(namespacesRoot, resolvedPath)
|
|
17110
|
-
) {
|
|
17111
|
-
return;
|
|
17112
|
-
}
|
|
17113
|
-
seenDirs.add(candidateRoot);
|
|
17114
|
-
matches.push({ storage, dir: candidateRoot, namespace });
|
|
17115
|
-
};
|
|
17116
|
-
|
|
17117
|
-
const fallbackNamespace =
|
|
17118
|
-
fallbackStorageDir !== null
|
|
17119
|
-
? this.storageDirNamespace(fallbackStorageDir)
|
|
17120
|
-
: this.config.defaultNamespace;
|
|
17121
|
-
maybeAddStorage(fallbackStorage, fallbackNamespace);
|
|
17122
|
-
|
|
17123
|
-
const candidateNamespaces = new Set<string>();
|
|
17124
|
-
candidateNamespaces.add(this.config.defaultNamespace);
|
|
17125
|
-
candidateNamespaces.add(this.config.sharedNamespace);
|
|
17126
|
-
for (const ns of recallNamespaces) {
|
|
17127
|
-
candidateNamespaces.add(ns);
|
|
17128
|
-
}
|
|
17129
|
-
if (isPathInsideStorageRoot(namespacesRoot, resolvedPath)) {
|
|
17130
|
-
const relativeToNamespaces = path.relative(namespacesRoot, resolvedPath);
|
|
17131
|
-
const [namespaceSegment] = relativeToNamespaces.split(/[\\/]/);
|
|
17132
|
-
if (namespaceSegment) {
|
|
17133
|
-
candidateNamespaces.add(
|
|
17134
|
-
namespaceIdentityFromToken(namespaceSegment) ?? namespaceSegment,
|
|
17135
|
-
);
|
|
17136
|
-
}
|
|
17137
|
-
}
|
|
17138
|
-
for (const policy of this.config.namespacePolicies ?? []) {
|
|
17139
|
-
candidateNamespaces.add(policy.name);
|
|
17140
|
-
}
|
|
17141
|
-
|
|
17142
|
-
for (const ns of candidateNamespaces) {
|
|
17143
|
-
if (!ns) continue;
|
|
17144
|
-
try {
|
|
17145
|
-
maybeAddStorage(await this.storageRouter.storageFor(ns), ns);
|
|
17146
|
-
} catch {
|
|
17147
|
-
continue;
|
|
17148
|
-
}
|
|
17149
|
-
}
|
|
17150
|
-
|
|
17151
|
-
matches.sort((a, b) => b.dir.length - a.dir.length);
|
|
17152
|
-
return matches[0] ?? null;
|
|
16743
|
+
return this.qmdResultResolver.storageForAbsoluteQmdResultPath(resultPath, fallbackStorage, recallNamespaces);
|
|
17153
16744
|
}
|
|
17154
16745
|
|
|
17155
16746
|
// Issue #1526: recall-rerank methods moved to RecallRerankCoordinator.
|
|
@@ -17211,18 +16802,7 @@ export class Orchestrator {
|
|
|
17211
16802
|
includedSections?: string[];
|
|
17212
16803
|
omittedSections?: string[];
|
|
17213
16804
|
}): LastRecallBudgetSummary {
|
|
17214
|
-
return
|
|
17215
|
-
requestedTopK: options.requestedTopK,
|
|
17216
|
-
appliedTopK: options.recallResultLimit,
|
|
17217
|
-
recallBudgetChars: this.getRecallBudgetChars(),
|
|
17218
|
-
maxMemoryTokens: this.config.maxMemoryTokens,
|
|
17219
|
-
qmdFetchLimit: options.qmdFetchLimit,
|
|
17220
|
-
qmdHybridFetchLimit: options.qmdHybridFetchLimit,
|
|
17221
|
-
finalContextChars: options.finalContextChars,
|
|
17222
|
-
truncated: options.truncated,
|
|
17223
|
-
includedSections: [...(options.includedSections ?? [])],
|
|
17224
|
-
omittedSections: [...(options.omittedSections ?? [])],
|
|
17225
|
-
};
|
|
16805
|
+
return this.recallSectionCoordinator.buildLastRecallBudgetSummary(options);
|
|
17226
16806
|
}
|
|
17227
16807
|
|
|
17228
16808
|
private collectLastRecallSources(
|
|
@@ -17234,16 +16814,10 @@ export class Orchestrator {
|
|
|
17234
16814
|
| "cold_fallback"
|
|
17235
16815
|
| "recent_scan",
|
|
17236
16816
|
): string[] {
|
|
17237
|
-
|
|
17238
|
-
|
|
17239
|
-
|
|
17240
|
-
|
|
17241
|
-
for (const [sectionId, chunks] of sectionBuckets.entries()) {
|
|
17242
|
-
if (chunks.length > 0) {
|
|
17243
|
-
used.add(sectionId);
|
|
17244
|
-
}
|
|
17245
|
-
}
|
|
17246
|
-
return [...used];
|
|
16817
|
+
return this.recallSectionCoordinator.collectLastRecallSources(
|
|
16818
|
+
sectionBuckets,
|
|
16819
|
+
recallSource,
|
|
16820
|
+
);
|
|
17247
16821
|
}
|
|
17248
16822
|
|
|
17249
16823
|
/**
|
|
@@ -18603,99 +18177,11 @@ export class Orchestrator {
|
|
|
18603
18177
|
supersededCreated: string;
|
|
18604
18178
|
supersededTags: string[];
|
|
18605
18179
|
} | null> {
|
|
18606
|
-
|
|
18607
|
-
|
|
18608
|
-
|
|
18609
|
-
|
|
18610
|
-
|
|
18611
|
-
namespaces: [namespaceScope],
|
|
18612
|
-
maxResults: 5,
|
|
18613
|
-
mode: "search",
|
|
18614
|
-
});
|
|
18615
|
-
|
|
18616
|
-
for (const result of results) {
|
|
18617
|
-
// Check similarity threshold
|
|
18618
|
-
if (result.score < this.config.contradictionSimilarityThreshold) {
|
|
18619
|
-
continue;
|
|
18620
|
-
}
|
|
18621
|
-
|
|
18622
|
-
// Get the existing memory
|
|
18623
|
-
const memoryId = this.extractMemoryIdsFromResults([result])[0];
|
|
18624
|
-
if (!memoryId) continue;
|
|
18625
|
-
|
|
18626
|
-
const resultNamespace = this.namespaceFromPath(result.path);
|
|
18627
|
-
if (resultNamespace !== namespaceScope) continue;
|
|
18628
|
-
const resultStorage =
|
|
18629
|
-
await this.storageRouter.storageFor(resultNamespace);
|
|
18630
|
-
const existingMemory = await resultStorage.getMemoryById(memoryId);
|
|
18631
|
-
if (!existingMemory) continue;
|
|
18632
|
-
|
|
18633
|
-
// Skip memories already resolved or explicitly forgotten. Other
|
|
18634
|
-
// non-active statuses remain valid contradiction candidates.
|
|
18635
|
-
if (
|
|
18636
|
-
existingMemory.frontmatter.status === "superseded" ||
|
|
18637
|
-
existingMemory.frontmatter.status === "forgotten"
|
|
18638
|
-
) {
|
|
18639
|
-
continue;
|
|
18640
|
-
}
|
|
18641
|
-
|
|
18642
|
-
// Verify contradiction with LLM
|
|
18643
|
-
const verification = await this.extraction.verifyContradiction(
|
|
18644
|
-
{ content, category },
|
|
18645
|
-
{
|
|
18646
|
-
id: existingMemory.frontmatter.id,
|
|
18647
|
-
content: existingMemory.content,
|
|
18648
|
-
category: existingMemory.frontmatter.category,
|
|
18649
|
-
created: existingMemory.frontmatter.created,
|
|
18650
|
-
},
|
|
18651
|
-
);
|
|
18652
|
-
|
|
18653
|
-
if (!verification) continue;
|
|
18654
|
-
|
|
18655
|
-
// Check if it's a real contradiction with high confidence
|
|
18656
|
-
if (
|
|
18657
|
-
verification.isContradiction &&
|
|
18658
|
-
verification.confidence >= this.config.contradictionMinConfidence
|
|
18659
|
-
) {
|
|
18660
|
-
// When the LLM says the existing memory is newer (whichIsNewer ===
|
|
18661
|
-
// "first") the incoming fact is the stale one in both resolve modes —
|
|
18662
|
-
// log and continue so the caller never marks contradictionDetected and
|
|
18663
|
-
// the semantic-skip gate can discard the outdated write normally.
|
|
18664
|
-
if (verification.whichIsNewer === "first") {
|
|
18665
|
-
log.info(
|
|
18666
|
-
`detected contradiction (confidence: ${verification.confidence}): ${existingMemory.frontmatter.id} vs new memory — existing is newer, incoming fact is stale`,
|
|
18667
|
-
);
|
|
18668
|
-
continue;
|
|
18669
|
-
}
|
|
18670
|
-
|
|
18671
|
-
// The new fact is newer than the existing one. When auto-resolve is
|
|
18672
|
-
// enabled, the caller retires the old memory AFTER the new write lands
|
|
18673
|
-
// and its tombstone status is known (#1645: defer auto-resolve until
|
|
18674
|
-
// tombstone status is known — a tombstone-blocked new write must not
|
|
18675
|
-
// retire the only active copy, leaving neither memory active). When
|
|
18676
|
-
// disabled, the old memory stays active for manual review. The
|
|
18677
|
-
// contradiction info is returned in both cases so the caller can apply
|
|
18678
|
-
// the deferred retire post-write.
|
|
18679
|
-
|
|
18680
|
-
// Return the contradiction info regardless of auto-resolve setting.
|
|
18681
|
-
// The caller uses this to set `contradictionDetected=true` which
|
|
18682
|
-
// prevents the semantic-skip guard from silently dropping a
|
|
18683
|
-
// legitimately contradictory update (the regression this fixes).
|
|
18684
|
-
log.info(
|
|
18685
|
-
`detected contradiction (confidence: ${verification.confidence}): ${existingMemory.frontmatter.id} vs new memory${this.config.contradictionAutoResolve ? " (auto-resolved)" : " (queued for manual review)"}`,
|
|
18686
|
-
);
|
|
18687
|
-
return {
|
|
18688
|
-
supersededId: existingMemory.frontmatter.id,
|
|
18689
|
-
confidence: verification.confidence,
|
|
18690
|
-
reason: verification.reasoning,
|
|
18691
|
-
supersededPath: existingMemory.path,
|
|
18692
|
-
supersededCreated: existingMemory.frontmatter.created,
|
|
18693
|
-
supersededTags: existingMemory.frontmatter.tags ?? [],
|
|
18694
|
-
};
|
|
18695
|
-
}
|
|
18696
|
-
}
|
|
18697
|
-
|
|
18698
|
-
return null;
|
|
18180
|
+
return this.contradictionLinkingCoordinator.checkForContradiction(
|
|
18181
|
+
content,
|
|
18182
|
+
category,
|
|
18183
|
+
namespaceScope,
|
|
18184
|
+
);
|
|
18699
18185
|
}
|
|
18700
18186
|
|
|
18701
18187
|
/**
|
|
@@ -18718,49 +18204,12 @@ export class Orchestrator {
|
|
|
18718
18204
|
newMemoryId: string,
|
|
18719
18205
|
postWriteGuard: boolean,
|
|
18720
18206
|
): Promise<void> {
|
|
18721
|
-
|
|
18722
|
-
|
|
18723
|
-
|
|
18724
|
-
|
|
18725
|
-
|
|
18726
|
-
|
|
18727
|
-
await storage.writeMemoryFrontmatter(blockedRow, { supersedes: undefined });
|
|
18728
|
-
}
|
|
18729
|
-
} catch (err) {
|
|
18730
|
-
log.warn(
|
|
18731
|
-
`contradiction auto-resolve supersedes clear failed for blocked ${newMemoryId}: ${err}`,
|
|
18732
|
-
);
|
|
18733
|
-
}
|
|
18734
|
-
}
|
|
18735
|
-
if (
|
|
18736
|
-
!contradiction ||
|
|
18737
|
-
!this.config.contradictionAutoResolve ||
|
|
18738
|
-
postWriteGuard
|
|
18739
|
-
) {
|
|
18740
|
-
return;
|
|
18741
|
-
}
|
|
18742
|
-
try {
|
|
18743
|
-
await storage.supersedeMemory(
|
|
18744
|
-
contradiction.supersededId,
|
|
18745
|
-
newMemoryId,
|
|
18746
|
-
contradiction.reason,
|
|
18747
|
-
);
|
|
18748
|
-
if (
|
|
18749
|
-
resolveIndexingCapabilities(this.config).queryAwareIndexing &&
|
|
18750
|
-
contradiction.supersededPath
|
|
18751
|
-
) {
|
|
18752
|
-
deindexMemory(
|
|
18753
|
-
this.config.memoryDir,
|
|
18754
|
-
contradiction.supersededPath,
|
|
18755
|
-
contradiction.supersededCreated,
|
|
18756
|
-
contradiction.supersededTags,
|
|
18757
|
-
);
|
|
18758
|
-
}
|
|
18759
|
-
} catch (err) {
|
|
18760
|
-
log.warn(
|
|
18761
|
-
`contradiction auto-resolve supersede failed for ${contradiction.supersededId}: ${err}`,
|
|
18762
|
-
);
|
|
18763
|
-
}
|
|
18207
|
+
return this.contradictionLinkingCoordinator.applyDeferredContradictionResolve(
|
|
18208
|
+
contradiction,
|
|
18209
|
+
storage,
|
|
18210
|
+
newMemoryId,
|
|
18211
|
+
postWriteGuard,
|
|
18212
|
+
);
|
|
18764
18213
|
}
|
|
18765
18214
|
|
|
18766
18215
|
// ---------------------------------------------------------------------------
|
|
@@ -18775,61 +18224,14 @@ export class Orchestrator {
|
|
|
18775
18224
|
category: string,
|
|
18776
18225
|
namespaceScope: string,
|
|
18777
18226
|
): Promise<MemoryLink[]> {
|
|
18778
|
-
|
|
18779
|
-
|
|
18780
|
-
|
|
18781
|
-
|
|
18782
|
-
query: content,
|
|
18783
|
-
namespaces: [namespaceScope],
|
|
18784
|
-
maxResults: 5,
|
|
18785
|
-
mode: "search",
|
|
18786
|
-
});
|
|
18787
|
-
if (results.length === 0) return [];
|
|
18788
|
-
|
|
18789
|
-
// Get full memory details for candidates
|
|
18790
|
-
const candidates: Array<{ id: string; content: string; category: string }> =
|
|
18791
|
-
[];
|
|
18792
|
-
for (const result of results) {
|
|
18793
|
-
const memoryId = this.extractMemoryIdsFromResults([result])[0];
|
|
18794
|
-
if (!memoryId) continue;
|
|
18795
|
-
|
|
18796
|
-
const resultNamespace = this.namespaceFromPath(result.path);
|
|
18797
|
-
if (resultNamespace !== namespaceScope) continue;
|
|
18798
|
-
const resultStorage =
|
|
18799
|
-
await this.storageRouter.storageFor(resultNamespace);
|
|
18800
|
-
const memory = await resultStorage.getMemoryById(memoryId);
|
|
18801
|
-
if (
|
|
18802
|
-
memory &&
|
|
18803
|
-
memory.frontmatter.status !== "superseded" &&
|
|
18804
|
-
memory.frontmatter.status !== "forgotten"
|
|
18805
|
-
) {
|
|
18806
|
-
candidates.push({
|
|
18807
|
-
id: memory.frontmatter.id,
|
|
18808
|
-
content: memory.content,
|
|
18809
|
-
category: memory.frontmatter.category,
|
|
18810
|
-
});
|
|
18811
|
-
}
|
|
18812
|
-
}
|
|
18813
|
-
|
|
18814
|
-
if (candidates.length === 0) return [];
|
|
18815
|
-
|
|
18816
|
-
// Ask LLM for link suggestions
|
|
18817
|
-
const suggestions = await this.extraction.suggestLinks(
|
|
18818
|
-
{ content, category },
|
|
18819
|
-
candidates,
|
|
18227
|
+
return this.contradictionLinkingCoordinator.suggestLinksForMemory(
|
|
18228
|
+
content,
|
|
18229
|
+
category,
|
|
18230
|
+
namespaceScope,
|
|
18820
18231
|
);
|
|
18821
|
-
|
|
18822
|
-
if (!suggestions || suggestions.links.length === 0) return [];
|
|
18823
|
-
|
|
18824
|
-
// Convert to MemoryLink format
|
|
18825
|
-
return suggestions.links.map((link) => ({
|
|
18826
|
-
targetId: link.targetId,
|
|
18827
|
-
linkType: link.linkType,
|
|
18828
|
-
strength: link.strength,
|
|
18829
|
-
reason: link.reason || undefined,
|
|
18830
|
-
}));
|
|
18831
18232
|
}
|
|
18832
18233
|
|
|
18234
|
+
|
|
18833
18235
|
private async graphSeedPathRelativeToStorage(
|
|
18834
18236
|
storage: StorageManager,
|
|
18835
18237
|
result: QmdSearchResult,
|