dsh-prime-memory 0.26.28 → 0.26.30

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/CHANGELOG.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # 更新日志(Changelog)
2
2
 
3
+ ## [0.26.30] — 2026-11-03
4
+
5
+ - **#22 机理刀三层防线 + 同会话批内去重 + DRSC 提示 + 锁文件修复**
6
+
7
+ > #22 机理刀:前几版只修了 token 护栏的**截断面**(把进模型的 token 压到 1536),机理本体未动——相邻两次大推理的 T² 张量在 BFCArena 高水位不回落时**共存叠加**(m=2),且崩一次就停摆到宿主重启。本版把防线从「只截」扩成**三层**:① token 帽 1536(既有)② 关 memPattern 压低共存峰(新)③ 崩溃有界自愈 respawn(新,默认开可关)。**诚实边界**:三层都在 Windows/纯 node 侧证峰值/状态机/续试;SIGTRAP 的消除只能由报告人在 macOS 回验裁决,#22 是否关闭取决于那次回验。
8
+
9
+ - **第二层:`resources/embedding-child.cjs` / `embedding-worker.cjs` 的 pipeline 加 `session_options:{enableMemPattern:false}`**。ORT 默认按图形预分配、把输入绑定驻留 BFCArena,连发时新旧 T² 张量共存把峰值叠成 m×T²;关掉后同形状连发峰值本机实测 **1597MB→1264MB(−333MB,m:2→1 方向)**、稳态 infer 零代价。关键——**同输入改前/改后向量 bit 级全同**(真 bge-m3 `--equivalence` 实测 `maxAbsDiff=0`,短文本+致死长文本两样本),所以**不触发重嵌**(库里向量不失效)。边界:对 macOS 分配器 trap 的消除效果本机不可证,**不得据此宣称「不再崩」**;决定性实验是报告人用 `scripts/repro` 在 macOS 重跑 `--budget 2048` 连发看是否仍 trap。
10
+ - **第三层:崩溃有界自愈 respawn(`src/store/local-embedding.ts`)。⚠ 有意翻转 `0.26.25` 公告的「本刀声明不做自愈」**——那是当时边界,本轮把 bound 面逐条补齐后开。默认**开**,新键 `embedding.respawnOnCrash`(`.boolean().default(true)`,只增不改键)可关回旧语义(崩一次停摆到重启)。做法:通道工厂化(`createChannel`)→ `crashCb` 为**唯一** respawn 发起点(消 warmup/embed/reindex 三入口的 fork 风暴,`respawnPromise` 单点合流)→ 复用 `loading` 态(**不加新契约态**,`contract.ts` 不动,现有 vectorsReady 门天然接管半成品窗口)→ 重建通道 + await warmup。**速率上限 60s 窗内 ≤2 次**,超限回 `failed`(旧终局)。
11
+ - **崩批断点续试(协议加 `ack`,只增不改)**:子进程对多条目批逐条实时上报 `embedProgress{cid,done}`,父侧记断点位;子进程被硬杀时最后的 `done` 就是重试切片位,`texts.slice(ack)` **仅续一次**,再败走既有 reject。**诚实边界(表述红线之二)**:头段 `ack` 条的向量随崩溃子进程一起丢失、本批不返回(返回位为空洞,交后台 backfill 逐条补)——所以自愈**不保证不丢向量**,只把「重做面」从整批压到尾部未完段,且毒输入最多吃 2 批不成活锁(`l1.ts` 重嵌腿已加 `undefined` 守卫,把空洞当「本轮未取到」跳过)。
12
+ - **第一层口径留痕(还 `0.26.25/27` 欠下的「无声混叠」债最小形态)**:生效 `tokenBudget` 写入 `embedding_meta` 新键 `embedding_token_budget`(`MemoryDb.recordEmbeddingTokenBudget`,**只记录不比对、不进 providerInfo drop 判据**——调档不重嵌,1536 仍是**实测经验值、不是证明**)。`index.ts` 在 db.init 后落一次。
13
+ - **worker 逃生门通道**同法接入(`RealWorkerChannel` 进度也按 cid、`lastProgressFor` 对齐),既有 worker 用例零回归。`smoke` 补三条产物/配置断言(child 含 memPattern、local-embedding 含 respawn 代码、`Config.embedding.respawnOnCrash` 默认 true)。
14
+ - **复现件收编 `scripts/repro/`(报告人 gist 三件,不进 `tests/`)**:`embedding-repeat-crash.repro.mjs`(独立 CLI,`--budget` 从 `dist` 读 `HARD_CAP_TOKENS` 不写死)、`embedding-repeat-crash.test.ts`(vitest 包装,三重门 darwin+开关+本机模型/宿主)、`README.md`。理由:CI 只 ubuntu-latest、三重门恒跳=负债件;macOS 每次崩会记 `.ips` 并弹「意外退出」污染维护者机器。跨平台可证的崩溃状态机走 `tests/embedding-respawn.test.ts`(SIGKILL 代替 SIGTRAP)。
15
+ - **L1 批内自去重(同轮/同会话)——修掉「同会话内容撑在一起再让 LLM 合并」的笨办法**:实测根因是候选池**只来自库**(`store.searchCandidates`),同批 `extracted[]` 之间从不互比,于是同一段对话抽出的多条碎片全进同一条 ≤20 条的 LLM 去重 prompt,只能由模型产出 `merged_content` 把内容拼成一条。现新增 `src/pipeline/intra-dedupe.ts`(纯函数):归一(trim/NFKC/空白折叠/去零宽)→ 精确合并 → **同 family+同 type** 内按余弦 ≥τ 贪心聚类;代表项正文原样保留(所以它的向量可直接复用),被吸收项的 `timestamps`/`source_message_ids` 取并集、`priority` 取最大。新键(只增不改键):`extract.intraBatchDedupe`(默认 `true`)、`extract.intraBatchCosine`(0.85–0.99,默认 0.92,越界 clamp+warn——不卡窄区间到配置树)。日志一行 `raw→exact→vector→effective`。**收益边界(诚实)**:只减**条数与总时长**,对 #22 的单次推理峰值 O(T²) 无任何降低。
16
+ - **同一条记忆不再嵌两次**:去重期 `searchCandidates` 已算过查询向量,写侧 `appendNew` 又 `helper.batch` 一遍。现 `appendNew(records,{vectors})` / `upsert(record,{vector})` 命中即复用(merge 产出的**新正文**仍实嵌,长度不匹配整批回落实嵌)。`searchCandidates` 增可选 `queryVector`,不再内部重嵌。实测(记账型 embed 注入):3 条新记忆只复用 2 条时**只触发一次单条嵌入**。
17
+ - **DRSC 依赖提示到位(设置面板 banner)**:`dsh.pluginDependencies` 在运行时不产生任何行为(宿主 boot 层 0 处引用),记忆插件只是 collector 的消费者、无权挂载它——于是「只开了记忆」的部署里蒸馏背景窗与跨会话检索**静默为空**且无任何提示。现新增探针 `probeDrscHealth()`(五态 ok/missing/not-running/stale/unknown;**不经 `moduleOf`、不写 `facadeMisses`**、复用 `storeHandle`,否则会污染读路径或每 60s 重开 185MB 库)→ 端点 `dsh-memory/drsc-health`(白名单/计数器 66→67)→ `DrscHealthBanner`(`ok` 与首帧不渲染;四态文案 + 影响说明 + 可复制指引)。文案明写「**只开启记忆不会自动启用参考会话库**」与 desktop 只能手改 profile + `pnpm install` + 重启三步。
18
+ - **修掉发布链阻塞:`package-lock.json` 与 `package.json` 脱同步**。锁文件停在 `0.2.0-rc.1` 一代(最后更新 2026-10-22),而 devDeps 已到 `0.2.1-rc.3` → `npm ci` 直接 `ERESOLVE`,CI 与 `publish.yml`(二者都以 `npm ci` 起手)**连续多轮必红**;本地因复用既有 `node_modules` 而假绿。现重生成 lock(根 0.26.30、`@deepseek-ai/dsh-*`=`0.2.1-rc.3`、371 包)并验证 `npm ci --dry-run` 在仓库内与**隔离目录**(等价 CI checkout)均通过。
19
+ - **测试**:新增 `tests/embedding-respawn.test.ts` 7 例(真 fork 无模型 stub:kill→respawn→ready→下一条成功、ack 断点续试一次、毒输入≤2 批不活锁、60s 速率上限超限转 failed、禁 respawn 变异对照、close 后 terminated 不复用、崩溃归因含 signal);`embedding-token-guard.test.ts` +2 例(两条通道 memPattern session_options 哨兵、respawnOnCrash 默认开可关);`memory-db.test.ts` +1 例(预算留痕写读且正交于重嵌判定);`intra-dedupe.test.ts` 14 例(归一/精确层/向量层/tau 边界/跨族跨类不合并/缺向量直通/关闭透传/嵌入失败降级);`l1-vector-reuse.test.ts` 5 例(复用位不嵌、未命中位实嵌、长度不匹配回退、upsert 复用、merge 新正文实嵌);`drsc-health.test.ts` 7 例(五态 + 句柄复用 + 门面抛错不误报)。全量 **1974 例 / 195 文件**全绿;typecheck 0、lint 0 error、build/build:smoke/smoke/verify-catalog 均 0。配置面**只增键不改键**(`embedding.respawnOnCrash` / `extract.intraBatchDedupe` / `extract.intraBatchCosine`)。对外表述红线三条:不写「消除崩溃」、不写「自愈不丢向量」、不写「批内去重降内存峰值」;1536 保持「经验值非证明」。
20
+
21
+ ## [0.26.29] — 2026-11-02
22
+
23
+ > #22 报告人(DESXIE)回验 `0.26.28`:**自动档预算 = 1536、`5×5000` 串行全过**,且用同脚本换 `--budget 2048` 作对照组仍在第 2 条 SIGTRAP——说明“全过”不是环境变了,是 1536 真拦住了。同时他拓出一个真 bug。
24
+
25
+ - **修:`tokensMax=未知` 在真实链路上根本到不了**(报告人实测发现)。子进程侧 `tokensMax` **初值是 0**,而累加用严格大于(`if (cut.seq > tokensMax)`),所以永远量不出 seq 的情形(tokenizer 不可达、预算为 0、护栏被关)得到的 `-1` **永远赢不了 0**;而主线程 `>= 0` 判据会把残留的 0 当有效值印出来——正好印成这行日志本想避免的「一条也没进」。现初值改为 `-1`,“不可证”与“真的零”不再撞同一取值。一行修复,但它使能了整条取证链:`tokensMax` 仅在“护栏被关/tokenizer 不可达”这种最需要告警的时刻才有价值,之前那时它说谎。
26
+ - **为什么没被自己的测试抓到**(比修复本身更值得记):`describeEmbedBatch(…, -1, …)` 的用例只测了**纯函数收到 -1 时印什么**,从来没测**子进程会不会送来 -1**。现已补 3 例:① 哨兵钉死子进程侧初值必须为 -1(结构改动时会提示同步);② 复现归并语义本身(初值 0 吃掉了不可证、初值 -1 不会,且任一有效值仍能抬高);③ 端到端走真 `shrinkToBudget`(预算 0 时)→ `-1` → 印「未知」。已反向验证:把初值改回 0,哨兵即转红。
27
+ - **报告人的其他三项标注(无需改动,但记下来防重复讨论)**:`code/signal` 归因与「停摆 warn + 带 record id 的失败日志」与 `0.26.25` 逐字相同,属**既有实现而非本批新增**(他说得对,我之前的行文容易让人误读成每版新修);`tokensMax` 独立复核与自报值一致(1535/2047 两档均双路吻合),护栏真截了。
28
+ - **采纳他的口径澄清**:`graph` 投影那串「连发」是**连续多次单条 `priority` 请求**(所以日志里 `n` 常见为 1),真正成批多条的只有 reindex(`CHUNK=16`);这不影响护栏结论,但读 `tokensMax` 时应知道 `n` 的含义。机理本身仍未动(1536 是实测经验值,不是证明)。
29
+ - 全量 **1938 例 / 191 文件**全绿(+3);typecheck 0、lint 0 error、build/build:smoke/smoke/verify-catalog 均 0。公开配置面无变更。
30
+
3
31
  ## [0.26.28] — 2026-11-02
