docs: correct accuracy issues from review

This commit is contained in:
youzini
2026-05-31 17:20:58 +00:00
parent 31ee161c6e
commit 40b4c316a0
6 changed files with 44 additions and 27 deletions

View File

@@ -14,20 +14,28 @@
聊天身份是一切持久化的主键。问题从来不是"chatId 这个键选错了",而是"有好几个来源都自称是当前身份,还互相偷偷顶替"。
身份核心在 `runtime/identity-resolver.js`,把身份明确拆成**四条独立通道**,绝不互相顶替:
身份核心在 `runtime/identity-resolver.js`,把身份明确**四类语义**区分对待,绝不互相顶替:
| 通道 | 含义 | 唯一来源 |
| 类别 | 含义 | 来源 |
| --- | --- | --- |
| **active identity** | 当前宿主活动聊天 | 只来自宿主上下文context integrity / hostChatId 的已知别名 / hostChatId |
| **active / current identity** | 当前宿主活动聊天 | 只来自宿主上下文context integrity / hostChatId 的已知别名 / hostChatId |
| **graph-owner identity** | 图谱自带的所属身份 | 图谱 meta只用于校验/恢复 |
| **queued identity** | 排队持久化的身份 | 持久化队列状态,只用于校验 |
| **queued identity** | 排队持久化的身份 | 持久化状态,只用于校验/恢复 |
| **marker identity** | commit marker 的身份 | commit marker只用于校验/恢复 |
实现上:
- **active/current** 由独立入口 `resolveCurrentChatIdentityCore()` 解析,只认宿主上下文来源。
- **graph-owner** 由 `resolveGraphOwnerIdentityCore()` 解析。
- **queued / marker** 没有各自独立的解析入口——它们和 graph-owner 一起,在 `resolveRuntimeGraphFallbackIdentityCore()` / `resolvePersistenceChatIdCore()` 这类**恢复/兜底**聚合里被读取(含 `persistenceState.queuedPersistChatId``persistenceState.commitMarker.chatId`),并配合调用方的身份等值校验使用。
关键不在于"每类都有独立函数",而在于**只有 active/current 这条通道能产出"当前聊天",其余通道一律只进校验/恢复,不能升格为活动身份**。
**核心不变量:**
> active identity 只能来自宿主上下文。graph-owner / queued / marker 身份只能用于校验和恢复,**绝不能"偷偷"变成当前聊天**。
这正是"未进入聊天"那类 bug 的根:旧代码用一个"优先级抽奖"函数接受十几个竞争来源,结果某个非活动身份被当成了活动聊天。现在 `resolveActiveIdentity` / `resolveGraphOwnerIdentity` / `resolveQueuedIdentity` / `resolveMarkerIdentity` 是分开的入口,不给聚合入口诱导污染
这正是"未进入聊天"那类 bug 的根:旧代码用一个"优先级抽奖"函数接受十几个竞争来源,结果某个非活动身份被当成了活动聊天。现在 active/current 有专门入口,恢复/兜底身份走单独的 fallback 聚合,不给"非活动身份污染活动身份"留口子
> 身份是每次操作解析一次、显式传递的,不是从全局随用随取。
@@ -35,7 +43,7 @@
持久化确认逻辑收敛在 `sync/persistence-reducer.js`,是**纯函数**:无 IO、无图谱变更、无 UI 副作用。
它把"这批记忆到底存好了没"变成 `(身份, 存储层 tier, 版本 revision, 证据)` 的纯函数。核心不变量写死进 reducer而不是到处打补丁
它把"这批记忆到底存好了没"变成关于 `(身份, 存储层 tier, 版本 revision, 证据)` 的纯计算。核心不变量:
```
已确认版本 >= 排队版本
@@ -44,6 +52,8 @@
⟹ pendingPersist 必须为 false
```
> 实现说明:这条不变量**不是**某个单一 reducer 事件全包的。`reducePersistenceStatePatch()` 处理通用 `ACCEPTED` / `QUEUED` 事件;`buildAcceptedPersistenceStatePatch()` 在规范 tier 被接受时清 `pendingPersist`(但它本身不查排队版本/身份);"陈旧 pending 自动清除"的规划逻辑在纯函数 `planAcceptedPendingClear()``sync/legacy-persistence-repair.js`,经 reducer re-export**身份等值校验在调用方**`index.js` 接受路径)完成后才调用应用函数。所以这条不变量 = 纯规划器 + 调用方身份门禁的合成,而非单个事件转换。
**派生不变量:**
> recovery-only tier`shadow` / `metadata-full` / `runtime-recovery` 等)永远不能推进确认状态。它们只用于灾难恢复,不能被当作"数据已安全落地"的证据。

