@remnic/core 9.3.749 → 9.3.751
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 +8 -8
- package/dist/access-boundary.js +15 -15
- package/dist/access-cli.js +39 -39
- package/dist/access-http.d.ts +8 -8
- package/dist/access-http.js +20 -20
- package/dist/access-mcp.d.ts +8 -8
- package/dist/access-mcp.js +19 -19
- package/dist/access-operations-batch.js +16 -16
- package/dist/access-operations.d.ts +8 -8
- package/dist/access-operations.js +18 -18
- package/dist/access-schema.d.ts +2 -2
- package/dist/access-schema.js +5 -5
- package/dist/{access-service-5-EVpt3v.d.ts → access-service-DmAEOJdJ.d.ts} +11 -3
- package/dist/access-service.d.ts +5 -5
- package/dist/access-service.js +14 -14
- package/dist/access-surface-catalog.d.ts +8 -8
- package/dist/action-confidence.d.ts +1 -1
- package/dist/active-memory-bridge.d.ts +1 -1
- package/dist/active-recall.d.ts +1 -1
- package/dist/active-recall.js +8 -1
- package/dist/active-recall.js.map +1 -1
- package/dist/behavior-learner.d.ts +1 -1
- package/dist/behavior-signals.d.ts +1 -1
- package/dist/bootstrap.d.ts +7 -7
- package/dist/briefing.d.ts +1 -1
- package/dist/briefing.js +7 -7
- package/dist/buffer-surprise-report.d.ts +1 -1
- package/dist/buffer.d.ts +1 -1
- package/dist/calibration.d.ts +1 -1
- package/dist/capabilities.d.ts +1 -1
- package/dist/{catalog-D_ZDxu8Y.d.ts → catalog-BpOcwHdE.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 +8 -8
- package/dist/causal-trajectory-graph.d.ts +1 -1
- package/dist/{chunk-C5WN74HH.js → chunk-2HAG7JOI.js} +8 -2
- package/dist/chunk-2HAG7JOI.js.map +1 -0
- package/dist/{chunk-GKRLPHPU.js → chunk-2KK5WNQB.js} +2 -2
- package/dist/{chunk-JRDPT6DA.js → chunk-4NWIGAIC.js} +2 -2
- package/dist/{chunk-OBJUKYDO.js → chunk-4XL3CVII.js} +2 -2
- package/dist/{chunk-WWVXXSLF.js → chunk-5PZCDUJ6.js} +4 -4
- package/dist/{chunk-URQLO7BX.js → chunk-6FNZ3NMS.js} +2 -2
- package/dist/{chunk-DRUDC2UX.js → chunk-6MMONPHM.js} +2 -2
- package/dist/{chunk-RB6A7OUN.js → chunk-6SXNQFHB.js} +2 -2
- package/dist/{chunk-ZGZNLRKF.js → chunk-7TWA7DKP.js} +5 -5
- package/dist/{chunk-KMNYXLPL.js → chunk-B35L45HZ.js} +2 -2
- package/dist/{chunk-SIV3JZPP.js → chunk-CGZWGVQF.js} +5 -5
- package/dist/{chunk-CKFLLAIS.js → chunk-DANV2HTH.js} +3 -3
- package/dist/{chunk-NVYF5OB6.js → chunk-DBRVU5PR.js} +3 -3
- package/dist/{chunk-LMFS64GY.js → chunk-E4PFDD3N.js} +4 -4
- package/dist/{chunk-DIHCFJVV.js → chunk-HYI2GP3F.js} +4 -4
- package/dist/{chunk-UIKZZ242.js → chunk-IKHKHADN.js} +2 -2
- package/dist/{chunk-PUR2CKX2.js → chunk-JS2HKKOK.js} +1 -1
- package/dist/{chunk-PUR2CKX2.js.map → chunk-JS2HKKOK.js.map} +1 -1
- package/dist/{chunk-R2OAN6IP.js → chunk-K2JM4DZZ.js} +2 -2
- package/dist/{chunk-3IJGF6K2.js → chunk-K2R3DEEH.js} +2 -2
- package/dist/{chunk-HIHCB2S6.js → chunk-QRRBXD24.js} +2 -2
- package/dist/{chunk-PNUOQYRJ.js → chunk-RWZB6MAY.js} +1953 -2172
- package/dist/chunk-RWZB6MAY.js.map +1 -0
- package/dist/{chunk-ZPZ4VVLT.js → chunk-SD34EK4Z.js} +2 -2
- package/dist/{chunk-WK3NK6SP.js → chunk-SNEXVX3U.js} +6 -6
- package/dist/{chunk-FVZ2ISIX.js → chunk-TPLE6SNY.js} +7 -7
- package/dist/{chunk-24YDB5QP.js → chunk-UETBEHBA.js} +44 -24
- package/dist/chunk-UETBEHBA.js.map +1 -0
- package/dist/{chunk-5IN26V6W.js → chunk-UU32EAIY.js} +5 -5
- package/dist/{chunk-ZGAJB74V.js → chunk-W3BFT5OJ.js} +2 -2
- package/dist/{chunk-L4N7SVNN.js → chunk-WA7FECSG.js} +11 -11
- package/dist/{chunk-Q3X7GUAQ.js → chunk-WOX2UW4K.js} +2 -2
- package/dist/{chunk-XTEWVF3C.js → chunk-WWSXVOGY.js} +2 -2
- package/dist/{chunk-PWWWLD7D.js → chunk-X64YLC24.js} +153 -27
- package/dist/chunk-X64YLC24.js.map +1 -0
- package/dist/{chunk-P4FW3ZU5.js → chunk-YGGXUNS4.js} +20 -20
- package/dist/{chunk-JHQUIH3W.js → chunk-ZBVQ4ZM4.js} +19 -19
- package/dist/{cli-DuWWjaKT.d.ts → cli-lmf5RGyQ.d.ts} +3 -3
- package/dist/cli.d.ts +9 -9
- package/dist/cli.js +33 -33
- package/dist/compounding/engine.d.ts +1 -1
- package/dist/compounding/engine.js +7 -7
- 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/config.js +8 -1
- package/dist/connectors/codex-materialize-runner.d.ts +1 -1
- package/dist/connectors/codex-materialize-runner.js +7 -7
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +7 -7
- package/dist/consolidation-provenance-check.d.ts +1 -1
- package/dist/consolidation-undo.d.ts +1 -1
- package/dist/contradiction/index.d.ts +1 -1
- package/dist/conversation-index/backend.d.ts +1 -1
- package/dist/conversation-index/chunker.d.ts +1 -1
- package/dist/conversation-index/faiss-adapter.d.ts +1 -1
- package/dist/conversation-index/indexer.d.ts +1 -1
- package/dist/conversation-index/search.d.ts +1 -1
- package/dist/day-summary.d.ts +1 -1
- package/dist/delinearize.d.ts +1 -1
- package/dist/direct-answer-wiring.d.ts +1 -1
- package/dist/direct-answer.d.ts +1 -1
- package/dist/embedding-fallback.d.ts +1 -1
- package/dist/enrichment/index.d.ts +1 -1
- package/dist/entity-retrieval.d.ts +1 -1
- package/dist/entity-retrieval.js +7 -7
- package/dist/entity-schema.d.ts +1 -1
- package/dist/explicit-capture.d.ts +7 -7
- package/dist/extraction-faithfulness.d.ts +1 -1
- package/dist/extraction-judge-telemetry.d.ts +1 -1
- package/dist/extraction-judge-training.d.ts +1 -1
- package/dist/extraction-judge.d.ts +1 -1
- package/dist/extraction.d.ts +1 -1
- package/dist/fallback-llm.d.ts +1 -1
- package/dist/graph-dashboard-diff.d.ts +1 -1
- package/dist/graph-dashboard-key.d.ts +1 -1
- package/dist/graph-dashboard-parser.d.ts +1 -1
- package/dist/graph-edge-reinforcement.d.ts +1 -1
- package/dist/graph-snapshot.d.ts +1 -1
- package/dist/graph.d.ts +1 -1
- package/dist/identity-continuity.d.ts +1 -1
- package/dist/importance.d.ts +1 -1
- package/dist/index.d.ts +10 -10
- package/dist/index.js +76 -72
- package/dist/intent.d.ts +1 -1
- package/dist/lcm/engine.d.ts +1 -1
- package/dist/lcm/index.d.ts +1 -1
- package/dist/lcm/tools.d.ts +1 -1
- package/dist/lifecycle.d.ts +1 -1
- package/dist/live-connectors-runner.d.ts +1 -1
- package/dist/local-llm.d.ts +1 -1
- package/dist/local-model-endpoint.d.ts +1 -1
- package/dist/maintenance/memory-governance.d.ts +1 -1
- package/dist/maintenance/memory-governance.js +7 -7
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +7 -7
- package/dist/maintenance/rebuild-memory-projection.js +8 -8
- 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 +8 -8
- package/dist/namespaces/principal.d.ts +1 -1
- package/dist/namespaces/search.d.ts +1 -1
- package/dist/namespaces/search.js +1 -1
- package/dist/namespaces/storage.d.ts +2 -2
- package/dist/namespaces/storage.js +7 -7
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/offline-sync.d.ts +108 -1
- package/dist/offline-sync.js +7 -1
- package/dist/operator-toolkit.d.ts +1 -1
- package/dist/operator-toolkit.js +15 -12
- package/dist/orchestration/compression-guideline-coordinator.d.ts +1 -1
- package/dist/orchestration/maintenance.d.ts +2 -2
- package/dist/orchestration/maintenance.js +9 -9
- package/dist/{orchestrator-CZI6hO_R.d.ts → orchestrator-D7bb8ZGp.d.ts} +193 -201
- package/dist/orchestrator.d.ts +5 -5
- package/dist/orchestrator.js +51 -41
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/policy-runtime.d.ts +1 -1
- package/dist/provenance.d.ts +1 -1
- package/dist/qmd-recall-cache.d.ts +1 -1
- package/dist/qmd.d.ts +1 -1
- package/dist/recall-disclosure-escalation.d.ts +1 -1
- package/dist/recall-explain-renderer.d.ts +1 -1
- package/dist/recall-explain-renderer.js +3 -3
- package/dist/recall-planner-llm.d.ts +1 -1
- package/dist/recall-state.d.ts +1 -1
- package/dist/recall-tag-filter.d.ts +1 -1
- package/dist/recall-xray-cli.d.ts +1 -1
- package/dist/recall-xray-cli.js +4 -4
- package/dist/recall-xray-renderer.d.ts +1 -1
- package/dist/recall-xray-renderer.js +3 -3
- package/dist/recall-xray.d.ts +1 -1
- package/dist/recall-xray.js +2 -2
- package/dist/resolve-auth-token.d.ts +1 -1
- package/dist/resume-bundles.js +9 -2
- package/dist/retrieval-agents.d.ts +1 -1
- package/dist/retrieval-tiers.d.ts +1 -1
- package/dist/routing/engine.d.ts +1 -1
- package/dist/routing/store.d.ts +1 -1
- package/dist/schemas.d.ts +22 -22
- package/dist/search/embed-helper.d.ts +1 -1
- package/dist/search/factory.d.ts +1 -1
- package/dist/search/factory.js +1 -1
- package/dist/search/index.d.ts +1 -1
- package/dist/search/index.js +1 -1
- package/dist/search/lancedb-backend.d.ts +1 -1
- package/dist/search/lancedb-backend.js +1 -1
- package/dist/search/meilisearch-backend.d.ts +1 -1
- package/dist/search/meilisearch-backend.js +1 -1
- package/dist/search/noop-backend.d.ts +1 -1
- package/dist/search/orama-backend.d.ts +1 -1
- package/dist/search/orama-backend.js +1 -1
- package/dist/search/port.d.ts +1 -1
- package/dist/search/remote-backend.d.ts +1 -1
- package/dist/{semantic-consolidation-D3aSiu9t.d.ts → semantic-consolidation-CTfbVwCA.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +8 -8
- package/dist/semantic-rule-promotion.js +7 -7
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/semantic-rule-verifier.js +7 -7
- package/dist/session-observer-bands.d.ts +1 -1
- package/dist/session-observer-state.d.ts +1 -1
- package/dist/shared-context/manager.d.ts +1 -1
- package/dist/signal.d.ts +1 -1
- package/dist/storage.d.ts +1 -1
- package/dist/storage.js +6 -6
- package/dist/summarizer.d.ts +1 -1
- package/dist/summary-snapshot.d.ts +1 -1
- package/dist/temporal-supersession.d.ts +1 -1
- package/dist/temporal-validity.d.ts +1 -1
- package/dist/threading.d.ts +1 -1
- package/dist/tier-migration.d.ts +1 -1
- package/dist/tier-routing.d.ts +1 -1
- package/dist/topics.d.ts +1 -1
- package/dist/transcript.d.ts +1 -1
- package/dist/transfer/types.d.ts +12 -12
- package/dist/trust-score-stage.d.ts +1 -1
- package/dist/trust-score.d.ts +1 -1
- package/dist/{types-CZm6rx9-.d.ts → types-D4NYDtXI.d.ts} +7 -0
- package/dist/types.d.ts +1 -1
- package/dist/types.js +1 -1
- package/dist/utility-runtime.d.ts +1 -1
- package/dist/verified-recall.js +7 -7
- package/package.json +2 -2
- package/src/access-service.ts +22 -0
- package/src/config.ts +5 -0
- package/src/index.ts +3 -1
- package/src/offline-sync.test.ts +354 -52
- package/src/offline-sync.ts +332 -24
- package/src/orchestration/extraction-run.ts +4 -34
- package/src/orchestration/namespace-read-fanout.ts +484 -0
- package/src/orchestration/orchestrator-helpers.ts +1130 -0
- package/src/orchestration/self-deps.ts +50 -0
- package/src/orchestration/workspace-ops.ts +789 -0
- package/src/orchestrator.ts +177 -2296
- package/src/types.ts +9 -0
- package/dist/chunk-24YDB5QP.js.map +0 -1
- package/dist/chunk-C5WN74HH.js.map +0 -1
- package/dist/chunk-PNUOQYRJ.js.map +0 -1
- package/dist/chunk-PWWWLD7D.js.map +0 -1
- /package/dist/{chunk-GKRLPHPU.js.map → chunk-2KK5WNQB.js.map} +0 -0
- /package/dist/{chunk-JRDPT6DA.js.map → chunk-4NWIGAIC.js.map} +0 -0
- /package/dist/{chunk-OBJUKYDO.js.map → chunk-4XL3CVII.js.map} +0 -0
- /package/dist/{chunk-WWVXXSLF.js.map → chunk-5PZCDUJ6.js.map} +0 -0
- /package/dist/{chunk-URQLO7BX.js.map → chunk-6FNZ3NMS.js.map} +0 -0
- /package/dist/{chunk-DRUDC2UX.js.map → chunk-6MMONPHM.js.map} +0 -0
- /package/dist/{chunk-RB6A7OUN.js.map → chunk-6SXNQFHB.js.map} +0 -0
- /package/dist/{chunk-ZGZNLRKF.js.map → chunk-7TWA7DKP.js.map} +0 -0
- /package/dist/{chunk-KMNYXLPL.js.map → chunk-B35L45HZ.js.map} +0 -0
- /package/dist/{chunk-SIV3JZPP.js.map → chunk-CGZWGVQF.js.map} +0 -0
- /package/dist/{chunk-CKFLLAIS.js.map → chunk-DANV2HTH.js.map} +0 -0
- /package/dist/{chunk-NVYF5OB6.js.map → chunk-DBRVU5PR.js.map} +0 -0
- /package/dist/{chunk-LMFS64GY.js.map → chunk-E4PFDD3N.js.map} +0 -0
- /package/dist/{chunk-DIHCFJVV.js.map → chunk-HYI2GP3F.js.map} +0 -0
- /package/dist/{chunk-UIKZZ242.js.map → chunk-IKHKHADN.js.map} +0 -0
- /package/dist/{chunk-R2OAN6IP.js.map → chunk-K2JM4DZZ.js.map} +0 -0
- /package/dist/{chunk-3IJGF6K2.js.map → chunk-K2R3DEEH.js.map} +0 -0
- /package/dist/{chunk-HIHCB2S6.js.map → chunk-QRRBXD24.js.map} +0 -0
- /package/dist/{chunk-ZPZ4VVLT.js.map → chunk-SD34EK4Z.js.map} +0 -0
- /package/dist/{chunk-WK3NK6SP.js.map → chunk-SNEXVX3U.js.map} +0 -0
- /package/dist/{chunk-FVZ2ISIX.js.map → chunk-TPLE6SNY.js.map} +0 -0
- /package/dist/{chunk-5IN26V6W.js.map → chunk-UU32EAIY.js.map} +0 -0
- /package/dist/{chunk-ZGAJB74V.js.map → chunk-W3BFT5OJ.js.map} +0 -0
- /package/dist/{chunk-L4N7SVNN.js.map → chunk-WA7FECSG.js.map} +0 -0
- /package/dist/{chunk-Q3X7GUAQ.js.map → chunk-WOX2UW4K.js.map} +0 -0
- /package/dist/{chunk-XTEWVF3C.js.map → chunk-WWSXVOGY.js.map} +0 -0
- /package/dist/{chunk-P4FW3ZU5.js.map → chunk-YGGXUNS4.js.map} +0 -0
- /package/dist/{chunk-JHQUIH3W.js.map → chunk-ZBVQ4ZM4.js.map} +0 -0
|
@@ -0,0 +1,484 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Namespace read-fanout coordinator — extracted from the orchestrator
|
|
3
|
+
* (issue #1526, seam 26).
|
|
4
|
+
*
|
|
5
|
+
* Owns namespace-scoped READ fanout (never namespace RESOLUTION — the
|
|
6
|
+
* ScopePlan resolver from #1521 stays the single authority for that):
|
|
7
|
+
* - storage-dir hint loading from the catalog
|
|
8
|
+
* - cross-namespace search and memory/archive reads
|
|
9
|
+
* - scoped memory candidate search and artifact recall fanout
|
|
10
|
+
* - artifact source status resolution (with per-storage cache)
|
|
11
|
+
* - path→namespace and storage-dir→namespace mapping helpers
|
|
12
|
+
*
|
|
13
|
+
* Behavior-preserving move from orchestrator.ts (late-binding deps rule,
|
|
14
|
+
* seams 18–25).
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
18
|
+
import { stat } from "node:fs/promises";
|
|
19
|
+
import path from "node:path";
|
|
20
|
+
import { resolveNamespaceCapabilities } from "../capabilities.js";
|
|
21
|
+
import { StorageManager } from "../index.js";
|
|
22
|
+
import { NamespaceCatalog } from "../namespaces/catalog.js";
|
|
23
|
+
import { namespaceIdentityFromToken, namespaceIdentityToken, normalizeNamespaceIdentity } from "../namespaces/identity.js";
|
|
24
|
+
import { NamespaceSearchRouter } from "../namespaces/search.js";
|
|
25
|
+
import { NamespaceStorageRouter } from "../namespaces/storage.js";
|
|
26
|
+
import { mergeArtifactRecallCandidates, tokenizeRecallQuery } from "./orchestrator-helpers.js";
|
|
27
|
+
import { qmdCollectionPathParts } from "./qmd-result-resolver.js";
|
|
28
|
+
import { resolveNamespaceFromStorageDir } from "../scopes/scope-plan.js";
|
|
29
|
+
import type { SearchBackend, SearchExecutionOptions, SearchQueryOptions } from "../search/port.js";
|
|
30
|
+
import type { MemoryFile, PluginConfig, QmdSearchResult } from "../types.js";
|
|
31
|
+
import {
|
|
32
|
+
Orchestrator,
|
|
33
|
+
} from "../orchestrator.js";
|
|
34
|
+
|
|
35
|
+
export interface NamespaceReadFanoutDeps {
|
|
36
|
+
readonly artifactSourceStatusCache: WeakMap<StorageManager, { loadedAtMs: number; statusVersion: number; statuses: Map<string, "active" | "superseded" | "archived" | "missing"> }>;
|
|
37
|
+
readonly config: PluginConfig;
|
|
38
|
+
configuredNamespaceList(): string[];
|
|
39
|
+
fetchActiveArtifactsForNamespace(
|
|
40
|
+
namespace: string,
|
|
41
|
+
prompt: string,
|
|
42
|
+
targetCount: number,
|
|
43
|
+
): Promise<MemoryFile[]>;
|
|
44
|
+
loadNamespaceStorageDirHintsFromCatalog(): void;
|
|
45
|
+
readonly namespaceCatalog: NamespaceCatalog;
|
|
46
|
+
namespaceFromPath(p: string): string;
|
|
47
|
+
readonly namespaceSearchRouter: NamespaceSearchRouter;
|
|
48
|
+
namespaceStorageDirHintOwnershipRank(
|
|
49
|
+
record: { namespace: string },
|
|
50
|
+
resolvedStorageDir: string,
|
|
51
|
+
configured: Set<string>,
|
|
52
|
+
): number;
|
|
53
|
+
readonly namespaceStorageDirHints: Map<string, Set<string>>;
|
|
54
|
+
namespaceStorageDirHintsLoaded: boolean;
|
|
55
|
+
preferNamespaceStorageDirHintOwner(
|
|
56
|
+
current: { namespace: string; identityToken: string; storageDir: string },
|
|
57
|
+
candidate: { namespace: string; identityToken: string; storageDir: string },
|
|
58
|
+
resolvedStorageDir: string,
|
|
59
|
+
configured: Set<string>,
|
|
60
|
+
): { namespace: string; identityToken: string; storageDir: string };
|
|
61
|
+
readonly qmd: SearchBackend;
|
|
62
|
+
qmdCollectionNamespaceFromPrefix(collectionPrefix: string): string | null;
|
|
63
|
+
rememberNamespaceStorageDirHint(namespace: string, storageDir?: string): void;
|
|
64
|
+
storageDirMatchesNamespaceHint(namespace: string, storageDir: string): boolean;
|
|
65
|
+
readonly storageRouter: NamespaceStorageRouter;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export class NamespaceReadFanoutCoordinator {
|
|
69
|
+
constructor(
|
|
70
|
+
private readonly deps: NamespaceReadFanoutDeps,
|
|
71
|
+
) {}
|
|
72
|
+
|
|
73
|
+
preferNamespaceStorageDirHintOwner(
|
|
74
|
+
current: { namespace: string; identityToken: string; storageDir: string },
|
|
75
|
+
candidate: { namespace: string; identityToken: string; storageDir: string },
|
|
76
|
+
resolvedStorageDir: string,
|
|
77
|
+
configured: Set<string>,
|
|
78
|
+
): { namespace: string; identityToken: string; storageDir: string } {
|
|
79
|
+
const currentRank = this.deps.namespaceStorageDirHintOwnershipRank(
|
|
80
|
+
current,
|
|
81
|
+
resolvedStorageDir,
|
|
82
|
+
configured,
|
|
83
|
+
);
|
|
84
|
+
const candidateRank = this.deps.namespaceStorageDirHintOwnershipRank(
|
|
85
|
+
candidate,
|
|
86
|
+
resolvedStorageDir,
|
|
87
|
+
configured,
|
|
88
|
+
);
|
|
89
|
+
if (candidateRank < currentRank) return candidate;
|
|
90
|
+
if (candidateRank > currentRank) return current;
|
|
91
|
+
|
|
92
|
+
const byName = candidate.namespace.localeCompare(current.namespace);
|
|
93
|
+
if (byName < 0) return candidate;
|
|
94
|
+
if (byName > 0) return current;
|
|
95
|
+
return candidate.identityToken.localeCompare(current.identityToken) < 0
|
|
96
|
+
? candidate
|
|
97
|
+
: current;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
loadNamespaceStorageDirHintsFromCatalog(): void {
|
|
101
|
+
if (this.deps.namespaceStorageDirHintsLoaded || !this.deps.namespaceCatalog.enabled) return;
|
|
102
|
+
this.deps.namespaceStorageDirHintsLoaded = true;
|
|
103
|
+
const catalogPath = path.join(this.deps.config.memoryDir, "state", "namespaces.jsonl");
|
|
104
|
+
if (!existsSync(catalogPath)) return;
|
|
105
|
+
|
|
106
|
+
let body: string;
|
|
107
|
+
try {
|
|
108
|
+
body = readFileSync(catalogPath, "utf8");
|
|
109
|
+
} catch {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const compactedByNamespace = new Map<
|
|
114
|
+
string,
|
|
115
|
+
{ namespace: string; identityToken: string; storageDir: string }
|
|
116
|
+
>();
|
|
117
|
+
for (const line of body.split(/\r?\n/)) {
|
|
118
|
+
const trimmed = line.trim();
|
|
119
|
+
if (!trimmed) continue;
|
|
120
|
+
try {
|
|
121
|
+
const parsed = JSON.parse(trimmed) as unknown;
|
|
122
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) continue;
|
|
123
|
+
const record = parsed as Record<string, unknown>;
|
|
124
|
+
if (
|
|
125
|
+
typeof record.namespace !== "string" ||
|
|
126
|
+
typeof record.storageDir !== "string" ||
|
|
127
|
+
typeof record.identityToken !== "string"
|
|
128
|
+
) {
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
const namespace = normalizeNamespaceIdentity(record.namespace);
|
|
132
|
+
if (!namespace || record.identityToken !== namespaceIdentityToken(namespace)) continue;
|
|
133
|
+
compactedByNamespace.set(namespace, {
|
|
134
|
+
namespace,
|
|
135
|
+
identityToken: record.identityToken,
|
|
136
|
+
storageDir: record.storageDir,
|
|
137
|
+
});
|
|
138
|
+
} catch {
|
|
139
|
+
// Catalog hints are best-effort. The catalog reader still owns full recovery.
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const configured = new Set(
|
|
144
|
+
this.deps.configuredNamespaceList().map((namespace) => normalizeNamespaceIdentity(namespace)),
|
|
145
|
+
);
|
|
146
|
+
const preferredByStorageDir = new Map<
|
|
147
|
+
string,
|
|
148
|
+
{ namespace: string; identityToken: string; storageDir: string }
|
|
149
|
+
>();
|
|
150
|
+
for (const record of compactedByNamespace.values()) {
|
|
151
|
+
if (!this.deps.storageDirMatchesNamespaceHint(record.namespace, record.storageDir)) {
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
const resolvedStorageDir = path.resolve(record.storageDir);
|
|
155
|
+
const current = preferredByStorageDir.get(resolvedStorageDir);
|
|
156
|
+
preferredByStorageDir.set(
|
|
157
|
+
resolvedStorageDir,
|
|
158
|
+
current
|
|
159
|
+
? this.deps.preferNamespaceStorageDirHintOwner(
|
|
160
|
+
current,
|
|
161
|
+
record,
|
|
162
|
+
resolvedStorageDir,
|
|
163
|
+
configured,
|
|
164
|
+
)
|
|
165
|
+
: record,
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
for (const record of preferredByStorageDir.values()) {
|
|
169
|
+
this.deps.rememberNamespaceStorageDirHint(record.namespace, record.storageDir);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
async searchAcrossNamespaces(options: {
|
|
174
|
+
query: string;
|
|
175
|
+
namespaces?: string[];
|
|
176
|
+
maxResults?: number;
|
|
177
|
+
mode?: "search" | "hybrid" | "bm25" | "vector";
|
|
178
|
+
searchOptions?: SearchQueryOptions;
|
|
179
|
+
execution?: SearchExecutionOptions;
|
|
180
|
+
}): Promise<QmdSearchResult[]> {
|
|
181
|
+
if (
|
|
182
|
+
resolveNamespaceCapabilities(this.deps.config).namespaces &&
|
|
183
|
+
options.namespaces !== undefined &&
|
|
184
|
+
options.namespaces.length === 0
|
|
185
|
+
) {
|
|
186
|
+
return [];
|
|
187
|
+
}
|
|
188
|
+
const namespaces = resolveNamespaceCapabilities(this.deps.config).namespaces
|
|
189
|
+
? Array.from(
|
|
190
|
+
new Set(
|
|
191
|
+
(options.namespaces?.length
|
|
192
|
+
? options.namespaces
|
|
193
|
+
: this.deps.configuredNamespaceList()
|
|
194
|
+
)
|
|
195
|
+
.map((value) => value.trim())
|
|
196
|
+
.filter(Boolean),
|
|
197
|
+
),
|
|
198
|
+
)
|
|
199
|
+
: [this.deps.config.defaultNamespace];
|
|
200
|
+
|
|
201
|
+
if (!resolveNamespaceCapabilities(this.deps.config).namespaces) {
|
|
202
|
+
switch (options.mode) {
|
|
203
|
+
case "hybrid":
|
|
204
|
+
return await this.deps.qmd.hybridSearch(
|
|
205
|
+
options.query,
|
|
206
|
+
undefined,
|
|
207
|
+
options.maxResults,
|
|
208
|
+
options.execution,
|
|
209
|
+
);
|
|
210
|
+
case "bm25":
|
|
211
|
+
return await this.deps.qmd.bm25Search(
|
|
212
|
+
options.query,
|
|
213
|
+
undefined,
|
|
214
|
+
options.maxResults,
|
|
215
|
+
options.execution,
|
|
216
|
+
);
|
|
217
|
+
case "vector":
|
|
218
|
+
return await this.deps.qmd.vectorSearch(
|
|
219
|
+
options.query,
|
|
220
|
+
undefined,
|
|
221
|
+
options.maxResults,
|
|
222
|
+
options.execution,
|
|
223
|
+
);
|
|
224
|
+
default:
|
|
225
|
+
return await this.deps.qmd.search(
|
|
226
|
+
options.query,
|
|
227
|
+
undefined,
|
|
228
|
+
options.maxResults,
|
|
229
|
+
options.searchOptions,
|
|
230
|
+
options.execution,
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
return await this.deps.namespaceSearchRouter.searchAcrossNamespaces({
|
|
236
|
+
query: options.query,
|
|
237
|
+
namespaces,
|
|
238
|
+
maxResults: options.maxResults,
|
|
239
|
+
mode: options.mode,
|
|
240
|
+
searchOptions: options.searchOptions,
|
|
241
|
+
execution: options.execution,
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
async resolveArtifactSourceStatuses(
|
|
246
|
+
storage: StorageManager,
|
|
247
|
+
sourceIds: string[],
|
|
248
|
+
): Promise<Map<string, "active" | "superseded" | "archived" | "missing">> {
|
|
249
|
+
const currentStatusVersion = storage.getMemoryStatusVersion();
|
|
250
|
+
const cached = this.deps.artifactSourceStatusCache.get(storage);
|
|
251
|
+
let snapshot = cached;
|
|
252
|
+
const isFresh =
|
|
253
|
+
snapshot !== undefined &&
|
|
254
|
+
Date.now() - snapshot.loadedAtMs <=
|
|
255
|
+
Orchestrator.ARTIFACT_STATUS_CACHE_TTL_MS &&
|
|
256
|
+
snapshot.statusVersion === currentStatusVersion;
|
|
257
|
+
|
|
258
|
+
const rebuildSnapshot = async () => {
|
|
259
|
+
const MAX_STABLE_READ_ATTEMPTS = 3;
|
|
260
|
+
let latestStatuses = new Map<
|
|
261
|
+
string,
|
|
262
|
+
"active" | "superseded" | "archived" | "missing"
|
|
263
|
+
>();
|
|
264
|
+
let latestVersionAfter = storage.getMemoryStatusVersion();
|
|
265
|
+
|
|
266
|
+
for (let attempt = 0; attempt < MAX_STABLE_READ_ATTEMPTS; attempt += 1) {
|
|
267
|
+
const versionBefore = storage.getMemoryStatusVersion();
|
|
268
|
+
const allMemories = await storage.readAllMemories();
|
|
269
|
+
const versionAfter = storage.getMemoryStatusVersion();
|
|
270
|
+
latestVersionAfter = versionAfter;
|
|
271
|
+
latestStatuses = new Map(
|
|
272
|
+
allMemories.map((m) => [
|
|
273
|
+
m.frontmatter.id,
|
|
274
|
+
(m.frontmatter.status ?? "active") as
|
|
275
|
+
| "active"
|
|
276
|
+
| "superseded"
|
|
277
|
+
| "archived"
|
|
278
|
+
| "missing",
|
|
279
|
+
]),
|
|
280
|
+
);
|
|
281
|
+
|
|
282
|
+
if (versionAfter === versionBefore) {
|
|
283
|
+
const rebuilt = {
|
|
284
|
+
loadedAtMs: Date.now(),
|
|
285
|
+
statusVersion: versionAfter,
|
|
286
|
+
statuses: latestStatuses,
|
|
287
|
+
};
|
|
288
|
+
this.deps.artifactSourceStatusCache.set(storage, rebuilt);
|
|
289
|
+
return rebuilt;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// Sustained write churn: return latest read without caching a potentially torn snapshot.
|
|
294
|
+
return {
|
|
295
|
+
loadedAtMs: Date.now(),
|
|
296
|
+
statusVersion: latestVersionAfter,
|
|
297
|
+
statuses: latestStatuses,
|
|
298
|
+
};
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
if (!isFresh) {
|
|
302
|
+
snapshot = await rebuildSnapshot();
|
|
303
|
+
} else {
|
|
304
|
+
// Warm cache may miss brand-new sourceMemoryId values created after snapshot build.
|
|
305
|
+
// Refresh once on-demand when unseen IDs are requested.
|
|
306
|
+
const hasUnknownSourceIds = sourceIds.some(
|
|
307
|
+
(id) => !snapshot?.statuses.has(id),
|
|
308
|
+
);
|
|
309
|
+
if (hasUnknownSourceIds) {
|
|
310
|
+
snapshot = await rebuildSnapshot();
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Persist negative lookups in the cached snapshot so stale source IDs do not
|
|
315
|
+
// trigger repeated full snapshot rebuilds on every matching recall.
|
|
316
|
+
for (const id of sourceIds) {
|
|
317
|
+
if (!snapshot?.statuses.has(id)) {
|
|
318
|
+
snapshot?.statuses.set(id, "missing");
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
const statuses = new Map<
|
|
323
|
+
string,
|
|
324
|
+
"active" | "superseded" | "archived" | "missing"
|
|
325
|
+
>();
|
|
326
|
+
for (const id of sourceIds) {
|
|
327
|
+
const status = snapshot?.statuses.get(id);
|
|
328
|
+
if (status) {
|
|
329
|
+
statuses.set(id, status);
|
|
330
|
+
} else {
|
|
331
|
+
statuses.set(id, "missing");
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
return statuses;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
async recallArtifactsAcrossNamespaces(
|
|
338
|
+
prompt: string,
|
|
339
|
+
recallNamespaces: string[],
|
|
340
|
+
targetCount: number,
|
|
341
|
+
): Promise<MemoryFile[]> {
|
|
342
|
+
if (targetCount <= 0) return [];
|
|
343
|
+
const namespaces = Array.from(new Set(recallNamespaces));
|
|
344
|
+
const filteredByNamespace = await Promise.all(
|
|
345
|
+
namespaces.map((namespace) =>
|
|
346
|
+
this.deps.fetchActiveArtifactsForNamespace(namespace, prompt, targetCount),
|
|
347
|
+
),
|
|
348
|
+
);
|
|
349
|
+
|
|
350
|
+
return mergeArtifactRecallCandidates(filteredByNamespace, targetCount);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
async searchScopedMemoryCandidates(
|
|
354
|
+
candidatePaths: Set<string>,
|
|
355
|
+
query: string,
|
|
356
|
+
limit: number,
|
|
357
|
+
options?: {
|
|
358
|
+
allowArchived?: boolean;
|
|
359
|
+
},
|
|
360
|
+
): Promise<QmdSearchResult[]> {
|
|
361
|
+
const cappedLimit = Math.max(0, limit);
|
|
362
|
+
if (cappedLimit === 0 || candidatePaths.size === 0) return [];
|
|
363
|
+
|
|
364
|
+
const tokens = Array.from(new Set(tokenizeRecallQuery(query)));
|
|
365
|
+
const memories = (
|
|
366
|
+
await Promise.all(
|
|
367
|
+
Array.from(candidatePaths).map(async (memoryPath) => {
|
|
368
|
+
const namespace = resolveNamespaceCapabilities(this.deps.config).namespaces
|
|
369
|
+
? this.deps.namespaceFromPath(memoryPath)
|
|
370
|
+
: this.deps.config.defaultNamespace;
|
|
371
|
+
const storage = await this.deps.storageRouter.storageFor(namespace);
|
|
372
|
+
return await storage.readMemoryByPath(memoryPath);
|
|
373
|
+
}),
|
|
374
|
+
)
|
|
375
|
+
).filter((memory): memory is MemoryFile => memory !== null);
|
|
376
|
+
|
|
377
|
+
const results: QmdSearchResult[] = [];
|
|
378
|
+
for (const memory of memories) {
|
|
379
|
+
const status = memory.frontmatter.status ?? "active";
|
|
380
|
+
if (!options?.allowArchived && status !== "active") continue;
|
|
381
|
+
|
|
382
|
+
const haystack = [
|
|
383
|
+
memory.content,
|
|
384
|
+
memory.frontmatter.category,
|
|
385
|
+
...(memory.frontmatter.tags ?? []),
|
|
386
|
+
]
|
|
387
|
+
.join(" ")
|
|
388
|
+
.toLowerCase();
|
|
389
|
+
let hits = 0;
|
|
390
|
+
for (const token of tokens) {
|
|
391
|
+
if (haystack.includes(token)) hits += 1;
|
|
392
|
+
}
|
|
393
|
+
const score = tokens.length > 0 ? hits / tokens.length : 0.01;
|
|
394
|
+
if (tokens.length > 0 && hits === 0) continue;
|
|
395
|
+
|
|
396
|
+
results.push({
|
|
397
|
+
docid: memory.frontmatter.id,
|
|
398
|
+
path: memory.path,
|
|
399
|
+
score,
|
|
400
|
+
snippet: memory.content.slice(0, 400).replace(/\n/g, " "),
|
|
401
|
+
transport: "scoped_prefilter",
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
return results.sort((a, b) => b.score - a.score).slice(0, cappedLimit);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
async resolveStateDirForNamespace(
|
|
409
|
+
namespace: string,
|
|
410
|
+
): Promise<string> {
|
|
411
|
+
if (!resolveNamespaceCapabilities(this.deps.config).namespaces) {
|
|
412
|
+
return path.join(this.deps.config.memoryDir, "state");
|
|
413
|
+
}
|
|
414
|
+
if (namespace !== this.deps.config.defaultNamespace) {
|
|
415
|
+
return path.join(this.deps.config.memoryDir, "namespaces", namespace, "state");
|
|
416
|
+
}
|
|
417
|
+
const candidate = path.join(
|
|
418
|
+
this.deps.config.memoryDir,
|
|
419
|
+
"namespaces",
|
|
420
|
+
this.deps.config.defaultNamespace,
|
|
421
|
+
);
|
|
422
|
+
try {
|
|
423
|
+
const candidateStat = await stat(candidate);
|
|
424
|
+
if (candidateStat.isDirectory()) {
|
|
425
|
+
return path.join(candidate, "state");
|
|
426
|
+
}
|
|
427
|
+
} catch {
|
|
428
|
+
// Fall back to the legacy root when the migrated default namespace directory is absent.
|
|
429
|
+
}
|
|
430
|
+
return path.join(this.deps.config.memoryDir, "state");
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
namespaceFromPath(p: string): string {
|
|
434
|
+
if (!resolveNamespaceCapabilities(this.deps.config).namespaces) return this.deps.config.defaultNamespace;
|
|
435
|
+
const parts = qmdCollectionPathParts(p);
|
|
436
|
+
const collectionNamespace = parts
|
|
437
|
+
? this.deps.qmdCollectionNamespaceFromPrefix(parts.collection)
|
|
438
|
+
: null;
|
|
439
|
+
if (collectionNamespace) return collectionNamespace;
|
|
440
|
+
const m = p.match(/[\\/]+namespaces[\\/]+([^\\/]+)(?:[\\/]|$)/);
|
|
441
|
+
if (!m?.[1]) return this.deps.config.defaultNamespace;
|
|
442
|
+
return namespaceIdentityFromToken(m[1]) ?? m[1];
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
storageDirNamespace(storageDir: string): string {
|
|
446
|
+
// #1521: delegates to the scope-module resolver. The inline dir→namespace
|
|
447
|
+
// derivation (token round-trip guard, catalog hints) is retired so the
|
|
448
|
+
// adHocNamespaceResolutions ratchet no longer counts this site. Hints are
|
|
449
|
+
// loaded lazily via the callback (only after early returns, matching the
|
|
450
|
+
// original behavior — codex P2).
|
|
451
|
+
return resolveNamespaceFromStorageDir(storageDir, {
|
|
452
|
+
config: this.deps.config,
|
|
453
|
+
configuredNamespaces: this.deps.configuredNamespaceList(),
|
|
454
|
+
hints: this.deps.namespaceStorageDirHints,
|
|
455
|
+
loadHints: () => this.deps.loadNamespaceStorageDirHintsFromCatalog(),
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
async readAllMemoriesForNamespaces(
|
|
460
|
+
namespaces: string[],
|
|
461
|
+
): Promise<MemoryFile[]> {
|
|
462
|
+
const uniq = Array.from(new Set(namespaces.filter(Boolean)));
|
|
463
|
+
const lists = await Promise.all(
|
|
464
|
+
uniq.map(async (ns) => {
|
|
465
|
+
const sm = await this.deps.storageRouter.storageFor(ns);
|
|
466
|
+
return sm.readAllMemories();
|
|
467
|
+
}),
|
|
468
|
+
);
|
|
469
|
+
return lists.flat();
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
async readArchivedMemoriesForNamespaces(
|
|
473
|
+
namespaces: string[],
|
|
474
|
+
): Promise<MemoryFile[]> {
|
|
475
|
+
const uniq = Array.from(new Set(namespaces.filter(Boolean)));
|
|
476
|
+
const lists = await Promise.all(
|
|
477
|
+
uniq.map(async (ns) => {
|
|
478
|
+
const sm = await this.deps.storageRouter.storageFor(ns);
|
|
479
|
+
return sm.readArchivedMemories();
|
|
480
|
+
}),
|
|
481
|
+
);
|
|
482
|
+
return lists.flat();
|
|
483
|
+
}
|
|
484
|
+
}
|