@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.
Files changed (100) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +7 -7
  3. package/build/package.json +6 -5
  4. package/build/src/_cli/_collections/fam-arg.util.js +48 -0
  5. package/build/src/_cli/_collections/fam-cli.const.js +40 -0
  6. package/build/src/_cli/_collections/fam-output.util.js +86 -0
  7. package/build/src/_cli/_collections/fam-project-discovery.util.js +98 -0
  8. package/build/src/_cli/_commands/capture.command.js +73 -0
  9. package/build/src/_cli/_commands/config.command.js +93 -0
  10. package/build/src/_cli/_commands/doctor.command.js +124 -0
  11. package/build/src/_cli/_commands/errors.command.js +66 -0
  12. package/build/src/_cli/_commands/export.command.js +65 -0
  13. package/build/src/_cli/_commands/find-duplicates.command.js +97 -0
  14. package/build/src/_cli/_commands/import.command.js +136 -0
  15. package/build/src/_cli/_commands/init.command.js +147 -0
  16. package/build/src/_cli/_commands/read.command.js +109 -0
  17. package/build/src/_cli/_commands/scan-projects.command.js +138 -0
  18. package/build/src/_cli/_commands/scan.command.js +98 -0
  19. package/build/src/_cli/_commands/seed.command.js +40 -0
  20. package/build/src/_cli/_commands/serve.command.js +350 -0
  21. package/build/src/_cli/_commands/start.command.js +134 -0
  22. package/build/src/_cli/_commands/stats.command.js +54 -0
  23. package/build/src/_cli/_commands/write.command.js +103 -0
  24. package/build/src/_cli/_models/interfaces/fam-cli-global-options.interface.js +2 -0
  25. package/build/src/_cli/_models/interfaces/fam-cli-output.interface.js +9 -0
  26. package/build/src/_cli/_models/interfaces/fam-client-result.interface.js +2 -0
  27. package/build/src/_cli/_services/fam-client.service.js +140 -0
  28. package/build/src/_cli/register-commands.js +86 -0
  29. package/build/src/_collections/config-catalog.const.js +67 -1
  30. package/build/src/_collections/fam-console.util.js +367 -0
  31. package/build/src/_collections/fam-entry-bootstrap.util.js +158 -4
  32. package/build/src/_collections/fam-error-factory.util.js +0 -9
  33. package/build/src/_collections/fam-mcp-bridge.util.js +49 -0
  34. package/build/src/_collections/fam-reference-code.util.js +105 -0
  35. package/build/src/_collections/fam-version.const.js +10 -0
  36. package/build/src/_models/data-models/fam-entry-base-properties.const.js +1 -0
  37. package/build/src/_models/data-models/fam-entry.data-model.js +6 -0
  38. package/build/src/_models/data-models/fam-ingest-run.data-model.js +3 -1
  39. package/build/src/_models/data-models/fam-reference.data-model.js +7 -0
  40. package/build/src/_modules/capture/_collections/fam-capture.const.js +11 -0
  41. package/build/src/_modules/capture/_services/fam-auto-capture.control-service.js +87 -0
  42. package/build/src/_modules/capture/index.js +8 -0
  43. package/build/src/_modules/embedding/_collections/fam-embedding-prefix.util.js +77 -0
  44. package/build/src/_modules/embedding/_services/fam-duplicate-scan.control-service.js +202 -0
  45. package/build/src/_modules/embedding/_services/fam-embedding-pipeline.control-service.js +33 -9
  46. package/build/src/_modules/embedding/_services/fam-embedding.control-service.js +21 -2
  47. package/build/src/_modules/embedding/_services/fam-entry.data-service.js +135 -0
  48. package/build/src/_modules/embedding/_services/fam-vector-search.control-service.js +42 -32
  49. package/build/src/_modules/embedding/index.js +4 -1
  50. package/build/src/_modules/export/_collections/fam-export.const.js +22 -0
  51. package/build/src/_modules/export/_services/fam-export.control-service.js +64 -0
  52. package/build/src/_modules/export/index.js +8 -0
  53. package/build/src/_modules/ingest/_collections/fam-famignore.util.js +83 -0
  54. package/build/src/_modules/ingest/_collections/fam-file-routing.util.js +59 -48
  55. package/build/src/_modules/ingest/_collections/fam-project-identity.util.js +134 -0
  56. package/build/src/_modules/ingest/_collections/fam-scan-progress.util.js +57 -0
  57. package/build/src/_modules/ingest/_collections/fam-scan-summary.util.js +60 -0
  58. package/build/src/_modules/ingest/_collections/fam-scan-weight.util.js +53 -0
  59. package/build/src/_modules/ingest/_collections/fam-secret-exclude.util.js +37 -14
  60. package/build/src/_modules/ingest/_collections/fam-sliding-chunker.util.js +34 -0
  61. package/build/src/_modules/ingest/_collections/fam-ts-chunker.util.js +200 -14
  62. package/build/src/_modules/ingest/_services/fam-delta-compare.util.js +4 -1
  63. package/build/src/_modules/ingest/_services/fam-ingest-run.data-service.js +7 -4
  64. package/build/src/_modules/ingest/_services/fam-ingest.control-service.js +346 -17
  65. package/build/src/_modules/ingest/_services/fam-scan.control-service.js +25 -2
  66. package/build/src/_modules/ingest/index.js +3 -1
  67. package/build/src/_modules/mcp/_collections/fam-active-rules.util.js +56 -0
  68. package/build/src/_modules/mcp/_collections/fam-core-tools.const.js +47 -6
  69. package/build/src/_modules/mcp/_services/fam-capabilities-tool.service.js +4 -4
  70. package/build/src/_modules/mcp/_services/fam-capability-registry.service.js +224 -18
  71. package/build/src/_modules/mcp/_services/fam-mcp-adapter.service.js +4 -4
  72. package/build/src/_modules/mcp/_services/fam-mcp-server.service.js +4 -4
  73. package/build/src/_modules/mcp/_services/fam-read-tool.service.js +53 -1
  74. package/build/src/_modules/mcp/_services/fam-write-tool.service.js +104 -8
  75. package/build/src/_modules/mcp/index.js +4 -4
  76. package/build/src/_modules/migration/_collections/fam-claude-mem-normalize.util.js +66 -3
  77. package/build/src/_modules/migration/_collections/fam-prompt-aggregate.util.js +143 -0
  78. package/build/src/_modules/migration/_collections/fam-target-mapping.util.js +19 -0
  79. package/build/src/_modules/migration/_enums/fam-claude-mem-source.type-enum.js +6 -0
  80. package/build/src/_modules/migration/_models/interfaces/fam-claude-mem.interface.js +5 -0
  81. package/build/src/_modules/migration/_services/fam-agent-memory-reader.service.js +125 -0
  82. package/build/src/_modules/migration/_services/fam-claude-mem-import.control-service.js +101 -18
  83. package/build/src/_modules/migration/_services/fam-import-dedup.data-service.js +53 -0
  84. package/build/src/_modules/migration/index.js +3 -1
  85. package/build/src/_modules/retrieval/_services/fam-retrieval-candidate.data-service.js +78 -4
  86. package/build/src/_modules/retrieval/_services/fam-retrieval.control-service.js +293 -50
  87. package/build/src/_modules/scope-reference/_collections/fam-scope-normalize.util.js +6 -3
  88. package/build/src/_modules/scope-reference/_services/fam-reference.data-service.js +18 -0
  89. package/build/src/_modules/scope-reference/_services/fam-scope-resolver.control-service.js +79 -20
  90. package/build/src/_routes/server/api/api.controller.js +34 -2
  91. package/build/src/_routes/server/client-app/client-app.control-service.js +1 -1
  92. package/build/src/_routes/server/server-status/server-status.controller.js +2 -1
  93. package/build/src/app.server.js +13 -1
  94. package/build/src/environments/environment.js +1 -1
  95. package/build/src/index.js +1 -1
  96. package/client-dist/{chunk-GHKRM4SM.js → chunk-I77GXVAQ.js} +1 -1
  97. package/client-dist/{chunk-LMTL7GA3.js → chunk-YXHWCJ5O.js} +1 -1
  98. package/client-dist/index.html +1 -1
  99. package/client-dist/{main-2KWB3QYK.js → main-PJPEDVJT.js} +1 -1
  100. package/package.json +6 -5
