@yottameta/yotta-memory 0.13.0 → 0.13.2

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,3 +1,33 @@
1
+ ## v0.13.2 (2026-09-16)
2
+
3
+ **安全修复:调用者认证 + agent_key 绑定**
4
+
5
+ - 私密操作不再把 owner ID 当身份:`whoami` / `context` / `profile` / `remember` / `recall` 需要显式 `--agent <id>` 或受信任的 MCP 环境身份。
6
+ - 新增 `agent_key` capability:`key bind <id>` 生成并只展示一次 agent_key;owner key 由 `keys/bindings/<id>.key.agent` 使用 agent_key 包裹。
7
+ - 删除对 `keys/cache/<id>.key` 明文 owner key 缓存的加载路径;legacy cache 只提示,不参与解密。
8
+ - MCP 必须同时配置 `YOTTA_AGENT_ID` + `YOTTA_MEMORY_AGENT_KEY` + `YOTTA_MEMORY_TRUST_ENV_AGENT=1`;普通 shell 的 `YOTTA_AGENT_ID` 默认不可信。
9
+ - 新增身份冲突、无 agent_key、错误 agent_key、冒充他人 ID、legacy cache 不加载等对抗性回归。
10
+ - `key list` 与失败的私密操作输出 `[YTM_MIGRATION_REQUIRED]`:列出仍有私密数据且未绑定的 agent 与原因,供 AI 主动引导用户完成绑定迁移;`doctor` 同步给出提醒。仅存在 legacy cache、没有可迁移私密数据的 owner 单独提示,不进入迁移清单;授权决策仍由用户逐个确认。
11
+ - 修复明文库 `migrate` 在身份解析处的崩溃,迁移后明确提示逐 agent `key bind`(不再写明文授权缓存)。
12
+ - `view` 平台授权会一次性弹出并展示 `agent_key`,页面可复制保存;已有 binding 时返回 409 并提示先吊销,防止误换 key 打断在用的智能体。授权 / 吊销入口新增 owner ID 路径穿越校验。
13
+ - `view` / `key bind` 授权后新增临时待领取文件 `keys/pending/<id>.key`;新增 `key status <id> --to <AI_HOME>` 与 `key claim <id> --to <AI_HOME>`,AI 可将 key 原子写入 `<AI_HOME>/.yotta-memory-agent-key`,回读校验后删除 pending。pending 不入 backup / export,避免备份包夹带明文 key。
14
+ - `key revoke` 现在同时删除 binding 与 pending;私密读取不再跨操作缓存 owner key,长驻 MCP 进程在吊销后继续使用旧 key 会立即校验失败,必须由用户重新授权生成新 key。
15
+ - 授权写入改为事务式:binding 写入后若 pending 交接文件写入失败,会回滚刚写入的 binding,避免产生“已绑定但用户拿不到 key”的孤儿授权。
16
+ - 修复 MCP stdio 私密读写未使用宿主注入的 `YOTTA_MEMORY_AGENT_KEY` 的缺陷;远程 MCP 新增 `X-Agent-Key` 请求头,token 只负责连接鉴权,加密私密读写仍必须持有匹配的 agent_key。
17
+ - `key bind` / `key revoke` / `token new` / `token revoke` / MCP `callTool` 统一拒绝非法 agent ID,阻止 `..` 或路径分隔符在密钥、token 与记忆路径入口被利用。
18
+ - MCP `import` 在写入前校验私密条目 `owner`,拒绝路径穿越;`view` 平台校验 Host / Origin,并对页面与 API 响应关闭缓存、补安全响应头,阻止 DNS rebinding / 跨站请求面。
19
+ - `key bind` 与 `view` 授权在 owner key 文件缺失时会先从 `keys/<owner>.key.recovery` 恢复原 key;原 key 与恢复文件都不可用且仍有密文时拒绝新建,避免旧数据被静默变成不可解密。
20
+ - 恢复演练不再读取 legacy `keys/cache/*.key` 明文缓存;解密必须提供恢复钥匙或主口令。
21
+ - 迁移边界:重新授权由用户在 `yotta-memory view` 平台逐个完成,AI 只转达 `[YTM_MIGRATION_REQUIRED]` 与操作步骤,不代替用户执行 `migrate` / `key bind`;`view` 授权确认框同步说明该操作属于用户侧。
22
+ - 查看平台 HTML 移出内嵌字符串,改存 `assets/view.html`。
23
+ - 发布前必须通过 security review;现有加密库需执行一次 `key bind` 迁移,明文库需先迁移加密。
24
+
25
+ ## v0.13.1 (2026-09-13)
26
+
27
+ - 清理发布文档与测试夹具中的本机专属盘符 / 路径示例,统一改为 `~/.yottamemory` 或占位路径。
28
+ - 修复 `forget --unsafe` 未透传到核心的缺陷,并补 CLI 回归测试;显式授权清理其它 owner 私密条目时行为与帮助文案一致。
29
+ - 发布前新增机器专属路径硬编码扫描闸门后,此类问题不允许再进入发布件。
30
+
1
31
  ## v0.13.0 (2026-09-13)
2
32
 
3
33
  **P0-4.6 元忆 after_milestone 试点**:
package/README.md CHANGED
@@ -23,6 +23,8 @@
23
23
 
24
24
  > 📖 The user-facing operations manual lives in [USER_GUIDE.md](USER_GUIDE.md).
25
25
 
26
+ > 🆕 **v0.13.2 (security)**: owner ID is not an authentication credential. Private reads/writes now require an explicit `agent_key`; the user creates it through `yotta-memory view` (or by running `yotta-memory key bind <id>`), then configures MCP with `YOTTA_AGENT_ID` + `YOTTA_MEMORY_AGENT_KEY` + `YOTTA_MEMORY_TRUST_ENV_AGENT=1` (or CLI `--agent <id> --agent-key <key>` / `--agent-key-file <file>`). Authorization also writes a temporary `keys/pending/<id>.key`; a new AI session runs `key status <id> --to <AI_HOME>` / `key claim <id> --to <AI_HOME>` to store it at `<AI_HOME>/.yotta-memory-agent-key` and delete pending, while the popup key is the user's separate backup. Legacy `keys/cache/*.key` is no longer loaded. When an owner still needs rebinding, `key list` and failed private operations print `[YTM_MIGRATION_REQUIRED]` with the affected agent IDs; the AI relays the steps and the user re-authorizes in `yotta-memory view`, which shows the one-time `agent_key` and refuses to overwrite an existing binding until it is revoked; the old key then fails validation.
27
+
26
28
  > 🆕 **v0.12.2**: reliability closure — `yotta-memory doctor` checks the store, key material, index, identity registry and latest backup; `maintain --apply`, `consolidate --apply`, `merge`, `archive` and `--purge` create a transaction snapshot before writing and refuse to proceed if the snapshot fails.
27
29
 
28
30
  > 🆕 **v0.12.1**: installation and update docs now distinguish the engine CLI (`yotta-memory`) from the skill installer (`yotta-memory-install`), with copy-ready upgrade commands.
@@ -68,7 +70,7 @@ Memory is classified into four types; the type decides visibility:
68
70
 
69
71
  - **Three read states**: public FACT always readable; own private always readable; other agents' private is denied by default (content not returned).
70
72
  - **Physically isolated directories**: private memory lives at `private/<owner>/<type>/`; different agents' private files are physically separated; legacy flat `prefs/` `bounds/` `commits/` auto-migrate on `reindex`.
