@yottameta/yotta-memory 0.22.9 → 0.23.0
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 +8 -0
- package/SKILL.md +6 -5
- package/USER_GUIDE.md +4 -4
- package/bin/yotta-memory.js +129 -16
- package/package.json +1 -1
- package/skill-manifest.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
## v0.23.0 (2026-10-20)
|
|
2
|
+
- **上下文包 COMMIT 段保留策略(根治上下文包无预算膨胀)**:开工上下文包第 6 段默认只展示最近 20 条 COMMIT,`weight ≥ 1.5` 或带 `pinned` / `evergreen` 标签的条目不受上限影响、始终展示;其余折叠为一行提示(不删除,`recall --type COMMIT` 仍可检索)。新配置键 `context_commits_limit`(0 = 全部展示,回旧行为);BOUND 段保持全量(底线保证不变)。
|
|
3
|
+
- **归档门槛与效用地板对齐(根治「库只长不瘦」)**:`maintain_archived_utility` 默认 0.35 → **0.55**(记忆默认 `confidence=1.0`,效用分地板约 0.42~0.47,旧门槛永远打不到);按分类型半衰形成退役阶梯:COMMIT 约 6 个月 / PREF 约 13 个月 / FACT 约 17 个月(无再访问时,且需超 180 天龄;BOUND / immutable / pinned / evergreen 豁免不变)。`context` 的「归档提醒」升级为可执行:显示超龄条数与已达门槛条数,并给出 `maintain` 预览 / `--apply` 命令。
|
|
4
|
+
- **规模体检补强(防复发)**:新增「超长 statement(> 2000 字)」与「单类型堆积」两项指标(info / warn 两档,新配置键 `scale_info_long_statements` / `scale_warn_long_statements` / `scale_info_type_count` / `scale_warn_type_count`),随 `doctor` / `context` 可靠性提醒展示。
|
|
5
|
+
- **用法引导**:`remember` 写超长 COMMIT(> 1200 字)时提示精简与常显标签;SKILL / USER_GUIDE 补充收工锚点与保留策略说明。
|
|
6
|
+
- **候选修订(WorkBuddy 首轮验收缺陷修复)**:① COMMIT 段排序修复——此前按 `updated`(仅到「日」)排序,同日条目平局后退化为索引插入序,取到的是最旧 N 条(刚写入的承诺反而被折叠);现按 `created` 倒序 + 同日按文件名序号倒序(写入先后),折叠提示范围同步校正。② `reindex` / 静默校准修复——未加密库的私密条目此前被 owner-key 门槛整段跳过,索引损坏后「重建」反而清空、库对 AI 永久不可检索;现以磁盘为准全量重建(未加密库私密条目与公共条目同存主索引),加密库无授权 key 时输出明确跳过提示与可执行路径。
|
|
7
|
+
- 兼容性:显式设置过 `maintain_archived_utility` / `context_commits_limit` 的用户不受默认值变化影响;`context_commits_limit 0` 可恢复「全部展示」旧行为。
|
|
8
|
+
|
|
1
9
|
## v0.22.9 (2026-10-11)
|
|
2
10
|
|
|
3
11
|
- **管理台「高级 / CLI」完整帮助:配置键块与 config 命令相邻化(UX-M-01)**:此前 39 键「配置键(config set)」块统一追加在所有命令分组之后,与「加密与安全」组末尾的 `config` 命令之间隔着整个「平台与服务」组,阅读流断裂;现在键表紧随 `config` 命令(同组相邻),找不到 config 命令时仍回退到末尾(`keysPlaced` 兜底)。
|
package/SKILL.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: yotta-memory
|
|
3
3
|
description: 元忆 —— 有权限边界的文件式智能体记忆。文件式、零依赖、可 diff/可回滚:让任何 AI 智能体活过会话,开工 recall 恢复上下文、重要信息 remember 落盘、收工归档。类型体系 FACT(公共共享)/ PREF / BOUND / COMMIT(私密隔离)。触发:记住、别忘了、记一笔、记忆、remember、recall、跨会话、上次说到、续测、交接、归档、记忆盘、共享记忆、局域网记忆、画像、开工上下文、长期理解摘要、近期走廊、会话闭环、记忆守则、profile、context、越用越懂、语义检索、反馈、维护、蒸馏、feedback、maintain、distill、explain、自我学习、自我进化、自我提升、查看平台分页、recall 候选预过滤、任务相关记忆、--focus、--embedding、压缩遗忘、consolidate、周期摘要、自动合并、分类型衰减、回滚、备份、backup、防误删、doctor、事务快照、基线探针、恢复演练、记忆库安全扫描、scan、命中打点、容量水位、--capacity、--propose、上下文压缩审计、context --audit
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.23.0
|
|
5
5
|
license: MIT
|
|
6
6
|
---
|
|
7
7
|
|
|
@@ -16,6 +16,7 @@ license: MIT
|
|
|
16
16
|
- **类型体系**:FACT(事实,公共共享)/ PREF(偏好,私密)/ BOUND(边界,私密)/ COMMIT(承诺,私密)。
|
|
17
17
|
- **双级存储**:用户级 `~/.yottamemory/`(跨项目)+ 项目级 `.yottamemory/`(随项目共享)。
|
|
18
18
|
- **越用越懂(v0.14.0)**:`context` 一键生成开工上下文包——长期理解摘要优先(复用 `consolidate` 产物)+ 用户画像(引擎零推断,只归组原文)+ 近期走廊(按更新时间取样)+ 近期高价值补位 + 边界 + 承诺 + 会话闭环契约;SKILL「记忆守则」规则层只注入规则与机制,不注入人格数据(出厂零数据)。
|
|
19
|
+
- **保留策略与归档根治(v0.23.0)**:`context` 的 COMMIT 段默认只展示最近 20 条(`config set context_commits_limit <N>`,0=全部),`weight ≥ 1.5` 或带 `pinned` / `evergreen` 标签的条目恒显,其余折叠为一行提示(不删除,`recall --type COMMIT` 可检索);BOUND 段保持全量(底线保证不变)。归档默认门槛 `maintain_archived_utility` 0.35 → **0.55**(与效用分地板对齐,COMMIT / PREF / FACT 形成约 6 / 13 / 17 个月退役阶梯);`context` 末尾的归档提醒会显示已达门槛条数与 `maintain` 命令。收工锚点建议 ≤500 字、重点放 subject。
|
|
19
20
|
- **MCP 工具分组(v0.15.0)**:`serve --tools core|full` 控制工具暴露面。`core` 固定为 `context / recall / search / remember`,适合常驻;`full` 为现有 16 工具,适合维护与诊断。未指定时默认 `full`,保持现有配置兼容。
|
|
20
21
|
- **身份模型(v0.16.0)**:身份不再从环境变量读取。HTTP / 远程 MCP 只认请求头 `Authorization` + `X-Agent-Id` + `X-Agent-Key`;stdio MCP 只认显式参数 `--agent-id` + `--agent-key-file`;CLI 用 `--agent` + `--agent-key` / `--agent-key-file`。旧身份 env 会在 MCP 启动时被明确拒绝。
|
|
21
22
|
- **未授权提示边界(v0.16.4)**:`--agent-key-file` 不存在时不再由主入口向全局 `stderr` 告警。公共 / 维护命令保持安静;只有真正访问私密区时才 fail-closed,并给出缺失文件、`view` / `key bind`、`key status` / `key claim` 的可操作步骤。`whoami --json`、`doctor --json`、`config get --json` 返回 `identity.mode` / `identity.agentKeyStatus`。
|
|
@@ -219,7 +220,7 @@ yotta-memory doctor --json
|
|
|
219
220
|
|
|
220
221
|
1. 开工:whoami → iam(身份)→ `context`(主注入)→ `recall`(关键词补细节)。
|
|
221
222
|
2. 进行中:增量写,触发信号即记;`remember --verify` 写后回读确认落盘。
|
|
222
|
-
3. 收工:先复盘本轮并检查关键结论是否落盘,再留交接锚点(COMMIT /
|
|
223
|
+
3. 收工:先复盘本轮并检查关键结论是否落盘,再留交接锚点(COMMIT / 笔记,建议 ≤500 字、重点放 subject);定期 `maintain`(建议每月一次;v0.23.0 起归档门槛与效用地板对齐、默认真正生效)。
|
|
223
224
|
|
|
224
225
|
### 6. 写后验证
|
|
225
226
|
|
|
@@ -299,7 +300,7 @@ yotta-memory doctor --json
|
|
|
299
300
|
|
|
300
301
|
**D. 开工主注入(context)**:
|
|
301
302
|
|
|
302
|
-
- 身份就绪后运行 `yotta-memory context [--limit 10] [--budget 1800]`(远端经 MCP 用 `recall` 补细节):一键拿到「身份 + 多智能体铁律 + 用户画像摘要 + 长期理解摘要 + 近期走廊 + 近期高价值记忆 + 边界提醒 + 承诺 / 锚点 + 会话闭环契约」;`--budget` 控制动态记忆字符预算,长期摘要 / 身份 / 铁律 / 画像 /
|
|
303
|
+
- 身份就绪后运行 `yotta-memory context [--limit 10] [--budget 1800]`(远端经 MCP 用 `recall` 补细节):一键拿到「身份 + 多智能体铁律 + 用户画像摘要 + 长期理解摘要 + 近期走廊 + 近期高价值记忆 + 边界提醒 + 承诺 / 锚点 + 会话闭环契约」;`--budget` 控制动态记忆字符预算,长期摘要 / 身份 / 铁律 / 画像 / 边界与闭环契约必保;承诺 / 锚点段按保留策略展示(默认最近 20 条 + weight≥1.5 / pinned / evergreen 恒显;`config set context_commits_limit <N>`,0=全部)。
|
|
303
304
|
- 无画像时 context 自动生成一次或降级输出其余段,不报错。
|
|
304
305
|
- 需要深挖旧事再 `recall <关键词>`。
|
|
305
306
|
- 私密记忆(PREF / BOUND / COMMIT)**必须有 owner**:未声明身份写私密会被引擎拒绝(公共 FACT 不受影响)。
|
|
@@ -319,12 +320,12 @@ yotta-memory doctor --json
|
|
|
319
320
|
| `yotta-memory remember <type> <subject> <statement> [--owner <id>] [--source <来源>] [--weight <0..>] [--verify] [--no-hint]` | 写入(同 subject+statement 自动更新;--owner 标注归属;--source 记录来源;--weight 重要性权重默认 1.0、去重取 max;--verify 写后回读校验;--no-hint 关闭类型启发式提示)|
|
|
320
321
|
| `yotta-memory recall [关键词] [--type T] [--limit N] [--year <yyyy>] [--agent <id>] [--owner <id>] [--all] [--unsafe] [--explain] [--semantic] [--embedding <command>] [--embedding-timeout N]` | 检索(v0.8.0 默认语义检索:同义词 / 拼音全拼+首字母 / 字段加权 / 模糊匹配 + 效用分融合排序;v0.9.0 支持可选本地 embedding 插件,失败自动降级;v0.17.0 起 `--year` 只检索指定年份,分片索引只读取对应分片、可重复传多次、不传即全量;`--explain` 显示命中理由与效用分项;`--semantic` 显式开启;读取分区过滤;越界读其它智能体私密默认拒绝,需 grant / identity=user / `--unsafe`;`--agent <其它>` 只作身份声明/展示,不授予跨读——读他人私密同样要授权;项目级优先)|
|
|
321
322
|
| `yotta-memory profile [--owner <id>]` | 生成用户画像(聚合 `private/<owner>/` 原文,零推断,写 `profile.md`;跨 owner 默认拒绝)|
|
|
322
|
-
| `yotta-memory context [--limit N] [--owner <id>] [--budget N] [--focus <关键词>] [--year <yyyy>] [--explain] [--embedding <command>]` | 生成开工上下文包(身份 + 多智能体铁律 + 画像 + 长期摘要 + 任务相关记忆 + 近期走廊 + 近期高价值 + 边界 + 承诺 + 会话闭环契约;--budget 控制动态记忆字符预算,0=不限;v0.17.0 起 `--year` 只装载指定年份,口径同 recall
|
|
323
|
+
| `yotta-memory context [--limit N] [--owner <id>] [--budget N] [--focus <关键词>] [--year <yyyy>] [--explain] [--embedding <command>]` | 生成开工上下文包(身份 + 多智能体铁律 + 画像 + 长期摘要 + 任务相关记忆 + 近期走廊 + 近期高价值 + 边界 + 承诺 + 会话闭环契约;--budget 控制动态记忆字符预算,0=不限;v0.17.0 起 `--year` 只装载指定年份,口径同 recall;v0.23.0 起 COMMIT 段默认只展示最近 20 条(`context_commits_limit`,0=全部;weight≥1.5 / pinned / evergreen 恒显);--explain 输出 included / dropped 选择 trace)|
|
|
323
324
|
| `yotta-memory forget <文件>` | 移入 `.trash/<时间>/` 回收区并写审计(v0.12.0;不再物理删除)|
|
|
324
325
|
| `yotta-memory backup volumes / setup --dir <目录> / status / ensure-daily / schedule enable|disable|status` | 每日自动备份(v0.12.0;只展示实际枚举的异卷、用户确认一次位置后默认每日执行,Windows Task Scheduler / systemd timer / launchd 调度,`serve` 补跑)|
|
|
325
326
|
| `yotta-memory backup create / list / doctor / restore <ID> --to <目录> / drill [<ID>] [--probe] [--against <库路径>]` | 备份、恢复与恢复演练(v0.12.0;独立盘校验、SHA-256 清单、排除 `keys/cache`、恢复默认只写新目录;drill 验证 manifest / 索引 / 测试私密解密;v0.17.0 起 `--probe` 在恢复副本上追加六类基线探针,`--against` 校验备份没有落后于源库)|
|
|
326
327
|
| `yotta-memory doctor [--json] [--runtime] [--mcp-config <文件>] [--skill-dir <目录>] [--baseline [--against <库路径>] [--template <文件>]]` | 开工可靠性检查(v0.12.2;根目录 / 密钥库 / 索引 / 身份 / 最近备份;严重异常时锁定破坏性写入);全新空库的缺失 index / agents 降为 info;输出 agent home 发现规则与 `YOTTA_MEMORY_AGENT_HOME` 提示;加 `--runtime` 检查 CLI / current / MCP 配置 / 运行中 server / 技能副本漂移;v0.16.4 起 `--json` 含身份 / agent-key 状态;v0.16.5 起顶层含 `schemaVersion` / `encryption` / `migration_required`;v0.17.0 起 `checks.scale` 给规模体检(条数 / 单目录文件数 / 索引体积 / 冷启动耗时,阈值 `scale_*`),`--baseline` 追加恢复 / 迁移基线探针(结果进 `checks.baseline`,失败 exit 2)|
|
|
327
|
-
| `yotta-memory archive [--days 180] [--threshold 0.
|
|
328
|
+
| `yotta-memory archive [--days 180] [--threshold 0.55] [--dry-run] [--force] [--json]` | 归档旧记忆(v0.8.0 统一效用分 + v0.10.0 分类型衰减;immutable / BOUND 豁免;v0.18.0 起默认豁免冷却期与 `evergreen` / `pinned`,`--force` 显式覆盖;私密归档入 `.archive/private/<owner>/<type>/`;阈值默认读 config `maintain_archived_utility`,v0.23.0 起默认 0.55)。`--dry-run` 只预览、零写入(不动文件 / 不建快照 / 不写审计),无候选时不建整库快照,`--json` 输出结构化报告 |
|
|
328
329
|
| `yotta-memory reindex` | 重建索引(手动改 .md 后校正)|
|
|
329
330
|
| `yotta-memory export [--out f.json]` / `import <f.json>` | 导出 / 导入 |
|
|
330
331
|
| `yotta-memory config set memory_home <目录>` / `config set backup_dir <目录>` / `config get [--json]` | 持久记住 / 查看记忆库位置与备份目录(`~/.yottamemory/config.json`;`get --json` 同时返回身份状态);数值类键含 `maintain_*` / `consolidate_*` / `scale_*` / `backup_max_age_hours` |
|
package/USER_GUIDE.md
CHANGED
|
@@ -94,7 +94,7 @@ yotta-memory iam <id> --name 元忆 --user 用户 --relationship 伙伴 # 自
|
|
|
94
94
|
```
|
|
95
95
|
|
|
96
96
|
- `profile` 引擎零推断:只按类型 / 主题 / 标签归组呈现原文,画像结论由 AI 内部形成,不当面贴标签。
|
|
97
|
-
- `context` 是每次会话开工的主注入,替代裸 `recall`;长期摘要优先、近期走廊按时间取样、近期高价值补位按文件去重;无画像时自动生成一次或降级,不报错;`--budget` 控制动态记忆字符预算,长期摘要 / 身份 / 铁律 / 画像 /
|
|
97
|
+
- `context` 是每次会话开工的主注入,替代裸 `recall`;长期摘要优先、近期走廊按时间取样、近期高价值补位按文件去重;无画像时自动生成一次或降级,不报错;`--budget` 控制动态记忆字符预算,长期摘要 / 身份 / 铁律 / 画像 / 边界与闭环契约必保;承诺 / 锚点段按保留策略展示(v0.23.0 起默认最近 20 条 + weight≥1.5 / pinned / evergreen 恒显,`config set context_commits_limit <N>`,0=全部)。
|
|
98
98
|
- `context --audit [--from <文件|->] [--json] [--gate N]`:把宿主压缩后的摘要或丢弃段落喂给元忆,逐条核对是否已落盘;输出已落盘 / 未落盘 / 无法判定与 `remember` 建议命令(只打印、不执行)。`--gate N` 在未落盘条数超过 N 时 exit 1,可接自动化。不传 `--from` 时审计当前上下文包的 dropped 清单。审计全程只读:不复制输入、不自动补写、不写命中打点。
|
|
99
99
|
- `remember --verify` 写后回读校验;`remember --no-hint` 关闭「疑似偏好,建议 PREF」的提示。
|
|
100
100
|
|
|
@@ -212,7 +212,7 @@ yotta-memory recall <关键词> --agent <id> --agent-key-file "<AI_HOME>/.yotta-
|
|
|
212
212
|
|
|
213
213
|
**规则层自组织(maintain)**
|
|
214
214
|
|
|
215
|
-
- `maintain`(默认 dry-run 预览):列出归档候选与遗忘候选(v0.10.0 起按**分类型衰减后**的效用分 + 年龄判定;默认:utility < 0.
|
|
215
|
+
- `maintain`(默认 dry-run 预览):列出归档候选与遗忘候选(v0.10.0 起按**分类型衰减后**的效用分 + 年龄判定;默认:utility < **0.55** 且超 180 天 = 归档候选,utility < 0.12 且超 365 天 = 遗忘候选)。v0.23.0 起归档门槛与效用分地板对齐(记忆默认 `confidence=1.0`,地板约 0.42~0.47——旧默认 0.35 永远打不到、实际不生效);COMMIT / PREF / FACT 由此形成约 6 / 13 / 17 个月退役阶梯。
|
|
216
216
|
- **immutable / BOUND 豁免**:红线与边界不参与任何自动归档 / 遗忘。
|
|
217
217
|
- `maintain --apply`:执行归档(公共 → `.archive/facts/`,私密 → `.archive/private/<owner>/<type>/`,可恢复;年/月分层文件保留原分层,如 `.archive/facts/2025/01/`)。
|
|
218
218
|
- `maintain --apply --purge`:真删遗忘候选(谨慎;硬删除不可回滚)。
|
|
@@ -220,11 +220,11 @@ yotta-memory recall <关键词> --agent <id> --agent-key-file "<AI_HOME>/.yotta-
|
|
|
220
220
|
- `maintain --dedup --apply`:自动合并同归属(同类型 + 同 scope/owner)高置信组:保留 confidence 最高的一条,合并 tags / 使用次数 / 反馈,其余移入 `.archive/` 并写批次审计(可 `consolidate --undo <batch>` 回滚)。**注意 `--dedup` 与归档互斥**:`--dedup [--apply]` 只查重 / 自动合并,不会顺手归档单条旧记忆——要归档请单独跑 `maintain --apply`。
|
|
221
221
|
- `maintain --merge A,B`:手动合并两条相似记忆(保留高 confidence,低 confidence 归档)。
|
|
222
222
|
- `maintain --capacity [--json]`:只读容量报告——水位(条目 / 文件字节 / 索引 / 单目录 / 冷启动)、30 / 90 天活跃度、LRU 与 LFU 淘汰候选、晋升建议(≥3 次命中且 ≥3 个不同查询)。候选排除 30 天冷却期与常青条目(immutable / BOUND / `evergreen` / `pinned`);每条候选 / 建议都带可执行命令,报告本身不改任何文件。
|
|
223
|
-
- 阈值与半衰可用 `config set maintain_archived_utility 0.
|
|
223
|
+
- 阈值与半衰可用 `config set maintain_archived_utility 0.6` / `config set maintain_decay_halflife_FACT 1000` 等调整(`config get` 查看;门槛调回 0.35 会重新低于效用地板、基本不生效);审计在 `.archive/audit-<日期>.jsonl`。
|
|
224
224
|
|
|
225
225
|
**归档(archive)**
|
|
226
226
|
|
|
227
|
-
- `archive [--days 180] [--threshold 0.
|
|
227
|
+
- `archive [--days 180] [--threshold 0.55] [--dry-run] [--json]`:把「效用低于阈值且超过 N 天没用」的旧记忆移入 `.archive/`(可恢复)。`--dry-run` 只打印将归档清单(文件 / 类型 / 天龄 / 效用 / subject)与跳过统计,**不动文件、不建事务快照、不写审计**。
|
|
228
228
|
- 默认豁免:冷却期(`config set capacity_cooldown_days`,默认 30 天)与常青条目(immutable / BOUND / `evergreen` / `pinned`)。`--force` 只覆盖冷却期与标签常青,immutable 与 BOUND 始终豁免。
|
|
229
229
|
- 真正执行前先过破坏性写入闸门(doctor + 独立备份 + 异卷)并创建事务快照;没有候选时不会建快照。`--json` 输出结构化报告(`mode / candidates / archived / skipped`),便于自动化读取。
|
|
230
230
|
|
package/bin/yotta-memory.js
CHANGED
|
@@ -25,7 +25,7 @@ const net = require('net');
|
|
|
25
25
|
const child_process = require('child_process');
|
|
26
26
|
const { AsyncLocalStorage } = require('async_hooks');
|
|
27
27
|
|
|
28
|
-
const VERSION = '0.
|
|
28
|
+
const VERSION = '0.23.0';
|
|
29
29
|
const CLI_VALUE_OPTS = new Set(['--type', '--limit', '--days', '--out', '--owner', '--agent', '--agent-id', '--agent-key', '--agent-key-file', '--plugin-data', '--threshold', '--scope', '--host', '--port', '--dir', '--name', '--user', '--relationship', '--source', '--weight', '--budget', '--password', '--new-password', '--recovery-key', '--recovery-key-out', '--reason', '--merge', '--model', '--subject', '--embedding', '--focus', '--embedding-timeout', '--min-age', '--min-idle', '--max-utility', '--min-group', '--period', '--to', '--id', '--time', '--tools', '--mcp-config', '--skill-dir', '--year', '--evalset', '--k', '--seed', '--bootstrap', '--gate', '--against', '--template', '--path', '--from']);
|
|
30
30
|
const CLI_FLAG_OPTS = new Set(['--project', '--all', '--unsafe', '--no-auth', '--stdio', '--onstart', '--from-current', '--restart', '--force', '--attach', '--allow-same-volume', '--verify', '--no-hint', '--encrypt', '--no-encrypt', '--password-stdin', '--json', '--manual', '--skip-schedule', '--useful', '--useless', '--undo', '--dry-run', '--apply', '--purge', '--dedup', '--batches', '--propose', '--audit', '--capacity', '--rules', '--explain', '--semantic', '--runtime', '--ablate', '--timing', '--baseline', '--probe', '--quarantine', '--restore', '--no-usage', '--yes', '--keep-memories', '--keep-identity']);
|
|
31
31
|
|
|
@@ -400,6 +400,9 @@ const PRIVATE_LEAF = ['prefs', 'bounds', 'commits'];
|
|
|
400
400
|
const ARCHIVE_DIR = '.archive';
|
|
401
401
|
const INDEX_FILE = 'index.json';
|
|
402
402
|
const PRIVATE_TYPES = ['PREF', 'BOUND', 'COMMIT'];
|
|
403
|
+
// v0.23.0 D1/D2:上下文包 COMMIT 段保留条数(0 = 全部)与归档默认门槛(与效用分地板对齐)
|
|
404
|
+
const CONTEXT_COMMITS_LIMIT_DEFAULT = 20;
|
|
405
|
+
const ARCHIVE_UTILITY_DEFAULT = 0.55;
|
|
403
406
|
const FIELD_ORDER = ['type', 'subject', 'statement', 'confidence', 'created', 'updated', 'tags', 'immutable', 'scope', 'owner', 'source', 'weight', 'access_count', 'last_accessed', 'feedback_net', 'hit_days', 'hit_queries'];
|
|
404
407
|
const CONFIG_FILE = 'config.json';
|
|
405
408
|
const SERVER_SUBDIR = '.server';
|
|
@@ -2567,10 +2570,17 @@ function buildIndex(root) {
|
|
|
2567
2570
|
if (skip.has(rel)) continue;
|
|
2568
2571
|
if (rel.indexOf(PRIVATE_DIR + '/') === 0) {
|
|
2569
2572
|
const owner = rel.split('/')[1] || '';
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2573
|
+
// v0.23.0 修复(WorkBuddy D2):未加密库没有 owner key(getOwnerKeyFor 恒为 null),
|
|
2574
|
+
// 私密条目须与公共条目同存主索引(与 upsertIndexEntry 口径一致),
|
|
2575
|
+
// 否则 reindex / 静默校准会把私密条目整段跳过,索引越重建越空。
|
|
2576
|
+
if (isEncrypted(root)) {
|
|
2577
|
+
if (!getOwnerKeyFor(root, owner)) continue;
|
|
2578
|
+
let e;
|
|
2579
|
+
try { e = readEntry(fp, root); } catch (err) { continue; }
|
|
2580
|
+
(privateByOwner[owner] = privateByOwner[owner] || []).push(e);
|
|
2581
|
+
} else {
|
|
2582
|
+
try { publicEntries.push(readEntry(fp, root)); } catch (err) { /* ignore */ }
|
|
2583
|
+
}
|
|
2574
2584
|
} else {
|
|
2575
2585
|
try { publicEntries.push(readEntry(fp, root)); } catch (err) { /* ignore */ }
|
|
2576
2586
|
}
|
|
@@ -3971,6 +3981,11 @@ const SCALE_THRESHOLD_DEFAULTS = {
|
|
|
3971
3981
|
scale_info_files_per_dir: 300,
|
|
3972
3982
|
scale_info_index_bytes: 3 * 1024 * 1024,
|
|
3973
3983
|
scale_info_cold_start_ms: 1200,
|
|
3984
|
+
// v0.23.0 D3:超长 statement / 单类型堆积(防写法走偏)
|
|
3985
|
+
scale_warn_long_statements: 50,
|
|
3986
|
+
scale_info_long_statements: 10,
|
|
3987
|
+
scale_warn_type_count: 500,
|
|
3988
|
+
scale_info_type_count: 200,
|
|
3974
3989
|
};
|
|
3975
3990
|
function scaleThreshold(cfg, key) {
|
|
3976
3991
|
const raw = cfg ? cfg[key] : undefined;
|
|
@@ -4015,6 +4030,20 @@ function scaleReport(root, cfg) {
|
|
|
4015
4030
|
const entries = collectEntryFiles(root).length;
|
|
4016
4031
|
const filesPerDir = Math.max(maxFilesInDir(path.join(root, PUBLIC_DIR)), maxFilesInDir(path.join(root, PRIVATE_DIR)));
|
|
4017
4032
|
const indexBytes = indexSizeBytes(root);
|
|
4033
|
+
// v0.23.0 D3:超长 statement(> 2000 字)与单类型堆积(读索引,不逐条解密读文件)
|
|
4034
|
+
const scaleEntries = loadIndex(root) || [];
|
|
4035
|
+
let longStatements = 0;
|
|
4036
|
+
const typeCounts = { FACT: 0, PREF: 0, BOUND: 0, COMMIT: 0 };
|
|
4037
|
+
for (const e of scaleEntries) {
|
|
4038
|
+
const t = String(e.type || 'FACT').toUpperCase();
|
|
4039
|
+
typeCounts[t] = (typeCounts[t] || 0) + 1;
|
|
4040
|
+
if (String(e.statement || '').length > 2000) longStatements++;
|
|
4041
|
+
}
|
|
4042
|
+
let typeMax = 0;
|
|
4043
|
+
let typeMaxName = 'FACT';
|
|
4044
|
+
for (const t of Object.keys(typeCounts)) {
|
|
4045
|
+
if (typeCounts[t] > typeMax) { typeMax = typeCounts[t]; typeMaxName = t; }
|
|
4046
|
+
}
|
|
4018
4047
|
// 冷启动取多次测量的中位数,避免单次抖动影响只读体检结果。
|
|
4019
4048
|
const samples = [];
|
|
4020
4049
|
for (let i = 0; i < 3; i++) samples.push(measureIndexColdStart(root));
|
|
@@ -4025,6 +4054,8 @@ function scaleReport(root, cfg) {
|
|
|
4025
4054
|
scaleMetric('files_per_dir', filesPerDir, '个文件', thresholds.scale_info_files_per_dir, thresholds.scale_warn_files_per_dir),
|
|
4026
4055
|
scaleMetric('index_bytes', indexBytes, '字节', thresholds.scale_info_index_bytes, thresholds.scale_warn_index_bytes),
|
|
4027
4056
|
scaleMetric('cold_start_ms', coldStartMs, 'ms', thresholds.scale_info_cold_start_ms, thresholds.scale_warn_cold_start_ms),
|
|
4057
|
+
scaleMetric('long_statements', longStatements, '条', thresholds.scale_info_long_statements, thresholds.scale_warn_long_statements),
|
|
4058
|
+
scaleMetric('type_max', typeMax, '条', thresholds.scale_info_type_count, thresholds.scale_warn_type_count),
|
|
4028
4059
|
];
|
|
4029
4060
|
const warnings = [];
|
|
4030
4061
|
if (metrics[0].level === 'warning') {
|
|
@@ -4039,6 +4070,12 @@ function scaleReport(root, cfg) {
|
|
|
4039
4070
|
if (metrics[3].level === 'warning') {
|
|
4040
4071
|
warnings.push('规模: 索引冷启动 ' + coldStartMs + 'ms 超过阈值 ' + thresholds.scale_warn_cold_start_ms + 'ms(可用 reindex 重建索引)');
|
|
4041
4072
|
}
|
|
4073
|
+
if (metrics[4].level === 'warning') {
|
|
4074
|
+
warnings.push('规模: 超长 statement(> 2000 字)' + longStatements + ' 条超过阈值 ' + thresholds.scale_warn_long_statements + '(建议拆分:记忆宜短句高密度,长文另存文档)');
|
|
4075
|
+
}
|
|
4076
|
+
if (metrics[5].level === 'warning') {
|
|
4077
|
+
warnings.push('规模: 单类型堆积(' + typeMaxName + ' ' + typeMax + ' 条)超过阈值 ' + thresholds.scale_warn_type_count + '(考虑归档 / 合并 / 精简;COMMIT 收工锚点建议短写)');
|
|
4078
|
+
}
|
|
4042
4079
|
// v0.18.0 A6:分级只影响 level 与提示文案;超 warn 仍进 warnings(既有行为),info 不阻断。
|
|
4043
4080
|
const level = metrics.some(function (m) { return m.level === 'warning'; })
|
|
4044
4081
|
? 'warning'
|
|
@@ -4699,6 +4736,9 @@ function rememberCore(type, subject, statement, opts) {
|
|
|
4699
4736
|
const hit = HINT_KEYWORDS.filter(function (w) { return stmt.indexOf(w) !== -1; });
|
|
4700
4737
|
if (hit.length) text += '\n[提示] statement 含主观/关系词(' + hit.join('、') + '),疑似用户偏好 / 关系内容——若属此类建议改用 PREF(私密,仅本人可读)。仅提示不拦截;--no-hint 可关闭。';
|
|
4701
4738
|
}
|
|
4739
|
+
if (opts.hint !== false && t === 'COMMIT' && stmt.length > 1200) {
|
|
4740
|
+
text += '\n[提示] 这条 COMMIT 较长(' + stmt.length + ' 字):开工上下文包默认只展示最近 ' + CONTEXT_COMMITS_LIMIT_DEFAULT + ' 条 COMMIT;收工锚点建议 ≤500 字(重点放 subject),重要承诺可加 --weight 1.5 或 tags pinned 保持常显。仅提示不拦截;--no-hint 可关闭。';
|
|
4741
|
+
}
|
|
4702
4742
|
if (opts.verify) {
|
|
4703
4743
|
const rel = path.relative(root, fp).replace(/\\/g, '/');
|
|
4704
4744
|
const ok = verifyWrittenReadable(root, rel, subj, selfAgent || opts.agent);
|
|
@@ -4742,6 +4782,9 @@ function rememberCore(type, subject, statement, opts) {
|
|
|
4742
4782
|
const hit = HINT_KEYWORDS.filter(function (w) { return stmt.indexOf(w) !== -1; });
|
|
4743
4783
|
if (hit.length) text += '\n[提示] statement 含主观/关系词(' + hit.join('、') + '),疑似用户偏好 / 关系内容——若属此类建议改用 PREF(私密,仅本人可读)。仅提示不拦截;--no-hint 可关闭。';
|
|
4744
4784
|
}
|
|
4785
|
+
if (opts.hint !== false && t === 'COMMIT' && stmt.length > 1200) {
|
|
4786
|
+
text += '\n[提示] 这条 COMMIT 较长(' + stmt.length + ' 字):开工上下文包默认只展示最近 ' + CONTEXT_COMMITS_LIMIT_DEFAULT + ' 条 COMMIT;收工锚点建议 ≤500 字(重点放 subject),重要承诺可加 --weight 1.5 或 tags pinned 保持常显。仅提示不拦截;--no-hint 可关闭。';
|
|
4787
|
+
}
|
|
4745
4788
|
if (opts.verify) {
|
|
4746
4789
|
const rel = path.relative(root, file).replace(/\\/g, '/');
|
|
4747
4790
|
const ok = verifyWrittenReadable(root, rel, subj, selfAgent || opts.agent);
|
|
@@ -5313,7 +5356,7 @@ function archiveCore(opts) {
|
|
|
5313
5356
|
opts = opts || {};
|
|
5314
5357
|
const cfg = loadConfig();
|
|
5315
5358
|
const days = opts.days || parseInt(cfg.maintain_archived_age || '180', 10) || 180;
|
|
5316
|
-
const threshold = (opts.threshold !== undefined && opts.threshold !== null) ? opts.threshold : (parseFloat(cfg.maintain_archived_utility ||
|
|
5359
|
+
const threshold = (opts.threshold !== undefined && opts.threshold !== null) ? opts.threshold : (parseFloat(cfg.maintain_archived_utility || ARCHIVE_UTILITY_DEFAULT));
|
|
5317
5360
|
const cooldownDays = capacityNumber(cfg, 'capacity_cooldown_days');
|
|
5318
5361
|
const root = userRoot();
|
|
5319
5362
|
if (!fs.existsSync(root)) return { error: false, text: '记忆库不存在。' };
|
|
@@ -5537,7 +5580,7 @@ function explainCore(ref, opts) {
|
|
|
5537
5580
|
const ageDays = entry.created ? daysBetween(entry.created, today()) : 0;
|
|
5538
5581
|
const cfg = loadConfig();
|
|
5539
5582
|
const hlText = entry.type === 'BOUND' ? 'BOUND 不衰减' : (decayHalflifeDays(entry.type, cfg) + ' 天');
|
|
5540
|
-
const archU = parseFloat(cfg.maintain_archived_utility ||
|
|
5583
|
+
const archU = parseFloat(cfg.maintain_archived_utility || ARCHIVE_UTILITY_DEFAULT);
|
|
5541
5584
|
const archAge = parseInt(cfg.maintain_archived_age || '180', 10) || 180;
|
|
5542
5585
|
const forgetU = parseFloat(cfg.maintain_forget_utility || 0.12);
|
|
5543
5586
|
const forgetAge = parseInt(cfg.maintain_forget_age || '365', 10) || 365;
|
|
@@ -5679,7 +5722,7 @@ function maintainCore(opts) {
|
|
|
5679
5722
|
if (guard.error) return { error: true, text: guard.text };
|
|
5680
5723
|
}
|
|
5681
5724
|
const cfg = loadConfig();
|
|
5682
|
-
const archU = parseFloat(opts.threshold !== undefined && opts.threshold !== null ? opts.threshold : (cfg.maintain_archived_utility ||
|
|
5725
|
+
const archU = parseFloat(opts.threshold !== undefined && opts.threshold !== null ? opts.threshold : (cfg.maintain_archived_utility || ARCHIVE_UTILITY_DEFAULT));
|
|
5683
5726
|
const archAge = parseInt(opts.age || cfg.maintain_archived_age || '180', 10) || 180;
|
|
5684
5727
|
const forgetU = parseFloat(cfg.maintain_forget_utility || 0.12);
|
|
5685
5728
|
const forgetAge = parseInt(cfg.maintain_forget_age || '365', 10) || 365;
|
|
@@ -7839,6 +7882,15 @@ function cmdReindex() {
|
|
|
7839
7882
|
for (const root of roots) {
|
|
7840
7883
|
const n = buildIndex(root).length;
|
|
7841
7884
|
console.log('已重建索引 ' + root + '(' + n + ' 条)');
|
|
7885
|
+
// v0.23.0 修复(WorkBuddy D2):无授权 key 的加密私密区无法重建——明确提示,
|
|
7886
|
+
// 避免「已重建索引」误导(doctor 建议 → reindex 死路),并给出可执行路径。
|
|
7887
|
+
try {
|
|
7888
|
+
const report = indexConsistencyReport(root);
|
|
7889
|
+
if (report.ownersSkipped && report.ownersSkipped.length) {
|
|
7890
|
+
console.log('[提示] 跳过无授权私密 owner: ' + report.ownersSkipped.join(', ')
|
|
7891
|
+
+ '(' + report.skippedFiles + ' 个文件未重建)。加密库重建私密索引请带 --agent <id> --agent-key-file <path> 重跑。');
|
|
7892
|
+
}
|
|
7893
|
+
} catch (e) { /* 提示失败不影响重建结果 */ }
|
|
7842
7894
|
}
|
|
7843
7895
|
}
|
|
7844
7896
|
function collectAll(root) {
|
|
@@ -8279,6 +8331,32 @@ function compareContextRecent(a, b) {
|
|
|
8279
8331
|
if (byTime !== 0) return byTime;
|
|
8280
8332
|
return (b.access_count || 0) - (a.access_count || 0);
|
|
8281
8333
|
}
|
|
8334
|
+
// v0.23.0 D1:COMMIT 段保留策略 —— 最近 N 条 + weight≥1.5 / pinned / evergreen 恒显;0 = 全部。
|
|
8335
|
+
function contextCommitsLimit(cfg) {
|
|
8336
|
+
const raw = cfg ? cfg.context_commits_limit : undefined;
|
|
8337
|
+
if (raw === undefined || raw === null || raw === '') return CONTEXT_COMMITS_LIMIT_DEFAULT;
|
|
8338
|
+
const n = parseInt(raw, 10);
|
|
8339
|
+
return (n >= 0) ? n : CONTEXT_COMMITS_LIMIT_DEFAULT;
|
|
8340
|
+
}
|
|
8341
|
+
function commitAlwaysShown(entry) {
|
|
8342
|
+
if (!entry) return false;
|
|
8343
|
+
const w = parseFloat(entry.weight || '1.0');
|
|
8344
|
+
if (w >= 1.5) return true;
|
|
8345
|
+
return isEvergreenTagged(entry);
|
|
8346
|
+
}
|
|
8347
|
+
// v0.23.0 修复(WorkBuddy D1):COMMIT 段按「立下时间」(created)倒序取最近 N 条;
|
|
8348
|
+
// 同日条目再按文件名序号倒序(写入先后)。旧实现按 updated(只到「日」)排序,
|
|
8349
|
+
// 同日全平局后退化为索引插入序(最旧在前)——刚写入的承诺被折叠、最老的反而进上下文。
|
|
8350
|
+
function commitRecencyKey(entry) {
|
|
8351
|
+
return String((entry && (entry.created || entry.updated)) || '');
|
|
8352
|
+
}
|
|
8353
|
+
function compareCommitRecency(a, b) {
|
|
8354
|
+
const byCreated = commitRecencyKey(b).localeCompare(commitRecencyKey(a));
|
|
8355
|
+
if (byCreated !== 0) return byCreated;
|
|
8356
|
+
const byFile = String((b && b.file) || '').localeCompare(String((a && a.file) || ''));
|
|
8357
|
+
if (byFile !== 0) return byFile;
|
|
8358
|
+
return (b.access_count || 0) - (a.access_count || 0);
|
|
8359
|
+
}
|
|
8282
8360
|
|
|
8283
8361
|
const MEMORY_HOOK_MAX_CANDIDATES = 500;
|
|
8284
8362
|
const MEMORY_HOOK_STATEMENT_LIMIT = 2000;
|
|
@@ -8830,9 +8908,25 @@ function contextCore(opts) {
|
|
|
8830
8908
|
lines.push('');
|
|
8831
8909
|
lines.push('## 6. 承诺 / 锚点(COMMIT)');
|
|
8832
8910
|
lines.push('');
|
|
8833
|
-
|
|
8834
|
-
|
|
8911
|
+
// v0.23.0 D1:保留策略 —— 默认只展示最近 N 条(context_commits_limit,0=全部);
|
|
8912
|
+
// weight≥1.5 / pinned / evergreen 恒显;其余折叠为一行提示(recall 仍可检索全部)。
|
|
8913
|
+
// v0.23.0 修复(WorkBuddy D1):排序键改 created 倒序 + 同日按文件名序号倒序(见 compareCommitRecency)。
|
|
8914
|
+
const ctxCfg = decayConfig();
|
|
8915
|
+
const commitsAll = readableEntries.filter(function (e) { return e.type === 'COMMIT'; }).sort(compareCommitRecency);
|
|
8916
|
+
const commitLimit = contextCommitsLimit(ctxCfg);
|
|
8917
|
+
const commits = [];
|
|
8918
|
+
const hiddenCommits = [];
|
|
8919
|
+
for (let i = 0; i < commitsAll.length; i++) {
|
|
8920
|
+
if (commitLimit > 0 && i >= commitLimit && !commitAlwaysShown(commitsAll[i])) hiddenCommits.push(commitsAll[i]);
|
|
8921
|
+
else commits.push(commitsAll[i]);
|
|
8922
|
+
}
|
|
8923
|
+
if (!commitsAll.length) lines.push('(无)');
|
|
8835
8924
|
for (const e of commits) lines.push('- ' + (e.subject || '承诺') + ': ' + e.statement);
|
|
8925
|
+
if (hiddenCommits.length) {
|
|
8926
|
+
const oldest = commitRecencyKey(hiddenCommits[hiddenCommits.length - 1]);
|
|
8927
|
+
const newest = commitRecencyKey(hiddenCommits[0]);
|
|
8928
|
+
lines.push('- (另有 ' + hiddenCommits.length + ' 条更早的 COMMIT 未展示:' + (oldest || '?') + ' ~ ' + (newest || '?') + ';可用 yotta-memory recall --type COMMIT 检索;重要承诺可加 weight / pinned 标签保持常显)');
|
|
8929
|
+
}
|
|
8836
8930
|
lines.push('');
|
|
8837
8931
|
lines.push('## 7. 本会话闭环契约');
|
|
8838
8932
|
lines.push('');
|
|
@@ -8849,8 +8943,22 @@ function contextCore(opts) {
|
|
|
8849
8943
|
const d = daysBetween(latest, today());
|
|
8850
8944
|
lines.push('- 最近承诺: ' + latest + (d > 7 ? '(超期 ' + d + ' 天,请补 COMMIT)' : ''));
|
|
8851
8945
|
}
|
|
8852
|
-
|
|
8853
|
-
|
|
8946
|
+
// v0.23.0 D2:归档提醒可执行化(按 config 门槛算达线条数;只读,不触发写入)
|
|
8947
|
+
const archiveAge = parseInt(ctxCfg.maintain_archived_age || '180', 10) || 180;
|
|
8948
|
+
const archiveUtilityRaw = parseFloat(ctxCfg.maintain_archived_utility || String(ARCHIVE_UTILITY_DEFAULT));
|
|
8949
|
+
const archiveUtility = isNaN(archiveUtilityRaw) ? ARCHIVE_UTILITY_DEFAULT : archiveUtilityRaw;
|
|
8950
|
+
const agedCount = allEntries.filter(function (e) { return e.created && daysBetween(e.created, today()) > archiveAge && classifyRead(e, owner, '', unsafe, selfAgent) !== 'denied'; }).length;
|
|
8951
|
+
const archivableCount = allEntries.filter(function (e) {
|
|
8952
|
+
if (!e.created || classifyRead(e, owner, '', unsafe, selfAgent) === 'denied') return false;
|
|
8953
|
+
if (daysBetween(e.created, today()) <= archiveAge) return false;
|
|
8954
|
+
if (e.immutable || e.type === 'BOUND' || isEvergreenTagged(e)) return false;
|
|
8955
|
+
return utilityScore(e) < archiveUtility;
|
|
8956
|
+
}).length;
|
|
8957
|
+
if (agedCount > 0) {
|
|
8958
|
+
lines.push('- 归档提醒: ' + agedCount + ' 条超 ' + archiveAge + ' 天' + (archivableCount > 0
|
|
8959
|
+
? ',其中 ' + archivableCount + ' 条已达归档门槛(运行 yotta-memory maintain 预览 / --apply 执行)'
|
|
8960
|
+
: ',暂无达门槛条目(可用 yotta-memory maintain 预览)'));
|
|
8961
|
+
}
|
|
8854
8962
|
if (explain) {
|
|
8855
8963
|
lines.push('');
|
|
8856
8964
|
lines.push('## 8. 选择解释(--explain)');
|
|
@@ -10196,11 +10304,11 @@ async function cmdScan(opts) {
|
|
|
10196
10304
|
|
|
10197
10305
|
// ---- config 命令 ----
|
|
10198
10306
|
// v0.10.0:maintain_* / consolidate_* 数值键纳入 config set/get(此前只支持 3 个键但文档已写可调)
|
|
10199
|
-
function isNumericConfigKey(key) { return /^(maintain_|consolidate_|scale_|backup_max_age_hours$|usage_retention_days$|usage_query_slots$|capacity_|promotion_|context_audit_min_coverage$)/.test(key); }
|
|
10307
|
+
function isNumericConfigKey(key) { return /^(maintain_|consolidate_|scale_|backup_max_age_hours$|usage_retention_days$|usage_query_slots$|capacity_|promotion_|context_audit_min_coverage$|context_commits_limit$)/.test(key); }
|
|
10200
10308
|
// v0.17.0 B2:doctor 规模体检阈值键(0 表示只要超过 0 就告警,便于压测与演练)
|
|
10201
|
-
const SCALE_CONFIG_KEYS = ['scale_warn_entries', 'scale_warn_files_per_dir', 'scale_warn_index_bytes', 'scale_warn_cold_start_ms', 'scale_info_entries', 'scale_info_files_per_dir', 'scale_info_index_bytes', 'scale_info_cold_start_ms'];
|
|
10309
|
+
const SCALE_CONFIG_KEYS = ['scale_warn_entries', 'scale_warn_files_per_dir', 'scale_warn_index_bytes', 'scale_warn_cold_start_ms', 'scale_info_entries', 'scale_info_files_per_dir', 'scale_info_index_bytes', 'scale_info_cold_start_ms', 'scale_warn_long_statements', 'scale_info_long_statements', 'scale_warn_type_count', 'scale_info_type_count'];
|
|
10202
10310
|
// v0.18.1 验收修正:config set / get 共用一份键列表,新增配置键不会再出现「读端认、写端拒」。
|
|
10203
|
-
const CONFIG_VALUE_KEYS = ['memory_home', 'backup_dir', 'backup_enabled', 'backup_schedule', 'backup_time', 'backup_max_age_hours', 'backup_setup_choice', 'embedding_cmd', 'embedding_timeout', 'maintain_archived_utility', 'maintain_archived_age', 'maintain_forget_utility', 'maintain_forget_age', 'maintain_decay_halflife_FACT', 'maintain_decay_halflife_PREF', 'maintain_decay_halflife_COMMIT', 'maintain_rule_min_hits', 'consolidate_min_age', 'consolidate_min_idle', 'consolidate_max_utility', 'consolidate_min_group', 'consolidate_period', 'usage_enabled', 'usage_retention_days', 'usage_query_slots', 'capacity_cooldown_days', 'capacity_warn_bytes', 'capacity_candidate_limit', 'promotion_min_hits', 'promotion_min_queries', 'context_audit_min_coverage'].concat(SCALE_CONFIG_KEYS);
|
|
10311
|
+
const CONFIG_VALUE_KEYS = ['memory_home', 'backup_dir', 'backup_enabled', 'backup_schedule', 'backup_time', 'backup_max_age_hours', 'backup_setup_choice', 'embedding_cmd', 'embedding_timeout', 'maintain_archived_utility', 'maintain_archived_age', 'maintain_forget_utility', 'maintain_forget_age', 'maintain_decay_halflife_FACT', 'maintain_decay_halflife_PREF', 'maintain_decay_halflife_COMMIT', 'maintain_rule_min_hits', 'consolidate_min_age', 'consolidate_min_idle', 'consolidate_max_utility', 'consolidate_min_group', 'consolidate_period', 'usage_enabled', 'usage_retention_days', 'usage_query_slots', 'capacity_cooldown_days', 'capacity_warn_bytes', 'capacity_candidate_limit', 'promotion_min_hits', 'promotion_min_queries', 'context_commits_limit', 'context_audit_min_coverage'].concat(SCALE_CONFIG_KEYS);
|
|
10204
10312
|
// v0.22.7:配置键逐键人话说明(管理台「高级 / CLI」页与官网 /product/ 共用;必须与 CONFIG_VALUE_KEYS 一一对应)
|
|
10205
10313
|
const CONFIG_KEY_HELP = {
|
|
10206
10314
|
memory_home: { what: '记忆库根目录:所有记忆文件、索引都放在这个文件夹里。改它 = 换一个记忆库,原库内容不会自动搬过去。', when: '默认 ~/.yottamemory。优先级:环境变量 YOTTA_MEMORY_HOME > 本键 > 默认。把库换到数据盘 / 移动盘时改这里,改完用 config get 复查。' },
|
|
@@ -10212,7 +10320,7 @@ const CONFIG_KEY_HELP = {
|
|
|
10212
10320
|
backup_setup_choice: { what: '备份配置向导的选择记录:上次选的是每日备份(daily)还是手动模式(manual)。', when: '默认 manual;选 manual 后 doctor 不再提醒“未配置备份”。一般由 backup setup 自动写入。' },
|
|
10213
10321
|
embedding_cmd: { what: '本地语义检索(embedding)插件命令:配置后,搜索会额外按“意思相近”找记忆,而不只是按字面词匹配。', when: '可选,默认关闭。命令只在本机执行、不联网上传;需要自备插件程序。示例:python embed.py' },
|
|
10214
10322
|
embedding_timeout: { what: 'embedding 插件的调用超时:超时就不等它,自动退回普通关键词检索。', when: '毫秒,默认 3000(3 秒)。插件较慢(如本地大模型)可调大,例如 15000。' },
|
|
10215
|
-
maintain_archived_utility: { what: '归档门槛之一:效用分(越高越有价值)低于这个值的旧记忆,才可能被 archive 归档。', when: '默认 0.
|
|
10323
|
+
maintain_archived_utility: { what: '归档门槛之一:效用分(越高越有价值)低于这个值的旧记忆,才可能被 archive 归档。', when: '默认 0.55(v0.23.0 起与效用分地板对齐——记忆写出来就有约 0.42~0.47 的底分,门槛低于它会永远打不到)。调低 = 更难归档(更保守),调高 = 更容易归档。改完可用 maintain 预览候选。' },
|
|
10216
10324
|
maintain_archived_age: { what: '归档门槛之一:只有保存超过这么多天的旧记忆,才可能被归档。', when: '默认 180 天。想保守可调大(如 365),想积极瘦身可调小。' },
|
|
10217
10325
|
maintain_forget_utility: { what: '遗忘(彻底删除)门槛之一:效用分低于这个值的记忆才可能进入遗忘候选,比归档更严格。', when: '默认 0.12,建议保持很低;误删不可恢复(只能靠备份)。' },
|
|
10218
10326
|
maintain_forget_age: { what: '遗忘(彻底删除)门槛之一:只有保存超过这么多天的记忆才可能进入遗忘候选。', when: '默认 365 天。' },
|
|
@@ -10233,6 +10341,7 @@ const CONFIG_KEY_HELP = {
|
|
|
10233
10341
|
capacity_candidate_limit: { what: 'maintain --capacity 一次最多列出多少个淘汰候选。', when: '默认 20。' },
|
|
10234
10342
|
promotion_min_hits: { what: '晋升建议门槛之一:一条记忆累计被命中至少这么多次,才可能被建议“升级”。', when: '默认 3 次;需与 promotion_min_queries 同时满足。' },
|
|
10235
10343
|
promotion_min_queries: { what: '晋升建议门槛之一:命中要来自至少这么多个不同查询(防止同一句话反复搜把分数刷上去)。', when: '默认 3 个。' },
|
|
10344
|
+
context_commits_limit: { what: '开工上下文包里 COMMIT(承诺 / 收工锚点)段最多展示多少条:超出的旧条目折叠为一行提示,不删除、仍可用 recall 检索。', when: '默认 20;0 = 全部展示(旧行为)。weight ≥ 1.5 或带 pinned / evergreen 标签的条目不受上限影响、始终展示。' },
|
|
10236
10345
|
context_audit_min_coverage: { what: 'context --audit 的覆盖率闸门:落盘覆盖率低于这个比例时,提示“还有内容没落盘”。', when: '0-1 之间的小数,默认 0.5(即 50%)。' },
|
|
10237
10346
|
scale_warn_entries: { what: '规模体检(doctor 的“规模”段):记忆条数超过这个值,升级为 warning 告警。', when: '默认 50000 条。' },
|
|
10238
10347
|
scale_warn_files_per_dir: { what: '规模体检:单个目录里的文件数超过这个值,升级为 warning。', when: '默认 500 个文件。' },
|
|
@@ -10242,6 +10351,10 @@ const CONFIG_KEY_HELP = {
|
|
|
10242
10351
|
scale_info_files_per_dir: { what: '规模体检:单目录文件数超过这个值,提示 info。', when: '默认 300 个文件。' },
|
|
10243
10352
|
scale_info_index_bytes: { what: '规模体检:索引体积超过这个值,提示 info。', when: '默认 3145728 字节(3 MB)。' },
|
|
10244
10353
|
scale_info_cold_start_ms: { what: '规模体检:索引冷启动超过这个值,提示 info。', when: '默认 1200 毫秒。' },
|
|
10354
|
+
scale_warn_long_statements: { what: '规模体检:超过 2000 字的 statement 条数超过这个值,升级为 warning。', when: '默认 50 条。记忆宜短句高密度,长文建议拆分或另存文档。' },
|
|
10355
|
+
scale_info_long_statements: { what: '规模体检:超过 2000 字的 statement 条数超过这个值,提示 info。', when: '默认 10 条。' },
|
|
10356
|
+
scale_warn_type_count: { what: '规模体检:单类型(FACT / PREF / BOUND / COMMIT 之一)条数超过这个值,升级为 warning。', when: '默认 500 条。COMMIT 堆积通常意味着收工锚点写太长或该跑 maintain 归档了。' },
|
|
10357
|
+
scale_info_type_count: { what: '规模体检:单类型条数超过这个值,提示 info。', when: '默认 200 条。' },
|
|
10245
10358
|
};
|
|
10246
10359
|
function cmdConfigSet(key, value) {
|
|
10247
10360
|
const known = CONFIG_VALUE_KEYS;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yottameta/yotta-memory",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.23.0",
|
|
4
4
|
"description": "Yuanyi (元忆) — boundary-aware, file-based memory for AI agents. File-based, zero-dependency, diff/rollback-able; FACT/PREF/BOUND/COMMIT types (public shared / private isolated), user-level + project-level storage; v0.12 reliability baseline (init guard, trash-based deletion, independent-volume backup/list/doctor/restore, start-of-work doctor, transactional snapshots before destructive writes), v0.10 consolidation (periodic summaries with provenance, near-duplicate auto-merge, per-type decay, batch audit + rollback), v0.9 recall quality + context focus + optional local embedding plugin, plus v0.8 semantic search, feedback loop, self-organization and distillation.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|