@@ -5,9 +5,11 @@ exports.FAM_TsChunker_Util = void 0;
5
5
  * `FAM_TsChunker_Util` (SP-4.2, dsgn-004 §3.1, **BFR-AM-005 workaround**) — TypeScript-szemantikus
6
6
  * chunker `.ts/.tsx/.mts/.js/.jsx`-re. A CCAP `PS_TypeScriptChunker_Util` regex/brace-depth
7
7
  * megközelítésének projekt-lokális portja: import-csoport → top-level deklarációk (class/interface/
8
- * enum/type/function/const-export) → osztály-blokk (a metódus-bontás brace-depth-fel a nagy-blokk
9
- * ágon történik) JSDoc + `@Decorator` a következő kód-chunkkal együtt nagy blokk soronkénti
10
- * sliding-window-ra bomlik. A méret-konstansok a config-ból (`chunk.ts.*`), default `1500/100/50`.
8
+ * enum/type/function/const-export) → JSDoc + `@Decorator` a következő kód-chunkkal együtt. A max-size
9
+ * FELETTI blokk darabolása: **class metódus-tudatos** (a class-body member-határai mentén; minden adekvát
10
+ * metódus a saját chunkja `['class:Foo','method:bar']` symbol-lánccal + `chunkType:'method'`, a class-fej +
11
+ * mezők egy `'class'` chunk), **egyéb nagy blokk** (hosszú függvény/interface/enum) → soronkénti
12
+ * sliding-window (örökölt chunkType + symbol-lánc). A méret-konstansok a config-ból (`chunk.ts.*`), default `1500/100/50`.
11
13
  *