71
- - **Three authorization gates** (any one grants reading another's private): 1. explicit grant in `grants.json`; 2. identity=user (`--agent user` / `--owner user` / `YOTTA_AGENT_ID=user`); 3. explicit `--unsafe` (user explicitly authorized).
73
+ - **Three authorization gates** (any one grants reading another's private): 1. explicit grant in `grants.json`; 2. identity=user (`--agent user` / `--owner user`); 3. explicit `--unsafe` (user explicitly authorized). The caller must still present the matching `agent_key`.
72
74
  - **Silent by default, explicit cross-read errors**: default recall silently skips other agents' private (no "there are N invisible private entries" leak); only explicit cross-agent reads (`--all` / `--owner <other>`) without authorization error / warn.
73
75
  - **`--agent <other>` does not cross**: it only declares identity for display; reading other agents' private still needs grant / identity=user / `--unsafe`.
74
76
  - **Isolation positioning**: scope: private guarantees semantic isolation between AIs; since v0.7 the private zone is mechanism-level confidentiality — files are AES-256-GCM envelope encrypted, so an AI without the owner key cannot decrypt them even if it reads the ciphertext; data sovereignty remains with the user, who can use `yotta-memory view` to unlock and view / export any memory file.
@@ -81,7 +83,7 @@ Each agent has a globally unique agent ID: it is the ownership key for private m
81
83
  - **Register (must be unique)**: `yotta-memory iam <id>` writes `agents.json` at the memory root, **enforcing uniqueness** — denied if the ID is already used by another host / source (including remote token registration); `--force` only when you confirm it is the same agent.
82
84
  - **Confirm identity**: `yotta-memory whoami` (remote MCP tool `agent_info`) reads the "declared identity of this session" — it never guesses or assumes.
83
85
  - **Self profile (forced to disk)**: `iam` auto-writes a PREF `subject=自我接入档案` (owner=self) with `; `-separated key:value: `agent_id / host / memory_home / mcp_mode / engine_url / token` (token not stored locally). Start work with `recall "自我接入档案"` to recover identity and connection info.
84
- - **No token locally**: local CLI / stdio direct connection bypasses the network and does not validate tokens; identity is declared via the agent's MCP `env.YOTTA_AGENT_ID`.
86
+ - **No network token locally**: local CLI / stdio bypasses HTTP tokens, but private access still requires `agent_id + agent_key`; MCP declares the key through per-process `YOTTA_MEMORY_AGENT_KEY` and `YOTTA_MEMORY_TRUST_ENV_AGENT=1`.
85
87
  - **Private memory requires an owner**: writing PREF / BOUND / COMMIT without declaring identity is rejected (public FACT is unaffected), mechanically preventing ID spoofing.
86
88
 
87
89
  ### Profile & start-of-work context (v0.6.0 + v0.9.0)
@@ -122,7 +124,7 @@ Each agent has a globally unique agent ID: it is the ownership key for private m
122
124
  |---|---|
123
125
  | Wrong memory type? | Hint only; forget and rewrite; --no-hint to disable |
124
126
  | Private encryption? | init encrypts by default (master password + recovery key); migrate to encrypt a plaintext store |
125
- | Multi-agent isolation? | FACT public; PREF/BOUND/COMMIT per-owner, grant via key authorize / view |
127
+ | Multi-agent isolation? | FACT public; PREF/BOUND/COMMIT per-owner + per-agent `agent_key`; the user binds once via `view` (or `key bind`) |
126
128
  | Memory not found? | config get -> reindex -> recall/search |
127
129
  | Lost master password? | reset-password with recovery key |
128
130
  | LAN connect? | lan enable + token new; client url+token |
@@ -196,14 +198,14 @@ This package exposes two separate commands:
196
198
  **init**:
197
199
 
198
200
  ```text
199
- Memory store initialized: D:/.yottamemory
201
+ Memory store initialized: ~/.yottamemory
200
202
  Master password set; recovery key: xxxx-xxxx-xxxx-xxxx (keep it safe)
201
203
  ```
202
204
 
203
205
  **remember** (with verify):
204
206
 
205
207
  ```text
206
- Recorded: D:/.yottamemory/facts/2026-09-01-0001.md
208
+ Recorded: ~/.yottamemory/facts/2026-09-01-0001.md
207
209
  [verify] read-back OK: facts/2026-09-01-0001.md
208
210
  ```
209
211
 
@@ -211,7 +213,7 @@ Recorded: D:/.yottamemory/facts/2026-09-01-0001.md
211
213
 
212
214
  ```text
213
215
  3 memories (top 3):
214
- [FACT] subject: statement... (D:/.yottamemory/facts/xxx.md)
216
+ [FACT] subject: statement... (~/.yottamemory/facts/xxx.md)
215
217
  ```
216
218
 
217
219
  **context**:
@@ -278,7 +280,7 @@ Optional post-upgrade self-check: `yotta-memory config get` (confirm `memory_hom
278
280
  | `yotta-memory whoami` | Show the current agent identity and registration status |
279
281
  | `yotta-memory iam <id> [--name <name>] [--user <user>] [--relationship <rel>] [--force]` | Register this agent's unique identity and auto-write the self profile (`agents.json`, ID must be unique) |
280
282
  | `yotta-memory token new --agent <id> [--force]` / `token list` / `token revoke --agent <id>` | Create / list / revoke access tokens for agents (registered at `.server/tokens.json`) |
281
- | `yotta-memory serve [--host 0.0.0.0] [--port 8787] [--no-auth] [--stdio]` | Start the MCP memory engine (streamable HTTP LAN / --stdio local zero-process mode; Bearer token + X-Agent-Id auth) |
283
+ | `yotta-memory serve [--host 0.0.0.0] [--port 8787] [--no-auth] [--stdio]` | Start the MCP memory engine (streamable HTTP LAN / --stdio local zero-process mode; Bearer token + X-Agent-Id + X-Agent-Key auth) |
282
284
  | `yotta-memory lan enable [--onstart] / disable / status` | Autostart management (Windows: scheduled task, default ONLOGON, --onstart needs admin, non-admin auto-degrades to user-level Startup; Linux: systemd user unit, falls back to user crontab @reboot) |
283
285
  | `yotta-memory maintain [--dry-run] [--apply] [--purge] [--threshold N] [--age N] [--dedup] [--dedup --apply] [--merge A,B]` | Self-organization: archive / forget candidates / confidence-scored dedup / auto-merge high-confidence groups; dry-run by default; `--dedup` is mutually exclusive with archiving |
284
286
  | `yotta-memory consolidate [--min-age N] [--min-idle N] [--max-utility N] [--min-group N] [--period N] [--type T] [--model <cmd>] [--apply] [--undo <batch>] [--batches]` | Periodic-summary compression (v0.10.0): group old idle low-value memories into one traceable summary and archive the originals; dry-run by default; `--undo <batch>` rolls a batch back; `--batches` lists batches |
@@ -300,7 +302,8 @@ yotta-memory recall --type FACT --limit 10
300
302
 
301
303
  Environment variables:
302
304
  - `YOTTA_MEMORY_HOME`: overrides the user-level store directory (default `~/.yottamemory/`).
303
- - `YOTTA_AGENT_ID` / `AGENT_ID`: current agent ID (local identity declaration; participates in read-partition decisions; private memory requires an owner, undeclared is rejected).
305
+ - `YOTTA_AGENT_ID` / `AGENT_ID`: per-process MCP identity only; trusted only with `YOTTA_MEMORY_TRUST_ENV_AGENT=1`, never as a user-level global fallback.
306
+ - `YOTTA_MEMORY_AGENT_KEY`: per-agent 32-byte key used to unwrap `keys/bindings/<id>.key.agent`; required for encrypted private reads/writes. After authorization, the AI runs `key status` / `key claim` to store it at `<AI_HOME>/.yotta-memory-agent-key`, and the MCP host injects it from that file.
304
307
 
305
308
  ## After the agent is wired up
306
309
 
@@ -311,7 +314,7 @@ Once the skill is installed into an agent, SKILL.md teaches it the workflow auto
311
314
  The store can live on any host or disk (= the memory engine) and be reached by agents on other LAN hosts:
312
315
 
313
316
  - **Local direct**: CLI reads/writes directly, no token;
314
- - **Remote**: the engine host runs `yotta-memory serve` (or registers `lan enable` autostart); remote agents connect via MCP with `url + token`.
317
+ - **Remote**: the engine host runs `yotta-memory serve` (or registers `lan enable` autostart); remote agents connect via MCP with `url + token + agent_key`. Same-host / shared-filesystem agents use `key claim`; cross-host setups without a shared filesystem require the user to transfer the host key securely.
315
318
  - **Local zero-process**: local MCP clients can use `serve --stdio` to launch the CLI on demand (no resident process).
316
319
 
317
320
  ### Engine side (the host where memory lives)
@@ -324,7 +327,7 @@ The store can live on any host or disk (= the memory engine) and be reached by a
324
327
  yotta-memory token revoke --agent <agent-id> # revoke
325
328
  ```
326
329
  > New tokens take effect immediately; no service restart needed.
327
- 3. Start the service (default listens on 0.0.0.0:8787, Bearer token + X-Agent-Id auth) — temporary run or register autostart:
330
+ 3. Start the service (default listens on 0.0.0.0:8787, Bearer token + X-Agent-Id + X-Agent-Key auth) — temporary run or register autostart:
328
331
  ```bash
329
332
  yotta-memory serve # temporary foreground
330
333
  yotta-memory lan enable # register autostart (Windows: scheduled task / user-level Startup; Linux: systemd user unit / user crontab)
@@ -336,7 +339,14 @@ The store can live on any host or disk (= the memory engine) and be reached by a
336
339
 
337
340
  ### Client side (remote agent)
338
341
 
339
- Register the connection in the agent's MCP config (`url` + two headers):
342
+ Before registering the connection, confirm the agent has claimed its key:
343
+
344
+ ```bash
345
+ yotta-memory key status <agent-id> --to <AI_HOME>
346
+ yotta-memory key claim <agent-id> --to <AI_HOME>
347
+ ```
348
+
349
+ If the engine and the agent do not share a filesystem, `key claim` cannot read the remote pending file directly; the user must transport the key through a password manager or a secure file transfer into the agent host directory. Then register the connection (`url` + three headers):
340
350
 
341
351
  ```json
342
352
  {
@@ -345,14 +355,15 @@ Register the connection in the agent's MCP config (`url` + two headers):
345
355
  "url": "http://<engine-host-ip>:8787/mcp",
346
356
  "headers": {
347
357
  "Authorization": "Bearer <TOKEN>",
348
- "X-Agent-Id": "<this-agent-id>"
358
+ "X-Agent-Id": "<this-agent-id>",
359
+ "X-Agent-Key": "<agent_key from this agent's host key file>"
349
360
  }
350
361
  }
351
362
  }
352
363
  }
353
364
  ```
354
365
 
355
- Once connected, MCP tools (remember / recall / search / context / doctor / forget / archive / reindex / export / import / agent_info) read/write memory and confirm identity; management actions (init / config / token / lan / serve) are not exposed via MCP, and token management is never exposed remotely. MCP `export` / `import` paths are restricted inside the memory root, MCP `distill` does not support `--model`, and MCP never accepts a raw embedding command from remote callers — the local embedding plugin must be configured on the engine host with `config set embedding_cmd`. `X-Agent-Id` must match the token's registered agent; read-partition rules are the same as the CLI (FACT public-readable, PREF / BOUND / COMMIT private).
366
+ Once connected, MCP tools (remember / recall / search / context / doctor / forget / archive / reindex / export / import / agent_info) read/write memory and confirm identity; management actions (init / config / token / lan / serve) are not exposed via MCP, and token management is never exposed remotely. MCP `export` / `import` paths are restricted inside the memory root, MCP `distill` does not support `--model`, and MCP never accepts a raw embedding command from remote callers — the local embedding plugin must be configured on the engine host with `config set embedding_cmd`. `X-Agent-Id` must match the token's registered agent, and encrypted private reads/writes additionally require the matching `X-Agent-Key`; read-partition rules are the same as the CLI (FACT public-readable, PREF / BOUND / COMMIT private).
356
367
 
357
368
  ### Location persistence
358
369
 
package/README.zh-CN.md CHANGED
@@ -23,6 +23,8 @@
23
23
 
24
24
  > 📖 面向用户的操作手册见 [USER_GUIDE.md](USER_GUIDE.md)。
25
25
 
26
+ > 🆕 **v0.13.2(安全)**:owner ID 不是认证凭证。私密读写必须持有 `agent_key`:由用户执行 `yotta-memory view` 授权(或自行运行 `yotta-memory key bind <id>`),再配置 MCP 注入 `YOTTA_AGENT_ID` + `YOTTA_MEMORY_AGENT_KEY` + `YOTTA_MEMORY_TRUST_ENV_AGENT=1`(CLI 用 `--agent <id> --agent-key <key>` 或 `--agent-key-file <文件>`)。授权同时写临时 `keys/pending/<id>.key`,AI 新会话用 `key status <id> --to <AI_HOME>` / `key claim <id> --to <AI_HOME>` 领取到 `<AI_HOME>/.yotta-memory-agent-key` 后删除 pending;弹窗 key 供用户单独备份。legacy `keys/cache/*.key` 不再加载。仍有 owner 需要重新绑定时,`key list` 与失败的私密操作会输出 `[YTM_MIGRATION_REQUIRED]` 并列出受影响 agent;AI 只提醒步骤,由用户在 `yotta-memory view` 逐个授权;平台一次性展示 `agent_key`,已有 binding 时需先「吊销」再重新授权,旧 key 随即校验失败。
27
+
26
28
  > 🆕 **v0.12.2**:可靠性收口——新增 `yotta-memory doctor` 开工检查;`maintain --apply`、`consolidate --apply`、`merge`、`archive` 与 `--purge` 在写入前自动创建事务快照,快照失败或严重异常时拒绝写入。
27
29
 
28
30
  > 🆕 **v0.12.1**:安装与更新文档明确区分引擎 CLI(`yotta-memory`)和技能安装器(`yotta-memory-install`),并补齐可直接复制的升级命令。
@@ -68,7 +70,7 @@
68
70
  | **越用越懂(v0.6.0)** | `profile` 画像聚合(零推断)+ `context` 开工上下文包(身份 / 画像 / 近期记忆 / 边界 / 承诺)+ SKILL「记忆守则」规则层,记忆随使用成长 |
69
71
  | **生态分发** | GitHub + npm 双源同步发布;npx / git clone / Download ZIP / install.sh 四种安装方式,覆盖 17+ 类智能体目录 |
70
72
  | **便携记忆盘(随盘走)** | 记忆库即引擎:装在硬盘 / 主机上,插上即恢复全部记忆;引擎主机只需装 CLI 当存放点,无需装任何 AI 智能体 |
71
- | **局域网共享与自启** | 每智能体独立 token(Bearer + X-Agent-Id)鉴权、可吊销;`lan enable` 注册开机自启(Windows:优先计划任务,非管理员自动降级用户级 Startup 静默自启;Linux:systemd 用户单元,不可用时自动降级用户 crontab @reboot);MCP 工具集与 CLI 一致(8 个工具),管理动作不远程暴露 |
73
+ | **局域网共享与自启** | 每智能体独立 token(Bearer + X-Agent-Id + X-Agent-Key)鉴权、可吊销;`lan enable` 注册开机自启(Windows:优先计划任务,非管理员自动降级用户级 Startup 静默自启;Linux:systemd 用户单元,不可用时自动降级用户 crontab @reboot);MCP 工具集与 CLI 一致(8 个工具),管理动作不远程暴露 |
72
74
  | **本地 / 局域网双模式** | 本地 `serve --stdio` 零进程、按需拉起(无常驻);局域网 streamable HTTP 常驻——两种模式可并存、按需选用 |
73
75
 
74
76
  ## 功能详解
@@ -94,7 +96,7 @@
94
96
  - **物理隔离目录**:私密记忆按 owner 存放于 `private/<owner>/<type>/`,不同智能体的私密文件物理分离;旧版根下平铺的 `prefs/` `bounds/` `commits/` 在 `reindex` 时自动迁移。
95
97
  - **三种授权入口(满足任一即可读他人私密)**:
96
98
  1. `grants.json` 显式授权:`{"<userAgent>": ["<ownerAgent>", ...]}`;
97
- 2. identity=user:`--agent user` / `--owner user` / 环境变量 `YOTTA_AGENT_ID=user`;
99
+ 2. identity=user:`--agent user` / `--owner user`,调用方仍需持有匹配的 agent_key;
98
100
  3. 显式 `--unsafe`(用户显式授权)。
99
101
  - **默认静默、显式跨读才报错**:默认 recall 遇其它 agent 私密静默跳过(不泄露「存在 N 条私密不可见」);仅当显式跨智能体读取(`--all` / `--owner <其它>`)且无授权命中时才报错 / 警告。
100
102
  - **`--agent <其它>` 不越界**:`--agent <其它agent>` 仅作身份声明 / 展示用,不授予读取他人私密;读其它智能体私密仍需 grant / identity=user / `--unsafe`。
@@ -103,12 +105,12 @@
103
105
 
104
106
  ### 智能体身份(唯一 ID + 自我档案)
105
107
 
106
- 每个智能体有一个**全局唯一的 agent ID**:它是私密记忆(PREF / BOUND / COMMIT)的归属键,也是远端接入的身份声明(`X-Agent-Id`)。
108
+ 每个智能体有一个**全局唯一的 agent ID**:它是私密记忆(PREF / BOUND / COMMIT)的归属键,也是远端接入的身份声明(`X-Agent-Id`);远端加密私密读写还需匹配的 `X-Agent-Key`。
107
109
 
108
110
  - **登记(必须唯一)**:`yotta-memory iam <id>` 写入记忆库根目录 `agents.json`,**强制唯一性**——ID 已被其它主机 / 来源(含远端 token 登记)占用时拒绝,确认是同一智能体才 `--force`。
109
- - **确认身份**:`yotta-memory whoami`(远端 MCP 工具 `agent_info`)读「当次声明身份」(本机 `YOTTA_AGENT_ID` / CLI `--agent`;远端 `X-Agent-Id`),不猜不默认。
111
+ - **确认身份**:`yotta-memory whoami --agent <id>`(远端 MCP 工具 `agent_info`);环境身份只在 MCP 信任标记下有效,不再接受用户级全局 `YOTTA_AGENT_ID`。
110
112
  - **自我档案(强制落盘)**:`iam` 自动写一条 PREF `subject=自我接入档案`(owner=自己),statement 为 `; ` 分隔的 key:value:`agent_id / host / memory_home / mcp_mode(stdio|http)/ engine_url(仅远端)/ token(仅远端;本机不存 token)`。开工先 `recall "自我接入档案"` 找回身份与接入信息。
111
- - **本机免 token**:本机 CLI / stdio 直连不经网络、不校验 token;身份经该智能体 MCP 配置的 `env.YOTTA_AGENT_ID` 声明。本机多个智能体各自声明唯一 ID,互不撞。
113
+ - **本机免网络 token**:本机 CLI / stdio 不校验 HTTP token,但私密访问仍必须 `agent_id + agent_key`;MCP 通过独立进程 env 注入。
112
114
  - **私密记忆必须有 owner**:写 PREF / BOUND / COMMIT 时未声明身份会被拒绝(公共 FACT 不受影响),从机制上防止「抄别人的 ID」。
113
115
 
114
116
  ### 画像与开工上下文(v0.6.0 + v0.9.0)
@@ -161,7 +163,7 @@
161
163
  |---|---|
162
164
  | 类型选错? | 只提示不阻止;forget 后重写;--no-hint 关提示 |
163
165
  | 私密区加密? | init 默认加密(主口令+恢复钥匙);明文库 migrate 升级 |
164
- | 多智能体权限? | FACT 公共;PREF/BOUND/COMMIT 按 owner 隔离,需 key authorize / view 授权 |
166
+ | 多智能体权限? | FACT 公共;PREF/BOUND/COMMIT 按 owner 隔离并绑定 agent_key,由用户通过 `view`(或 `key bind`)授权 |
165
167
  | 记忆找不到? | config get 查位置 → reindex 重建索引 → recall/search |
166
168
  | 忘记主口令? | 用恢复钥匙 reset-password(无私密区锁定的预期行为) |
167
169
  | 局域网怎么连? | 引擎 lan enable + token new;客户端配 url+token |
@@ -235,14 +237,14 @@ bash install.sh --list # 列出智能体 -> 默认目录
235
237
  **init(初始化记忆库)**:
236
238
 
237
239
  ```text
238
- 初始化记忆库成功:D:\.yottamemory
240
+ 初始化记忆库成功:~/.yottamemory
239
241
  主口令已设置;恢复钥匙:xxxx-xxxx-xxxx-xxxx(请妥善保存)
240
242
  ```
241
243
 
242
244
  **remember(写入记忆,带 verify 回读)**:
243
245
 
244
246
  ```text
245
- 已记录: D:\.yottamemory\facts\2026-09-01-0001.md
247
+ 已记录: ~/.yottamemory/facts/2026-09-01-0001.md
246
248
  [verify] 已写回读 OK: facts/2026-09-01-0001.md
247
249
  ```
248
250
 
@@ -250,7 +252,7 @@ bash install.sh --list # 列出智能体 -> 默认目录
250
252
 
251
253
  ```text
252
254
  共 3 条记忆(前 3 条):
253
- [FACT] 项目名: 描述……(D:\.yottamemory\facts\xxx.md)
255
+ [FACT] 项目名: 描述……(~/.yottamemory/facts/xxx.md)
254
256
  ```
255
257
 
256
258
  **context(开工上下文包)**:
@@ -316,10 +318,10 @@ bash install.sh --agent <智能体名称>
316
318
  | `yotta-memory reindex` | 重建索引(手动改 .md 后校正)|
317
319
  | `yotta-memory export [--out f.json]` / `import <f.json>` | 导出 / 导入 |
318
320
  | `yotta-memory config set <键> <值>` / `config get` | 记忆库位置与引擎参数(`memory_home` / `embedding_cmd` / `embedding_timeout` / `maintain_archived_utility` / `maintain_decay_halflife_<TYPE>` / `consolidate_*` 等)|
319
- | `yotta-memory whoami` | 查看当前智能体身份与登记状态(读 `YOTTA_AGENT_ID` / `X-Agent-Id`,不猜不默认)|
321
+ | `yotta-memory whoami --agent <id>` | 查看当前显式身份与登记状态;环境身份仅在 MCP 信任标记下有效 |
320
322
  | `yotta-memory iam <id> [--name <显示名>] [--user <用户名>] [--relationship <关系>] [--force]` | 登记本智能体唯一身份并自动落自我档案(`agents.json`,ID 必须唯一;可选扩展显示名 / 用户 / 关系)|
321
323
  | `yotta-memory token new --agent <id> [--force]` / `token list` / `token revoke --agent <id>` | 为智能体生成 / 列出 / 吊销访问 token(登记于记忆库 `.server/tokens.json`;同 ID 已被其它来源占用需 `--force` 覆盖,防不同智能体合流)|
322
- | `yotta-memory serve [--host 0.0.0.0] [--port 8787] [--no-auth] [--stdio]` | 启动 MCP 记忆引擎(streamable HTTP 局域网 / --stdio 本地零进程模式;Bearer token + X-Agent-Id 鉴权)|
324
+ | `yotta-memory serve [--host 0.0.0.0] [--port 8787] [--no-auth] [--stdio]` | 启动 MCP 记忆引擎(streamable HTTP 局域网 / --stdio 本地零进程模式;Bearer token + X-Agent-Id + X-Agent-Key 鉴权)|
323
325
  | `yotta-memory lan enable [--onstart] / disable / status` | 开机自启管理(Windows:计划任务,默认 ONLOGON、--onstart 开机即启需管理员,非管理员自动降级用户级 Startup 静默自启;Linux:systemd 用户单元,不可用时自动降级用户 crontab @reboot)|
324
326
  | `yotta-memory maintain [--dry-run] [--apply] [--purge] [--threshold N] [--age N] [--dedup] [--dedup --apply] [--merge A,B]` | 记忆自组织:归档 / 遗忘候选 / 置信度查重 / 自动合并高置信组;默认 dry-run;`--dedup` 与归档互斥 |
325
327
  | `yotta-memory consolidate [--min-age N] [--min-idle N] [--max-utility N] [--min-group N] [--period N] [--type T] [--model <cmd>] [--apply] [--undo <batch>] [--batches]` | 周期摘要压缩(v0.10.0):同主题旧记忆 → 带溯源摘要 + 原文归档;默认 dry-run;`--undo <batch>` 回滚批次;`--batches` 查批次 |
@@ -341,7 +343,8 @@ yotta-memory recall --type FACT --limit 10
341
343
 
342
344
  环境变量:
343
345
  - `YOTTA_MEMORY_HOME`:覆盖用户级记忆库目录(默认 `~/.yottamemory/`)。
344
- - `YOTTA_AGENT_ID` / `AGENT_ID`:当前 agent 标识(本机声明身份用,参与读取分区判定;私密记忆必须有 owner,未声明会被拒绝)。
346
+ - `YOTTA_AGENT_ID` / `AGENT_ID`:仅用于 MCP 进程身份,必须配合 `YOTTA_MEMORY_TRUST_ENV_AGENT=1`;禁止用户级全局 fallback。
347
+ - `YOTTA_MEMORY_AGENT_KEY`:per-agent 32 字节 key,用于解开 `keys/bindings/<id>.key.agent`;加密私密读写必填。授权后先由 AI 执行 `key status` / `key claim` 领取到 `<AI_HOME>/.yotta-memory-agent-key`,MCP 宿主再从该文件注入。
345
348
 
346
349
  ## 智能体接入后怎么用
347
350
 
@@ -352,7 +355,7 @@ yotta-memory recall --type FACT --limit 10
352
355
  记忆库可以装在任何主机或硬盘上(= 记忆引擎),供局域网内其它主机上的智能体远程接入:
353
356
 
354
357
  - **本机直连**:CLI 直接读写,无需 token;
355
- - **远程接入**:引擎主机运行 `yotta-memory serve` 常驻(或 `lan enable` 注册开机自启),远程智能体通过 MCP 以 `url + token` 连接。
358
+ - **远程接入**:引擎主机运行 `yotta-memory serve` 常驻(或 `lan enable` 注册开机自启),远程智能体通过 MCP 以 `url + token + agent_key` 连接;同机 / 共享文件系统用 `key claim` 领取,跨机不共享文件系统时由用户安全传输宿主 key 文件。
356
359
  - **本地零进程**:本机 MCP 客户端可用 `serve --stdio` 按需拉起 CLI(无常驻进程)。
357
360
 
358
361
  ### 引擎侧(记忆所在主机)
@@ -365,7 +368,7 @@ yotta-memory recall --type FACT --limit 10
365
368
  yotta-memory token revoke --agent <智能体ID> # 吊销
366
369
  ```
367
370
  > 新生成的 token 即时生效,无需重启服务。
368
- 3. 启动服务(默认监听 0.0.0.0:8787,Bearer token + X-Agent-Id 鉴权)——临时运行或注册开机自启二选一:
371
+ 3. 启动服务(默认监听 0.0.0.0:8787,Bearer token + X-Agent-Id + X-Agent-Key 鉴权)——临时运行或注册开机自启二选一:
369
372
  ```bash
370
373
  yotta-memory serve # 临时前台运行
371
374
  yotta-memory lan enable # 注册开机自启(Windows:计划任务/用户级 Startup;Linux:systemd 用户单元/用户 crontab)
@@ -377,7 +380,14 @@ yotta-memory recall --type FACT --limit 10
377
380
 
378
381
  ### 客户端侧(远程智能体)
379
382
 
380
- 在智能体 MCP 配置中登记连接(`url` + 两个请求头):
383
+ 在智能体 MCP 配置中登记连接前,先确认该 AI 已领取 agent_key:
384
+
385
+ ```bash
386
+ yotta-memory key status <智能体ID> --to <AI_HOME>
387
+ yotta-memory key claim <智能体ID> --to <AI_HOME>
388
+ ```
389
+
390
+ 如果引擎与 AI 不在同一文件系统,`key claim` 不能在远端直接读取 pending,需要用户用密码管理器或安全文件传输把 key 放到目标宿主目录。然后再登记连接(`url` + 三个请求头):
381
391
 
382
392
  ```json
383
393
  {
@@ -386,14 +396,15 @@ yotta-memory recall --type FACT --limit 10
386
396
  "url": "http://<引擎主机IP>:8787/mcp",
387
397
  "headers": {
388
398
  "Authorization": "Bearer <TOKEN>",
389
- "X-Agent-Id": "<本智能体ID>"
399
+ "X-Agent-Id": "<本智能体ID>",
400
+ "X-Agent-Key": "<本智能体宿主 key 文件中的 agent_key>"
390
401
  }
391
402
  }
392
403
  }
393
404
  }
394
405
  ```
395
406
 
396
- 连接后可通过 MCP tools(remember / recall / search / context / doctor / forget / archive / reindex / export / import / agent_info)读写记忆与确认身份;管理动作(init / config / token / lan / serve)不进 MCP,token 管理不远程暴露;MCP export/import 路径限记忆库内、distill 不支持 `--model`,MCP 也不接受远端传入 embedding 命令——embedding 插件只能由引擎主机本地 `config set embedding_cmd` 配置。`X-Agent-Id` 必须与 token 登记的智能体一致;读取分区规则与 CLI 相同(FACT 公共可读,PREF / BOUND / COMMIT 私密隔离)。
407
+ 连接后可通过 MCP tools(remember / recall / search / context / doctor / forget / archive / reindex / export / import / agent_info)读写记忆与确认身份;管理动作(init / config / token / lan / serve)不进 MCP,token 管理不远程暴露;MCP export/import 路径限记忆库内、distill 不支持 `--model`,MCP 也不接受远端传入 embedding 命令——embedding 插件只能由引擎主机本地 `config set embedding_cmd` 配置。`X-Agent-Id` 必须与 token 登记的智能体一致;加密私密读写还必须携带匹配的 `X-Agent-Key`。读取分区规则与 CLI 相同(FACT 公共可读,PREF / BOUND / COMMIT 私密隔离)。
397
408
 
398
409
  ### 位置持久化
399
410
 
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、事务快照
4
- version: 0.13.0
4
+ version: 0.13.2
5
5
  license: MIT
6
6
  ---
7
7
 
@@ -104,8 +104,8 @@ yotta-memory backup doctor --id <备份ID>
104
104
  yotta-memory backup restore <备份ID> --to <新目录>
105
105
 
106
106
  # 恢复演练:恢复到隔离副本,校验 manifest、索引并解密一条测试私密
107
- # 默认用本机已有的 owner 授权缓存;完全裸恢复请加 --recovery-key
108
- yotta-memory backup drill [<备份ID>]
107
+ # 解密必须有 --recovery-key 或 --password;legacy keys/cache 不参与
108
+ yotta-memory backup drill [<备份ID>] --recovery-key <钥匙>
109
109
  ```
110
110
 
111
111
  - 备份覆盖:`facts/`、`private/`、`keys/`(排除 `keys/cache/` 授权缓存)、`agents.json`、`index.json`、`.archive/`。
@@ -218,7 +218,7 @@ yotta-memory doctor --json
218
218
  - 输出 `memory_home: <目录>`(已显式设置)→ 直接用该位置。
219
219
  - 输出 `memory_home: (未设置,默认 ~/.yottamemory)` → 🔒 征得同意后引导设置:问用户用默认还是指定目录(项目级 `<repo>/.yottamemory`、记忆盘等),确认后 AI 执行 `yotta-memory config set memory_home <目录>`,回读 `config get` 验证。
220
220
  2. **已有记忆**:目标目录已存在 `facts/` 等子目录或 `index.json` → 直接 recall;全新目录 → 按「便携记忆盘模式 §0.3」初始化。
221
- 3. **私密区已加密(存在 `keys/`)**:先 `yotta-memory key list` 确认本智能体是否有授权缓存;没有 → 提醒用户 `yotta-memory view` → 在平台「授权本智能体」后再读写私密(公共 FACT 不受影响)。
221
+ 3. **私密区已加密(存在 `keys/`)**:先 `yotta-memory key list` 确认本智能体是否有 agent binding;没有 → 告知用户由用户自己执行 `yotta-memory view` → 浏览器打开平台 → 输入主口令 → 点「授权」并保存只展示一次的 `agent_key`。用户授权后服务端会写 `keys/pending/<id>.key`;AI 在新会话执行 `yotta-memory key status <id> --to <AI_HOME>`,有 pending 就执行 `yotta-memory key claim <id> --to <AI_HOME>`,落到 `<AI_HOME>/.yotta-memory-agent-key` 后再使用 `--agent-key-file`。**升级后首次调用元忆 / 重启会话时**,若输出 `[YTM_MIGRATION_REQUIRED]`,必须主动把 marker、受影响 agent 和处理步骤转达给用户。**AI 不得代替用户执行 `migrate` / `key bind` 迁移**,只负责提醒和讲解(marker 只列仍有私密数据、未绑定的 agent;仅有 legacy cache、无迁移数据的 owner 会单独提示,不进入迁移清单;公共 FACT 不受影响)。
222
222
 
223
223
  **B. 确认本智能体唯一身份(强制,写私密记忆前必做)**:
224
224
 
@@ -231,7 +231,7 @@ yotta-memory doctor --json
231
231
  - 回读:`yotta-memory whoami` 显示「已登记 + 自我档案」。
232
232
  3. **自我档案校验**:`yotta-memory recall "自我接入档案"`(本智能体)能读回字段才算就绪:
233
233
  `agent_id / host / memory_home / mcp_mode(stdio|http)/ engine_url(仅远端)/ token(仅远端;本机不存 token)`,可扩展 `agent_name / user_name / relationship`(`iam --name/--user/--relationship` 写入)。
234
- 4. **本机多智能体**:本机多个 AI 智能体共用引擎时,**每个都必须**在它自己的 MCP 配置里声明唯一 `YOTTA_AGENT_ID`(如 `env: { YOTTA_AGENT_ID: "<该智能体唯一ID>" }`),各自 `whoami` 各回各的、互不撞;本机走 stdio 免 token。
234
+ 4. **本机多智能体(v0.13.2 安全模型)**:owner ID 不是身份认证。每个 AI 必须同时持有自己的 `agent_key`,并在 MCP 配置里注入 `YOTTA_AGENT_ID` + `YOTTA_MEMORY_AGENT_KEY` + `YOTTA_MEMORY_TRUST_ENV_AGENT=1`;CLI 直连用 `--agent <id> --agent-key <key>` 或 `--agent-key-file <文件>`。没有 agent_key 时,私密读写一律 fail-closed;禁止使用用户级 / 机器级 `YOTTA_AGENT_ID` fallback。
235
235
 
236
236
  **C. 身份红线(强制)**:
237
237
 
@@ -253,10 +253,10 @@ yotta-memory doctor --json
253
253
  | 命令 | 作用 |
254
254
  |---|---|
255
255
  | `yotta-memory init [--project] [--dir <目录>] [--attach] [--encrypt|--no-encrypt]` | 初始化(**新建默认加密**:设主口令 + 抄下恢复钥匙;已有库必须用 `--attach`,默认拒绝覆盖;`--no-encrypt` 降级明文;老明文库用 `migrate`)|
256
- | `yotta-memory migrate` | 明文私密区 → 密文迁移(需主口令;迁移后打印恢复钥匙;当前智能体自动获得授权缓存)|
256
+ | `yotta-memory migrate` | 明文私密区 → 密文迁移(**由用户执行**;需主口令;迁移后打印恢复钥匙;不写明文授权缓存,授权由用户在 `view` 平台完成)|
257
257
  | `yotta-memory view [--port 8788] [--host 127.0.0.1]` | 用户查看平台(本机 Web:口令解锁浏览 / 搜索 / 导出全部 AI 记忆 + 授权 / 吊销 AI + 重设口令 + 显示恢复钥匙)|
258
258
  | `yotta-memory reset-password [--password <当前> | --recovery-key <钥匙>] [--new-password <新>]` | 重设主口令(忘口令用恢复钥匙)|
259
- | `yotta-memory key list / authorize <id> / revoke <id>` | 管理 AI 私密读取授权缓存(authorize 需主口令;revoke 立即吊销该 AI 解密能力)|
259
+ | `yotta-memory key list / bind <id> / rotate <id> / claim <id> --to <AI_HOME> / status <id> / revoke <id>` | 管理 agent_key binding(**bind/rotate 由用户执行**,需主口令或恢复钥匙;claim/status 由 AI 读取 pending 并落到宿主目录;revoke 立即吊销该 AI 解密能力,旧 key 随即校验失败;`key list` 输出 `[YTM_MIGRATION_REQUIRED]` 时提醒用户走 `view` 重新授权)|
260
260
  | `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 关闭类型启发式提示)|
261
261
  | `yotta-memory recall [关键词] [--type T] [--limit N] [--agent <id>] [--owner <id>] [--all] [--unsafe] [--explain] [--semantic] [--embedding <command>] [--embedding-timeout N]` | 检索(v0.8.0 默认语义检索:同义词 / 拼音全拼+首字母 / 字段加权 / 模糊匹配 + 效用分融合排序;v0.9.0 支持可选本地 embedding 插件,失败自动降级;`--explain` 显示命中理由与效用分项;`--semantic` 显式开启;读取分区过滤;越界读其它智能体私密默认拒绝,需 grant / identity=user / `--unsafe`;`--agent <其它>` 只作身份声明/展示,不授予跨读——读他人私密同样要授权;项目级优先)|
262
262
  | `yotta-memory profile [--owner <id>]` | 生成用户画像(聚合 `private/<owner>/` 原文,零推断,写 `profile.md`;跨 owner 默认拒绝)|
@@ -269,10 +269,10 @@ yotta-memory doctor --json
269
269
  | `yotta-memory reindex` | 重建索引(手动改 .md 后校正)|
270
270
  | `yotta-memory export [--out f.json]` / `import <f.json>` | 导出 / 导入 |
271
271
  | `yotta-memory config set memory_home <目录>` / `config set backup_dir <目录>` / `config get` | 持久记住 / 查看记忆库位置与备份目录(`~/.yottamemory/config.json`)|
272
- | `yotta-memory whoami` | 查看当前智能体身份与登记状态(读 `YOTTA_AGENT_ID` / `X-Agent-Id`,不猜不默认)|
272
+ | `yotta-memory whoami --agent <id> [--agent-key <key>]` | 查看当前显式身份与登记状态;环境身份仅在 MCP 信任标记下有效 |
273
273
  | `yotta-memory iam <id> [--name <显示名>] [--user <用户名>] [--relationship <关系>] [--force]` | 登记本智能体唯一身份并自动落自我档案(`agents.json`,ID 必须唯一;可选扩展显示名 / 用户 / 关系)|
274
274
  | `yotta-memory token new --agent <id> [--force]` / `token list` / `token revoke --agent <id>` | 每智能体访问 token:生成 / 列出 / 吊销(登记 `<记忆库>/.server/tokens.json`;同 ID 已被其它来源占用需 `--force` 覆盖,防不同智能体合流)|
275
- | `yotta-memory serve [--host 0.0.0.0] [--port 8787] [--no-auth] [--stdio]` | 启动 MCP 记忆引擎(streamable HTTP 局域网 / --stdio 本地零进程模式;Bearer token + X-Agent-Id 鉴权)|
275
+ | `yotta-memory serve [--host 0.0.0.0] [--port 8787] [--no-auth] [--stdio]` | 启动 MCP 记忆引擎(streamable HTTP 局域网 / --stdio 本地零进程模式;Bearer token + X-Agent-Id + X-Agent-Key 鉴权)|
276
276
  | `yotta-memory lan enable [--onstart] / disable / status` | 开机自启管理(Windows:计划任务,默认 ONLOGON、--onstart 开机即启需管理员,非管理员自动降级用户级 Startup 静默自启,v0.6.3 起 VBS 自愈不弹 80070002;Linux:systemd 用户单元,不可用时自动降级用户 crontab @reboot)|
277
277
  | `yotta-memory feedback <文件|主题> --useful|--useless [--reason <原因>] [--undo]` | 显式使用反馈(v0.8.0 自我学习闭环:useful → weight×1.2 / useless → weight×0.8,confidence / feedback_net 同步演化;`--undo` 回滚最近一次;审计写 `.archive/feedback-<日期>.jsonl`)|
278
278
  | `yotta-memory maintain [--dry-run] [--apply] [--purge] [--threshold N] [--age N] [--dedup] [--dedup --apply] [--merge A,B]` | 记忆自组织(v0.8.0 自我进化 + v0.10.0 自动合并):默认 dry-run 预览;`--apply` 执行归档(immutable / BOUND 豁免;私密归档入 `.archive/private/<owner>/<type>/`),`--purge` 才真删遗忘候选;`--dedup` 查重并给**置信度分档**(≥0.85 高置信 / 0.65–0.85 建议手动 / 其余忽略),`--dedup --apply` 自动合并同归属高置信组(写批次审计可回滚;与归档互斥,不误归档);`--merge A,B` 手动合并两条;审计写 `.archive/audit-<日期>.jsonl`)|
@@ -292,7 +292,7 @@ yotta-memory doctor --json
292
292
  ├── private/<owner>/index.enc # 加密库:每 owner 加密索引(YTMIDX1,Owner Key 加密)
293
293
  ├── .archive/ # 归档区
294
294
  ├── index.json # 公共 FACT 检索索引(加密库只含公共条目)
295
- ├── keys/ # 加密库密钥库:salt / <owner>.key.enc(UMK 包裹) / <owner>.key.recovery(恢复钥匙包裹) / recovery.key.enc / cache/<id>.key(授权缓存 600)
295
+ ├── keys/ # 加密库密钥库:salt / <owner>.key.enc(UMK 包裹) / <owner>.key.recovery(恢复钥匙包裹) / recovery.key.enc / bindings/<id>.key.agent;legacy cache/<id>.key 不再加载
296
296
  └── agents.json # 智能体身份登记表(唯一性)
297
297
  ```
298
298
 
@@ -318,10 +318,64 @@ yotta-memory doctor --json
318
318
 
319
319
  ### 流程
320
320
  1. **建加密库**:`yotta-memory init --encrypt`(新建默认加密)→ 设主口令 → 抄下恢复钥匙离线保存。
321
- 2. **老库迁移**:`yotta-memory migrate`(需主口令)→ 明文私密逐文件加密后删除明文 → 打印恢复钥匙 → 当前智能体自动获得授权缓存,其余 AI 需平台授权。
322
- 3. **AI 读写自己的私密**:AI 声明身份后需**平台授权一次**——`yotta-memory view` → 输口令 → 点「授权 <该AI>」→ 平台把 owner key 写入 `keys/cache/<id>.key`(600 权限)。之后该 AI 正常 `remember / recall / profile / context`(私有读写自动加解密);未授权时写私密报「需在用户平台授权」,公共 FACT 不受影响。
321
+ 2. **老库迁移**:由用户执行 `yotta-memory migrate`(需主口令)→ 明文私密逐文件加密后删除明文 → 打印恢复钥匙。迁移不写明文授权缓存;每个 AI 的重新授权由用户自己在 `yotta-memory view` 平台完成并自行备份弹窗 `agent_key`;AI 随后用 `key status` / `key claim` 领取(AI 只提醒授权,不代执行 `migrate` / `key bind`)。
322
+ 3. **AI 读写自己的私密(v0.13.2)**:用户侧完成一次 `yotta-memory view` 授权(或用户自行执行 `yotta-memory key bind <id>`),生成只展示一次的 `agent_key`,并写入 `keys/bindings/<id>.key.agent` 与临时 `keys/pending/<id>.key`。AI 新会话用 `key status` / `key claim` 将 pending 落到 `<AI_HOME>/.yotta-memory-agent-key`,之后 CLI 用 `--agent <id> --agent-key-file <宿主key文件>`;MCP 注入 `YOTTA_AGENT_ID` + `YOTTA_MEMORY_AGENT_KEY` + `YOTTA_MEMORY_TRUST_ENV_AGENT=1`。owner ID 单独存在时不能解密私密;legacy `keys/cache/<id>.key` 不再加载。
323
323
  4. **用户查看全部 AI 记忆**:`yotta-memory view` → 输口令 → 浏览 / 搜索 / 导出全部(含各 AI 私密明文,仅用户可见)。口令只在本地内存派生,不落盘、不发远端;默认仅 127.0.0.1,远程需 `--host` 显式开启。
324
- 5. **口令管理**:`yotta-memory reset-password`(当前口令或恢复钥匙);`key revoke <id>` 立即吊销某 AI 的授权缓存(该 AI 随即失去解密能力)。
324
+ 5. **口令管理**:`yotta-memory reset-password`(当前口令或恢复钥匙);`key revoke <id>` 立即吊销某 AI 的 agent binding(该 AI 随即失去解密能力)。`view` 平台的「授权」只对未绑定 agent 生成新 key;已绑定的 agent 需先「吊销」再授权,避免误打断在用的 agent_key。
325
+
326
+ ## agent_key 本地领取与恢复流程(v0.13.2,AI 必读)
327
+
328
+ > 目标:用户只负责在 `view` 平台授权和备份弹窗 key;AI 负责把待领取 key 落到自己的宿主目录,并在新会话稳定读取。模型上下文不需要出现 key 明文。
329
+
330
+ ### 1. 首次授权
331
+
332
+ 1. 用户在 `yotta-memory view` 中解锁并点「授权」。
333
+ 2. 引擎生成该 AI 的 `agent_key`,写入:
334
+ - 校验器:`keys/bindings/<agent_id>.key.agent`
335
+ - 临时待领取:`keys/pending/<agent_id>.key`
336
+ 3. 页面弹窗显示一次 `agent_key`。**这是用户侧备份**,用户可选择保存到密码管理器或自己保管;AI 不要求用户把 key 发到聊天。
337
+
338
+ ### 2. AI 新会话领取
339
+
340
+ AI 在开工身份检查后执行:
341
+
342
+ ```bash
343
+ yotta-memory key status <agent_id> --to <AI_HOME>
344
+ ```
345
+
346
+ 若输出 `pending: yes`,执行:
347
+
348
+ ```bash
349
+ yotta-memory key claim <agent_id> --to <AI_HOME>
350
+ ```
351
+
352
+ `claim` 会:
353
+
354
+ 1. 读取 `keys/pending/<agent_id>.key`
355
+ 2. 用 binding 验证 key 是否正确
356
+ 3. 原子写入 `<AI_HOME>/.yotta-memory-agent-key`
357
+ 4. 回读校验
358
+ 5. 删除 pending 文件
359
+
360
+ 成功后 CLI 使用:
361
+
362
+ ```bash
363
+ yotta-memory context --agent <agent_id> --agent-key-file <AI_HOME>/.yotta-memory-agent-key
364
+ ```
365
+
366
+ MCP 模式由宿主把宿主 key 文件内容注入 `YOTTA_MEMORY_AGENT_KEY`,并设置 `YOTTA_AGENT_ID` + `YOTTA_MEMORY_TRUST_ENV_AGENT=1`。
367
+
368
+ ### 3. key 丢失与重新授权
369
+
370
+ - AI 宿主 key 文件丢失、用户还留着弹窗备份:把备份写回 `<AI_HOME>/.yotta-memory-agent-key`,不需要重新授权。
371
+ - AI 文件和用户备份都丢失:用户先在 `view` 中「吊销」,再「授权」。新 key 会重新生成;**旧 key 立即校验失败**,pending 会重新产生,AI 再执行一次 `key claim`。
372
+ - `key revoke` 会删除 binding 和 pending;长驻 MCP 进程也会在后续读取时重新校验 binding,不能继续使用旧 key。
373
+
374
+ ### 4. 安全边界
375
+
376
+ - pending 文件与宿主 key 文件是临时/本地凭据,备份和 export 默认排除 pending。
377
+ - 本模型不承诺对抗同一 OS 用户下的恶意进程;其他 AI 若拥有同用户文件读取能力,理论上仍可能读取宿主 key。
378
+ - 用户弹窗备份用于恢复,AI 宿主 key 用于运行;两者职责分离。
325
379
 
326
380
  ## 便携记忆盘模式(局域网多机共享)
327
381
 
@@ -340,7 +394,7 @@ yotta-memory doctor --json
340
394
  |---|---|---|
341
395
  | 用户级(默认) | `~/.yottamemory` | 个人跨项目记忆 |
342
396
  | 项目级 | `<repo>/.yottamemory` | 随项目提交共享 |
343
- | 便携记忆盘 | 硬盘上目录(如 `D:\memory` / 挂载点) | 记忆盘 / 局域网共享 |
397
+ | 便携记忆盘 | 任意盘符或挂载点下的目录(如 `<memory-disk>/yottamemory`) | 记忆盘 / 局域网共享 |
344
398
 
345
399
  **步骤 0.3 接入现有 vs 初始化新库(关键判断)**
346
400
  1. 检查目标目录是否已是记忆库:存在 `facts/` 等子目录或 `index.json`。
@@ -356,7 +410,7 @@ yotta-memory doctor --json
356
410
  > 记忆盘场景:硬盘插上 → AI 检查盘上目录是否有数据 → 有则接入 + config 记住 → 插盘即恢复,机器记住位置。
357
411
 
358
412
  **步骤 0.5 启动记忆引擎(仅引擎主机,供远程接入)**
359
- - 本机若作引擎:🔒 **征得同意后**启动服务——临时运行 `yotta-memory serve`(默认 `0.0.0.0:8787`,Bearer token + X-Agent-Id 鉴权;`--no-auth` 仅限可信内网),或注册开机自启 `yotta-memory lan enable`(Windows:优先计划任务,默认登录自启;非管理员自动降级用户级 Startup 静默自启,免管理员)。
413
+ - 本机若作引擎:🔒 **征得同意后**启动服务——临时运行 `yotta-memory serve`(默认 `0.0.0.0:8787`,Bearer token + X-Agent-Id + X-Agent-Key 鉴权;`--no-auth` 仅限可信内网),或注册开机自启 `yotta-memory lan enable`(Windows:优先计划任务,默认登录自启;非管理员自动降级用户级 Startup 静默自启,免管理员)。
360
414
  - 本地零进程模式:本机 AI 也可用 `serve --stdio` 由 MCP 客户端按需拉起 CLI(无常驻进程)。
361
415
  - 远程客户端接入前,先确认引擎主机 serve 已运行(`lan status` 可查)。
362
416
 
@@ -376,14 +430,15 @@ yotta-memory doctor --json
376
430
  ### 4.4 本机直连
377
431
  确认记忆库目录(`config get` / `YOTTA_MEMORY_HOME` / 默认 `~/.yottamemory`)→ 直接 CLI 读写,**不配置 MCP、不需要 token**。
378
432
 
379
- ### 4.5 远程连接:AI 引导用户获取 token(用户只做复制粘贴)
433
+ ### 4.5 远程连接:AI 引导用户获取 token 与 agent_key
380
434
  1. AI 告知需要为本智能体申请访问 token。
381
435
  2. AI 引导用户在**引擎主机**执行:`yotta-memory token new --agent <本智能体ID>`(引擎主机没装 → 按 4.0 先装;或请引擎主机上的 AI 代执行)。
382
436
  3. 命令打印 token(`ytm_...`),只打印一次,请用户妥善保管。
383
- 4. AI 请用户复制 token 发给 AI。
384
- 5. 用户发来 → AI 继续 4.6。
437
+ 4. 确认本智能体已持有 `agent_key`;没有时由用户在引擎主机执行 `yotta-memory view` 授权并保存弹窗 key,引擎会同时写 `keys/pending/<id>.key`。
438
+ 5. 如果 AI 宿主与记忆库同机或能访问同一文件系统:AI 执行 `yotta-memory key status <id> --to <AI_HOME>`,有 pending 就 `key claim`,写到 `<AI_HOME>/.yotta-memory-agent-key`。
439
+ 6. 如果 AI 宿主与引擎主机不共享文件系统:pending 不能跨机自动读取。用户必须通过密码管理器、加密文件传输或目标主机本地输入把 key 放到 AI 宿主目录;不要粘贴到聊天窗口。
385
440
 
386
- > 用户不会操作时:AI 逐步引导(开终端 → 粘贴命令 → 回车 → 复制输出),直到成功。**除复制粘贴外用户不做别的**。
441
+ > token 可以按用户习惯复制;agent_key 属于私密能力,优先走 `key claim` 或安全文件传输,不走对话明文。
387
442
 
388
443
  ### 4.6 配置 MCP(AI 自己完成,🔒 需同意)
389
444
  1. 🔒 说明将把 yotta-memory 写入本智能体 MCP 配置并请用户同意;
@@ -412,16 +467,19 @@ yotta-memory doctor --json
412
467
  "url": "http://<IP>:8787/mcp",
413
468
  "headers": {
414
469
  "Authorization": "Bearer <TOKEN>",
415
- "X-Agent-Id": "<本智能体ID>"
470
+ "X-Agent-Id": "<本智能体ID>",
471
+ "X-Agent-Key": "<本智能体的 agent_key>"
416
472
  }
417
473
  }
418
474
  }
419
475
  }
420
476
  ```
421
477
 
478
+ `X-Agent-Key` 的值来自该 AI 的宿主 key 文件 `<AI_HOME>/.yotta-memory-agent-key`。同机 / 共享文件系统先用 `key claim` 写入;不共享文件系统时由用户安全传输,不要把 key 发到对话里。配置文件写入前仍需获得用户同意。
479
+
422
480
  ### 4.9 验证连接(循环兜底)
423
481
  - 🔒 连接远程引擎前已获同意(4.5 / 4.6)→ 调一次 `recall` / `search` 确认能读到记忆 → 成功。
424
- - 失败:查 IP / 端口 / token 完整性 / 防火墙 / token 吊销;仍失败回 4.3。
482
+ - 失败:查 IP / 端口 / token 完整性 / agent_key 是否匹配 / 是否已吊销 / 防火墙 / token 吊销;仍失败回 4.3。
425
483
 
426
484
  ### 4.10 复用
427
485
  - 成功后优先复用现有连接;失败(token 吊销等)再回 4.3。
@@ -431,7 +489,7 @@ yotta-memory doctor --json
431
489
  常见问题与避坑见 `references/faq.md`:
432
490
  - 类型选错 → 只提示不阻止;`forget` 后按正确类型重写;
433
491
  - 私密区加密 → `init` 默认加密(主口令+恢复钥匙),明文库 `migrate` 升级,`view` 平台口令解锁;
434
- - 多智能体权限 → FACT 公共、私密按 owner 隔离,需 `key authorize` / `view` 授权;
492
+ - 多智能体权限 → FACT 公共、私密按 owner 隔离;用户授权后写 binding + pending,AI 用 `key claim` 领取到宿主目录;owner ID 不是认证,吊销后旧 key 立即失效;
435
493
  - 记忆找不到 → `config get` 查位置 → `reindex` → `recall` / `search`;
436
494
  - 忘记主口令 → 用恢复钥匙 `reset-password`;
437
495
  - 局域网 → 引擎 `lan enable` + `token new`,客户端配 url+token。