@futdevpro/fdp-agent-memory 0.1.0 → 1.1.12
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/LICENSE +21 -0
- package/README.md +7 -7
- package/build/package.json +6 -5
- package/build/src/_cli/_collections/fam-arg.util.js +48 -0
- package/build/src/_cli/_collections/fam-cli.const.js +40 -0
- package/build/src/_cli/_collections/fam-output.util.js +86 -0
- package/build/src/_cli/_collections/fam-project-discovery.util.js +98 -0
- package/build/src/_cli/_commands/capture.command.js +73 -0
- package/build/src/_cli/_commands/config.command.js +93 -0
- package/build/src/_cli/_commands/doctor.command.js +124 -0
- package/build/src/_cli/_commands/errors.command.js +66 -0
- package/build/src/_cli/_commands/export.command.js +65 -0
- package/build/src/_cli/_commands/find-duplicates.command.js +97 -0
- package/build/src/_cli/_commands/import.command.js +136 -0
- package/build/src/_cli/_commands/init.command.js +147 -0
- package/build/src/_cli/_commands/read.command.js +109 -0
- package/build/src/_cli/_commands/scan-projects.command.js +138 -0
- package/build/src/_cli/_commands/scan.command.js +98 -0
- package/build/src/_cli/_commands/seed.command.js +40 -0
- package/build/src/_cli/_commands/serve.command.js +350 -0
- package/build/src/_cli/_commands/start.command.js +134 -0
- package/build/src/_cli/_commands/stats.command.js +54 -0
- package/build/src/_cli/_commands/write.command.js +103 -0
- package/build/src/_cli/_models/interfaces/fam-cli-global-options.interface.js +2 -0
- package/build/src/_cli/_models/interfaces/fam-cli-output.interface.js +9 -0
- package/build/src/_cli/_models/interfaces/fam-client-result.interface.js +2 -0
- package/build/src/_cli/_services/fam-client.service.js +140 -0
- package/build/src/_cli/register-commands.js +86 -0
- package/build/src/_collections/config-catalog.const.js +67 -1
- package/build/src/_collections/fam-console.util.js +367 -0
- package/build/src/_collections/fam-entry-bootstrap.util.js +158 -4
- package/build/src/_collections/fam-error-factory.util.js +0 -9
- package/build/src/_collections/fam-mcp-bridge.util.js +49 -0
- package/build/src/_collections/fam-reference-code.util.js +105 -0
- package/build/src/_collections/fam-version.const.js +10 -0
- package/build/src/_models/data-models/fam-entry-base-properties.const.js +1 -0
- package/build/src/_models/data-models/fam-entry.data-model.js +6 -0
- package/build/src/_models/data-models/fam-ingest-run.data-model.js +3 -1
- package/build/src/_models/data-models/fam-reference.data-model.js +7 -0
- package/build/src/_modules/capture/_collections/fam-capture.const.js +11 -0
- package/build/src/_modules/capture/_services/fam-auto-capture.control-service.js +87 -0
- package/build/src/_modules/capture/index.js +8 -0
- package/build/src/_modules/embedding/_collections/fam-embedding-prefix.util.js +77 -0
- package/build/src/_modules/embedding/_services/fam-duplicate-scan.control-service.js +202 -0
- package/build/src/_modules/embedding/_services/fam-embedding-pipeline.control-service.js +33 -9
- package/build/src/_modules/embedding/_services/fam-embedding.control-service.js +21 -2
- package/build/src/_modules/embedding/_services/fam-entry.data-service.js +135 -0
- package/build/src/_modules/embedding/_services/fam-vector-search.control-service.js +42 -32
- package/build/src/_modules/embedding/index.js +4 -1
- package/build/src/_modules/export/_collections/fam-export.const.js +22 -0
- package/build/src/_modules/export/_services/fam-export.control-service.js +64 -0
- package/build/src/_modules/export/index.js +8 -0
- package/build/src/_modules/ingest/_collections/fam-famignore.util.js +83 -0
- package/build/src/_modules/ingest/_collections/fam-file-routing.util.js +59 -48
- package/build/src/_modules/ingest/_collections/fam-project-identity.util.js +134 -0
- package/build/src/_modules/ingest/_collections/fam-scan-progress.util.js +57 -0
- package/build/src/_modules/ingest/_collections/fam-scan-summary.util.js +60 -0
- package/build/src/_modules/ingest/_collections/fam-scan-weight.util.js +53 -0
- package/build/src/_modules/ingest/_collections/fam-secret-exclude.util.js +37 -14
- package/build/src/_modules/ingest/_collections/fam-sliding-chunker.util.js +34 -0
- package/build/src/_modules/ingest/_collections/fam-ts-chunker.util.js +200 -14
- package/build/src/_modules/ingest/_services/fam-delta-compare.util.js +4 -1
- package/build/src/_modules/ingest/_services/fam-ingest-run.data-service.js +7 -4
- package/build/src/_modules/ingest/_services/fam-ingest.control-service.js +346 -17
- package/build/src/_modules/ingest/_services/fam-scan.control-service.js +25 -2
- package/build/src/_modules/ingest/index.js +3 -1
- package/build/src/_modules/mcp/_collections/fam-active-rules.util.js +56 -0
- package/build/src/_modules/mcp/_collections/fam-core-tools.const.js +47 -6
- package/build/src/_modules/mcp/_services/fam-capabilities-tool.service.js +4 -4
- package/build/src/_modules/mcp/_services/fam-capability-registry.service.js +224 -18
- package/build/src/_modules/mcp/_services/fam-mcp-adapter.service.js +4 -4
- package/build/src/_modules/mcp/_services/fam-mcp-server.service.js +4 -4
- package/build/src/_modules/mcp/_services/fam-read-tool.service.js +53 -1
- package/build/src/_modules/mcp/_services/fam-write-tool.service.js +104 -8
- package/build/src/_modules/mcp/index.js +4 -4
- package/build/src/_modules/migration/_collections/fam-claude-mem-normalize.util.js +66 -3
- package/build/src/_modules/migration/_collections/fam-prompt-aggregate.util.js +143 -0
- package/build/src/_modules/migration/_collections/fam-target-mapping.util.js +19 -0
- package/build/src/_modules/migration/_enums/fam-claude-mem-source.type-enum.js +6 -0
- package/build/src/_modules/migration/_models/interfaces/fam-claude-mem.interface.js +5 -0
- package/build/src/_modules/migration/_services/fam-agent-memory-reader.service.js +125 -0
- package/build/src/_modules/migration/_services/fam-claude-mem-import.control-service.js +101 -18
- package/build/src/_modules/migration/_services/fam-import-dedup.data-service.js +53 -0
- package/build/src/_modules/migration/index.js +3 -1
- package/build/src/_modules/retrieval/_services/fam-retrieval-candidate.data-service.js +78 -4
- package/build/src/_modules/retrieval/_services/fam-retrieval.control-service.js +293 -50
- package/build/src/_modules/scope-reference/_collections/fam-scope-normalize.util.js +6 -3
- package/build/src/_modules/scope-reference/_services/fam-reference.data-service.js +18 -0
- package/build/src/_modules/scope-reference/_services/fam-scope-resolver.control-service.js +79 -20
- package/build/src/_routes/server/api/api.controller.js +34 -2
- package/build/src/_routes/server/client-app/client-app.control-service.js +1 -1
- package/build/src/_routes/server/server-status/server-status.controller.js +2 -1
- package/build/src/app.server.js +13 -1
- package/build/src/environments/environment.js +1 -1
- package/build/src/index.js +1 -1
- package/client-dist/{chunk-GHKRM4SM.js → chunk-I77GXVAQ.js} +1 -1
- package/client-dist/{chunk-LMTL7GA3.js → chunk-YXHWCJ5O.js} +1 -1
- package/client-dist/index.html +1 -1
- package/client-dist/{main-2KWB3QYK.js → main-PJPEDVJT.js} +1 -1
- package/package.json +6 -5
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FAM_AgentMemoryReader_Service = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const fs = tslib_1.__importStar(require("fs"));
|
|
6
|
+
const path = tslib_1.__importStar(require("path"));
|
|
7
|
+
const error_codes_const_1 = require("../../../_collections/error-codes.const");
|
|
8
|
+
const fam_error_factory_util_1 = require("../../../_collections/fam-error-factory.util");
|
|
9
|
+
const fam_claude_mem_source_type_enum_1 = require("../_enums/fam-claude-mem-source.type-enum");
|
|
10
|
+
const fam_claude_mem_interface_1 = require("../_models/interfaces/fam-claude-mem.interface");
|
|
11
|
+
/**
|
|
12
|
+
* `FAM_AgentMemoryReader_Service` (agent-memory import, SP-11.1-mintára) — az agent (Claude) tartós
|
|
13
|
+
* memóriáját (`.claude/.../memory/*.md`) olvassa be **függőség-mentesen** (fs + egyszerű frontmatter-parse),
|
|
14
|
+
* és `FAM_ClaudeMemRecord[]`-dá normalizálja → a meglévő import-engine (preview/run/rollback/dedup/embed)
|
|
15
|
+
* VÁLTOZATLANUL feldolgozza (a `readSource` `agent-memory`-ágáról hívva).
|
|
16
|
+
*
|
|
17
|
+
* **Forrás-shape (a memória-fájlok frontmatter-e):**
|
|
18
|
+
* ```
|
|
19
|
+
* ---
|
|
20
|
+
* name: <kebab-slug>
|
|
21
|
+
* description: <egy-soros>
|
|
22
|
+
* metadata:
|
|
23
|
+
* type: user | feedback | project | reference
|
|
24
|
+
* ---
|
|
25
|
+
* <markdown body … [[link]] …>
|
|
26
|
+
* ```
|
|
27
|
+
* A `MEMORY.md` (mutató-index, NEM memória) **kihagyva**. Defenzív: parse-hiba/üres fájl → `warnings`, a
|
|
28
|
+
* többi folytatódik (nothing-lost). A cél-tár a `type`-ról képződik a `FAM_TargetMapping_Util`-ban
|
|
29
|
+
* (reference→knowledge, feedback→rules, project→memory, user→knowledge).
|
|
30
|
+
*/
|
|
31
|
+
class FAM_AgentMemoryReader_Service {
|
|
32
|
+
static _instance;
|
|
33
|
+
issuer = 'FAM_AgentMemoryReader_Service';
|
|
34
|
+
/** A mutató-index fájl (egy-soros pointer-lista, NEM önálló memória) — az importból kihagyva. */
|
|
35
|
+
static INDEX_FILE = 'MEMORY.md';
|
|
36
|
+
/** Az agent-memory rekordok rögzített scope-projektje (egy scope minden bejegyzésre; a run auto-create-eli). */
|
|
37
|
+
static SCOPE_PROJECT = 'agent-memory';
|
|
38
|
+
static getInstance() {
|
|
39
|
+
if (!FAM_AgentMemoryReader_Service._instance) {
|
|
40
|
+
FAM_AgentMemoryReader_Service._instance = new FAM_AgentMemoryReader_Service();
|
|
41
|
+
}
|
|
42
|
+
return FAM_AgentMemoryReader_Service._instance;
|
|
43
|
+
}
|
|
44
|
+
/** A memória-mappa beolvasása → normalizált rekordok (a `path` a `*.md`-ket tartalmazó könyvtár). */
|
|
45
|
+
async read(set) {
|
|
46
|
+
const dir = set.path ?? '';
|
|
47
|
+
if (!dir || !fs.existsSync(dir) || !fs.statSync(dir).isDirectory()) {
|
|
48
|
+
throw fam_error_factory_util_1.FAM_Error_Util.create({
|
|
49
|
+
errorCode: error_codes_const_1.FAM_ERROR_CODES.impSource,
|
|
50
|
+
message: `Az agent-memory mappa nem található vagy nem könyvtár: '${dir}'.`,
|
|
51
|
+
issuer: this.issuer,
|
|
52
|
+
context: { operation: 'agent-memory-read' },
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
const warnings = [];
|
|
56
|
+
const files = fs.readdirSync(dir)
|
|
57
|
+
.filter((file) => file.toLowerCase().endsWith('.md') && file !== FAM_AgentMemoryReader_Service.INDEX_FILE)
|
|
58
|
+
.sort();
|
|
59
|
+
const records = [];
|
|
60
|
+
for (const file of files) {
|
|
61
|
+
const full = path.join(dir, file);
|
|
62
|
+
try {
|
|
63
|
+
const parsed = FAM_AgentMemoryReader_Service.parse(fs.readFileSync(full, 'utf8'));
|
|
64
|
+
if (!parsed.body.trim() && !(parsed.description && parsed.description.trim())) {
|
|
65
|
+
warnings.push(`üres memória-fájl kihagyva: ${file}`);
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
records.push(this.toRecord(file, full, parsed));
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
warnings.push(`agent-memory parse-hiba (${file}): ${error?.message}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
from: fam_claude_mem_source_type_enum_1.FAM_ClaudeMemSource_Type.agentMemory,
|
|
76
|
+
records: records,
|
|
77
|
+
sessions: [],
|
|
78
|
+
counts: { observations: records.length, summaries: 0, prompts: 0, sessions: 0 },
|
|
79
|
+
warnings: warnings,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/** Egy parse-olt memória → `FAM_ClaudeMemRecord` (entity=agentMemory; type a cél-tárhoz; slug a dedup-hoz). */
|
|
83
|
+
toRecord(file, fullPath, parsed) {
|
|
84
|
+
const slug = (parsed.name && parsed.name.trim()) ? parsed.name.trim() : file.replace(/\.md$/i, '');
|
|
85
|
+
return {
|
|
86
|
+
entity: fam_claude_mem_interface_1.FAM_ClaudeMemEntity_Type.agentMemory,
|
|
87
|
+
sourceRowId: slug,
|
|
88
|
+
project: FAM_AgentMemoryReader_Service.SCOPE_PROJECT,
|
|
89
|
+
type: parsed.type,
|
|
90
|
+
title: parsed.description,
|
|
91
|
+
narrative: parsed.body,
|
|
92
|
+
concepts: parsed.links,
|
|
93
|
+
filesRead: [],
|
|
94
|
+
filesModified: [fullPath],
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Egy `.md` fájl frontmatter + body + `[[link]]` parse-e (függőség-mentes, defenzív). A frontmatter a
|
|
99
|
+
* `---\n…\n---` blokk; a `name`/`description` top-szintű, a `type` a `metadata:` alatt indentált — mindet a
|
|
100
|
+
* sor-szintű `field`-regex húzza (az indentet `^\s*` engedi). Frontmatter nélkül a teljes szöveg a body.
|
|
101
|
+
*/
|
|
102
|
+
static parse(raw) {
|
|
103
|
+
const links = [...new Set((raw.match(/\[\[([^\]]+)\]\]/g) ?? []).map((m) => m.slice(2, -2).trim()))]
|
|
104
|
+
.filter((link) => link.length > 0);
|
|
105
|
+
const frontMatch = raw.match(/^---\s*\n([\s\S]*?)\n---\s*\n?([\s\S]*)$/);
|
|
106
|
+
if (!frontMatch) {
|
|
107
|
+
return { body: raw.trim(), links: links };
|
|
108
|
+
}
|
|
109
|
+
const front = frontMatch[1];
|
|
110
|
+
const body = (frontMatch[2] ?? '').trim();
|
|
111
|
+
return {
|
|
112
|
+
name: FAM_AgentMemoryReader_Service.field(front, 'name'),
|
|
113
|
+
description: FAM_AgentMemoryReader_Service.field(front, 'description'),
|
|
114
|
+
type: FAM_AgentMemoryReader_Service.field(front, 'type'),
|
|
115
|
+
body: body,
|
|
116
|
+
links: links,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
/** Egy frontmatter-mező értéke (`key: value`, sor-szintű, indent-toleráns; a körülvevő idézőjel levágva). */
|
|
120
|
+
static field(front, key) {
|
|
121
|
+
const match = front.match(new RegExp(`^\\s*${key}\\s*:\\s*(.+)$`, 'm'));
|
|
122
|
+
return match ? match[1].trim().replace(/^["']|["']$/g, '').trim() : undefined;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
exports.FAM_AgentMemoryReader_Service = FAM_AgentMemoryReader_Service;
|
|
@@ -14,12 +14,15 @@ const scope_reference_1 = require("../../scope-reference");
|
|
|
14
14
|
const fam_claude_mem_source_type_enum_1 = require("../_enums/fam-claude-mem-source.type-enum");
|
|
15
15
|
const fam_import_content_hash_util_1 = require("../_collections/fam-import-content-hash.util");
|
|
16
16
|
const fam_target_mapping_util_1 = require("../_collections/fam-target-mapping.util");
|
|
17
|
+
const fam_agent_memory_reader_service_1 = require("./fam-agent-memory-reader.service");
|
|
17
18
|
const fam_claude_mem_export_reader_service_1 = require("./fam-claude-mem-export-reader.service");
|
|
18
19
|
const fam_claude_mem_sqlite_reader_service_1 = require("./fam-claude-mem-sqlite-reader.service");
|
|
19
20
|
const fam_claude_mem_worker_reader_service_1 = require("./fam-claude-mem-worker-reader.service");
|
|
20
21
|
const fam_import_dedup_data_service_1 = require("./fam-import-dedup.data-service");
|
|
21
22
|
/** A preview `mappingPreview` mintájának mérete (nem a teljes lista — a `map` adja a teljeset). */
|
|
22
23
|
const PREVIEW_SAMPLE_SIZE = 10;
|
|
24
|
+
/** Hány feldolgozott rekordonként írjon a run egy progress-sort a szerver-konzolra (user: „more feedback in logs"). */
|
|
25
|
+
const PROGRESS_LOG_EVERY = 2000;
|
|
23
26
|
/** A claude-mem `project` raw név alapértelmezett scope-layer-e (dsgn-009 §4 — project-layer). */
|
|
24
27
|
const PROJECT_SCOPE_LAYER = 'project';
|
|
25
28
|
/**
|
|
@@ -69,11 +72,15 @@ class FAM_ClaudeMemImport_ControlService {
|
|
|
69
72
|
const dedup = { willImport: 0, willSkipExisting: 0, willSkipDuplicateContent: 0 };
|
|
70
73
|
const mappingPreview = [];
|
|
71
74
|
const previewUncertainty = [];
|
|
75
|
+
// FAM-REV-063: per-projekt scope-feloldás memoizálás (különben 68k rekord = 68k embed → preview-timeout).
|
|
76
|
+
const scopeCache = new Map();
|
|
77
|
+
// FAM-REV-063: dedup-batch-index (a per-rekord 3 DB-query helyett in-memory) — a cél-tárak EGYSZER töltve.
|
|
78
|
+
const dedupIndex = await fam_import_dedup_data_service_1.FAM_ImportDedup_DataService.getInstance().buildIndex(this.targetTablesFor(data, request));
|
|
72
79
|
for (const record of data.records) {
|
|
73
|
-
const plan = await this.buildPlan({ record: record, request: request, allowCreateScope: false, uncertainty: previewUncertainty });
|
|
74
|
-
const verdict =
|
|
75
|
-
|
|
76
|
-
});
|
|
80
|
+
const plan = await this.buildPlan({ record: record, request: request, allowCreateScope: false, uncertainty: previewUncertainty, scopeCache: scopeCache });
|
|
81
|
+
const verdict = fam_import_dedup_data_service_1.FAM_ImportDedup_DataService.getInstance().verdictForIndexed({
|
|
82
|
+
table: plan.table, importSourceId: plan.importSourceId, contentHash: plan.contentHash,
|
|
83
|
+
}, dedupIndex);
|
|
77
84
|
this.tallyDedup(dedup, verdict);
|
|
78
85
|
if (mappingPreview.length < PREVIEW_SAMPLE_SIZE) {
|
|
79
86
|
mappingPreview.push(plan);
|
|
@@ -105,9 +112,10 @@ class FAM_ClaudeMemImport_ControlService {
|
|
|
105
112
|
const warnings = [...data.warnings];
|
|
106
113
|
const uncertainty = [];
|
|
107
114
|
const plans = [];
|
|
115
|
+
const scopeCache = new Map(); // FAM-REV-063
|
|
108
116
|
for (const record of data.records) {
|
|
109
117
|
plans.push(await this.buildPlan({
|
|
110
|
-
record: record, request: request, allowCreateScope: false, uncertainty: uncertainty,
|
|
118
|
+
record: record, request: request, allowCreateScope: false, uncertainty: uncertainty, scopeCache: scopeCache,
|
|
111
119
|
}));
|
|
112
120
|
}
|
|
113
121
|
return {
|
|
@@ -139,14 +147,26 @@ class FAM_ClaudeMemImport_ControlService {
|
|
|
139
147
|
let failed = 0;
|
|
140
148
|
// Embedding-költség pillanatkép a batch ELŐTT (a delta a batch embed-költsége — BFR-AM-007).
|
|
141
149
|
const costBefore = embedding_1.FAM_EmbeddingCost_ControlService.getInstance().getStats().totalEstimatedCostUsd;
|
|
150
|
+
// FAM-REV-063: per-projekt scope-feloldás memoizálás (a 68k rekord ~25 projektje egyszer oldódjon fel/
|
|
151
|
+
// auto-create-elődjön; a run dominánsan a content-embed, de a scope-embed így is 68k→25-re csökken).
|
|
152
|
+
const scopeCache = new Map();
|
|
153
|
+
// FAM-REV-063: dedup-batch-index (in-memory, futó-akkumulátor) a per-rekord DB-query helyett.
|
|
154
|
+
const dedupIndex = await fam_import_dedup_data_service_1.FAM_ImportDedup_DataService.getInstance().buildIndex(this.targetTablesFor(data, request));
|
|
155
|
+
// Progress-feedback (user-direktíva 2026-06-21: „add more feedback in logs"): a hosszú import alatt a
|
|
156
|
+
// szerver-konzol mutassa a haladást (nem csak az LM Studio pörög). START + periodikus + KÉSZ sorok.
|
|
157
|
+
const total = data.records.length;
|
|
158
|
+
const startMs = Date.now();
|
|
159
|
+
let processed = 0;
|
|
160
|
+
fsm_dynamo_1.DyFM_Log.log(`[claude-mem import] ▶ START — ${total} rekord, batch=${batchId} `
|
|
161
|
+
+ `(includePrompts=${request.includePrompts ?? false}). A dedup-skip nem embeddel (gyors); az ÚJ rekordok embeddelődnek.`);
|
|
142
162
|
for (const record of data.records) {
|
|
143
163
|
try {
|
|
144
164
|
const plan = await this.buildPlan({
|
|
145
|
-
record: record, request: request, allowCreateScope: true, uncertainty: uncertaintyNotes,
|
|
146
|
-
});
|
|
147
|
-
const verdict = await fam_import_dedup_data_service_1.FAM_ImportDedup_DataService.getInstance().verdictFor({
|
|
148
|
-
record: record, table: plan.table, importSourceId: plan.importSourceId, contentHash: plan.contentHash,
|
|
165
|
+
record: record, request: request, allowCreateScope: true, uncertainty: uncertaintyNotes, scopeCache: scopeCache,
|
|
149
166
|
});
|
|
167
|
+
const verdict = fam_import_dedup_data_service_1.FAM_ImportDedup_DataService.getInstance().verdictForIndexed({
|
|
168
|
+
table: plan.table, importSourceId: plan.importSourceId, contentHash: plan.contentHash,
|
|
169
|
+
}, dedupIndex);
|
|
150
170
|
if (verdict !== 'import') {
|
|
151
171
|
// A skip-eltek NEM embeddelődnek (cost-takarékosság — dsgn-009 §5.3 / §9.3).
|
|
152
172
|
skipped++;
|
|
@@ -171,7 +191,19 @@ class FAM_ClaudeMemImport_ControlService {
|
|
|
171
191
|
importSourceId: fam_target_mapping_util_1.FAM_TargetMapping_Util.importSourceId(record),
|
|
172
192
|
});
|
|
173
193
|
}
|
|
194
|
+
// Periodikus progress (minden PROGRESS_LOG_EVERY rekord + a legvégén): feldolgozva / összes,
|
|
195
|
+
// ingested/skipped/failed, processed-ráta + durva ETA — a szerver-konzolon élőben látszik.
|
|
196
|
+
processed++;
|
|
197
|
+
if (processed % PROGRESS_LOG_EVERY === 0 || processed === total) {
|
|
198
|
+
const elapsedS = Math.max(1, Math.round((Date.now() - startMs) / 1000));
|
|
199
|
+
const procRate = processed / elapsedS;
|
|
200
|
+
const etaMin = procRate > 0 ? Math.round((total - processed) / procRate / 60) : 0;
|
|
201
|
+
fsm_dynamo_1.DyFM_Log.log(`[claude-mem import] ${processed}/${total} — ingested ${ingested}, skipped ${skipped} (dedup), `
|
|
202
|
+
+ `failed ${failed} | ${procRate.toFixed(1)} rec/s, ~${etaMin} perc hátra (elapsed ${elapsedS}s).`);
|
|
203
|
+
}
|
|
174
204
|
}
|
|
205
|
+
fsm_dynamo_1.DyFM_Log.log(`[claude-mem import] ✓ KÉSZ — ${ingested} ingested + ${skipped} skipped (dedup) + ${failed} failed `
|
|
206
|
+
+ `= ${total} rekord, ${Math.max(1, Math.round((Date.now() - startMs) / 1000))}s alatt. batch=${batchId}.`);
|
|
175
207
|
const costAfter = embedding_1.FAM_EmbeddingCost_ControlService.getInstance().getStats().totalEstimatedCostUsd;
|
|
176
208
|
const status = this.runStatus(ingested, failed);
|
|
177
209
|
const result = {
|
|
@@ -249,14 +281,22 @@ class FAM_ClaudeMemImport_ControlService {
|
|
|
249
281
|
const from = this.resolveFrom(request);
|
|
250
282
|
const includePrompts = this.resolveIncludePrompts(request);
|
|
251
283
|
const path = request.path ?? '';
|
|
284
|
+
let data;
|
|
252
285
|
switch (from) {
|
|
253
286
|
case fam_claude_mem_source_type_enum_1.FAM_ClaudeMemSource_Type.exportJson:
|
|
254
|
-
|
|
287
|
+
data = await fam_claude_mem_export_reader_service_1.FAM_ClaudeMemExportReader_Service.getInstance().read({ path: path, includePrompts: includePrompts });
|
|
288
|
+
break;
|
|
255
289
|
case fam_claude_mem_source_type_enum_1.FAM_ClaudeMemSource_Type.sqlite:
|
|
256
|
-
|
|
290
|
+
data = await fam_claude_mem_sqlite_reader_service_1.FAM_ClaudeMemSqliteReader_Service.getInstance().read({ path: path, includePrompts: includePrompts });
|
|
291
|
+
break;
|
|
257
292
|
case fam_claude_mem_source_type_enum_1.FAM_ClaudeMemSource_Type.workerApi:
|
|
258
|
-
|
|
259
|
-
|
|
293
|
+
data = await fam_claude_mem_worker_reader_service_1.FAM_ClaudeMemWorkerReader_Service.getInstance().read({ baseUrl: path, includePrompts: includePrompts });
|
|
294
|
+
break;
|
|
295
|
+
case fam_claude_mem_source_type_enum_1.FAM_ClaudeMemSource_Type.agentMemory:
|
|
296
|
+
// Agent-memory markdown-mappa (`.claude/.../memory/*.md`) — a reader `FAM_ClaudeMemRecord`-ot
|
|
297
|
+
// termel, így a teljes run/preview/rollback/dedup/embed VÁLTOZATLANUL feldolgozza.
|
|
298
|
+
data = await fam_agent_memory_reader_service_1.FAM_AgentMemoryReader_Service.getInstance().read({ path: path });
|
|
299
|
+
break;
|
|
260
300
|
default:
|
|
261
301
|
throw fam_error_factory_util_1.FAM_Error_Util.create({
|
|
262
302
|
errorCode: error_codes_const_1.FAM_ERROR_CODES.impSource,
|
|
@@ -265,6 +305,24 @@ class FAM_ClaudeMemImport_ControlService {
|
|
|
265
305
|
context: { operation: 'import-read-source' },
|
|
266
306
|
});
|
|
267
307
|
}
|
|
308
|
+
return this.applyImportFilters(data, request);
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Kurált-subset szűrés a beolvasott rekordokra (L3 „A" opció + teszt-limit). `excludeTypes` → a megadott
|
|
312
|
+
* observation-`type`-ok kihagyva (a summary/prompt — nincs `type` — MARAD); `maxRecords` → a szűrt lista
|
|
313
|
+
* levágva. Mindkettő a `preview`-ban ÉS a `run`-ban hat (a `readSource` a közös belépő). Szűrés nélkül a
|
|
314
|
+
* forrás-objektum változatlanul tér vissza (nincs fölös másolás).
|
|
315
|
+
*/
|
|
316
|
+
applyImportFilters(data, request) {
|
|
317
|
+
let records = data.records;
|
|
318
|
+
if (request.excludeTypes && request.excludeTypes.length) {
|
|
319
|
+
const exclude = new Set(request.excludeTypes);
|
|
320
|
+
records = records.filter((record) => !(record.type && exclude.has(record.type)));
|
|
321
|
+
}
|
|
322
|
+
if (typeof request.maxRecords === 'number' && request.maxRecords >= 0) {
|
|
323
|
+
records = records.slice(0, request.maxRecords);
|
|
324
|
+
}
|
|
325
|
+
return records === data.records ? data : { ...data, records: records };
|
|
268
326
|
}
|
|
269
327
|
// =========================================================================
|
|
270
328
|
// leképezési-terv építés (SP-11.2: target-mapping + scope-resolve)
|
|
@@ -276,6 +334,17 @@ class FAM_ClaudeMemImport_ControlService {
|
|
|
276
334
|
* `resolveForWrite` (auto-create-elhet). A scope-feloldás van-match-bizonytalansága az `uncertainty`
|
|
277
335
|
* gyűjtőbe (NEM hiba).
|
|
278
336
|
*/
|
|
337
|
+
/**
|
|
338
|
+
* A rekordok DISTINCT cél-tárai (FAM-REV-063, a dedup-index építéséhez) — OLCSÓ: csak a target-mapping
|
|
339
|
+
* (`resolveTarget`) fut rekordonként (NINCS embed/scope-feloldás), így a 68k rekordon is ms-ek.
|
|
340
|
+
*/
|
|
341
|
+
targetTablesFor(data, request) {
|
|
342
|
+
const tables = new Set();
|
|
343
|
+
for (const record of data.records) {
|
|
344
|
+
tables.add(fam_target_mapping_util_1.FAM_TargetMapping_Util.resolveTarget({ record: record, overrides: request.overrides }).table);
|
|
345
|
+
}
|
|
346
|
+
return Array.from(tables);
|
|
347
|
+
}
|
|
279
348
|
async buildPlan(set) {
|
|
280
349
|
const target = fam_target_mapping_util_1.FAM_TargetMapping_Util.resolveTarget({ record: set.record, overrides: set.request.overrides });
|
|
281
350
|
const content = fam_target_mapping_util_1.FAM_TargetMapping_Util.composeContent(set.record);
|
|
@@ -284,7 +353,7 @@ class FAM_ClaudeMemImport_ControlService {
|
|
|
284
353
|
});
|
|
285
354
|
const importSourceId = fam_target_mapping_util_1.FAM_TargetMapping_Util.importSourceId(set.record);
|
|
286
355
|
const scopeResolve = await this.resolveScopeForRecord({
|
|
287
|
-
record: set.record, request: set.request, allowCreateScope: set.allowCreateScope,
|
|
356
|
+
record: set.record, request: set.request, allowCreateScope: set.allowCreateScope, cache: set.scopeCache,
|
|
288
357
|
});
|
|
289
358
|
for (const note of scopeResolve.uncertaintyNotes) {
|
|
290
359
|
set.uncertainty.push(note);
|
|
@@ -315,14 +384,28 @@ class FAM_ClaudeMemImport_ControlService {
|
|
|
315
384
|
if (!rawScope || !rawScope.length) {
|
|
316
385
|
return { scopePath: [], uncertaintyNotes: [] };
|
|
317
386
|
}
|
|
387
|
+
// FAM-REV-063: a scope a rekord `project`-jétől függ (a 68k rekord ~25 distinct projektre), de a
|
|
388
|
+
// feloldás (`previewResolveScope`/`resolveForWrite`) EMBEDDEL → per-rekord hívás = 68k embed (preview-
|
|
389
|
+
// timeout). Memoizálás a rawScope-kulcson: projektenként EGYSZER oldunk fel. Cache-HIT → a scopePath
|
|
390
|
+
// ugyanaz, de az uncertaintyNotes ÜRES (a note-ot az első [miss] feloldás már begyűjtötte → nincs 68k dup).
|
|
391
|
+
const cacheKey = JSON.stringify(rawScope);
|
|
392
|
+
const cached = set.cache?.get(cacheKey);
|
|
393
|
+
if (cached) {
|
|
394
|
+
return { scopePath: cached.scopePath, uncertaintyNotes: [] };
|
|
395
|
+
}
|
|
396
|
+
let resolved;
|
|
318
397
|
if (set.allowCreateScope) {
|
|
319
398
|
// run: a write-path teljes feloldása (auto-create-elhet — createdBy='agent-write' a MP-3-ban).
|
|
320
399
|
const resolve = await scope_reference_1.FAM_ScopeResolver_ControlService.getInstance().resolveForWrite(rawScope);
|
|
321
|
-
|
|
400
|
+
resolved = { scopePath: resolve.scopePath, uncertaintyNotes: resolve.uncertaintyNotes };
|
|
401
|
+
}
|
|
402
|
+
else {
|
|
403
|
+
// preview/map: read-only — a read-expand-szerű feloldás NEM hoz létre scope-ot. A trace-feloldáson
|
|
404
|
+
// át döntjük el, feloldható-e biztosan; ha nem, üres scopePath + a bizonytalanság jelezve.
|
|
405
|
+
resolved = await this.previewResolveScope(rawScope);
|
|
322
406
|
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
return this.previewResolveScope(rawScope);
|
|
407
|
+
set.cache?.set(cacheKey, resolved);
|
|
408
|
+
return resolved;
|
|
326
409
|
}
|
|
327
410
|
/**
|
|
328
411
|
* Egy rekord nyers scope-lánca: az override `scope['project:<name>']` explicit `scopePath`-ja
|
|
@@ -71,6 +71,59 @@ class FAM_ImportDedup_DataService {
|
|
|
71
71
|
}
|
|
72
72
|
return 'import';
|
|
73
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* **Batch-index építése (FAM-REV-063)** — a per-rekord `verdictFor` 3 DB-query-je 68k rekordon ~136s
|
|
76
|
+
* (preview-timeout). Ehelyett a cél-tárak MEGLÉVŐ claude-mem entry-jeinek `importSourceId` + `contentHash`
|
|
77
|
+
* kulcsait EGYSZER töltjük Set-ekbe (táranként), és a `verdictForIndexed` in-memory dönt. Első importnál a
|
|
78
|
+
* forrás-szűrt halmaz üres → azonnali. (Megjegyzés: a betöltés még nem projektált [lean-find = BFR-AM-013],
|
|
79
|
+
* így RE-importnál a már beimportált halmaz teljes entry-it tölti — első importnál ez 0.)
|
|
80
|
+
*/
|
|
81
|
+
async buildIndex(tables) {
|
|
82
|
+
const byTable = new Map();
|
|
83
|
+
for (const table of tables) {
|
|
84
|
+
const entry = { sourceIds: new Set(), contentHashes: new Set() };
|
|
85
|
+
byTable.set(table, entry);
|
|
86
|
+
const dataService = this.dataServiceFor(table);
|
|
87
|
+
if (!dataService) {
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
const existing = await dataService.findHydratableList({
|
|
91
|
+
importSource: FAM_ImportDedup_DataService.IMPORT_SOURCE,
|
|
92
|
+
});
|
|
93
|
+
for (const item of existing) {
|
|
94
|
+
if (item.importSourceId) {
|
|
95
|
+
entry.sourceIds.add(item.importSourceId);
|
|
96
|
+
}
|
|
97
|
+
if (item.contentHash) {
|
|
98
|
+
entry.contentHashes.add(item.contentHash);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return { byTable: byTable };
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* In-memory dedup-verdikt a batch-indexszel (FAM-REV-063) — a `verdictFor` (1)+(2) lépcsőjének
|
|
106
|
+
* O(1) megfelelője, NULLA DB-query-vel. Az index egyben **futó-akkumulátor**: az `import`-nak ítélt
|
|
107
|
+
* rekord kulcsai bekerülnek, így a forráson-belüli (within-batch) duplikátumok is `skip-duplicate-content`-
|
|
108
|
+
* et kapnak (pontosabb forecast + a sequential run idempotenciája). A (3) ritka, (2)-vel gyakorlatilag
|
|
109
|
+
* redundáns kompozit-fallback NEM része az indexelt útnak (perf-tradeoff — dsgn-009 §3).
|
|
110
|
+
*/
|
|
111
|
+
verdictForIndexed(set, index) {
|
|
112
|
+
let entry = index.byTable.get(set.table);
|
|
113
|
+
if (!entry) {
|
|
114
|
+
entry = { sourceIds: new Set(), contentHashes: new Set() };
|
|
115
|
+
index.byTable.set(set.table, entry);
|
|
116
|
+
}
|
|
117
|
+
if (entry.sourceIds.has(set.importSourceId)) {
|
|
118
|
+
return 'skip-existing';
|
|
119
|
+
}
|
|
120
|
+
if (entry.contentHashes.has(set.contentHash)) {
|
|
121
|
+
return 'skip-duplicate-content';
|
|
122
|
+
}
|
|
123
|
+
entry.sourceIds.add(set.importSourceId);
|
|
124
|
+
entry.contentHashes.add(set.contentHash);
|
|
125
|
+
return 'import';
|
|
126
|
+
}
|
|
74
127
|
/** A (3) fallback kompozit-kulcs jelenléte: sdk_session_id + title + created_at_epoch mind kell. */
|
|
75
128
|
hasCompositeKey(record) {
|
|
76
129
|
return Boolean(record.sdkSessionId && record.title && typeof record.createdAtEpoch === 'number');
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* függőség (BFR-AM-009 fallback) — a bedrock-reader landolásakor (MP-15) CSAK a reader-impl cserélődik.
|
|
12
12
|
*/
|
|
13
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
-
exports.FAM_ClaudeMemEntity_Type = exports.FAM_ClaudeMemSource_Type = exports.FAM_ImportContentHash_Util = exports.FAM_TargetMapping_Util = exports.FAM_ImportDedup_DataService = exports.FAM_ClaudeMemNormalize_Util = exports.FAM_ClaudeMemWorkerReader_Service = exports.FAM_ClaudeMemSqliteReader_Service = exports.FAM_ClaudeMemExportReader_Service = exports.FAM_ClaudeMemImport_ControlService = void 0;
|
|
14
|
+
exports.FAM_ClaudeMemEntity_Type = exports.FAM_ClaudeMemSource_Type = exports.FAM_ImportContentHash_Util = exports.FAM_TargetMapping_Util = exports.FAM_ImportDedup_DataService = exports.FAM_ClaudeMemNormalize_Util = exports.FAM_AgentMemoryReader_Service = exports.FAM_ClaudeMemWorkerReader_Service = exports.FAM_ClaudeMemSqliteReader_Service = exports.FAM_ClaudeMemExportReader_Service = exports.FAM_ClaudeMemImport_ControlService = void 0;
|
|
15
15
|
// SP-11.3 — a migrációs engine (preview → map → run → rollback)
|
|
16
16
|
var fam_claude_mem_import_control_service_1 = require("./_services/fam-claude-mem-import.control-service");
|
|
17
17
|
Object.defineProperty(exports, "FAM_ClaudeMemImport_ControlService", { enumerable: true, get: function () { return fam_claude_mem_import_control_service_1.FAM_ClaudeMemImport_ControlService; } });
|
|
@@ -22,6 +22,8 @@ var fam_claude_mem_sqlite_reader_service_1 = require("./_services/fam-claude-mem
|
|
|
22
22
|
Object.defineProperty(exports, "FAM_ClaudeMemSqliteReader_Service", { enumerable: true, get: function () { return fam_claude_mem_sqlite_reader_service_1.FAM_ClaudeMemSqliteReader_Service; } });
|
|
23
23
|
var fam_claude_mem_worker_reader_service_1 = require("./_services/fam-claude-mem-worker-reader.service");
|
|
24
24
|
Object.defineProperty(exports, "FAM_ClaudeMemWorkerReader_Service", { enumerable: true, get: function () { return fam_claude_mem_worker_reader_service_1.FAM_ClaudeMemWorkerReader_Service; } });
|
|
25
|
+
var fam_agent_memory_reader_service_1 = require("./_services/fam-agent-memory-reader.service");
|
|
26
|
+
Object.defineProperty(exports, "FAM_AgentMemoryReader_Service", { enumerable: true, get: function () { return fam_agent_memory_reader_service_1.FAM_AgentMemoryReader_Service; } });
|
|
25
27
|
var fam_claude_mem_normalize_util_1 = require("./_collections/fam-claude-mem-normalize.util");
|
|
26
28
|
Object.defineProperty(exports, "FAM_ClaudeMemNormalize_Util", { enumerable: true, get: function () { return fam_claude_mem_normalize_util_1.FAM_ClaudeMemNormalize_Util; } });
|
|
27
29
|
// SP-11.2 — dedup + target-mapping + content-hash
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.FAM_RetrievalCandidate_DataService = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const mongoose_1 = tslib_1.__importDefault(require("mongoose"));
|
|
4
6
|
const fam_table_type_enum_1 = require("../../../_enums/fam-table.type-enum");
|
|
5
7
|
const embedding_1 = require("../../embedding");
|
|
6
8
|
/**
|
|
@@ -33,8 +35,77 @@ class FAM_RetrievalCandidate_DataService {
|
|
|
33
35
|
return [];
|
|
34
36
|
}
|
|
35
37
|
const filter = this.buildFilter(input, registryEntry);
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
return this.findActiveCandidates(registryEntry, filter);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* FEAT-003 — egy tár azon entry-jei, amik az adott azonosító-kódok BÁRMELYIKÉT citálják
|
|
42
|
+
* (`referenceCodes $in codes`), az AZONOS prefilter-kontextussal (scope subtree + tag + kind +
|
|
43
|
+
* `rules.isActive` guard), mint a vektor-jelölt-betöltés. Ez a determinisztikus read-expanzió Mongo-
|
|
44
|
+
* lekérdezése: a kód-keresés a vektor-hasonlóság HELYETT explicit link → az ÖSSZES citáló elem,
|
|
45
|
+
* `embeddingStatus`-tól függetlenül. Üres kód-lista / ismeretlen tár → üres lista (no-op).
|
|
46
|
+
*/
|
|
47
|
+
async loadByReferenceCodes(input, codes) {
|
|
48
|
+
if (!codes.length) {
|
|
49
|
+
return [];
|
|
50
|
+
}
|
|
51
|
+
const registryEntry = embedding_1.FAM_StoreRegistry_Util.getEntry(input.table);
|
|
52
|
+
if (!registryEntry) {
|
|
53
|
+
return [];
|
|
54
|
+
}
|
|
55
|
+
const filter = this.buildFilter(input, registryEntry);
|
|
56
|
+
filter.referenceCodes = { $in: codes };
|
|
57
|
+
return this.findActiveCandidates(registryEntry, filter);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* A topK-hit metaadat-betöltése `_id`-listából (az UNSCOPED read-fast-path-hez, SP-5.x perf). A főpool-
|
|
61
|
+
* keresés UTÁN CSAK a tényleges hit-eket tölti (a hit-row + weight + recency összefűzéséhez), NEM mind a
|
|
62
|
+
* jelöltet — unscoped query-nél ez a Mongo-munkát ~242×-ére csökkenti (mért: 727ms → 3ms). Aktív-only
|
|
63
|
+
* (`_deleted:null`) + `contentVector`-kihagyó lean (a `findActiveCandidates`-en át; a `_id $in` string-ID-it
|
|
64
|
+
* a Mongoose a `_id`-úton ObjectId-ra castolja). Üres lista / ismeretlen tár → üres (no-op).
|
|
65
|
+
*/
|
|
66
|
+
async loadByIds(table, ids) {
|
|
67
|
+
if (!ids.length) {
|
|
68
|
+
return [];
|
|
69
|
+
}
|
|
70
|
+
const registryEntry = embedding_1.FAM_StoreRegistry_Util.getEntry(table);
|
|
71
|
+
if (!registryEntry) {
|
|
72
|
+
return [];
|
|
73
|
+
}
|
|
74
|
+
const filter = {};
|
|
75
|
+
filter._id = { $in: ids };
|
|
76
|
+
return this.findActiveCandidates(registryEntry, filter);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* PERF (FAM-REV / BFR-AM-013): a jelölt-betöltés a `contentVector`-t (a domináns memória-/transzfer-
|
|
80
|
+
* költség: ~2560 float ≈ 20 KB/entry; 23k codebase-entry ≈ 486 MB) **KIHAGYJA** — a vektorok MÁR az
|
|
81
|
+
* in-memory LVS-pool-ban élnek, a candidate-stage SOHA nem olvassa az `entry.contentVector`-t (a
|
|
82
|
+
* `toHit`/`mergeCodeHit` sem). **Lean** (plain object, NEM Mongoose-doc → nincs schema-hidratálás) +
|
|
83
|
+
* `contentVector`-kihagyó projekció a mongoose-modellen → a per-query jelölt-load **~40s → ~1s** (mért
|
|
84
|
+
* 46,9× a raw-load-on; a Mongoose-hidratálás-megtakarítás tetézi). A `_deleted:null` az aktív-szűrő
|
|
85
|
+
* (a `findDataList` DB-service-szintű soft-delete-kizárását replikálja: a soft-delete `_deleted`-et
|
|
86
|
+
* `Date`-re állítja, az aktív entry-n hiányzik/`null`). Model-hiány (boot-előtt) → `findDataList`-fallback
|
|
87
|
+
* (korrekt, csak lassabb).
|
|
88
|
+
*/
|
|
89
|
+
async findActiveCandidates(registryEntry, filter) {
|
|
90
|
+
const dataName = registryEntry.dataParams.dataName;
|
|
91
|
+
const model = mongoose_1.default.models[dataName];
|
|
92
|
+
if (!model) {
|
|
93
|
+
// Fallback: a model még nincs regisztrálva (pl. boot-bootstrap előtt) → teljes-doc findDataList.
|
|
94
|
+
const dataService = new embedding_1.FAM_Entry_DataService({ dataParams: registryEntry.dataParams, issuer: this.issuer });
|
|
95
|
+
return dataService.findDataList(filter);
|
|
96
|
+
}
|
|
97
|
+
// `_deleted:null` → aktív-only (a soft-delete Date-marker kizárva); `contentVector:0` → a 486MB pool-
|
|
98
|
+
// duplikátum kihagyva; `.lean()` → nincs Mongoose-doc hidratálás.
|
|
99
|
+
const leanFilter = { ...filter, _deleted: null };
|
|
100
|
+
const docs = await model.find(leanFilter, { contentVector: 0 }).lean().exec();
|
|
101
|
+
// KRITIKUS (_id-konzisztencia): a `.lean()` a NYERS Mongo `_id`-t adja (ObjectId), DE a
|
|
102
|
+
// `DyFM_Metadata._id` STRING, és a vektor-pool-kulcsok + a `findDataList` is string `_id`-vel
|
|
103
|
+
// dolgoznak. ObjectId-kulcs SOHA nem egyezne a string pool-kulccsal (`Map.get` referencia-
|
|
104
|
+
// egyenlőség) → a candidateId-match 0 jelöltet adna → 0 hit. Stringify → bit-azonos a findDataList-tel.
|
|
105
|
+
for (const doc of docs) {
|
|
106
|
+
doc._id = String(doc._id);
|
|
107
|
+
}
|
|
108
|
+
return docs;
|
|
38
109
|
}
|
|
39
110
|
/**
|
|
40
111
|
* A Mongo-prefilter összeállítása (dsgn-005 §2.1/§2.2). A `scopePath.scopeId $in scopeIdSet`
|
|
@@ -57,9 +128,12 @@ class FAM_RetrievalCandidate_DataService {
|
|
|
57
128
|
if (input.kindFilter) {
|
|
58
129
|
filter.kind = input.kindFilter;
|
|
59
130
|
}
|
|
60
|
-
// Soft-delete/aktív guard a `rules` táron (dsgn-001 §4): inaktív szabály SOHA nem jelölt.
|
|
131
|
+
// Soft-delete/aktív guard a `rules` táron (dsgn-001 §4): inaktív szabály SOHA nem jelölt. „Inaktív"
|
|
132
|
+
// = EXPLICIT `isActive:false`; a hiányzó/`true` mező AKTÍV (a `create` a bázis `FAM_Entry`-t menti,
|
|
133
|
+
// amin a per-tár `isActive:true` schema-default nem mindig perzisztálódik → `$ne:false` robusztus,
|
|
134
|
+
// hogy az újonnan írt szabály is jelölt legyen; csak a kézzel-deaktivált zárandó ki).
|
|
61
135
|
if (registryEntry.table === fam_table_type_enum_1.FAM_Table.rules) {
|
|
62
|
-
filter.isActive =
|
|
136
|
+
filter.isActive = { $ne: false };
|
|
63
137
|
}
|
|
64
138
|
return filter;
|
|
65
139
|
}
|