12
14
  * **BFR-AM-005 (dsgn-004 §3.1 megjegyzés):** a regex/brace-depth téved string-literálban lévő `{`/`}`
13
15
  * vagy template-literál esetén — a `countBraces` konzervatívan kihagyja a string-/line-comment-
@@ -27,6 +29,8 @@ class FAM_TsChunker_Util {
27
29
  static TYPE_ALIAS_START = /^(?:export\s+)?type\s+(\w+)\s*=/;
28
30
  static STANDALONE_FUNCTION = /^(?:export\s+)?(?:default\s+)?(?:async\s+)?function\s+(\w+)/;
29
31
  static CONST_EXPORT = /^(?:export\s+)?const\s+(\w+)/;
32
+ /** Class-member-signature → metódus-név (modifierek után `név(`); getter/setter/constructor is). */
33
+ static METHOD_SIG = /^(?:public|private|protected|static|async|readonly|abstract|override|get|set|\s)*\*?\s*([\w$]+)\s*(?:<[^>]*>)?\s*\(/;
30
34
  static DECORATOR_LINE = /^\s*@\w+/;
31
35
  static JSDOC_OPEN = /^\s*\/\*\*/;
32
36
  static JSDOC_CLOSE = /\*\//;
@@ -271,40 +275,222 @@ class FAM_TsChunker_Util {
271
275
  }
272
276
  return depth;
273
277
  }
274
- /** Nagy blokk soronkénti sliding-window-ja (örökölt chunkType + symbol-`headingPath`). */
278
+ /**
279
+ * Nagy (max-size feletti) blokk darabolása. `class` (entityName-mel) → **metódus-tudatos** member-bontás
280
+ * (`splitClassByMembers`); egyéb nagy blokk (hosszú függvény/interface/enum) VAGY sikertelen class-parse →
281
+ * soronkénti sliding-window (`slidingWindowLines`).
282
+ */
275
283
  static splitLargeBlock(block, sizing, headingPath) {
284
+ if (block.blockType === 'class' && block.entityName) {
285
+ const classChunks = FAM_TsChunker_Util.splitClassByMembers(block, sizing, headingPath);
286
+ if (classChunks.length) {
287
+ return classChunks;
288
+ }
289
+ }
290
+ return FAM_TsChunker_Util.slidingWindowLines({
291
+ lines: block.lines, charStart: block.charStart, lineStart: block.lineStart,
292
+ sizing: sizing, headingPath: headingPath, chunkType: block.blockType,
293
+ });
294
+ }
295
+ /**
296
+ * Soronkénti sliding-window egy sor-tömbre (a nem-class nagy blokkok + a túl nagy egyetlen metódus
297
+ * fallbackja). Örökli a kapott `chunkType`-ot + `headingPath`-ot; a sub-chunkok a maxSize körül törnek,
298
+ * `overlap/80` sornyi átfedéssel lépnek.
299
+ *
300
+ * **FAM-REV-061:** minden ablak a SAJÁT abszolút `charStart`-ját kapja (a blokk-kezdet + az ablak első
301
+ * soráig tartó char-offset) — korábban MINDEN ablak `set.charStart`-ot kapott (a blokk kezdete), így a nagy
302
+ * blokk összes sub-chunkja azonos charStart-ra ütközött (a location-info „hányadik char/sor" félrevezetett).
303
+ */
304
+ static slidingWindowLines(set) {
276
305
  const chunks = [];
277
- const lines = block.lines;
278
- const overlapLines = Math.max(1, Math.floor(sizing.overlap / 80));
306
+ const lines = set.lines;
307
+ const overlapLines = Math.max(1, Math.floor(set.sizing.overlap / 80));
308
+ // Sor-kezdő char-offsetek a blokkon belül (a per-ablak abszolút charStart-hoz; +1 a `\n`-ért).
309
+ const lineCharOffset = [];
310
+ let acc = 0;
311
+ for (let i = 0; i < lines.length; i++) {
312
+ lineCharOffset[i] = acc;
313
+ acc += lines[i].length + 1;
314
+ }
279
315
  let startIdx = 0;
280
316
  while (startIdx < lines.length) {
281
317
  let currentText = '';
282
318
  let endIdx = startIdx;
283
319
  while (endIdx < lines.length) {
284
320
  const candidate = currentText + (currentText ? '\n' : '') + lines[endIdx];
285
- if (candidate.length > sizing.maxSize && currentText.length) {
321
+ if (candidate.length > set.sizing.maxSize && currentText.length) {
286
322
  break;
287
323
  }
288
324
  currentText = candidate;
289
325
  endIdx++;
290
326
  }
291
- if (currentText.trim().length >= sizing.minSize) {
327
+ if (currentText.trim().length >= set.sizing.minSize) {
328
+ const windowCharStart = set.charStart + (lineCharOffset[startIdx] ?? 0);
292
329
  chunks.push({
293
330
  content: currentText,
294
331
  position: {
295
- charStart: block.charStart,
296
- charEnd: block.charStart + currentText.length,
297
- lineStart: block.lineStart + startIdx,
298
- lineEnd: block.lineStart + endIdx - 1,
332
+ charStart: windowCharStart,
333
+ charEnd: windowCharStart + currentText.length,
334
+ lineStart: set.lineStart + startIdx,
335
+ lineEnd: set.lineStart + endIdx - 1,
299
336
  },
300
- chunkType: block.blockType,
301
- headingPath: headingPath,
337
+ chunkType: set.chunkType,
338
+ headingPath: set.headingPath,
302
339
  });
303
340
  }
304
341
  startIdx = Math.max(startIdx + 1, endIdx - overlapLines);
305
342
  }
306
343
  return chunks;
307
344
  }
345
+ /**
346
+ * Metódus-tudatos class-darabolás (FAM-REV-049): a class-body MEMBER-határait (brace-depth) követve a
347
+ * class-fejet + a metódusokat külön chunkokra bontja — minden adekvát (>= minSize) metódus a saját
348
+ * chunkja a beágyazott symbol-lánccal (`['class:Foo','method:bar']`, `chunkType:'method'`). A
349
+ * `parseClassUnits` 1-nél több unitot ad (class-fej + 1+ member) → `packClassUnits`; különben üres
350
+ * (a hívó soros slidingjára esik).
351
+ */
352
+ static splitClassByMembers(block, sizing, classHeadingPath) {
353
+ const units = FAM_TsChunker_Util.parseClassUnits(block);
354
+ if (units.length <= 1) {
355
+ return [];
356
+ }
357
+ return FAM_TsChunker_Util.packClassUnits(units, block, sizing, classHeadingPath);
358
+ }
359
+ /**
360
+ * A class-blokk member-egységekre bontása (FAM-REV-049): az első unit a class-FEJ (JSDoc + signature a
361
+ * body-nyitásig), majd a class-body memberei a brace-depth member-határai mentén (egy member zár, ha a
362
+ * body-szintre [depth 1] tér vissza, VAGY egy `;`-re végződő egy-soros field). Brace-depth (NEM AST).
363
+ */
364
+ static parseClassUnits(block) {
365
+ const lines = block.lines;
366
+ // (1) class-body nyitás: az első sor, ahol a kumulált brace-depth >= 1.
367
+ let depth = 0;
368
+ let openIdx = -1;
369
+ for (let i = 0; i < lines.length; i++) {
370
+ depth += FAM_TsChunker_Util.countBraces(lines[i]);
371
+ if (depth >= 1) {
372
+ openIdx = i;
373
+ break;
374
+ }
375
+ }
376
+ if (openIdx < 0) {
377
+ return [];
378
+ }
379
+ const units = [];
380
+ units.push({ lines: lines.slice(0, openIdx + 1), lineOffset: 0, isMethod: false });
381
+ // (2) a body memberei (depth 1-ről indulva).
382
+ let current = [];
383
+ let currentStart = openIdx + 1;
384
+ let bodyDepth = 1;
385
+ for (let i = openIdx + 1; i < lines.length; i++) {
386
+ const line = lines[i];
387
+ const before = bodyDepth;
388
+ bodyDepth += FAM_TsChunker_Util.countBraces(line);
389
+ if (bodyDepth <= 0) {
390
+ // class-záró `}` → a maradékot flush-öljük (a záró brace-sort nem külön chunkoljuk).
391
+ if (current.length) {
392
+ units.push(FAM_TsChunker_Util.makeMemberUnit(current, currentStart));
393
+ }
394
+ break;
395
+ }
396
+ if (!current.length) {
397
+ currentStart = i;
398
+ }
399
+ current.push(line);
400
+ const closedBackToBody = before > 1 && bodyDepth === 1; // braced member (metódus) lezárult
401
+ const oneLineField = before === 1 && bodyDepth === 1 && line.trim().endsWith(';');
402
+ if (closedBackToBody || oneLineField) {
403
+ units.push(FAM_TsChunker_Util.makeMemberUnit(current, currentStart));
404
+ current = [];
405
+ }
406
+ }
407
+ return units;
408
+ }
409
+ /** Egy member-sortömb → `FAM_ClassUnit` (a signature-sorból kinyert metódus-névvel). */
410
+ static makeMemberUnit(lines, lineOffset) {
411
+ const sigLine = lines.find((line) => {
412
+ const trimmed = line.trim();
413
+ return trimmed.length > 0
414
+ && !trimmed.startsWith('/*') && !trimmed.startsWith('*') && !trimmed.startsWith('//')
415
+ && !trimmed.startsWith('@');
416
+ }) ?? '';
417
+ const match = sigLine.trim().match(FAM_TsChunker_Util.METHOD_SIG);
418
+ const isMethod = !!match && sigLine.includes('(');
419
+ return { lines: lines, lineOffset: lineOffset, name: match ? match[1] : undefined, isMethod: isMethod };
420
+ }
421
+ /**
422
+ * A member-egységek chunkokra csomagolása (FAM-REV-049): minSize-ig akkumulál (semmi ne essen ki a
423
+ * zaj-szűrőn), maxSize előtt flush-öl; az adekvát egy-metódusú chunk `method:`-symbol-láncot + `'method'`
424
+ * típust kap, a többi (class-fej / field-csoport) a `'class'` típust + a class-symbol-láncot. A maxSize
425
+ * feletti egyetlen member soros sliding-window-ra bomlik (örökölt symbol-lánc).
426
+ */
427
+ static packClassUnits(units, block, sizing, classHeadingPath) {
428
+ // Sor-kezdő char-offsetek a class-blokkon belül (a pontos charStart-hoz).
429
+ const lineCharOffset = [];
430
+ let acc = 0;
431
+ for (let i = 0; i < block.lines.length; i++) {
432
+ lineCharOffset[i] = acc;
433
+ acc += block.lines[i].length + 1;
434
+ }
435
+ const chunks = [];
436
+ let group = [];
437
+ const groupText = () => group.map((unit) => unit.lines.join('\n')).join('\n');
438
+ const flush = () => {
439
+ if (!group.length) {
440
+ return;
441
+ }
442
+ const text = groupText();
443
+ if (text.trim().length) {
444
+ const first = group[0];
445
+ const last = group[group.length - 1];
446
+ const lastLineOffset = last.lineOffset + last.lines.length - 1;
447
+ const single = group.length === 1 && first.isMethod && !!first.name;
448
+ const baseChar = block.charStart + (lineCharOffset[first.lineOffset] ?? 0);
449
+ chunks.push({
450
+ content: text,
451
+ position: {
452
+ charStart: baseChar,
453
+ charEnd: baseChar + text.length,
454
+ lineStart: block.lineStart + first.lineOffset,
455
+ lineEnd: block.lineStart + lastLineOffset,
456
+ },
457
+ chunkType: single ? 'method' : 'class',
458
+ headingPath: single ? [...classHeadingPath, `method:${first.name}`] : classHeadingPath,
459
+ });
460
+ }
461
+ group = [];
462
+ };
463
+ for (const unit of units) {
464
+ const unitText = unit.lines.join('\n');
465
+ // Túl nagy egyetlen member → flush + soros sliding (örökölt method/class symbol-lánc).
466
+ if (unitText.length > sizing.maxSize) {
467
+ flush();
468
+ const headPath = unit.isMethod && unit.name
469
+ ? [...classHeadingPath, `method:${unit.name}`]
470
+ : classHeadingPath;
471
+ chunks.push(...FAM_TsChunker_Util.slidingWindowLines({
472
+ lines: unit.lines,
473
+ charStart: block.charStart + (lineCharOffset[unit.lineOffset] ?? 0),
474
+ lineStart: block.lineStart + unit.lineOffset,
475
+ sizing: sizing,
476
+ headingPath: headPath,
477
+ chunkType: unit.isMethod ? 'method' : 'class',
478
+ }));
479
+ continue;
480
+ }
481
+ // maxSize-túllépés a csoporttal → előbb flush.
482
+ if (group.length && (groupText().length + 1 + unitText.length) > sizing.maxSize) {
483
+ flush();
484
+ }
485
+ group.push(unit);
486
+ // Elérte a minSize-t → flush (az adekvát metódus így a SAJÁT chunkja marad).
487
+ if (groupText().trim().length >= sizing.minSize) {
488
+ flush();
489
+ }
490
+ }
491
+ flush();
492
+ return chunks;
493
+ }
308
494
  /** A symbol-`headingPath` egy blokkhoz (`['class:Foo']`); generic / névtelen → üres tömb. */
309
495
  static buildHeadingPath(block) {
310
496
  if (block.entityName && block.blockType !== 'generic' && block.blockType !== 'imports') {
@@ -51,7 +51,10 @@ class FAM_DeltaCompare_Util {
51
51
  }
52
52
  matchedIndices.add(chunk.chunkIndex);
53
53
  if (existingEntry.contentHash === contentHash) {
54
- items.push({ verdict: 'equal', chunk: chunk, existingId: existingEntry._id, contentHash: contentHash });
54
+ items.push({
55
+ verdict: 'equal', chunk: chunk, existingId: existingEntry._id, contentHash: contentHash,
56
+ existingEmbeddingStatus: existingEntry.embeddingStatus, // FAM-REV-066: a re-embed-if-not-completed-hez
57
+ });
55
58
  }
56
59
  else {
57
60
  items.push({ verdict: 'modified', chunk: chunk, existingId: existingEntry._id, contentHash: contentHash });
@@ -31,13 +31,16 @@ class FAM_IngestRun_DataService extends nts_dynamo_1.DyNTS_DataService {
31
31
  return new nts_dynamo_1.DyNTS_ArchiveDataService(new fam_ingest_run_data_model_1.FAM_IngestRun_DataModel(), this.dataParams, this.issuer);
32
32
  }
33
33
  /**
34
- * A run megnyitása a scan ELEJÉN (dsgn-004 §5). A `_id` = a hívó által generált runId (UUID v4),
35
- * hogy a chunkok az `ingestRunId`-vel HIVATKOZHASSANAK MÉG a run-zárás előtt. Friss `saveData`
36
- * (új rekord nincs Mixed-mutáció). A számlálók/verdiktek a `close`-ban frissülnek.
34
+ * A run megnyitása a scan ELEJÉN (dsgn-004 §5). A `_id`-t a Dynamo `saveData` GENERÁLJA (Mongo
35
+ * ObjectId, stringként) a `FAM_Scope` mintáját követve (`findOrCreateScope`). **NEM** állítunk
36
+ * client-generált UUID `_id`-t: a Dynamo db-rétege a get-by-id-t `findById`-dal végzi, ami a `_id`-t
37
+ * ObjectId-ra cast-olja → egy UUID-string cast-ja elhasal (`DyNTS-DBS-GI0`). A hívó a VISSZAADOTT
38
+ * rekord `_id`-jét használja runId-ként (a chunkok ezzel az `ingestRunId`-vel hivatkoznak rá MÉG a
39
+ * run-zárás előtt). Friss `saveData` (új rekord — nincs Mixed-mutáció); a számlálók/verdiktek a
40
+ * `close`-ban frissülnek.
37
41
  */
38
42
  async open(set) {
39
43
  const record = new fam_ingest_run_data_model_1.FAM_IngestRun_DataModel({
40
- _id: set.runId,
41
44
  trigger: set.trigger,
42
45
  table: set.table,
43
46
  scopePath: set.scopePath,