View File

@@ -5,7 +5,7 @@ ST-BME 可以独立运行(纯前端),也可以在检测到 st-doa/Authorit
## 核心原则
1. **BME 独立运行是第一公民。** 没有 st-doa 时BME 必须完整可用,优雅降级,不报错。纯前端模式显示"纯前端模式",不是错误状态。
2. **第三方自定义 URL embedding 是主流路径。** OpenAI 兼容 `/v1/embeddings`、one-api、new-api、litellm、vLLM、llama.cpp、Ollama 桥接等都是一等公民。embedding 默认在客户端执行(`embeddingExecution` 默认 `client`)。
2. **第三方自定义 URL embedding 是主流路径。** OpenAI 兼容 `/v1/embeddings`、one-api、new-api、litellm、vLLM、llama.cpp、Ollama 桥接等都是一等公民。embedding 默认在客户端执行(`embeddingTransportMode` 默认 `"direct"`,直连第三方 URL)。
3. **集成是自动的,不需要用户配置。** 能力探测驱动的升级/降级,没有面向用户的"服务器模式"开关。既要优雅降级(无 st-doa也要优雅升级有 st-doa全程零用户干预。
> Authority 是**增强层**,不是硬依赖。它不生成 embedding——只通过 Trivium 存储/搜索向量,并要求调用方提供向量。

View File

@@ -39,16 +39,18 @@ ST-BME 的图谱数据可能存在多种位置,取决于宿主环境和服务
这是保证"ST-BME 以后不需要再做 v4/v5 大迁移"的核心机制。它**不是**一个信封框架或预留字段,而是一条解析纪律:
### 1. 宽容解析(保留未知字段)
### 1. 宽容解析(保留未知嵌套字段)
> 读取方遇到不认识的字段,必须保留、不报错、不丢弃。
> 读取方遇到不认识的**嵌套**字段(在 meta / state / 各记录里),必须保留、不报错、不丢弃。
具体现状:
- 节点 / 边 / tombstone 记录:整对象克隆,未知字段天然保留。
- `meta`:展开保留,已有 `meta.schemaVersion`
- 顶层:冻结为六键 + 保留未知顶层字段
- **顶层:冻结为六键,未知顶层键会被丢弃**——顶层是契约层,新增顶层键是契约违规(`normalizeGraphSnapshotShape` 只返回这六个键)
原理:如果读取代码遇到不认识的字段就崩或就丢,那么**任何**格式改动都会逼出一次迁移;如果遇到不认识的字段就忽略并原样保留,那么以后所有改动都是**加法**,老版本读新数据照样不崩,永远不需要换命名空间、不需要大搬家。这是 protobuf 这类协议几十年验证过的做法。
> **所以演进规则是:永远不要新增顶层键;新字段一律放进 `meta` / `state` / 记录对象里,那里才保证 round-trip。**
原理:如果读取代码遇到不认识的嵌套字段就崩或就丢,那么**任何**字段改动都会逼出一次迁移;如果遇到不认识的嵌套字段就忽略并原样保留,那么以后所有改动都是**加法**,老版本读新数据照样不崩,永远不需要换命名空间、不需要大搬家。这是 protobuf 这类协议几十年验证过的做法。冻结顶层 + 演进只走嵌套,是这套纪律的边界。
### 2. 只加不减