4
32
 
5
33
  > 本版只修一个错:**我在 `0.26.26`/`0.26.27` 的 CHANGELOG 与 issue 留言里说「子进程上报本批实测进模型的最大 token 数」,但那个值从来没进过日志**。它只被本地验证脚本的探针读到,插件自己的 `memory.log` 里一行都没有——而 #22 这类问题事后能核的只有日志。计划本身是要求这一行落盘的(每批 info 记 `n / 最大tokens / inferMs`,fork 时记 `pid`),是我执行时漏了两项。
package/README.de.md CHANGED
@@ -301,6 +301,7 @@ Drei Embedding-Quellen: **aus** (Standard, reine BM25-Schlüsselwortsuche), **re
301
301
  | `extract.idleSeconds` | `300` | Inaktivitäts-Auffangnetz: nach N Sekunden Stille der Sitzung werden undestillierte Scheiben verbucht (fängt „Nutzer ging vor Erreichen des Schwellwerts"); `0` deaktiviert |
302
302
  | `extract.backgroundMessages` | `10` | Zahl der Kontextnachrichten, die der Extraktion beiliegen (je Sitzung frisch aus L0 erfragt, keine Verschmutzung zwischen Sitzungen) |
303
303
  | `extract.candidatePool` | `5` | Größe des Dedupe-Kandidatenpools |
304
+ | `extract.intraBatchDedupe` | `true` | Dedupe innerhalb eines Batches (gleiche Runde/Session): Normalisierung + Vektor-Clustering (gleiche Familie/Typ) vor dem LLM-Dedupe, damit Fragmente derselben Konversation nicht zu einem langen Eintrag verschmolzen werden (senkt nur Anzahl und Laufzeit, nicht den Peak pro Inferenz) |
304
305
  | `l2.enabled` | `true` | L2-Szenenkonsolidierung |
305
306
  | `l2.minNewMemories` | `5` | Schwellwert neuer Erinnerungen seit der letzten L2-Konsolidierung |
306
307
  | `l2.maxScenes` | `12` | Obergrenze der Szenenblöcke |
@@ -324,6 +325,7 @@ Drei Embedding-Quellen: **aus** (Standard, reine BM25-Schlüsselwortsuche), **re
324
325
  | `embedding.dimensions` | `0` | Vektordimension (bei Aktivierung Pflicht, muss zur Modellausgabe passen) |
325
326
  | `embedding.maxInputChars` | `5000` | Maximale Zeichen je Text (bei Überlänge abgeschnitten) |
326
327
  | `embedding.maxInputTokens` | `0` | **Token**-Budget pro Text für lokale Einbettung: `0` (Standard) = min(Modellfenster, harte Grenze 1536); >0 = explizit, bei Überschreitung geklemmt inkl. warn. Andere Rolle als die Zeile oben – das Zeichenlimit betrifft nur Remote-Modus & IPC-Größe, die lokale Absturz-/Speichergrenze muss in Tokens stehen (#22) |
328
+ | `embedding.respawnOnCrash` | `true` | Ob der lokale Einbettungs-Kindprozess nach hartem Abschuss **begrenzt selbst heilt** (#22): Standard an – Re-fork + Re-warm ≤2× pro 60s-Fenster, Stapel setzen einmal am Live-Checkpoint wieder an (die mit dem abgestürzten Kind verlorenen Kopf-Vektoren holt das Backfill nach); aus = altes Verhalten (ein Absturz stoppt bis Host-Neustart / Quellenwechsel). Bewusste Umkehr der 0.26.25-Ankündigung „kein Self-Healing“. Drei Schichten = Grenzwall(1536)/Peak-Senkung(memPattern)/Selbstheilung(respawn). |
327
329
  | `embedding.timeoutMs` | `10000` | Timeout eines einzelnen Embedding-Aufrufs (ms) |
328
330
  | `embedding.allowLocalModels` | `true` | Lokale Embedding-Stufe erlauben (Deployment-Obergrenze: ausgeschaltet kann die Einstellungsseite keine Modelle laden und nicht auf Lokal schalten) |
329
331
  | `embedding.mirror` | `https://hf-mirror.com` | Wurzeladresse des Download-Spiegels für lokale Modelle (zurücksetzbar auf das offizielle `https://huggingface.co`) |
package/README.en.md CHANGED
@@ -308,6 +308,7 @@ the bundle layer appends and causes `duplicate loader entry id` startup failure)
308
308
  | `extract.idleSeconds` | `300` | Idle flush: distill a session's pending slice after N seconds of silence (catches "user left before reaching the threshold"); `0` disables |
309
309
  | `extract.backgroundMessages` | `10` | Background messages attached to extraction (fetched per session from L0 — no cross-session contamination) |
310
310
  | `extract.candidatePool` | `5` | Dedup candidate pool size |
311
+ | `extract.intraBatchDedupe` | `true` | Intra-batch dedupe (same round/session): normalise + cluster by vector within the same family/type before the LLM dedup call, so one conversation's fragments are not merged into a single long memory (cuts count and runtime only, not the per-inference peak) |
311
312
  | `l2.enabled` | `true` | L2 scene consolidation |
312
313
  | `l2.minNewMemories` | `5` | New-memory threshold since last L2 consolidation |
313
314
  | `l2.maxScenes` | `12` | Scene block count cap |
@@ -331,6 +332,7 @@ the bundle layer appends and causes `duplicate loader entry id` startup failure)
331
332
  | `embedding.dimensions` | `0` | Vector dimensions (required when enabled; must match model output) |
332
333
  | `embedding.maxInputChars` | `5000` | Max characters per text (overlong inputs truncated) |
333
334
  | `embedding.maxInputTokens` | `0` | Per-text **token** budget for local embedding: `0` (default) = min(model window, hard cap 1536); >0 = explicit, clamped with a warn above the cap. Not the same guard as the row above — the character cap only bounds the remote tier and IPC size, while local crash/memory limits must be in tokens (#22) |
335
+ | `embedding.respawnOnCrash` | `true` | Whether the local-embedding child **self-heals (bounded)** after being hard-killed (#22): default on — re-fork + re-warm ≤2× per 60s window, multi-item batches resume once from the live checkpoint (the head vectors lost with the crashed child are recovered by background backfill); off returns to the old behavior (one crash stalls until host restart / source switch). Intentionally reverses the 0.26.25 "no self-heal" note. Three-layer defense = guardrail(1536) / peak-reduction(memPattern) / self-heal(respawn). |
334
336
  | `embedding.timeoutMs` | `10000` | Per-call embedding timeout (ms) |
335
337
  | `embedding.allowLocalModels` | `true` | Allow the local embedding tier (deployment ceiling; when off, no model downloads and no local tier in settings) |
336
338
  | `embedding.mirror` | `https://hf-mirror.com` | Download mirror root for local models (can be changed back to `https://huggingface.co`) |
package/README.es.md CHANGED
@@ -302,6 +302,7 @@ Los ajustes que pisan los valores por defecto se escriben en el `cordis.patch.ym
302
302
  | `extract.idleSeconds` | `300` | Red de seguridad por inactividad: tras N segundos de silencio de la sesión las rebanadas sin destilar se sacan del bache (atrapa el caso «se fue sin llegar al umbral»); `0` lo desactiva |
303
303
  | `extract.backgroundMessages` | `10` | Número de mensajes de contexto adjuntos a la extracción (consultados al vuelo en L0 por la sesión, sin contaminación entre sesiones) |
304
304
  | `extract.candidatePool` | `5` | Tamaño del vaso de candidatos de deduplicación |
305
+ | `extract.intraBatchDedupe` | `true` | Deduplicación intra-lote (misma ronda/sesión): normaliza + agrupa por vectores (misma familia/tipo) antes del dedupe LLM, para que los fragmentos de una conversación no se fusionen en una sola memoria larga (solo reduce número y tiempo, no el pico por inferencia) |
305
306
  | `l2.enabled` | `true` | Consolidación de escenas L2 |
306
307
  | `l2.minNewMemories` | `5` | Umbral de memorias nuevas desde la última consolidación L2 |
307
308
  | `l2.maxScenes` | `12` | Límite superior de bloques de escena |
@@ -325,6 +326,7 @@ Los ajustes que pisan los valores por defecto se escriben en el `cordis.patch.ym
325
326
  | `embedding.dimensions` | `0` | Dimensión de los vectores (obligatoria si está activada, debe coincidir con la salida del modelo) |
326
327
  | `embedding.maxInputChars` | `5000` | Número máximo de caracteres por texto (recorte si se supera) |
327
328
  | `embedding.maxInputTokens` | `0` | Presupuesto de **tokens** por texto para la incrustación local: `0` (pred.) = min(ventana del modelo, límite 1536); >0 = explícito, recortado con warn si excede. No es el mismo límite que la fila de arriba: el de caracteres solo cubre el modo remoto y el tamaño de IPC, y la protección local contra fallos/memoria debe ir en tokens (#22) |
329
+ | `embedding.respawnOnCrash` | `true` | Si el subproceso de incrustación local se **autorrepara de forma acotada** tras un fallo brusco (#22): pred. activado — re-fork + recalentado ≤2 veces por ventana de 60s, los lotes reanudan una vez desde el punto de control en vivo (los vectores de cabecera perdidos con el hijo caído los recupera el backfill); desactivado = comportamiento anterior (un fallo detiene hasta reinicio del host / cambio de fuente). Revoca deliberadamente el aviso 0.26.25 de «sin autorreparación». Tres capas = vallado(1536) / reducción de pico(memPattern) / autorreparación(respawn). |
328
330
  | `embedding.timeoutMs` | `10000` | Tiempo máximo de una llamada de embeddings (ms) |
329
331
  | `embedding.allowLocalModels` | `true` | Permite el modo de embeddings local (techo de despliegue: desactivado, la página de ajustes no puede descargar modelos ni pasar a local) |
330
332
  | `embedding.mirror` | `https://hf-mirror.com` | Raíz del espejo de descarga de modelos locales (se puede devolver al oficial `https://huggingface.co`) |
package/README.fr.md CHANGED
@@ -300,6 +300,7 @@ Les réglages par-dessus les valeurs par défaut s'écrivent dans le `cordis.pat
300
300
  | `extract.idleSeconds` | `300` | Filet d'inactivité : après N secondes de silence de la session, enregistre les tranches non distillées (rattrape « l'utilisateur parti avant d'atteindre le seuil ») ; `0` désactive |
301
301
  | `extract.backgroundMessages` | `10` | Nombre de messages de contexte joints à l'extraction (interrogés à la volée dans L0 pour la session en question, sans contamination entre sessions) |
302
302
  | `extract.candidatePool` | `5` | Taille du bassin de candidats de déduplication |
303
+ | `extract.intraBatchDedupe` | `true` | Déduplication intra-lot (même tour/session) : normalisation + regroupement vectoriel (même famille/type) avant l'appel LLM, pour que les fragments d'une conversation ne soient pas fusionnés en une seule mémoire longue (réduit le nombre et la durée, pas le pic par inférence) |
303
304
  | `l2.enabled` | `true` | Consolidation de scènes L2 |
304
305
  | `l2.minNewMemories` | `5` | Seuil de nouvelles mémoires depuis la dernière consolidation L2 |
305
306
  | `l2.maxScenes` | `12` | Nombre maximal de blocs de scène |
@@ -323,6 +324,7 @@ Les réglages par-dessus les valeurs par défaut s'écrivent dans le `cordis.pat
323
324
  | `embedding.dimensions` | `0` | Dimension des vecteurs (obligatoire si activé, doit correspondre à la sortie du modèle) |
324
325
  | `embedding.maxInputChars` | `5000` | Nombre maximal de caractères par texte (troncature au-delà) |
325
326
  | `embedding.maxInputTokens` | `0` | Budget de **jetons** par texte pour l'intégration locale : `0` (défaut) = min(fenêtre du modèle, plafond 1536) ; >0 = explicite, réduit avec un warn s'il dépasse. Ce n'est pas la même limite que la ligne au-dessus : celle en caractères ne borne que le mode distant et la taille IPC, la protection locale doit être en jetons (#22) |
327
+ | `embedding.respawnOnCrash` | `true` | Si le sous-processus d'intégration locale **se réauto-répare de façon bornée** après un plantage brutal (#22) : défaut activé — re-fork + re-chauffe ≤2 fois par fenêtre de 60 s, les lots reprennent une fois depuis le point de contrôle en direct (les vecteurs d'en-tête perdus avec l'enfant tué sont rattrapés par le backfill) ; désactivé = comportement antérieur (un plantage bloque jusqu'au redémarrage / changement de source). Revoque délibérément la note 0.26.25 « pas d'auto-réparation ». Trois couches = garde-fou(1536) / baisse du pic(memPattern) / auto-réparation(respawn). |
326
328
  | `embedding.timeoutMs` | `10000` | Délai maximal d'un appel d'embedding (ms) |
327
329
  | `embedding.allowLocalModels` | `true` | Autorise le mode embedding local (plafond de déploiement : désactivé, la page de paramètres ne peut plus télécharger de modèles ni passer en local) |
328
330
  | `embedding.mirror` | `https://hf-mirror.com` | Racine du miroir de téléchargement des modèles locaux (ramenérable à l'officiel `https://huggingface.co`) |
package/README.it.md CHANGED
@@ -302,6 +302,7 @@ Le impostazioni che scavalcano i predefiniti si scrivono nel `cordis.patch.yml`
302
302
  | `extract.idleSeconds` | `300` | Rete d'inattività: dopo N secondi di silenzio della sessione le fette non distillate vengono incassate (recupera «l'utente andato via prima della soglia»); `0` disattiva |
303
303
  | `extract.backgroundMessages` | `10` | Numero di messaggi di contesto allegati all'estrazione (interrogati al volo da L0 per la sessione, senza contaminazione tra sessioni) |
304
304
  | `extract.candidatePool` | `5` | Dimensione del bacino di candidati della deduplica |
305
+ | `extract.intraBatchDedupe` | `true` | Deduplica intra-batch (stesso turno/sessione): normalizzazione + clustering vettoriale (stessa famiglia/tipo) prima della deduplica LLM, così i frammenti di una conversazione non vengono fusi in un'unica memoria lunga (riduce solo numero e durata, non il picco per inferenza) |
305
306
  | `l2.enabled` | `true` | Consolidamento delle scene L2 |
306
307
  | `l2.minNewMemories` | `5` | Soglia di nuove memorie dall'ultimo consolidamento L2 |
307
308
  | `l2.maxScenes` | `12` | Limite superiore di blocchi di scena |
@@ -325,6 +326,7 @@ Le impostazioni che scavalcano i predefiniti si scrivono nel `cordis.patch.yml`
325
326
  | `embedding.dimensions` | `0` | Dimensione dei vettori (obbligatoria se attiva, deve corrispondere all'output del modello) |
326
327
  | `embedding.maxInputChars` | `5000` | Numero massimo di caratteri per testo (troncamento oltre) |
327
328
  | `embedding.maxInputTokens` | `0` | Budget di **token** per testo per l'embedding locale: `0` (default) = min(finestra del modello, limite 1536); >0 = esplicito, ridotto con un warn se oltre il limite. Non è lo stesso limite della riga sopra: quello in caratteri copre solo modalità remota e dimensione IPC, la protezione locale contro cadute/memoria deve essere in token (#22) |
329
+ | `embedding.respawnOnCrash` | `true` | Se il processo figlio dell'embedding locale si **auto-ripara in modo limitato** dopo un arresto brusco (#22): default attivo — re-fork + ri-riscaldamento ≤2 volte per finestra da 60s, i lotti ripartono una volta dal checkpoint live (i vettori di testa persi col figlio ucciso li recupera il backfill); disattivo = comportamento precedente (un arresto blocca fino a riavvio host / cambio sorgente). Revoca deliberatamente la nota 0.26.25 "nessuna auto-riparazione". Tre strati = guard-rail(1536) / riduzione del picco(memPattern) / auto-riparazione(respawn). |
328
330
  | `embedding.timeoutMs` | `10000` | Timeout di una singola chiamata d'embedding (ms) |
329
331
  | `embedding.allowLocalModels` | `true` | Consente la modalità d'embedding locale (tetto di distribuzione: disattivata, la pagina impostazioni non può scaricare modelli né passare in locale) |
330
332
  | `embedding.mirror` | `https://hf-mirror.com` | Radice del mirror di scaricamento dei modelli locali (riportabile all'ufficiale `https://huggingface.co`) |
package/README.ja.md CHANGED
@@ -252,6 +252,7 @@ node bench/harness/retrieval-metrics.mjs <runDir> --flood 200,600
252
252
  | `extract.idleSeconds` | `300` | アイドル兜底:セッションが N 秒無言で未蒸留スライスを落とす。`0` で無効 |
253
253
  | `extract.backgroundMessages` | `10` | 抽出時付随の背景メッセージ数 |
254
254
  | `extract.candidatePool` | `5` | 重複排除候補プールサイズ |
255
+ | `extract.intraBatchDedupe` | `true` | バッチ内の重複排除(同一ラウンド/セッション):LLM 去重の前に正規化+同族・同型のベクトルクラスタリングを行い、同一会話の断片が1件の長い記憶に融合されるのを防ぐ(件数と所要時間を削減するだけで、推論ごとのピークは下げない) |
255
256
  | `l2.enabled` | `true` | L2 シナリオ統合 |
256
257
  | `l2.minNewMemories` | `5` | 前回 L2 からの新記憶閾値 |
257
258
  | `l2.maxScenes` | `12` | シナリオブロック数上限 |
@@ -275,6 +276,7 @@ node bench/harness/retrieval-metrics.mjs <runDir> --flood 200,600
275
276
  | `embedding.dimensions` | `0` | ベクトル次元(有効時必須) |
276
277
  | `embedding.maxInputChars` | `5000` | 単テキスト最大文字数(超長は切り捨て) |
277
278
  | `embedding.maxInputTokens` | `0` | ローカル埋め込みの 1 件あたり **トークン** 予算:`0`(既定)= モデル窓と上限 1536 の小さい方、>0 = 明示値(超過は clamp + warn)。上の行とは役割が異なる——文字上限はリモートモードと IPC サイズのみを制限し、ローカルのクラッシュ/メモリ防護はトークン単位が必須(#22) |
279
+ | `embedding.respawnOnCrash` | `true` | ローカル埋め込み子プロセスが強制殺された後**有界で自己回復**するか(#22):既定オン——60s ウィンドウ内 ≤2 回の再 fork+再ウォームアップ、複数項目バッチはライブ中間点から 1 回だけ再開(落ちた子と共になくなった先頭部ベクトルは backfill が補う);オフにすると旧挙動(一度クラッシュするとホスト再起動/ソース切替まで停止)。0.26.25 の「自己回復しない」告知を意図的に反転。三層=ガードレール(1536)/ピーク低減(memPattern)/自己回復(respawn)。 |
278
280
  | `embedding.timeoutMs` | `10000` | 単回埋め込み呼び出しタイムアウト(ms) |
279
281
  | `embedding.allowLocalModels` | `true` | ローカル埋め込み档を許可(デプロイ上限) |
280
282
  | `embedding.mirror` | `https://hf-mirror.com` | ローカルモデルダウンロードミラー根 |
package/README.ko.md CHANGED
@@ -252,6 +252,7 @@ node bench/harness/retrieval-metrics.mjs <runDir> --flood 200,600
252
252
  | `extract.idleSeconds` | `300` | 유휴兜底:세션이 N초 무음이면 미증류 슬라이스 투하. `0` 비활성 |
253
253
  | `extract.backgroundMessages` | `10` | 추출 시 수반하는 배경 메시지 수 |
254
254
  | `extract.candidatePool` | `5` | 중복 제거 후보 풀 크기 |
255
+ | `extract.intraBatchDedupe` | `true` | 배치 내 중복 제거(같은 라운드/세션): LLM 중복 제거 전에 정규화 + 동일 family/type 벡터 클러스터링으로, 같은 대화의 파편이 하나의 긴 기억으로 합쳐지는 것을 막음(개수와 소요 시간만 줄이고, 추론 1회당 피크는 낮추지 않음) |
255
256
  | `l2.enabled` | `true` | L2 장면 통합 |
256
257
  | `l2.minNewMemories` | `5` | 직전 L2 이후 신규 기억 임계값 |
257
258
  | `l2.maxScenes` | `12` | 장면 블록 수 상한 |
@@ -275,6 +276,7 @@ node bench/harness/retrieval-metrics.mjs <runDir> --flood 200,600
275
276
  | `embedding.dimensions` | `0` | 벡터 차원(활성 시 필수) |
276
277
  | `embedding.maxInputChars` | `5000` | 단텍스트 최대 문자 수(초장 잘림) |
277
278
  | `embedding.maxInputTokens` | `0` | 로컬 임베딩 1건당 **토큰** 예산: `0`(기본) = 모델 창과 상한 1536 중 작은 값, >0 = 명시값(초과 시 clamp + warn). 위 행과 역할이 다름 — 문자 상한은 원격 모드와 IPC 크기만 제한하고, 로컬 충돌/메모리 방지는 토큰 단위가 필수(#22) |
279
+ | `embedding.respawnOnCrash` | `true` | 로컬 임베딩 자식 프로세스가 강제 종료 후 **유한하게 자가 복구**하는지(#22): 기본 켜짐 — 60초 창 내 재 fork+재워밍 ≤2회, 다중 항목 배치는 라이브 지점에서 한 번만 재시도(죽은 자식과 함께 사라진 머리 벡터는 backfill가 보충); 끄면 기존 동작(한 번 충돌하면 호스트 재시작/소스 전환까지 정지). 0.26.25의 "자가 복구 없음" 공지를 의도적으로 뒤집음. 삼중 방어 = 가드레일(1536)/피크 감소(memPattern)/자가 복구(respawn). |
278
280
  | `embedding.timeoutMs` | `10000` | 단회 임베딩 호출 타임아웃(ms) |
279
281
  | `embedding.allowLocalModels` | `true` | 로컬 임베딩档 허용(배포 상한) |
280
282
  | `embedding.mirror` | `https://hf-mirror.com` | 로컬 모델 다운로드 미러 루트 |
package/README.md CHANGED
@@ -320,6 +320,7 @@ ONNX 量化 **CPU 推理**——无需 API Key,数据不出本机)。本地
320
320
  | `extract.idleSeconds` | `300` | 闲置兜底:会话静默 N 秒后把未蒸馏切片落袋(接住"没攒够阈值用户就离开");`0` 关闭 |
321
321
  | `extract.backgroundMessages` | `10` | 抽取时附带的背景消息条数(按会话从 L0 现查,会话间互不污染) |
322
322
  | `extract.candidatePool` | `5` | 去重候选池大小 |
323
+ | `extract.intraBatchDedupe` | `true` | 批内自去重(同轮/同会话):进 LLM 去重前先归一化 + 同族同类向量聚类,避免同会话碎片被合并成一条长记忆(只减条数与耗时,不降低单次推理峰值) |
323
324
  | `l2.enabled` | `true` | L2 场景整合 |
324
325
  | `l2.minNewMemories` | `5` | 距上次 L2 整合的新记忆阈值 |
325
326
  | `l2.maxScenes` | `12` | 场景块数量上限 |
@@ -343,6 +344,7 @@ ONNX 量化 **CPU 推理**——无需 API Key,数据不出本机)。本地
343
344
  | `embedding.dimensions` | `0` | 向量维度(启用时必填,须与模型输出一致) |
344
345
  | `embedding.maxInputChars` | `5000` | 单条文本最大字符数(超长截断) |
345
346
  | `embedding.maxInputTokens` | `0` | 本地嵌入的单条 **token** 预算:`0`(默认)= 按模型窗口与硬上限 1536 自动取小;>0 = 显式预算,超上限会被 clamp 并记 warn。与上一行不是同类护栏——字符帽只管远程档与 IPC 体积,本地推理的崩溃/内存护栏必须按 token(#22) |
347
+ | `embedding.respawnOnCrash` | `true` | 本地嵌入子进程被硬杀后是否**有界自愈**(#22 机理刀):默认开——60s 窗内 ≤2 次重 fork+重预热,多条目批按实时断点续试一次(头段向量丢失交 backfill 补);关掉回到旧语义(崩一次停摆到宿主重启/换源)。有意翻转 0.26.25「不做自愈」公告。三层防线=护栏(1536)/降峰(memPattern)/自愈(respawn)。 |
346
348
  | `embedding.timeoutMs` | `10000` | 单次 embedding 调用超时(ms) |
347
349
  | `embedding.allowLocalModels` | `true` | 允许本地嵌入档(部署上限:关闭后设置页不能下载模型、不能切本地档) |
348
350
  | `embedding.mirror` | `https://hf-mirror.com` | 本地模型下载镜像根地址(可改回官方 `https://huggingface.co`) |
package/README.ru.md CHANGED
@@ -302,6 +302,7 @@ node bench/harness/retrieval-metrics.mjs <runDir> --flood 200,600
302
302
  | `extract.idleSeconds` | `300` | Страховка по простою: после N секунд тишины сессии недистиллированные срезы записываются в дело (ловит случай «ушёл, не набрав порога»); `0` — выключено |
303
303
  | `extract.backgroundMessages` | `10` | Число фоновых сообщений, прилагаемых к извлечению (запрашиваются на лету из L0 по сессии, без загрязнения между сессиями) |
304
304
  | `extract.candidatePool` | `5` | Размер пула кандидатов дедупликации |
305
+ | `extract.intraBatchDedupe` | `true` | Дедупликация внутри батча (тот же раунд/сессия): нормализация + векторная кластеризация (та же семья/тип) перед LLM-дедупликацией, чтобы фрагменты одной беседы не сливались в одну длинную запись (сокращает только количество и время, но не пик на один вывод) |
305
306
  | `l2.enabled` | `true` | Консолидация сцен L2 |
306
307
  | `l2.minNewMemories` | `5` | Порог новых воспоминаний с последней консолидации L2 |
307
308
  | `l2.maxScenes` | `12` | Верхний предел числа блоков сцен |
@@ -325,6 +326,7 @@ node bench/harness/retrieval-metrics.mjs <runDir> --flood 200,600
325
326
  | `embedding.dimensions` | `0` | Размерность векторов (при включении обязательна, должна совпадать с выходом модели) |
326
327
  | `embedding.maxInputChars` | `5000` | Максимум символов на один текст (сверх — усечение) |
327
328
  | `embedding.maxInputTokens` | `0` | Бюджет **токенов** на один текст для локальных эмбеддингов: `0` (умолч.) = min(окно модели, жёсткий лимит 1536); >0 = явное значение, при превыщении усекается с warn. Это не тот же лимит, что строкой выше: символьный ограничивает только удалённый режим и размер IPC, а локальная защита от падений/памяти должна считаться в токенах (#22) |
329
+ | `embedding.respawnOnCrash` | `true` | Самоизлечивается ли дочерний процесс локальных эмбеддингов после жёсткого завершения **с ограничением** (#22): по умолчанию вкл — повторный fork + прогрев ≤2 раза за окно 60с, батчи один раз возобновляются от живой контрольной точки (головные векторы, потерянные вместе с убитым потомком, добирает backfill); выкл = прежнее поведение (один сбой блокирует до перезапуска хоста / смены источника). Намеренно отменяет заметку 0.26.25 «без самоизлечения». Три слоя = рубеж(1536) / снижение пика(memPattern) / самоизлечение(respawn). |
328
330
  | `embedding.timeoutMs` | `10000` | Таймаут одного вызова эмбеддинга (мс) |
329
331
  | `embedding.allowLocalModels` | `true` | Разрешить локальный режим эмбеддингов (потолок развёртывания: выключено — страница настроек не может скачивать модели и переключаться в локальный) |
330
332
  | `embedding.mirror` | `https://hf-mirror.com` | Корень зеркала загрузки локальных моделей (можно вернуть на официальный `https://huggingface.co`) |