@futdevpro/fdp-agent-memory 1.1.21 → 1.1.112

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.
Files changed (89) hide show
  1. package/build/package.json +2 -2
  2. package/build/src/_cli/_commands/find-duplicates.command.js +41 -16
  3. package/build/src/_cli/_commands/scan-projects.command.js +113 -113
  4. package/build/src/_cli/_commands/scan.command.js +2 -0
  5. package/build/src/_cli/_commands/serve.command.js +110 -10
  6. package/build/src/_cli/_services/fam-client.service.js +25 -1
  7. package/build/src/_cli/register-commands.js +28 -0
  8. package/build/src/_collections/config-catalog.const.js +152 -33
  9. package/build/src/_collections/error-codes.const.js +2 -0
  10. package/build/src/_collections/fam-console.util.js +38 -260
  11. package/build/src/_collections/fam-db-models.const.js +2 -0
  12. package/build/src/_collections/fam-entry-bootstrap.util.js +20 -6
  13. package/build/src/_collections/fam-error-context.util.js +1 -0
  14. package/build/src/_collections/fam-mcp-bridge.util.js +15 -1
  15. package/build/src/_collections/fam-operation-queue.service.js +85 -0
  16. package/build/src/_collections/fam-project-discovery.util.js +148 -0
  17. package/build/src/_collections/fam-request-origin.util.js +41 -0
  18. package/build/src/_collections/fam-retry.util.js +48 -0
  19. package/build/src/_collections/fam-scan-progress-sink.service.js +26 -0
  20. package/build/src/_collections/title.const.js +26 -26
  21. package/build/src/_enums/fam-rule-scope.type-enum.js +25 -0
  22. package/build/src/_models/data-models/fam-entry.data-model.js +29 -0
  23. package/build/src/_models/data-models/fam-memory.data-model.js +5 -0
  24. package/build/src/_models/data-models/fam-rules.data-model.js +24 -0
  25. package/build/src/_models/data-models/fam-scan-job.data-model.js +73 -0
  26. package/build/src/_models/data-models/fam-scope.data-model.js +9 -0
  27. package/build/src/_modules/capture/_services/fam-auto-capture.control-service.js +1 -1
  28. package/build/src/_modules/embedding/_services/fam-dedup-warn.control-service.js +40 -0
  29. package/build/src/_modules/embedding/_services/fam-duplicate-scan.control-service.js +74 -16
  30. package/build/src/_modules/embedding/_services/fam-embedding-bootstrap.control-service.js +50 -0
  31. package/build/src/_modules/embedding/_services/fam-embedding-pipeline.control-service.js +32 -6
  32. package/build/src/_modules/embedding/_services/fam-embedding.control-service.js +142 -9
  33. package/build/src/_modules/embedding/_services/fam-entry.data-service.js +32 -1
  34. package/build/src/_modules/embedding/_services/fam-hydration-coordinator.control-service.js +159 -0
  35. package/build/src/_modules/embedding/_services/fam-lmstudio-embedding.provider.js +41 -4
  36. package/build/src/_modules/embedding/_services/fam-vector-search.control-service.js +67 -12
  37. package/build/src/_modules/embedding/index.js +5 -1
  38. package/build/src/_modules/ingest/_collections/fam-file-routing.util.js +10 -0
  39. package/build/src/_modules/ingest/_collections/fam-frontmatter.util.js +134 -0
  40. package/build/src/_modules/ingest/_collections/fam-project-identity.util.js +30 -0
  41. package/build/src/_modules/ingest/_collections/fam-scan-progress.util.js +5 -2
  42. package/build/src/_modules/ingest/_collections/fam-scan-summary.util.js +55 -29
  43. package/build/src/_modules/ingest/_collections/fam-split-chunker.util.js +139 -0
  44. package/build/src/_modules/ingest/_models/interfaces/fam-scan-job.interface.js +2 -0
  45. package/build/src/_modules/ingest/_services/fam-chunker.control-service.js +10 -0
  46. package/build/src/_modules/ingest/_services/fam-delta-compare.util.js +68 -1
  47. package/build/src/_modules/ingest/_services/fam-ingest-run.data-service.js +1 -1
  48. package/build/src/_modules/ingest/_services/fam-ingest.control-service.js +177 -37
  49. package/build/src/_modules/ingest/_services/fam-scan-job.control-service.js +429 -0
  50. package/build/src/_modules/ingest/_services/fam-scan-job.data-service.js +34 -0
  51. package/build/src/_modules/ingest/_services/fam-scan.control-service.js +6 -4
  52. package/build/src/_modules/ingest/index.js +6 -1
  53. package/build/src/_modules/mcp/_collections/fam-core-tools.const.js +1 -1
  54. package/build/src/_modules/mcp/_services/fam-capability-registry.service.js +264 -41
  55. package/build/src/_modules/mcp/_services/fam-read-tool.service.js +71 -1
  56. package/build/src/_modules/mcp/_services/fam-write-tool.service.js +36 -0
  57. package/build/src/_modules/migration/_services/fam-claude-mem-import.control-service.js +1 -1
  58. package/build/src/_modules/retrieval/_collections/fam-lexical-match.util.js +69 -0
  59. package/build/src/_modules/retrieval/_collections/fam-memory-activation.util.js +66 -0
  60. package/build/src/_modules/retrieval/_collections/fam-rule-injection.util.js +125 -0
  61. package/build/src/_modules/retrieval/_collections/fam-rule-propagation.util.js +95 -0
  62. package/build/src/_modules/retrieval/_collections/fam-rule-scope-context.util.js +74 -0
  63. package/build/src/_modules/retrieval/_services/fam-global-rule.control-service.js +82 -0
  64. package/build/src/_modules/retrieval/_services/fam-memory-cold-search.control-service.js +121 -0
  65. package/build/src/_modules/retrieval/_services/fam-memory-dormancy.control-service.js +99 -0
  66. package/build/src/_modules/retrieval/_services/fam-memory-reactivation.control-service.js +68 -0
  67. package/build/src/_modules/retrieval/_services/fam-retrieval-candidate.data-service.js +15 -2
  68. package/build/src/_modules/retrieval/_services/fam-retrieval.control-service.js +197 -5
  69. package/build/src/_modules/retrieval/_services/fam-rule-injection.control-service.js +102 -0
  70. package/build/src/_modules/retrieval/index.js +12 -1
  71. package/build/src/_modules/scope-reference/_collections/fam-scope-maintenance.util.js +134 -0
  72. package/build/src/_modules/scope-reference/_services/fam-scope-maintenance.control-service.js +423 -0
  73. package/build/src/_modules/scope-reference/_services/fam-scope-resolver.control-service.js +2 -2
  74. package/build/src/_modules/scope-reference/_services/fam-scope.data-service.js +25 -0
  75. package/build/src/_modules/scope-reference/index.js +4 -1
  76. package/build/src/_routes/server/api/api.controller.js +324 -23
  77. package/build/src/_routes/server/api/fam-doctor.control-service.js +156 -0
  78. package/build/src/_routes/server/config/config.control-service.js +2 -2
  79. package/build/src/app.server.js +29 -27
  80. package/client-dist/{chunk-YXHWCJ5O.js → chunk-GF3FJP7E.js} +71 -71
  81. package/client-dist/chunk-NMUCMQY6.js +1 -0
  82. package/client-dist/favicon.ico +0 -0
  83. package/client-dist/index.html +3 -3
  84. package/client-dist/main-YK4YIVAQ.js +2 -0
  85. package/package.json +2 -2
  86. package/build/src/_cli/_collections/fam-project-discovery.util.js +0 -98
  87. package/build/src/_collections/fam-heap-guard.control-service.js +0 -176
  88. package/client-dist/chunk-I77GXVAQ.js +0 -1
  89. package/client-dist/main-PJPEDVJT.js +0 -2
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FAM_MemoryDormancy_ControlService = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const mongoose_1 = tslib_1.__importDefault(require("mongoose"));
6
+ const fsm_dynamo_1 = require("@futdevpro/fsm-dynamo");
7
+ const config_control_service_1 = require("../../../_routes/server/config/config.control-service");
8
+ const embedding_1 = require("../../embedding");
9
+ const fam_memory_data_model_1 = require("../../../_models/data-models/fam-memory.data-model");
10
+ /**
11
+ * `FAM_MemoryDormancy_ControlService` (dsgn-013 §5, MAM F3) — a memória-DORMANCY sweep-je: a régóta-nem-felidézett,
12
+ * ritkán-használt `memory`-bejegyzéseket ALVÓ-vá (`dormant=true`) jelöli. Az alvó memória NEM hidratálódik a hot
13
+ * LVS-poolba (RAM-/boot-spórolás, dsgn-013 §5.2), de Mongo-oldali COLD kereséssel elérhető (§5.3) + megtaláláskor
14
+ * reaktiválódik (visszakerül a hot készletbe). **SOHA nem töröl** — a `dormant` csak hidratálás-kihagyás.
15
+ *
16
+ * **Mongo-kifejezhető szabály (== a pure `FAM_MemoryActivation_Util.isDormant` age+recall kapuja):** `lastRecalledAt`
17
+ * (hiányában `__created`) régebbi mint `minAgeDays`, ÉS `recallCount < maxRecallCount`. A sokszor-felidézett memória
18
+ * SOHA nem dormant. A sweep `updateMany` — nem érinti a vektor-poolt (a hatás a következő (re)hidratáláskor jön).
19
+ */
20
+ class FAM_MemoryDormancy_ControlService {
21
+ static _instance;
22
+ issuer = 'FAM_MemoryDormancy_ControlService';
23
+ static MS_PER_DAY = 86_400_000;
24
+ static getInstance() {
25
+ if (!FAM_MemoryDormancy_ControlService._instance) {
26
+ FAM_MemoryDormancy_ControlService._instance = new FAM_MemoryDormancy_ControlService();
27
+ }
28
+ return FAM_MemoryDormancy_ControlService._instance;
29
+ }
30
+ /**
31
+ * A dormancy-sweep: a kvalifikáló `memory`-bejegyzések `dormant=true`-vá jelölése. Best-effort — a hiba logolódik és
32
+ * 0-val tér vissza (a boot-ot/működést nem buktatja). A `nowMs` injektálható (teszt-determinizmus). `dormancyEnabled
33
+ * = false` → no-op.
34
+ */
35
+ async sweep(nowMs) {
36
+ try {
37
+ const config = config_control_service_1.FAM_Config_ControlService.getInstance();
38
+ const enabledValue = (await config.resolve('memory.dormancyEnabled', {})).value;
39
+ if (enabledValue === false) {
40
+ return { enabled: false, markedDormant: 0 };
41
+ }
42
+ const minAgeDays = await this.resolveNumber(config, 'memory.dormantMinAgeDays', 180);
43
+ const maxRecallCount = await this.resolveNumber(config, 'memory.dormantMaxRecallCount', 2);
44
+ const model = this.memoryModel();
45
+ if (!model) {
46
+ return { enabled: true, markedDormant: 0 };
47
+ }
48
+ const filter = FAM_MemoryDormancy_ControlService.buildSweepFilter({
49
+ nowMs: nowMs, minAgeDays: minAgeDays, maxRecallCount: maxRecallCount,
50
+ });
51
+ const res = await model.updateMany(filter, { $set: { dormant: true } });
52
+ const marked = res.modifiedCount ?? 0;
53
+ if (marked > 0) {
54
+ fsm_dynamo_1.DyFM_Log.info(`[FAM memoryDormancy] ${marked} memória-bejegyzés ALVÓ-vá jelölve (age>${minAgeDays}d, recall<${maxRecallCount}).`);
55
+ }
56
+ return { enabled: true, markedDormant: marked };
57
+ }
58
+ catch (error) {
59
+ fsm_dynamo_1.DyFM_Log.warn(`[FAM memoryDormancy] sweep sikertelen (best-effort): ${error?.message}`);
60
+ return { enabled: true, markedDormant: 0 };
61
+ }
62
+ }
63
+ /**
64
+ * A sweep Mongo-filtere (PURE, tesztelhető): `completed` + még-nem-dormant + age-gát (`lastRecalledAt` VAGY a
65
+ * fallback `__created` a `minAgeDays`-cutoff előtt) + recall-gát (`recallCount < maxRecallCount`, a hiányzót is
66
+ * beleértve). A flag-csak frissítés → a vektor-poolt nem érinti.
67
+ */
68
+ static buildSweepFilter(set) {
69
+ const cutoffMs = set.nowMs - set.minAgeDays * FAM_MemoryDormancy_ControlService.MS_PER_DAY;
70
+ const cutoffDate = new Date(cutoffMs);
71
+ // age-gát: explicit lastRecalledAt a cutoff előtt, VAGY nincs lastRecalledAt és a __created a cutoff előtt.
72
+ const ageGate = {
73
+ $or: [
74
+ { lastRecalledAt: { $lt: cutoffMs } },
75
+ { lastRecalledAt: { $exists: false }, __created: { $lt: cutoffDate } },
76
+ ],
77
+ };
78
+ // recall-gát: recallCount < max (a hiányzó/0 is kvalifikál).
79
+ const recallGate = {
80
+ $or: [{ recallCount: { $lt: set.maxRecallCount } }, { recallCount: { $exists: false } }],
81
+ };
82
+ return {
83
+ embeddingStatus: 'completed',
84
+ dormant: { $ne: true },
85
+ $and: [ageGate, recallGate],
86
+ };
87
+ }
88
+ /** Egy szám-config feloldása a default-tal (a `resolve.value` lehet más típus → fallback). */
89
+ async resolveNumber(config, key, fallback) {
90
+ const value = (await config.resolve(key, {})).value;
91
+ return typeof value === 'number' ? value : fallback;
92
+ }
93
+ /** A `fam_memory` mongoose-modellje (a DS-példányosítás regisztrálja). */
94
+ memoryModel() {
95
+ new embedding_1.FAM_Entry_DataService({ dataParams: fam_memory_data_model_1.famMemory_dataParams, issuer: this.issuer });
96
+ return mongoose_1.default.models[fam_memory_data_model_1.famMemory_dataParams.dataName];
97
+ }
98
+ }
99
+ exports.FAM_MemoryDormancy_ControlService = FAM_MemoryDormancy_ControlService;
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FAM_MemoryReactivation_ControlService = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const mongoose_1 = tslib_1.__importDefault(require("mongoose"));
6
+ const fsm_dynamo_1 = require("@futdevpro/fsm-dynamo");
7
+ const fam_table_type_enum_1 = require("../../../_enums/fam-table.type-enum");
8
+ const embedding_1 = require("../../embedding");
9
+ const fam_memory_data_model_1 = require("../../../_models/data-models/fam-memory.data-model");
10
+ /**
11
+ * `FAM_MemoryReactivation_ControlService` (dsgn-013 §4, MAM F2) — a memória FELIDÉZÉS-megerősítése. Amikor a `read`
12
+ * ténylegesen VISSZAAD egy `memory`-hitet (a felhasználó/agent felidézte), az „új energiát kap": `lastRecalledAt = now`,
13
+ * `recallCount += 1`, `dormant = false`. Ez az emberi memória retrieval-practice-e — a felidézett emlék megerősödik,
14
+ * feljebb rangsorol (a dsgn-013 §2 frequencyBoost + a friss recency), és ha alvó volt, visszakerül a hot készletbe.
15
+ *
16
+ * **Fire-and-forget:** a `read`-ből async, NEM blokkolja a választ; batch-elt `updateMany` (egy DB-hívás a top-K-ra).
17
+ * CSAK a ténylegesen visszaadott (használt) hitre fut → nincs „gyakran-keresett-de-irreleváns" felhízás. A hiba
18
+ * NÉMA-best-effort (a read már sikerült; a felidézés-frissítés elvesztése nem hiba). A flag NEM érinti a vektor-poolt.
19
+ */
20
+ class FAM_MemoryReactivation_ControlService {
21
+ static _instance;
22
+ issuer = 'FAM_MemoryReactivation_ControlService';
23
+ static getInstance() {
24
+ if (!FAM_MemoryReactivation_ControlService._instance) {
25
+ FAM_MemoryReactivation_ControlService._instance = new FAM_MemoryReactivation_ControlService();
26
+ }
27
+ return FAM_MemoryReactivation_ControlService._instance;
28
+ }
29
+ /**
30
+ * A megadott `memory`-entry-k FELIDÉZÉS-frissítése (`updateMany`): `lastRecalledAt = nowMs`, `recallCount += 1`,
31
+ * `dormant = false`. Üres id-lista → no-op (0). Visszaadja a módosított darabszámot. **Nem dob** — a hiba logolódik
32
+ * és `0`-val tér vissza (best-effort, a read-et nem buktatja).
33
+ */
34
+ async reactivate(ids, nowMs) {
35
+ const uniqueIds = Array.from(new Set(ids.filter((id) => typeof id === 'string' && id.length)));
36
+ if (!uniqueIds.length) {
37
+ return 0;
38
+ }
39
+ try {
40
+ const model = this.memoryModel();
41
+ if (!model) {
42
+ return 0;
43
+ }
44
+ const res = await model.updateMany({ _id: { $in: uniqueIds } }, { $set: { lastRecalledAt: nowMs, dormant: false }, $inc: { recallCount: 1 } });
45
+ return res.modifiedCount ?? 0;
46
+ }
47
+ catch (error) {
48
+ fsm_dynamo_1.DyFM_Log.warn(`[FAM memoryReactivation] felidézés-frissítés sikertelen (best-effort): ${error?.message}`);
49
+ return 0;
50
+ }
51
+ }
52
+ /**
53
+ * A reaktiválandó `memory`-hit `_id`-k kiválasztása a read-eredmény hitjeiből (PURE, tesztelhető): CSAK a
54
+ * `memory`-táras, `_id`-vel bíró hitek, deduplikálva. A NEM-memory hitek (codebase/documents/…) kimaradnak.
55
+ */
56
+ static selectMemoryIds(hits) {
57
+ const ids = hits
58
+ .filter((hit) => hit.table === fam_table_type_enum_1.FAM_Table.memory && typeof hit.id === 'string' && hit.id.length > 0)
59
+ .map((hit) => hit.id);
60
+ return Array.from(new Set(ids));
61
+ }
62
+ /** A `fam_memory` mongoose-modellje (a DS-példányosítás regisztrálja). */
63
+ memoryModel() {
64
+ new embedding_1.FAM_Entry_DataService({ dataParams: fam_memory_data_model_1.famMemory_dataParams, issuer: this.issuer });
65
+ return mongoose_1.default.models[fam_memory_data_model_1.famMemory_dataParams.dataName];
66
+ }
67
+ }
68
+ exports.FAM_MemoryReactivation_ControlService = FAM_MemoryReactivation_ControlService;
@@ -117,8 +117,21 @@ class FAM_RetrievalCandidate_DataService {
117
117
  const filter = {};
118
118
  // ① scope-prefilter (subtree scopeId-halmaz). null → nincs scope-szűrés (teljes tár).
119
119
  if (input.scopeIdSet) {
120
- // A scopePath denormalizált scope-ref tömb; a scopeId-ra szűrünk (dot-path a Mixed tömbön).
121
- filter['scopePath.scopeId'] = { $in: input.scopeIdSet };
120
+ const isGlobalRulesTable = registryEntry.table === fam_table_type_enum_1.FAM_Table.rules && input.includeGlobalRules !== false;
121
+ if (isGlobalRulesTable) {
122
+ // GLOBÁLIS HARD-RULE öröklés (user-FR 2026-06-22 — a FAM fő feature-je): a scope-szűrt `rules`-lekérdezés
123
+ // a subtree-scope rule-jai MELLÉ a `globalRule:true` (workspace-szintű hard-rules) bejegyzéseket is
124
+ // behúzza — `(scope subtree-ben) VAGY (globális hard-rule)`. Így egy al-scope-ban is megkapjuk a
125
+ // mindenhol érvényes hard-rules-t. (A `$or` a tag/kind/isActive AND-feltételekkel kombinálódik.)
126
+ filter.$or = [
127
+ { 'scopePath.scopeId': { $in: input.scopeIdSet } },
128
+ { globalRule: true },
129
+ ];
130
+ }
131
+ else {
132
+ // A scopePath denormalizált scope-ref tömb; a scopeId-ra szűrünk (dot-path a Mixed tömbön).
133
+ filter['scopePath.scopeId'] = { $in: input.scopeIdSet };
134
+ }
122
135
  }
123
136
  // ② tag-prefilter (OR a tagek között): bármely tag-match bekerül.
124
137
  if (input.tagFilter && input.tagFilter.length) {
@@ -8,6 +8,10 @@ const embedding_1 = require("../../embedding");
8
8
  const scope_reference_1 = require("../../scope-reference");
9
9
  const fam_retrieval_candidate_data_service_1 = require("./fam-retrieval-candidate.data-service");
10
10
  const fam_retrieval_suggestions_util_1 = require("./fam-retrieval-suggestions.util");
11
+ const fam_memory_activation_util_1 = require("../_collections/fam-memory-activation.util");
12
+ const fam_lexical_match_util_1 = require("../_collections/fam-lexical-match.util");
13
+ const fam_memory_reactivation_control_service_1 = require("./fam-memory-reactivation.control-service");
14
+ const fam_memory_cold_search_control_service_1 = require("./fam-memory-cold-search.control-service");
11
15
  /** A topK / lapozás abszolút plafonja (CCAP MAX_PAGE_SIZE=500; dsgn-005 §6). */
12
16
  const MAX_PAGE_SIZE = 500;
13
17
  /**
@@ -95,8 +99,57 @@ class FAM_Retrieval_ControlService {
95
99
  const relevantSet = visibleHits.filter((hit) => this.codeExactRank(hit) > 0 || hit.finalScore >= config.minScore);
96
100
  // ⑦ rendezés (finalScore desc → recency → _id asc).
97
101
  this.sortHits(relevantSet, config.scoreOrder);
102
+ // ⑦b R1 duplikátum-dedup (FAM-REV 2026-06-22, eval-lelet): az AZONOS-tartalmú (kereszt-repo) hitek összevonása
103
+ // a top-K ELŐTT — a kanonikus (legjobb-ranked) marad, a másolat-szám a `duplicateCount`-ban. A közös fájlok
104
+ // (`.cursor/rules` / CLAUDE.md / guideline) ne pazarolják a top-K-t 4-5 azonos másolattal. A `sortHits` UTÁN fut
105
+ // (a megtartott a legjobb-rangsorolt); a contentHash-mentes hitek érintetlenek.
106
+ const dedupedSet = FAM_Retrieval_ControlService.dedupeByContentHash(relevantSet);
98
107
  // ⑧ topK-vágás + dense-detektálás + suggestions.
99
- return this.buildResult({ query, relevantSet, config, scopeExpand, detectedCodes });
108
+ const result = this.buildResult({ query, relevantSet: dedupedSet, config, scopeExpand, detectedCodes });
109
+ // dsgn-013 §4 (MAM F2) — FELIDÉZÉS-megerősítés: a ténylegesen VISSZAADOTT `memory`-hitek „új energiát kapnak"
110
+ // (lastRecalledAt=now, recallCount++, dormant=false). ASYNC fire-and-forget — NEM blokkolja a read választ.
111
+ this.reactivateReturnedMemoryHits(result.hits, config);
112
+ return result;
113
+ }
114
+ /**
115
+ * A visszaadott top-K `memory`-hitek async felidézés-megerősítése (dsgn-013 §4). Fire-and-forget (void): a read
116
+ * már elkészült, a felidézés-frissítés best-effort. Csak a `memory`-táras, `_id`-vel bíró hitre; üres → no-op.
117
+ * `memoryReactivateOnRead=false` → kikapcsolva.
118
+ */
119
+ reactivateReturnedMemoryHits(hits, config) {
120
+ if (!config.memoryReactivateOnRead) {
121
+ return;
122
+ }
123
+ const memoryIds = fam_memory_reactivation_control_service_1.FAM_MemoryReactivation_ControlService.selectMemoryIds(hits);
124
+ if (!memoryIds.length) {
125
+ return;
126
+ }
127
+ void fam_memory_reactivation_control_service_1.FAM_MemoryReactivation_ControlService.getInstance().reactivate(memoryIds, Date.now());
128
+ }
129
+ /**
130
+ * R1 dedup (pure): az AZONOS `contentHash`-ű hitek összevonása — az ELSŐ (a `sortHits` után legjobb-ranked) marad,
131
+ * a többi azonos-tartalmú másolatot beleszámoljuk a megtartott `duplicateCount`-jába. A `contentHash`-mentes hitek
132
+ * (pl. compact-mode projekció nélkül) NEM dedup-olódnak (mind egyedi). Sorrend-tartó.
133
+ */
134
+ static dedupeByContentHash(hits) {
135
+ const keptByHash = new Map();
136
+ const result = [];
137
+ for (const hit of hits) {
138
+ const key = hit.contentHash;
139
+ if (!key) {
140
+ result.push(hit);
141
+ continue;
142
+ }
143
+ const kept = keptByHash.get(key);
144
+ if (kept) {
145
+ kept.duplicateCount = (kept.duplicateCount ?? 0) + 1;
146
+ }
147
+ else {
148
+ keptByHash.set(key, hit);
149
+ result.push(hit);
150
+ }
151
+ }
152
+ return result;
100
153
  }
101
154
  // =========================================================================
102
155
  // ④b KÓD-EXPANZIÓ (FEAT-003) — determinisztikus link-retrieval a vektor MELLÉ
@@ -171,6 +224,7 @@ class FAM_Retrieval_ControlService {
171
224
  weight: set.weight,
172
225
  finalScore: 1.0 * set.weight,
173
226
  content: set.includeContent ? set.entry.content : undefined,
227
+ contentHash: set.entry.contentHash,
174
228
  kind: set.entry.kind,
175
229
  tags: set.entry.tags ?? [],
176
230
  ...this.ruleMeta(set.entry, set.table),
@@ -256,6 +310,8 @@ class FAM_Retrieval_ControlService {
256
310
  });
257
311
  }
258
312
  // ⑤ weight-szorzó: finalScore = score × (weight ?? 1); weight ≤ 0 → kizárt (nem kerül a hits közé).
313
+ // Improvement 2: a query lexikai term-jeit EGYSZER tokenizáljuk (a hibrid keyword-boost-hoz a toHit-ban).
314
+ const queryTerms = fam_lexical_match_util_1.FAM_LexicalMatch_Util.tokenize(set.query.query);
259
315
  const hits = [];
260
316
  for (const vectorHit of vectorHits) {
261
317
  const entry = byId.get(vectorHit.id);
@@ -267,12 +323,63 @@ class FAM_Retrieval_ControlService {
267
323
  continue;
268
324
  }
269
325
  hits.push(this.toHit({
270
- entry, vectorHit, table: set.table, weight,
271
- importChunkWeight: set.config.importChunkWeight, includeContent: set.includeContent,
326
+ entry, vectorHit, table: set.table, weight, queryTerms: queryTerms,
327
+ importChunkWeight: set.config.importChunkWeight, importSourceWeight: set.config.importSourceWeight,
328
+ includeContent: set.includeContent, config: set.config, nowMs: Date.now(),
272
329
  }));
273
330
  }
331
+ // dsgn-013 §5.3 (MAM F3b) — COLD-search supplement: ha `memory` + engedélyezett + a hot pool kevés ERŐSEN-
332
+ // releváns találatot ad. FONTOS: NEM a candidate-darabszámot nézzük (a vektor-keresés ~MAX_PAGE_SIZE jelöltet ad
333
+ // vissza, így a `hits.length` szinte mindig nagy) — hanem az ERŐS (raw cosine ≥ relevanceFloor) hot hitek számát.
334
+ // Ha ezekből kevesebb mint topK van, a hot pool nem elégítette ki a query-t → a dormant készleten keresünk.
335
+ const strongHotHits = hits.filter((hit) => hit.score >= set.config.relevanceFloor).length;
336
+ if (set.table === fam_table_type_enum_1.FAM_Table.memory && set.config.memoryColdSearchEnabled && strongHotHits < set.config.topK) {
337
+ await this.supplementWithColdSearch(set, hits, set.query);
338
+ }
274
339
  return hits;
275
340
  }
341
+ /**
342
+ * A hot memória-találatok kiegészítése a dormant készletből (dsgn-013 §5.3). A cold-hiteket a `toHit`-en át
343
+ * (decay + faktorok) fűzzük be, a már látott `_id`-ket kiszűrve; a `weight ≤ 0` továbbra is kizárt.
344
+ */
345
+ async supplementWithColdSearch(set, hits, query) {
346
+ // `topK` cold-jelölt (NEM `topK - hits.length` — a `hits` itt a teljes candidate-halmaz, ~MAX_PAGE_SIZE, ami
347
+ // negatívot adna). A cold-hitek a NORMÁL ranking-pipeline-ba kerülnek; a végső topK-vágás (buildResult) dönt.
348
+ // A tag/kind prefilter UGYANAZ, mint a hot-path-é (különben kiszűrt entry-ket hozna vissza a cold-supplement).
349
+ const coldHits = await fam_memory_cold_search_control_service_1.FAM_MemoryColdSearch_ControlService.getInstance().search({
350
+ queryVector: set.queryVector,
351
+ scopeIdSet: set.scopeExpand.scopeIdSet ?? [],
352
+ topK: set.config.topK,
353
+ maxCandidates: set.config.memoryColdSearchMaxCandidates,
354
+ nowMs: Date.now(),
355
+ tagFilter: query.tagFilter,
356
+ kindFilter: query.kindFilter,
357
+ });
358
+ const seen = new Set(hits.map((hit) => hit.id));
359
+ const queryTerms = fam_lexical_match_util_1.FAM_LexicalMatch_Util.tokenize(query.query);
360
+ for (const cold of coldHits) {
361
+ const id = cold.entry._id;
362
+ const weight = cold.entry.weight ?? 1;
363
+ if (!id || seen.has(id) || weight <= 0) {
364
+ continue;
365
+ }
366
+ hits.push(this.toHit({
367
+ entry: cold.entry, vectorHit: { id: id, score: cold.score }, table: set.table, weight: weight, queryTerms: queryTerms,
368
+ importChunkWeight: set.config.importChunkWeight, importSourceWeight: set.config.importSourceWeight,
369
+ includeContent: set.includeContent, config: set.config, nowMs: Date.now(),
370
+ }));
371
+ seen.add(id);
372
+ // KRITIKUS (dsgn-013 §5.3 promóció-gap fix): a cold-talált entry vektorát AZONNAL a hot poolba is upsert-eljük.
373
+ // Különben — miután a reaktiváció `dormant=false`-ra állítja — az entry SEM a hot poolban (csak boot-kor
374
+ // hidratálódik), SEM a cold-keresésben (a `dormant:true` szűrő kizárja) nem lenne megtalálható a következő
375
+ // re-hidratálásig → „elérhetetlen a promóció után". A pool-upsert idempotens; a (ritka) topK-ból kieső,
376
+ // de még dormant entry a következő bootkor úgyis kiesik a poolból (a hidratálás-szűrő korrigálja).
377
+ const vector = (cold.entry.contentVector ?? []);
378
+ if (vector.length) {
379
+ embedding_1.FAM_VectorSearch_ControlService.getInstance().upsertVector({ table: set.table, id: id, vector: vector });
380
+ }
381
+ }
382
+ }
276
383
  /**
277
384
  * Az import-only chunkok (`chunkType:"imports"`) read-idejű rangsor-szorzója (FAM-REV-060). Egy import-sor
278
385
  * (`import { X } from "./y"`) magas cosine-t kap egy szimbólum-név query-re, de alacsony az ÉRTÉKe (csak
@@ -282,18 +389,70 @@ class FAM_Retrieval_ControlService {
282
389
  chunkTypeFactor(chunkType, importChunkWeight) {
283
390
  return chunkType === 'imports' ? importChunkWeight : 1;
284
391
  }
392
+ /**
393
+ * R2 import-source faktor (2026-06-22 eval-lelet): a `source.type:'import'` (claude-mem-import) entry-k finalScore-ja
394
+ * `importSourceWeight`-tel szorzódik (<1), hogy a kurált (`manual`/`agent`/scan) tanulságok a `memory`/`knowledge`
395
+ * táblákon FÖLÉ rangsoroljanak — az import zaja ne temesse őket. Minden NEM-import source érintetlen (×1).
396
+ * READ-time, a nyers `score` (relevancia) változatlan; `importSourceWeight=1` → kikapcsolva (változatlan rangsor).
397
+ */
398
+ importSourceFactor(source, importSourceWeight) {
399
+ return source?.type === 'import' ? importSourceWeight : 1;
400
+ }
401
+ /**
402
+ * Memory Activation Model decay-szorzó (dsgn-013 §3) — CSAK a `memory` táron, ha engedélyezett. A frissen/gyakran
403
+ * FELIDÉZETT memória felül-, a régóta érintetlen alul-rangsorol, de a `floorWeight > 0` miatt SOSEM esik ki. A
404
+ * `lastRecalledAt` hiányában a `__created` ideje a fallback (cold-start kegyelmi idő). Minden más tár → ×1.
405
+ */
406
+ memoryDecayFactor(entry, table, config, nowMs) {
407
+ if (table !== fam_table_type_enum_1.FAM_Table.memory) {
408
+ return 1;
409
+ }
410
+ let factor = 1;
411
+ if (config.memoryActivationEnabled) {
412
+ const createdMs = entry.__created ? new Date(entry.__created).getTime() : undefined;
413
+ factor = fam_memory_activation_util_1.FAM_MemoryActivation_Util.decayFactor({
414
+ lastRecalledAt: entry.lastRecalledAt,
415
+ recallCount: entry.recallCount,
416
+ nowMs: nowMs,
417
+ fallbackMs: createdMs,
418
+ config: {
419
+ halfLifeDays: config.memoryHalfLifeDays, floorWeight: config.memoryFloorWeight,
420
+ maxFrequencyBoost: config.memoryMaxFrequencyBoost, activationWeight: config.memoryActivationWeight,
421
+ },
422
+ });
423
+ }
424
+ // dsgn-013 §6 (MAM F4): a LEVÁLTOTT (superseded) régi tartalom penalizálva — a friss verzió fölébe kerül (de
425
+ // megmarad, cold-kereshető). A penalty az aktiváció-decay MELLÉ szorzódik (akkor is hat, ha a decay ki van kapcsolva).
426
+ if (entry.superseded) {
427
+ factor *= config.memorySupersededPenalty;
428
+ }
429
+ return factor;
430
+ }
285
431
  /** Egy candidate-entry + a vektor-hit → `FAM_RetrievalHit` (finalScore + denormalizált mezők). */
286
432
  toHit(set) {
287
433
  const lastModified = set.entry.__lastModified;
288
- // ⑤ weight-szorzó + FAM-REV-060 import-chunk read-faktor: finalScore = score × weight × chunkTypeFactor.
434
+ // ⑤ weight-szorzó + FAM-REV-060 import-chunk read-faktor + R2 import-SOURCE faktor (2026-06-22 eval-lelet:
435
+ // a claude-mem-import zaja ne temesse a kurált tanulságokat) + dsgn-013 memory-decay (CSAK a memory táron) +
436
+ // Improvement 2 hibrid LEXIKAI keyword-boost (a literal-match felszínre kerül, BOOST-only) →
437
+ // finalScore = score × weight × chunkF × sourceF × decayF × (1 + keywordWeight × lexicalScore).
289
438
  const chunkFactor = this.chunkTypeFactor(set.entry.chunkType, set.importChunkWeight);
439
+ const sourceFactor = this.importSourceFactor(set.entry.source, set.importSourceWeight);
440
+ const decayFactor = this.memoryDecayFactor(set.entry, set.table, set.config, set.nowMs);
441
+ const lexicalScore = set.config.keywordWeight > 0
442
+ ? fam_lexical_match_util_1.FAM_LexicalMatch_Util.score(set.queryTerms, {
443
+ content: set.entry.content, headingPath: set.entry.headingPath, sourceFilePath: set.entry.source?.path,
444
+ })
445
+ : 0;
446
+ const keywordBoost = 1 + set.config.keywordWeight * lexicalScore;
290
447
  return {
291
448
  id: set.vectorHit.id,
292
449
  table: set.table,
293
450
  score: set.vectorHit.score,
294
451
  weight: set.weight,
295
- finalScore: set.vectorHit.score * set.weight * chunkFactor,
452
+ finalScore: set.vectorHit.score * set.weight * chunkFactor * sourceFactor * decayFactor * keywordBoost,
453
+ lexicalScore: lexicalScore,
296
454
  content: set.includeContent ? set.entry.content : undefined,
455
+ contentHash: set.entry.contentHash,
297
456
  kind: set.entry.kind,
298
457
  tags: set.entry.tags ?? [],
299
458
  ...this.ruleMeta(set.entry, set.table),
@@ -324,6 +483,13 @@ class FAM_Retrieval_ControlService {
324
483
  category: rule.category,
325
484
  isActive: rule.isActive,
326
485
  applicableScopes: (rule.applicableScopes ?? []),
486
+ // Rules-Management MP-1 mezők a hit-en (read-DTO bővítés) — a hívó/reflex így megkülönbözteti a KURÁLT
487
+ // kanonikus szabályt (ruleScope/importance/userApproved/ruleId) a nyers, scannelt rules-korpusztól.
488
+ ruleScope: rule.ruleScope,
489
+ ruleScopeTopic: rule.ruleScopeTopic,
490
+ importance: rule.importance,
491
+ userApproved: rule.userApproved,
492
+ ruleId: rule.ruleId,
327
493
  };
328
494
  }
329
495
  // =========================================================================
@@ -488,18 +654,44 @@ class FAM_Retrieval_ControlService {
488
654
  const minScore = query.minScore ?? await this.resolveNumber(config, 'read.minScore', ctx, 0);
489
655
  const relevanceFloor = await this.resolveNumber(config, 'read.relevanceFloor', ctx, 0.5);
490
656
  const importChunkWeight = await this.resolveNumber(config, 'read.importChunkWeight', ctx, 0.4);
657
+ const importSourceWeight = await this.resolveNumber(config, 'read.importSourceWeight', ctx, 0.85);
658
+ const keywordWeight = await this.resolveNumber(config, 'read.keywordWeight', ctx, 0.6);
491
659
  const denseResultRatio = await this.resolveNumber(config, 'read.denseResultRatio', ctx, 2.0);
492
660
  const denseResultAbsMin = await this.resolveNumber(config, 'read.denseResultAbsMin', ctx, 25);
493
661
  const scoreOrderValue = (await config.resolve('read.scoreOrder', ctx)).value;
494
662
  const scoreOrder = typeof scoreOrderValue === 'string' ? scoreOrderValue : 'weighted';
663
+ // Memory Activation Model (dsgn-013) — a `memory.*` namespace; a decay CSAK a memory táron alkalmazódik (toHit).
664
+ const memoryActivationValue = (await config.resolve('memory.activationEnabled', ctx)).value;
665
+ const memoryActivationEnabled = memoryActivationValue !== false;
666
+ const memoryHalfLifeDays = await this.resolveNumber(config, 'memory.decayHalfLifeDays', ctx, 90);
667
+ const memoryFloorWeight = await this.resolveNumber(config, 'memory.floorWeight', ctx, 0.05);
668
+ const memoryMaxFrequencyBoost = await this.resolveNumber(config, 'memory.maxFrequencyBoost', ctx, 2.5);
669
+ const memoryActivationWeight = await this.resolveNumber(config, 'memory.activationWeight', ctx, 0.35);
670
+ const memoryReactivateValue = (await config.resolve('memory.reactivateOnRead', ctx)).value;
671
+ const memoryReactivateOnRead = memoryReactivateValue !== false;
672
+ const memoryColdSearchValue = (await config.resolve('memory.coldSearchEnabled', ctx)).value;
673
+ const memoryColdSearchEnabled = memoryColdSearchValue !== false;
674
+ const memoryColdSearchMaxCandidates = await this.resolveNumber(config, 'memory.coldSearchMaxCandidates', ctx, 5000);
675
+ const memorySupersededPenalty = await this.resolveNumber(config, 'memory.supersededPenalty', ctx, 0.25);
495
676
  return {
496
677
  topK: Math.min(topKDefault, MAX_PAGE_SIZE),
497
678
  minScore: minScore,
498
679
  relevanceFloor: relevanceFloor,
499
680
  importChunkWeight: importChunkWeight,
681
+ importSourceWeight: importSourceWeight,
682
+ keywordWeight: keywordWeight,
500
683
  denseResultRatio: denseResultRatio,
501
684
  denseResultAbsMin: denseResultAbsMin,
502
685
  scoreOrder: scoreOrder,
686
+ memoryActivationEnabled: memoryActivationEnabled,
687
+ memoryHalfLifeDays: memoryHalfLifeDays,
688
+ memoryFloorWeight: memoryFloorWeight,
689
+ memoryMaxFrequencyBoost: memoryMaxFrequencyBoost,
690
+ memoryActivationWeight: memoryActivationWeight,
691
+ memoryReactivateOnRead: memoryReactivateOnRead,
692
+ memoryColdSearchEnabled: memoryColdSearchEnabled,
693
+ memoryColdSearchMaxCandidates: memoryColdSearchMaxCandidates,
694
+ memorySupersededPenalty: memorySupersededPenalty,
503
695
  };
504
696
  }
505
697
  /** Egy szám-config feloldása a default-tal (a `resolve.value` lehet más típus → fallback). */
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FAM_RuleInjection_ControlService = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const mongoose_1 = tslib_1.__importDefault(require("mongoose"));
6
+ const error_codes_const_1 = require("../../../_collections/error-codes.const");
7
+ const fam_error_factory_util_1 = require("../../../_collections/fam-error-factory.util");
8
+ const fam_rules_data_model_1 = require("../../../_models/data-models/fam-rules.data-model");
9
+ const embedding_1 = require("../../embedding");
10
+ const fam_rule_injection_util_1 = require("../_collections/fam-rule-injection.util");
11
+ const fam_rule_propagation_util_1 = require("../_collections/fam-rule-propagation.util");
12
+ const fam_rule_scope_context_util_1 = require("../_collections/fam-rule-scope-context.util");
13
+ /**
14
+ * `FAM_RuleInjection_ControlService` (Rules-Management MP-2) — a SessionStart-injektálás (+ a `read`-reflex) szerver-oldali
15
+ * ASSEMBLY-je: a `cwd`-ből (vagy explicit felülírásból) detektálja a tier-kontextust, prefilterezi a `fam_rules`-t a
16
+ * MOST érvényes TIER-ekre (`FAM_RuleInjection_Util.buildFilter`), `importance`-rangsorolja, és char-budgetbe illeszti
17
+ * a „(…and N more)" záró sorral. A hook így DUMB marad (csak hív + az `additionalContext`-be teszi a blokkot) — a teljes
18
+ * ranking/scope/budget logika ITT, szerver-oldalon, unit-tesztelhetően él (mint a `/api/doctor`).
19
+ */
20
+ class FAM_RuleInjection_ControlService {
21
+ static _instance;
22
+ issuer = 'FAM_RuleInjection_ControlService';
23
+ static getInstance() {
24
+ if (!FAM_RuleInjection_ControlService._instance) {
25
+ FAM_RuleInjection_ControlService._instance = new FAM_RuleInjection_ControlService();
26
+ }
27
+ return FAM_RuleInjection_ControlService._instance;
28
+ }
29
+ /** A MOST érvényes always-apply rule-blokk összeállítása (detektált/felülírt kontextus alapján). */
30
+ async assembleInjection(input) {
31
+ const context = this.resolveContext(input);
32
+ const rules = await this.loadRulesForContext(context);
33
+ const assembled = fam_rule_injection_util_1.FAM_RuleInjection_Util.assemble({
34
+ rules: rules, budgetChars: input.budgetChars,
35
+ });
36
+ return { ...assembled, context: context };
37
+ }
38
+ /**
39
+ * MP-5 — a kontextusra érvényes szabályok GENERÁLT, marker-keretezett `CLAUDE.md`-blokkja (propagáció a FAM-nélküli
40
+ * projekt-agenteknek). Budget NÉLKÜL (minden alkalmazható szabály bekerül), dedup `ruleId`/`derivedFrom` szerint.
41
+ */
42
+ async assemblePropagation(input) {
43
+ const context = this.resolveContext(input);
44
+ const rules = await this.loadRulesForContext(context);
45
+ const block = fam_rule_propagation_util_1.FAM_RulePropagation_Util.wrap(fam_rule_propagation_util_1.FAM_RulePropagation_Util.renderBlock(rules));
46
+ return { block: block, ruleCount: fam_rule_propagation_util_1.FAM_RulePropagation_Util.dedup(rules).length, context: context };
47
+ }
48
+ /** A tier-kontextusra érvényes, aktív `rules`-entry-k betöltése injektálható view-ként (közös SSOT a két assembly-hez). */
49
+ async loadRulesForContext(context) {
50
+ const model = this.rulesModel();
51
+ if (!model) {
52
+ throw fam_error_factory_util_1.FAM_Error_Util.create({
53
+ errorCode: error_codes_const_1.FAM_ERROR_CODES.vecSearch,
54
+ message: 'A `fam_rules` model nincs regisztrálva (boot-előtt?).',
55
+ issuer: this.issuer,
56
+ context: { operation: 'load-rules-for-context' },
57
+ });
58
+ }
59
+ const filter = fam_rule_injection_util_1.FAM_RuleInjection_Util.buildFilter(context);
60
+ // CSAK a rangsorhoz/megjelenítéshez kellő mezők (a vektor NEM kell → könnyű lean-query).
61
+ const docs = await model.find(filter, {
62
+ content: 1, importance: 1, weight: 1, globalRule: 1, category: 1,
63
+ ruleScope: 1, ruleScopeTopic: 1, ruleId: 1, derivedFrom: 1, __lastModified: 1,
64
+ }).lean();
65
+ return docs.map((doc) => this.toInjectable(doc));
66
+ }
67
+ /** Explicit felülírás > `cwd`-detekció. A `projectType`/`topics`/budget mindig az inputból. */
68
+ resolveContext(input) {
69
+ const detected = fam_rule_scope_context_util_1.FAM_RuleScopeContext_Util.detect(input.cwd);
70
+ return {
71
+ isFdp: input.isFdp ?? detected.isFdp,
72
+ inProject: input.inProject ?? detected.inProject,
73
+ projectName: detected.projectName,
74
+ projectRoot: detected.projectRoot,
75
+ projectType: input.projectType ?? detected.projectType,
76
+ topics: input.topics ?? detected.topics,
77
+ };
78
+ }
79
+ /** Egy lean Mongo-doc → `FAM_InjectableRule` view. */
80
+ toInjectable(doc) {
81
+ const lastModified = doc.__lastModified;
82
+ return {
83
+ id: typeof doc._id === 'string' ? doc._id : (doc._id ? String(doc._id) : undefined),
84
+ content: typeof doc.content === 'string' ? doc.content : undefined,
85
+ importance: typeof doc.importance === 'number' ? doc.importance : undefined,
86
+ weight: typeof doc.weight === 'number' ? doc.weight : undefined,
87
+ globalRule: doc.globalRule === true,
88
+ category: typeof doc.category === 'string' ? doc.category : undefined,
89
+ ruleScope: typeof doc.ruleScope === 'string' ? doc.ruleScope : undefined,
90
+ ruleScopeTopic: typeof doc.ruleScopeTopic === 'string' ? doc.ruleScopeTopic : undefined,
91
+ ruleId: typeof doc.ruleId === 'string' ? doc.ruleId : undefined,
92
+ derivedFrom: typeof doc.derivedFrom === 'string' ? doc.derivedFrom : undefined,
93
+ lastModifiedMs: lastModified ? new Date(lastModified).getTime() : 0,
94
+ };
95
+ }
96
+ /** A `fam_rules` mongoose-modellje (a DS-példányosítás regisztrálja). */
97
+ rulesModel() {
98
+ new embedding_1.FAM_Entry_DataService({ dataParams: fam_rules_data_model_1.famRules_dataParams, issuer: this.issuer });
99
+ return mongoose_1.default.models[fam_rules_data_model_1.famRules_dataParams.dataName];
100
+ }
101
+ }
102
+ exports.FAM_RuleInjection_ControlService = FAM_RuleInjection_ControlService;
@@ -10,10 +10,21 @@
10
10
  * opcionális relevance-filter = BACKLOG (NEM épül).
11
11
  */
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
- exports.FAM_RetrievalSuggestions_Util = exports.FAM_RetrievalCandidate_DataService = exports.FAM_Retrieval_ControlService = void 0;
13
+ exports.FAM_RetrievalSuggestions_Util = exports.FAM_RetrievalCandidate_DataService = exports.FAM_RuleScopeContext_Util = exports.FAM_RulePropagation_Util = exports.FAM_RuleInjection_Util = exports.FAM_RuleInjection_ControlService = exports.FAM_GlobalRule_ControlService = exports.FAM_Retrieval_ControlService = void 0;
14
14
  // SP-5.1/5.2/5.3 — a read-pipeline orchestrátor
15
15
  var fam_retrieval_control_service_1 = require("./_services/fam-retrieval.control-service");
16
16
  Object.defineProperty(exports, "FAM_Retrieval_ControlService", { enumerable: true, get: function () { return fam_retrieval_control_service_1.FAM_Retrieval_ControlService; } });
17
+ var fam_global_rule_control_service_1 = require("./_services/fam-global-rule.control-service");
18
+ Object.defineProperty(exports, "FAM_GlobalRule_ControlService", { enumerable: true, get: function () { return fam_global_rule_control_service_1.FAM_GlobalRule_ControlService; } });
19
+ // Rules-Management MP-2 — always-apply rule-injektálás (SessionStart inject + read-reflex) szerver-oldali assembly
20
+ var fam_rule_injection_control_service_1 = require("./_services/fam-rule-injection.control-service");
21
+ Object.defineProperty(exports, "FAM_RuleInjection_ControlService", { enumerable: true, get: function () { return fam_rule_injection_control_service_1.FAM_RuleInjection_ControlService; } });
22
+ var fam_rule_injection_util_1 = require("./_collections/fam-rule-injection.util");
23
+ Object.defineProperty(exports, "FAM_RuleInjection_Util", { enumerable: true, get: function () { return fam_rule_injection_util_1.FAM_RuleInjection_Util; } });
24
+ var fam_rule_propagation_util_1 = require("./_collections/fam-rule-propagation.util");
25
+ Object.defineProperty(exports, "FAM_RulePropagation_Util", { enumerable: true, get: function () { return fam_rule_propagation_util_1.FAM_RulePropagation_Util; } });
26
+ var fam_rule_scope_context_util_1 = require("./_collections/fam-rule-scope-context.util");
27
+ Object.defineProperty(exports, "FAM_RuleScopeContext_Util", { enumerable: true, get: function () { return fam_rule_scope_context_util_1.FAM_RuleScopeContext_Util; } });
17
28
  // SP-5.1 ① scope + ② tag/kind Mongo-prefilter (a vektor-keresés ELŐTT)
18
29
  var fam_retrieval_candidate_data_service_1 = require("./_services/fam-retrieval-candidate.data-service");
19
30
  Object.defineProperty(exports, "FAM_RetrievalCandidate_DataService", { enumerable: true, get: function () { return fam_retrieval_candidate_data_service_1.FAM_RetrievalCandidate_DataService; } });