liquid-loop 0.6.4__tar.gz → 0.7.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. {liquid_loop-0.6.4 → liquid_loop-0.7.1}/PKG-INFO +58 -8
  2. {liquid_loop-0.6.4 → liquid_loop-0.7.1}/README.md +57 -7
  3. {liquid_loop-0.6.4 → liquid_loop-0.7.1}/liquid_loop/__init__.py +3 -3
  4. liquid_loop-0.7.1/liquid_loop/mesh/__init__.py +50 -0
  5. liquid_loop-0.7.1/liquid_loop/mesh/v2.py +173 -0
  6. {liquid_loop-0.6.4 → liquid_loop-0.7.1}/liquid_loop/storage.py +27 -1
  7. {liquid_loop-0.6.4 → liquid_loop-0.7.1}/liquid_loop/workspace.py +67 -13
  8. {liquid_loop-0.6.4 → liquid_loop-0.7.1}/liquid_loop.egg-info/PKG-INFO +58 -8
  9. {liquid_loop-0.6.4 → liquid_loop-0.7.1}/liquid_loop.egg-info/SOURCES.txt +4 -0
  10. {liquid_loop-0.6.4 → liquid_loop-0.7.1}/pyproject.toml +1 -1
  11. liquid_loop-0.7.1/tests/test_consensus_expansion.py +45 -0
  12. liquid_loop-0.7.1/tests/test_nucleate_dual_track.py +115 -0
  13. {liquid_loop-0.6.4 → liquid_loop-0.7.1}/LICENSE +0 -0
  14. {liquid_loop-0.6.4 → liquid_loop-0.7.1}/liquid_loop/__main__.py +0 -0
  15. {liquid_loop-0.6.4 → liquid_loop-0.7.1}/liquid_loop/cli.py +0 -0
  16. {liquid_loop-0.6.4 → liquid_loop-0.7.1}/liquid_loop/cognitive_budget.py +0 -0
  17. {liquid_loop-0.6.4 → liquid_loop-0.7.1}/liquid_loop/entropy.py +0 -0
  18. {liquid_loop-0.6.4 → liquid_loop-0.7.1}/liquid_loop.egg-info/dependency_links.txt +0 -0
  19. {liquid_loop-0.6.4 → liquid_loop-0.7.1}/liquid_loop.egg-info/entry_points.txt +0 -0
  20. {liquid_loop-0.6.4 → liquid_loop-0.7.1}/liquid_loop.egg-info/requires.txt +0 -0
  21. {liquid_loop-0.6.4 → liquid_loop-0.7.1}/liquid_loop.egg-info/top_level.txt +0 -0
  22. {liquid_loop-0.6.4 → liquid_loop-0.7.1}/setup.cfg +0 -0
  23. {liquid_loop-0.6.4 → liquid_loop-0.7.1}/tests/test_entropy.py +0 -0
  24. {liquid_loop-0.6.4 → liquid_loop-0.7.1}/tests/test_peek_seal.py +0 -0
  25. {liquid_loop-0.6.4 → liquid_loop-0.7.1}/tests/test_seal_persistence.py +0 -0
  26. {liquid_loop-0.6.4 → liquid_loop-0.7.1}/tests/test_self_evolve.py +0 -0
  27. {liquid_loop-0.6.4 → liquid_loop-0.7.1}/tests/test_workspace.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: liquid-loop
3
- Version: 0.6.4
3
+ Version: 0.7.1
4
4
  Summary: Self-Organizing Cognitive Memory for AI Agents — Liquid Loop theory implementation
5
5
  Author: fishbook0001
6
6
  Maintainer: fishbook0001
@@ -72,7 +72,7 @@ Dynamic: license-file
72
72
  | **Anchor** 锚点 | 晶种 | 认知关注点,有稳定性值 s ∈ [0,1] |
73
73
  | **Evidence** 证据 | 附着粒子 | 锚点下的具体观察,权重指数衰减 w×0.95ᵗ |
74
74
  | **Memory** 结晶 | 结晶体 | 2+ 条一致 Evidence 自动凝聚,有置信度 c |
75
- | **Entropy** 熵值 | 流体无序度 | 八维加权(锚点漂移 / 冲突密度 / 碎片 / 活跃间隔 / 价值衰减 / 锚定强度 / CPE 三维) |
75
+ | **Entropy** 熵值 (LEI) | 流体无序度 | 八维加权(锚点漂移 / 冲突密度 / 碎片 / 活跃间隔 / 价值衰减 / 锚定强度 / CPE 三维) |
76
76
 
77
77
  **状态判定:**
78
78
  ```
@@ -81,6 +81,12 @@ YELLOW (0.3 ≤ entropy < 0.6) — 需关注
81
81
  RED (entropy ≥ 0.6) — 需清理
82
82
  ```
83
83
 
84
+ > **关于 "Entropy" 的语义澄清 — Liquid Entropy Index (LEI)**
85
+ >
86
+ > 本项目中的 `entropy` 是 **Liquid Entropy Index (LEI): a system-stability deviation metric, inspired by entropy but NOT equivalent to thermodynamic entropy.**
87
+ > 它不是物理熵 `S = -k Σ pᵢ log pᵢ`,而是对**系统状态偏离稳定流形程度**的综合度量——由八个可解释分量人工加权而成(锚点漂移 / 冲突密度 / 证据碎片 / 活跃间隔 / 价值衰减 / 锚定强度 + CPE 三维:回顾性衰退 / 策略漂移 / 泛化崩塌)。
88
+ > 代码层函数名保留 `calculate()`(历史连续性);文档 / 论文层一律以 **LEI** 指称,避免与热力学熵混淆。
89
+
84
90
  ---
85
91
 
86
92
  ## 快速开始
@@ -93,7 +99,7 @@ pip install liquid-loop
93
99
 
94
100
  ### 3 分钟上手
95
101
  ```python
96
- from liquid_loop import WorkspaceState, load, save, calculate_entropy
102
+ from liquid_loop import WorkspaceState, load, save, calculate
97
103
 
98
104
  # 1. 创建/加载工作区
99
105
  state = WorkspaceState() # 或 load(Path("."))
@@ -111,7 +117,7 @@ for m in state.memories:
111
117
  print(f"结晶: {m.content[:50]}... (置信度={m.confidence:.2f})")
112
118
 
113
119
  # 5. 监控认知健康
114
- entropy = calculate_entropy(state)
120
+ entropy = calculate(state)
115
121
  print(f"熵值: {entropy:.4f} → {'🟢GREEN' if entropy < 0.3 else '🟡YELLOW' if entropy < 0.6 else '🔴RED'}")
116
122
 
117
123
  # 6. 持久化
@@ -147,6 +153,46 @@ liquid-loop snapshot
147
153
 
148
154
  ---
149
155
 
156
+ ## MESH 集成(多智能体共识)
157
+
158
+ 液环从 v0.7.0 起内置官方 MESH 集成 `liquid_loop.mesh`,把"多智能体共识协议"落地为可复用代码,作为 agent-mesh 节点的标准接入层。
159
+
160
+ ```python
161
+ from liquid_loop.mesh import validate_evidence, compute_cci, cognitive_health, fetch_state
162
+
163
+ # agent 写入前契约自检(零向量:content 必须精确字符串,禁 embedding)
164
+ ok, errs = validate_evidence({"agent_id": "vera", "content": "用户偏好简洁输出"})
165
+
166
+ # 从 8790 拉取记忆状态,算主体间性共识指数 CCI
167
+ items = fetch_state("http://127.0.0.1:8790")
168
+ health = cognitive_health(items)
169
+ print(health["CCI"], health["consensus_crystals"])
170
+ ```
171
+
172
+ 零向量哲学:一致性判定走**结构化精确相等 + 审计链哈希**,绝不引入任何 embedding / 相似度。规范详见 `mesh/liquid_loop_mesh_v2_spec.md`。
173
+
174
+ ---
175
+
176
+ ## 定位:Self-Regulating Persistent Memory Dynamics
177
+
178
+ 液环的本质不是"AI 意识",而是一套 **agent 系统的自调节持久记忆动力学(Self-Regulating Persistent Memory Dynamics for Agent Systems)**。`AuditChain + LEI(Entropy) + Memory decay` 三者组合形成闭环,使记忆从"外部管理"转向"内部自组织":
179
+
180
+ ```
181
+ Input Evidence
182
+ ↓
183
+ Memory State ←──────────────┐
184
+ ↓ │
185
+ LEI Evaluation (八维熵) │
186
+ ↓ │
187
+ Decay / Reinforcement ────────┘
188
+ ↓
189
+ AuditChain (SHA256 链式追溯)
190
+ ```
191
+
192
+ 这比单独的 memory store 更接近一个可被实验检验的**动态系统**:输入驱动状态、熵评估稳定性、衰减/强化回流状态、审计链保证来源可信。
193
+
194
+ ---
195
+
150
196
  ## 架构对比
151
197
 
152
198
  ```
@@ -193,7 +239,8 @@ liquid-loop/
193
239
  │ ├── __init__.py # 公共 API 导出
194
240
  │ ├── workspace.py # 核心数据模型 + AuditChain + auto_classify + decay
195
241
  │ ├── storage.py # JSON 持久化 + 审计链写入
196
- │ ├── entropy.py # 四维熵值计算
242
+ │ ├── entropy.py # 八维熵值计算(含 CPE 三维)
243
+ │ ├── mesh/ # MESH v2 多智能体共识协议集成(validate_evidence / compute_cci / ...)
197
244
  │ └── cli.py # Click CLI (11 命令)
198
245
  ├── examples/
199
246
  │ └── quickstart.py
@@ -219,12 +266,15 @@ pytest -v
219
266
 
220
267
  ## 路线图
221
268
 
222
- - [ ] 语义一致性结晶(嵌入相似度替代精确匹配)
223
- - [ ] 多 Agent 液环耦合
224
- - [ ] LX 扩展:世界模型预测纳入液环
269
+ - [x] 多 Agent 液环耦合(`liquid_loop.mesh` v2 共识协议,2026-07-15 落地)
270
+ - [ ] **[v0.8] 反证轨(Evidence Graph)**:Evidence 分 support / contradiction,一致增稳、冲突降稳,驱动 memory stability score(不再"一致即真")
271
+ - [ ] **[v0.8] 显式时间动力学**:`M(t+1) = M(t) + reinforcement − decay − contradiction_penalty`,让记忆成为"过程"而非"对象"(真正的液态循环)
272
+ - [ ] **[v0.8] 三实验**:E2 错误记忆恢复(核心)→ E3 多 agent 冲突(mesh 价值)→ E1 长期漂移(压力测试)
225
273
  - [ ] LoCoMo / LongMemEval 基准对比
226
274
  - [ ] 边缘端部署优化(<50KB)
227
275
 
276
+ > 零向量是液环的硬约束:一致性判定永不引入 embedding / 相似度(这正是液环要替代的方案)。
277
+
228
278
  ---
229
279
 
230
280
  ## 许可证
@@ -33,7 +33,7 @@
33
33
  | **Anchor** 锚点 | 晶种 | 认知关注点,有稳定性值 s ∈ [0,1] |
34
34
  | **Evidence** 证据 | 附着粒子 | 锚点下的具体观察,权重指数衰减 w×0.95ᵗ |
35
35
  | **Memory** 结晶 | 结晶体 | 2+ 条一致 Evidence 自动凝聚,有置信度 c |
36
- | **Entropy** 熵值 | 流体无序度 | 八维加权(锚点漂移 / 冲突密度 / 碎片 / 活跃间隔 / 价值衰减 / 锚定强度 / CPE 三维) |
36
+ | **Entropy** 熵值 (LEI) | 流体无序度 | 八维加权(锚点漂移 / 冲突密度 / 碎片 / 活跃间隔 / 价值衰减 / 锚定强度 / CPE 三维) |
37
37
 
38
38
  **状态判定:**
39
39
  ```
@@ -42,6 +42,12 @@ YELLOW (0.3 ≤ entropy < 0.6) — 需关注
42
42
  RED (entropy ≥ 0.6) — 需清理
43
43
  ```
44
44
 
45
+ > **关于 "Entropy" 的语义澄清 — Liquid Entropy Index (LEI)**
46
+ >
47
+ > 本项目中的 `entropy` 是 **Liquid Entropy Index (LEI): a system-stability deviation metric, inspired by entropy but NOT equivalent to thermodynamic entropy.**
48
+ > 它不是物理熵 `S = -k Σ pᵢ log pᵢ`,而是对**系统状态偏离稳定流形程度**的综合度量——由八个可解释分量人工加权而成(锚点漂移 / 冲突密度 / 证据碎片 / 活跃间隔 / 价值衰减 / 锚定强度 + CPE 三维:回顾性衰退 / 策略漂移 / 泛化崩塌)。
49
+ > 代码层函数名保留 `calculate()`(历史连续性);文档 / 论文层一律以 **LEI** 指称,避免与热力学熵混淆。
50
+
45
51
  ---
46
52
 
47
53
  ## 快速开始
@@ -54,7 +60,7 @@ pip install liquid-loop
54
60
 
55
61
  ### 3 分钟上手
56
62
  ```python
57
- from liquid_loop import WorkspaceState, load, save, calculate_entropy
63
+ from liquid_loop import WorkspaceState, load, save, calculate
58
64
 
59
65
  # 1. 创建/加载工作区
60
66
  state = WorkspaceState() # 或 load(Path("."))
@@ -72,7 +78,7 @@ for m in state.memories:
72
78
  print(f"结晶: {m.content[:50]}... (置信度={m.confidence:.2f})")
73
79
 
74
80
  # 5. 监控认知健康
75
- entropy = calculate_entropy(state)
81
+ entropy = calculate(state)
76
82
  print(f"熵值: {entropy:.4f} → {'🟢GREEN' if entropy < 0.3 else '🟡YELLOW' if entropy < 0.6 else '🔴RED'}")
77
83
 
78
84
  # 6. 持久化
@@ -108,6 +114,46 @@ liquid-loop snapshot
108
114
 
109
115
  ---
110
116
 
117
+ ## MESH 集成(多智能体共识)
118
+
119
+ 液环从 v0.7.0 起内置官方 MESH 集成 `liquid_loop.mesh`,把"多智能体共识协议"落地为可复用代码,作为 agent-mesh 节点的标准接入层。
120
+
121
+ ```python
122
+ from liquid_loop.mesh import validate_evidence, compute_cci, cognitive_health, fetch_state
123
+
124
+ # agent 写入前契约自检(零向量:content 必须精确字符串,禁 embedding)
125
+ ok, errs = validate_evidence({"agent_id": "vera", "content": "用户偏好简洁输出"})
126
+
127
+ # 从 8790 拉取记忆状态,算主体间性共识指数 CCI
128
+ items = fetch_state("http://127.0.0.1:8790")
129
+ health = cognitive_health(items)
130
+ print(health["CCI"], health["consensus_crystals"])
131
+ ```
132
+
133
+ 零向量哲学:一致性判定走**结构化精确相等 + 审计链哈希**,绝不引入任何 embedding / 相似度。规范详见 `mesh/liquid_loop_mesh_v2_spec.md`。
134
+
135
+ ---
136
+
137
+ ## 定位:Self-Regulating Persistent Memory Dynamics
138
+
139
+ 液环的本质不是"AI 意识",而是一套 **agent 系统的自调节持久记忆动力学(Self-Regulating Persistent Memory Dynamics for Agent Systems)**。`AuditChain + LEI(Entropy) + Memory decay` 三者组合形成闭环,使记忆从"外部管理"转向"内部自组织":
140
+
141
+ ```
142
+ Input Evidence
143
+ ↓
144
+ Memory State ←──────────────┐
145
+ ↓ │
146
+ LEI Evaluation (八维熵) │
147
+ ↓ │
148
+ Decay / Reinforcement ────────┘
149
+ ↓
150
+ AuditChain (SHA256 链式追溯)
151
+ ```
152
+
153
+ 这比单独的 memory store 更接近一个可被实验检验的**动态系统**:输入驱动状态、熵评估稳定性、衰减/强化回流状态、审计链保证来源可信。
154
+
155
+ ---
156
+
111
157
  ## 架构对比
112
158
 
113
159
  ```
@@ -154,7 +200,8 @@ liquid-loop/
154
200
  │ ├── __init__.py # 公共 API 导出
155
201
  │ ├── workspace.py # 核心数据模型 + AuditChain + auto_classify + decay
156
202
  │ ├── storage.py # JSON 持久化 + 审计链写入
157
- │ ├── entropy.py # 四维熵值计算
203
+ │ ├── entropy.py # 八维熵值计算(含 CPE 三维)
204
+ │ ├── mesh/ # MESH v2 多智能体共识协议集成(validate_evidence / compute_cci / ...)
158
205
  │ └── cli.py # Click CLI (11 命令)
159
206
  ├── examples/
160
207
  │ └── quickstart.py
@@ -180,12 +227,15 @@ pytest -v
180
227
 
181
228
  ## 路线图
182
229
 
183
- - [ ] 语义一致性结晶(嵌入相似度替代精确匹配)
184
- - [ ] 多 Agent 液环耦合
185
- - [ ] LX 扩展:世界模型预测纳入液环
230
+ - [x] 多 Agent 液环耦合(`liquid_loop.mesh` v2 共识协议,2026-07-15 落地)
231
+ - [ ] **[v0.8] 反证轨(Evidence Graph)**:Evidence 分 support / contradiction,一致增稳、冲突降稳,驱动 memory stability score(不再"一致即真")
232
+ - [ ] **[v0.8] 显式时间动力学**:`M(t+1) = M(t) + reinforcement − decay − contradiction_penalty`,让记忆成为"过程"而非"对象"(真正的液态循环)
233
+ - [ ] **[v0.8] 三实验**:E2 错误记忆恢复(核心)→ E3 多 agent 冲突(mesh 价值)→ E1 长期漂移(压力测试)
186
234
  - [ ] LoCoMo / LongMemEval 基准对比
187
235
  - [ ] 边缘端部署优化(<50KB)
188
236
 
237
+ > 零向量是液环的硬约束:一致性判定永不引入 embedding / 相似度(这正是液环要替代的方案)。
238
+
189
239
  ---
190
240
 
191
241
  ## 许可证
@@ -1,10 +1,10 @@
1
- """Liquid Loop — Workspace Cognitive Runtime v0.6.1 (CPE-fused, proactive, rhythmic sampling)"""
2
- __version__ = "0.6.1"
1
+ """Liquid Loop — Workspace Cognitive Runtime v0.7.1 (CPE-fused, SEAL dual-opt, dual-track multi-agent, MESH v2 integration)"""
2
+ __version__ = "0.7.1"
3
3
 
4
4
  from .workspace import (
5
5
  WorkspaceState, Anchor, Evidence, Memory, Conflict,
6
6
  AuditChain, CPERegularizer, SelfRefineEngine,
7
7
  rhythmic_retrieve,
8
8
  )
9
- from .storage import load, save
9
+ from .storage import load, save, locked_state
10
10
  from .entropy import calculate, calculate_detail, calculate as calculate_entropy
@@ -0,0 +1,50 @@
1
+ """
2
+ liquid_loop.mesh — 液环 MESH 进阶版(v2)共识协议集成
3
+ =====================================================
4
+ 把"多智能体共识协议规范"从文档落地为可复用代码,作为 liquid-loop 的官方
5
+ MESH 集成层。零向量哲学:一致性判定走结构化精确相等 + 审计链哈希,绝不引入
6
+ 任何 embedding / 相似度。
7
+
8
+ 职责(详见 .v2):
9
+ - validate_evidence() agent 侧契约自检(结构化证据 schema)
10
+ - check_contract() 双向契约合规检查(身份 / 写 / 消费 / 冲突)
11
+ - compute_cci() 主体间性共识指数(记忆层)
12
+ - cognitive_health() 统一认知健康仪表盘(CCI / drift / H_e / P_mem)
13
+ - detect_conflict() 同锚点冲突证据检测
14
+ - fetch_state() 从 8790 REST /list 拉取当前状态
15
+ - main() 连接 8790 打印认知健康报告(CLI)
16
+
17
+ 快速使用:
18
+ from liquid_loop.mesh import validate_evidence, compute_cci, cognitive_health
19
+ from liquid_loop.mesh import fetch_state, main
20
+
21
+ ok, errs = validate_evidence({"agent_id": "vera", "content": "..."})
22
+ health = cognitive_health(fetch_state())
23
+ """
24
+ from .v2 import (
25
+ REGISTRY,
26
+ CLAIM_TYPES,
27
+ SCOPES,
28
+ Evidence,
29
+ validate_evidence,
30
+ check_contract,
31
+ compute_cci,
32
+ cognitive_health,
33
+ detect_conflict,
34
+ fetch_state,
35
+ main,
36
+ )
37
+
38
+ __all__ = [
39
+ "REGISTRY",
40
+ "CLAIM_TYPES",
41
+ "SCOPES",
42
+ "Evidence",
43
+ "validate_evidence",
44
+ "check_contract",
45
+ "compute_cci",
46
+ "cognitive_health",
47
+ "detect_conflict",
48
+ "fetch_state",
49
+ "main",
50
+ ]
@@ -0,0 +1,173 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ liquid_loop_mesh_v2.py — 液环 MESH 进阶版(v2)参考实现
4
+ ======================================================
5
+ 把"共识协议规范"从文档落地为可复用代码。零向量哲学:一致性判定走
6
+ 结构化精确相等 + 审计链哈希,绝不引入任何 embedding / 相似度。
7
+
8
+ 职责:
9
+ 1. validate_evidence() — agent 侧契约自检(结构化证据 schema)
10
+ 2. check_contract() — 双向契约合规检查(身份/写/消费/冲突)
11
+ 3. compute_cci() — 主体间性共识指数(记忆层)
12
+ 4. cognitive_health() — 统一认知健康仪表盘(CCI / drift / H_e / P_mem)
13
+ 5. detect_conflict() — 同锚点冲突证据检测
14
+ 6. fetch_state() — 从 8790 REST /list 拉取当前状态
15
+
16
+ 依赖:标准库 + 可选 liquid_loop(仅类型提示)。可直接 import 使用,
17
+ 也可 `python3 liquid_loop_mesh_v2.py` 连 8790 打印健康报告。
18
+ """
19
+ from __future__ import annotations
20
+ import json
21
+ import sys
22
+ import urllib.request
23
+ from dataclasses import dataclass, field
24
+ from typing import Optional
25
+
26
+ # ── agent-mesh 注册表(接入 agent 的唯一 id 白名单)──────────────
27
+ REGISTRY = {"workbuddy", "vera", "qwenpaw", "marvis", "parlant-ctrl", "cawpaw", "tabbit", "llama"}
28
+
29
+ CLAIM_TYPES = {"fact", "conclusion", "preference", "conflict"}
30
+ SCOPES = {"private", "consensus"}
31
+
32
+
33
+ # ── 1. 结构化证据 schema 校验 ──────────────────────────────────
34
+ @dataclass
35
+ class Evidence:
36
+ agent_id: str
37
+ content: str
38
+ category: str = "fact"
39
+ claim_type: str = "fact"
40
+ value: Optional[float] = None
41
+ session_id: str = ""
42
+ prev_hash: str = ""
43
+ id: str = ""
44
+
45
+ def to_dict(self) -> dict:
46
+ return {
47
+ "agent_id": self.agent_id,
48
+ "content": self.content,
49
+ "category": self.category,
50
+ "claim_type": self.claim_type,
51
+ "value": self.value,
52
+ "session_id": self.session_id,
53
+ "prev_hash": self.prev_hash,
54
+ "id": self.id,
55
+ }
56
+
57
+
58
+ def validate_evidence(ev: dict) -> tuple[bool, list[str]]:
59
+ """agent 侧契约自检:返回 (ok, 错误列表)。"""
60
+ errs: list[str] = []
61
+ if not ev.get("agent_id"):
62
+ errs.append("agent_id 必填(共用机制要求声明写入者标识)")
63
+ elif ev["agent_id"] not in REGISTRY:
64
+ errs.append(f"agent_id '{ev['agent_id']}' 未在 mesh 注册表(禁止匿名污染)")
65
+ if not ev.get("content"):
66
+ errs.append("content 必填(一致性比对键)")
67
+ ct = ev.get("claim_type", "fact")
68
+ if ct not in CLAIM_TYPES:
69
+ errs.append(f"claim_type '{ct}' 非法,须为 {sorted(CLAIM_TYPES)}")
70
+ # content 精确相等判定 → 禁止任何 embedding/相似度
71
+ if ev.get("content") and not isinstance(ev["content"], str):
72
+ errs.append("content 必须为精确字符串(零向量一致性比对键)")
73
+ return (len(errs) == 0, errs)
74
+
75
+
76
+ # ── 2. 双向契约合规检查 ────────────────────────────────────────
77
+ def check_contract(agent_id: str, did_recall: bool, wrote_structured: bool) -> tuple[bool, list[str]]:
78
+ """①身份 ②结构化写 ③主动消费 ④冲突响应(由 detect_conflict 触发)。"""
79
+ errs: list[str] = []
80
+ if agent_id not in REGISTRY:
81
+ errs.append("① 身份未声明/未注册")
82
+ if not wrote_structured:
83
+ errs.append("② 未结构化写入(缺 claim_type/session_id/prev_hash)")
84
+ if not did_recall:
85
+ errs.append("③ 会话未主动消费 consensus 视图(退化成孤岛)")
86
+ return (len(errs) == 0, errs)
87
+
88
+
89
+ # ── 3. CCI 主体间性共识指数(记忆层)────────────────────────────
90
+ def compute_cci(items: list[dict]) -> dict:
91
+ """CCI_mem = |consensus| / (|consensus| + |private|)。"""
92
+ cons = [x for x in items if x.get("scope") == "consensus"]
93
+ priv = [x for x in items if x.get("scope") == "private"]
94
+ denom = len(cons) + len(priv)
95
+ cci = (len(cons) / denom) if denom else 0.0
96
+ # 共识强度 secondary:平均 contributors 基数
97
+ strengths = [len(x.get("contributors", [])) for x in cons] or [0]
98
+ avg_strength = sum(strengths) / len(strengths) if strengths else 0
99
+ return {
100
+ "cci": round(cci, 4),
101
+ "consensus": len(cons),
102
+ "private": len(priv),
103
+ "avg_contributors": round(avg_strength, 2),
104
+ }
105
+
106
+
107
+ # ── 4. 统一认知健康仪表盘 ─────────────────────────────────────
108
+ def cognitive_health(items: list[dict], drift_rate: float = 0.0,
109
+ H_e: float = 0.0, P_mem: float = 0.0) -> dict:
110
+ cci = compute_cci(items)
111
+ evs = [x for x in items if x.get("type") == "evidence"]
112
+ from collections import Counter
113
+ by_agent = Counter(x.get("agent_id") for x in evs)
114
+ return {
115
+ "CCI": cci["cci"],
116
+ "consensus_crystals": cci["consensus"],
117
+ "private_crystals": cci["private"],
118
+ "drift_rate": drift_rate,
119
+ "H_e": H_e,
120
+ "P_mem": P_mem,
121
+ "total_evidence": len(evs),
122
+ "agents": dict(by_agent),
123
+ }
124
+
125
+
126
+ # ── 5. 冲突检测 ───────────────────────────────────────────────
127
+ def detect_conflict(items: list[dict]) -> list[dict]:
128
+ """同锚点下 claim_type=conflict 或同 content 反义 → 标记冲突 agent。"""
129
+ conflicts = []
130
+ by_cat = {}
131
+ for x in items:
132
+ if x.get("type") in ("evidence", "memory"):
133
+ by_cat.setdefault(x.get("category", "?"), []).append(x)
134
+ for cat, recs in by_cat.items():
135
+ conflict_recs = [r for r in recs if r.get("claim_type") == "conflict"]
136
+ if conflict_recs:
137
+ agents = sorted({r.get("agent_id") for r in conflict_recs if r.get("agent_id")})
138
+ conflicts.append({"anchor": cat, "conflict_agents": agents,
139
+ "kind": "explicit_conflict"})
140
+ return conflicts
141
+
142
+
143
+ # ── 6. 从 8790 拉取状态 ───────────────────────────────────────
144
+ def fetch_state(base: str = "http://127.0.0.1:8790") -> list[dict]:
145
+ req = urllib.request.Request(base + "/list", data=b"{}",
146
+ headers={"Content-Type": "application/json"})
147
+ with urllib.request.urlopen(req, timeout=5) as r:
148
+ d = json.load(r)
149
+ return d if isinstance(d, list) else d.get("result", d.get("items", []))
150
+
151
+
152
+ # ── CLI:打印健康报告 ──────────────────────────────────────────
153
+ def main():
154
+ try:
155
+ items = fetch_state()
156
+ except Exception as e:
157
+ print(f"[ERR] 无法连接 8790: {e}")
158
+ sys.exit(1)
159
+ health = cognitive_health(items)
160
+ print("=== 液环 MESH v2 认知健康仪表盘 ===")
161
+ for k, v in health.items():
162
+ print(f" {k:18}: {v}")
163
+ conf = detect_conflict(items)
164
+ if conf:
165
+ print("\n=== 冲突锚点 ===")
166
+ for c in conf:
167
+ print(" ", c)
168
+ else:
169
+ print("\n[OK] 无显式冲突")
170
+
171
+
172
+ if __name__ == "__main__":
173
+ main()
@@ -36,7 +36,12 @@ def _file_lock(filepath: str, mode: str = "w"):
36
36
  finally:
37
37
  fcntl.flock(f, fcntl.LOCK_UN)
38
38
 
39
+ def _lock_path(workspace_root: Path) -> Path:
40
+ return _ensure_dir(workspace_root) / "state.lock"
41
+
42
+
39
43
  def load(workspace_root: Path) -> WorkspaceState:
44
+ """纯读取,无锁。并发安全由上层 locked_state 上下文保证。"""
40
45
  path = _ensure_dir(workspace_root) / STATE_FILE
41
46
  if not path.exists():
42
47
  return WorkspaceState()
@@ -46,6 +51,7 @@ def load(workspace_root: Path) -> WorkspaceState:
46
51
 
47
52
 
48
53
  def save(state: WorkspaceState, workspace_root: Path):
54
+ """原子写(temp+rename):崩溃永不留下半截文件。锁由 locked_state 持有。"""
49
55
  state.updated_at = now()
50
56
  path = _ensure_dir(workspace_root) / STATE_FILE
51
57
  # 审计链:记录并回写哈希
@@ -59,8 +65,28 @@ def save(state: WorkspaceState, workspace_root: Path):
59
65
  data = asdict(state)
60
66
  # overlap_cache 仅为运行时熵计算缓存,键为 tuple,不可 JSON 序列化,且不具持久价值
61
67
  data.pop("overlap_cache", None)
62
- with open(path, "w", encoding="utf-8") as f:
68
+ tmp = path.with_suffix(".tmp")
69
+ with open(tmp, "w", encoding="utf-8") as f:
63
70
  json.dump(data, f, indent=2, ensure_ascii=False)
71
+ f.flush()
72
+ os.fsync(f.fileno())
73
+ os.replace(tmp, path) # POSIX 原子替换,读端永不看到半截文件
74
+
75
+
76
+ @contextmanager
77
+ def locked_state(workspace_root: Path):
78
+ """单一锁层:排他锁跨 load→modify→save 整段,根除并发丢写(P0)。
79
+ 跨进程安全(fcntl 建议锁);server 与批量喂入脚本共用同一把锁。"""
80
+ d = _ensure_dir(workspace_root)
81
+ lk = open(d / "state.lock", "w")
82
+ fcntl.flock(lk, fcntl.LOCK_EX)
83
+ try:
84
+ st = load(workspace_root)
85
+ yield st
86
+ save(st, workspace_root)
87
+ finally:
88
+ fcntl.flock(lk, fcntl.LOCK_UN)
89
+ lk.close()
64
90
 
65
91
 
66
92
  def _from_dict(data: dict) -> WorkspaceState:
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  from dataclasses import dataclass, field
2
4
  from datetime import datetime, timezone
3
5
  from typing import Optional, List, Dict, Any
@@ -153,6 +155,7 @@ class Evidence:
153
155
  weight: float = 1.0
154
156
  quality: str = "normal"
155
157
  archived: bool = False # 预算超额冷归档标记(PEEK 落地,零丢失)
158
+ agent_id: str = "" # 多智能体共用:写入者标识(共用机制,缺省=legacy/单实例)
156
159
 
157
160
 
158
161
  @dataclass
@@ -162,6 +165,8 @@ class Memory:
162
165
  formed_at: str = field(default_factory=now)
163
166
  evidence_ids: list[str] = field(default_factory=list)
164
167
  confidence: float = 0.0
168
+ scope: str = "private" # 结晶来源: private(同 agent≥2一致) / consensus(跨 distinct owner≥2一致)
169
+ contributors: list[str] = field(default_factory=list) # 参与成核的 agent_id 列表
165
170
 
166
171
 
167
172
  @dataclass
@@ -243,10 +248,17 @@ class WorkspaceState:
243
248
  self.updated_at = now()
244
249
  return a
245
250
 
246
- def add_evidence(self, anchor: str, content: str, quality: float = 1.0) -> Optional[Evidence]:
251
+ def add_evidence(self, anchor, content: str, quality: float = 1.0, agent_id: str = "",
252
+ dedup: bool = False) -> Optional[Evidence]:
247
253
  """向指定锚点添加一条证据。
248
254
 
249
255
  anchor 参数兼容:锚点名称(str) | 锚点ID(str) | Anchor对象
256
+ agent_id:多智能体共用写入者标识(缺省空=legacy/单实例)
257
+ dedup:幂等去重开关(默认 False)。
258
+ - False(默认,核心语义):同内容可重复写入——"≥2 条一致证据自动结晶"依赖此行为
259
+ (README quickstart / 双轨成核 / 理论定义)。
260
+ - True(mesh/API 层显式启用):同锚点+同内容+同 agent 已存在则复用,防网络重试/高频喂入膨胀。
261
+ 幂等应由 mesh/API 层按需开启,核心模型默认不吞掉"重复观察"这一结晶信号。
250
262
  """
251
263
  target = None
252
264
  if isinstance(anchor, Anchor):
@@ -258,9 +270,14 @@ class WorkspaceState:
258
270
  target = next((a for a in self.anchors if a.id == anchor), None)
259
271
  if not target:
260
272
  return None
273
+ # 幂等去重(仅当 dedup=True):同锚点+同内容+同 agent 已存在则复用
274
+ if dedup:
275
+ for ex in self.evidences:
276
+ if ex.anchor_id == target.id and ex.content == content and ex.agent_id == agent_id:
277
+ return ex
261
278
  e = Evidence(
262
279
  id=uid(), anchor_id=target.id, content=content,
263
- quality=quality, timestamp=now(),
280
+ quality=quality, timestamp=now(), agent_id=agent_id,
264
281
  )
265
282
  self.evidences.append(e)
266
283
  target.evidence_ids.append(e.id)
@@ -289,31 +306,68 @@ class WorkspaceState:
289
306
  e.weight = max(e.weight * 0.95, 0.1)
290
307
 
291
308
  def _nucleate(self, anchor_id: str):
292
- """成核:同锚点下 >= 2 条一致证据形成记忆结晶。
309
+ """双轨成核(多智能体共用机制):
310
+
311
+ - private 轨:同一 agent_id 下 >= 2 条一致证据 -> scope=private 结晶
312
+ - consensus 轨:同一 content 被 >= 2 个 distinct agent_id 证据支持 -> scope=consensus 结晶
293
313
 
294
- 复合键判定:查重限定在当前锚点内((anchor_id, content)),避免跨锚点
295
- 同 content 证据被错误吞掉或并入同一结晶(P0 跨锚点误结晶修复, v0.6.2)。
314
+ 复合键 (anchor_id, content, scope) 防跨锚点/跨轨污染。
315
+ 兼容 legacy:agent_id 为空视为单实例私有(走 private 轨,contributors=["legacy"])。
296
316
  """
297
317
  group = [e for e in self.evidences if e.anchor_id == anchor_id]
298
318
  if len(group) < 2:
299
319
  return
300
- # 本锚点已结晶的 content 集合(复合键判定,杜绝跨锚点污染)
301
- crystallized_contents: set[str] = set()
320
+ # 已结晶键集合(复合键判定,杜绝跨锚点/跨轨污染)
321
+ crystallized_keys: set = set()
302
322
  for m in self.memories:
303
323
  for eid in m.evidence_ids:
304
324
  ev = next((e for e in self.evidences if e.id == eid), None)
305
325
  if ev is not None and ev.anchor_id == anchor_id:
306
- crystallized_contents.add(m.content)
326
+ crystallized_keys.add((m.content, m.scope))
307
327
  break
308
- content_counts = Counter(e.content for e in group)
309
- for content, count in content_counts.items():
310
- if count >= 2 and content not in crystallized_contents:
311
- evidence_ids = [e.id for e in group if e.content == content]
312
- confidence = min(count / len(group), 1.0)
328
+ from collections import defaultdict
329
+ # ── private 轨:按 agent_id 分组,组内同 content >= 2 ──
330
+ by_agent: dict = defaultdict(list)
331
+ for e in group:
332
+ by_agent[e.agent_id if e.agent_id else "legacy"].append(e)
333
+ for owner, evs in by_agent.items():
334
+ content_counts = Counter(e.content for e in evs)
335
+ for content, count in content_counts.items():
336
+ if count >= 2 and (content, "private") not in crystallized_keys:
337
+ evidence_ids = [e.id for e in evs if e.content == content]
338
+ confidence = min(count / len(evs), 1.0)
339
+ self.memories.append(Memory(
340
+ content=content,
341
+ evidence_ids=evidence_ids,
342
+ confidence=confidence,
343
+ scope="private",
344
+ contributors=[owner],
345
+ ))
346
+ # ── consensus 轨:跨 distinct owner 同 content >= 2 ──
347
+ owners_by_content: dict = defaultdict(set)
348
+ for e in group:
349
+ if not e.agent_id:
350
+ continue # legacy 不参与共识轨(无法跨主体)
351
+ owners_by_content[e.content].add(e.agent_id)
352
+ for content, owners in owners_by_content.items():
353
+ if len(owners) < 2:
354
+ continue
355
+ # 已存在的共识结晶:把新一致方并入 contributors(动态扩展,支撑三方+ CCI 计量)
356
+ existing = next((m for m in self.memories if m.scope == "consensus" and m.content == content), None)
357
+ if existing is not None:
358
+ merged = set(existing.contributors) | owners
359
+ if merged != set(existing.contributors):
360
+ existing.contributors = sorted(merged)
361
+ continue
362
+ if (content, "consensus") not in crystallized_keys:
363
+ evidence_ids = [e.id for e in group if e.content == content and e.agent_id in owners]
364
+ confidence = min(len(owners) / 2.0, 1.0)
313
365
  self.memories.append(Memory(
314
366
  content=content,
315
367
  evidence_ids=evidence_ids,
316
368
  confidence=confidence,
369
+ scope="consensus",
370
+ contributors=sorted(owners),
317
371
  ))
318
372
  # 成核后触发自动描述回流(仅当描述为空)
319
373
  self._auto_describe_anchor(anchor_id)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: liquid-loop
3
- Version: 0.6.4
3
+ Version: 0.7.1
4
4
  Summary: Self-Organizing Cognitive Memory for AI Agents — Liquid Loop theory implementation
5
5
  Author: fishbook0001
6
6
  Maintainer: fishbook0001
@@ -72,7 +72,7 @@ Dynamic: license-file
72
72
  | **Anchor** 锚点 | 晶种 | 认知关注点,有稳定性值 s ∈ [0,1] |
73
73
  | **Evidence** 证据 | 附着粒子 | 锚点下的具体观察,权重指数衰减 w×0.95ᵗ |
74
74
  | **Memory** 结晶 | 结晶体 | 2+ 条一致 Evidence 自动凝聚,有置信度 c |
75
- | **Entropy** 熵值 | 流体无序度 | 八维加权(锚点漂移 / 冲突密度 / 碎片 / 活跃间隔 / 价值衰减 / 锚定强度 / CPE 三维) |
75
+ | **Entropy** 熵值 (LEI) | 流体无序度 | 八维加权(锚点漂移 / 冲突密度 / 碎片 / 活跃间隔 / 价值衰减 / 锚定强度 / CPE 三维) |
76
76
 
77
77
  **状态判定:**
78
78
  ```
@@ -81,6 +81,12 @@ YELLOW (0.3 ≤ entropy < 0.6) — 需关注
81
81
  RED (entropy ≥ 0.6) — 需清理
82
82
  ```
83
83
 
84
+ > **关于 "Entropy" 的语义澄清 — Liquid Entropy Index (LEI)**
85
+ >
86
+ > 本项目中的 `entropy` 是 **Liquid Entropy Index (LEI): a system-stability deviation metric, inspired by entropy but NOT equivalent to thermodynamic entropy.**
87
+ > 它不是物理熵 `S = -k Σ pᵢ log pᵢ`,而是对**系统状态偏离稳定流形程度**的综合度量——由八个可解释分量人工加权而成(锚点漂移 / 冲突密度 / 证据碎片 / 活跃间隔 / 价值衰减 / 锚定强度 + CPE 三维:回顾性衰退 / 策略漂移 / 泛化崩塌)。
88
+ > 代码层函数名保留 `calculate()`(历史连续性);文档 / 论文层一律以 **LEI** 指称,避免与热力学熵混淆。
89
+
84
90
  ---
85
91
 
86
92
  ## 快速开始
@@ -93,7 +99,7 @@ pip install liquid-loop
93
99
 
94
100
  ### 3 分钟上手
95
101
  ```python
96
- from liquid_loop import WorkspaceState, load, save, calculate_entropy
102
+ from liquid_loop import WorkspaceState, load, save, calculate
97
103
 
98
104
  # 1. 创建/加载工作区
99
105
  state = WorkspaceState() # 或 load(Path("."))
@@ -111,7 +117,7 @@ for m in state.memories:
111
117
  print(f"结晶: {m.content[:50]}... (置信度={m.confidence:.2f})")
112
118
 
113
119
  # 5. 监控认知健康
114
- entropy = calculate_entropy(state)
120
+ entropy = calculate(state)
115
121
  print(f"熵值: {entropy:.4f} → {'🟢GREEN' if entropy < 0.3 else '🟡YELLOW' if entropy < 0.6 else '🔴RED'}")
116
122
 
117
123
  # 6. 持久化
@@ -147,6 +153,46 @@ liquid-loop snapshot
147
153
 
148
154
  ---
149
155
 
156
+ ## MESH 集成(多智能体共识)
157
+
158
+ 液环从 v0.7.0 起内置官方 MESH 集成 `liquid_loop.mesh`,把"多智能体共识协议"落地为可复用代码,作为 agent-mesh 节点的标准接入层。
159
+
160
+ ```python
161
+ from liquid_loop.mesh import validate_evidence, compute_cci, cognitive_health, fetch_state
162
+
163
+ # agent 写入前契约自检(零向量:content 必须精确字符串,禁 embedding)
164
+ ok, errs = validate_evidence({"agent_id": "vera", "content": "用户偏好简洁输出"})
165
+
166
+ # 从 8790 拉取记忆状态,算主体间性共识指数 CCI
167
+ items = fetch_state("http://127.0.0.1:8790")
168
+ health = cognitive_health(items)
169
+ print(health["CCI"], health["consensus_crystals"])
170
+ ```
171
+
172
+ 零向量哲学:一致性判定走**结构化精确相等 + 审计链哈希**,绝不引入任何 embedding / 相似度。规范详见 `mesh/liquid_loop_mesh_v2_spec.md`。
173
+
174
+ ---
175
+
176
+ ## 定位:Self-Regulating Persistent Memory Dynamics
177
+
178
+ 液环的本质不是"AI 意识",而是一套 **agent 系统的自调节持久记忆动力学(Self-Regulating Persistent Memory Dynamics for Agent Systems)**。`AuditChain + LEI(Entropy) + Memory decay` 三者组合形成闭环,使记忆从"外部管理"转向"内部自组织":
179
+
180
+ ```
181
+ Input Evidence
182
+ ↓
183
+ Memory State ←──────────────┐
184
+ ↓ │
185
+ LEI Evaluation (八维熵) │
186
+ ↓ │
187
+ Decay / Reinforcement ────────┘
188
+ ↓
189
+ AuditChain (SHA256 链式追溯)
190
+ ```
191
+
192
+ 这比单独的 memory store 更接近一个可被实验检验的**动态系统**:输入驱动状态、熵评估稳定性、衰减/强化回流状态、审计链保证来源可信。
193
+
194
+ ---
195
+
150
196
  ## 架构对比
151
197
 
152
198
  ```
@@ -193,7 +239,8 @@ liquid-loop/
193
239
  │ ├── __init__.py # 公共 API 导出
194
240
  │ ├── workspace.py # 核心数据模型 + AuditChain + auto_classify + decay
195
241
  │ ├── storage.py # JSON 持久化 + 审计链写入
196
- │ ├── entropy.py # 四维熵值计算
242
+ │ ├── entropy.py # 八维熵值计算(含 CPE 三维)
243
+ │ ├── mesh/ # MESH v2 多智能体共识协议集成(validate_evidence / compute_cci / ...)
197
244
  │ └── cli.py # Click CLI (11 命令)
198
245
  ├── examples/
199
246
  │ └── quickstart.py
@@ -219,12 +266,15 @@ pytest -v
219
266
 
220
267
  ## 路线图
221
268
 
222
- - [ ] 语义一致性结晶(嵌入相似度替代精确匹配)
223
- - [ ] 多 Agent 液环耦合
224
- - [ ] LX 扩展:世界模型预测纳入液环
269
+ - [x] 多 Agent 液环耦合(`liquid_loop.mesh` v2 共识协议,2026-07-15 落地)
270
+ - [ ] **[v0.8] 反证轨(Evidence Graph)**:Evidence 分 support / contradiction,一致增稳、冲突降稳,驱动 memory stability score(不再"一致即真")
271
+ - [ ] **[v0.8] 显式时间动力学**:`M(t+1) = M(t) + reinforcement − decay − contradiction_penalty`,让记忆成为"过程"而非"对象"(真正的液态循环)
272
+ - [ ] **[v0.8] 三实验**:E2 错误记忆恢复(核心)→ E3 多 agent 冲突(mesh 价值)→ E1 长期漂移(压力测试)
225
273
  - [ ] LoCoMo / LongMemEval 基准对比
226
274
  - [ ] 边缘端部署优化(<50KB)
227
275
 
276
+ > 零向量是液环的硬约束:一致性判定永不引入 embedding / 相似度(这正是液环要替代的方案)。
277
+
228
278
  ---
229
279
 
230
280
  ## 许可证
@@ -14,7 +14,11 @@ liquid_loop.egg-info/dependency_links.txt
14
14
  liquid_loop.egg-info/entry_points.txt
15
15
  liquid_loop.egg-info/requires.txt
16
16
  liquid_loop.egg-info/top_level.txt
17
+ liquid_loop/mesh/__init__.py
18
+ liquid_loop/mesh/v2.py
19
+ tests/test_consensus_expansion.py
17
20
  tests/test_entropy.py
21
+ tests/test_nucleate_dual_track.py
18
22
  tests/test_peek_seal.py
19
23
  tests/test_seal_persistence.py
20
24
  tests/test_self_evolve.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "liquid-loop"
7
- version = "0.6.4"
7
+ version = "0.7.1"
8
8
  description = "Self-Organizing Cognitive Memory for AI Agents — Liquid Loop theory implementation"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
@@ -0,0 +1,45 @@
1
+ """共识结晶 contributors 随新一致方动态扩展(三方+ CCI 计量)。"""
2
+ from liquid_loop import WorkspaceState
3
+ from liquid_loop.workspace import Anchor, Evidence, Memory
4
+
5
+
6
+ def _add(st, name, content, agent_id):
7
+ a = next((x for x in st.anchors if x.name == name), None)
8
+ if a is None:
9
+ a = st.add_anchor(name)
10
+ e = Evidence(content=content, anchor_id=a.id, agent_id=agent_id)
11
+ st.add_evidence(a, content, agent_id=agent_id)
12
+ return a
13
+
14
+
15
+ def test_consensus_expands_with_third_agent():
16
+ st = WorkspaceState()
17
+ # qwenpaw + vera 先达成共识
18
+ _add(st, "液环", "液环是零向量记忆", "qwenpaw")
19
+ _add(st, "液环", "液环是零向量记忆", "qwenpaw") # qwenpaw >=2 -> private
20
+ _add(st, "液环", "液环是零向量记忆", "vera") # +vera -> consensus[qwenpaw,vera]
21
+ cons = next(m for m in st.memories if m.scope == "consensus")
22
+ assert cons.contributors == ["qwenpaw", "vera"], cons.contributors
23
+ # marvis 也写同内容 -> 应并入三方共识
24
+ _add(st, "液环", "液环是零向量记忆", "marvis")
25
+ cons = next(m for m in st.memories if m.scope == "consensus")
26
+ assert cons.contributors == ["marvis", "qwenpaw", "vera"], cons.contributors
27
+
28
+
29
+ def test_consensus_no_duplicate_on_repeat():
30
+ st = WorkspaceState()
31
+ _add(st, "fact", "X", "a")
32
+ _add(st, "fact", "X", "a") # private[a]
33
+ _add(st, "fact", "X", "b") # consensus[a,b]
34
+ _add(st, "fact", "X", "b") # b 重复,不应扩
35
+ cons = next(m for m in st.memories if m.scope == "consensus")
36
+ assert cons.contributors == ["a", "b"], cons.contributors
37
+
38
+
39
+ def test_private_untouched_by_consensus_expansion():
40
+ st = WorkspaceState()
41
+ _add(st, "fact", "Y", "qwenpaw")
42
+ _add(st, "fact", "Y", "qwenpaw") # private[qwenpaw]
43
+ _add(st, "fact", "Y", "vera") # consensus
44
+ priv = [m for m in st.memories if m.scope == "private"]
45
+ assert priv and priv[0].contributors == ["qwenpaw"], priv
@@ -0,0 +1,115 @@
1
+ """双轨成核 + 防污染回归测试(多智能体共用机制)。
2
+
3
+ 锁住行为:
4
+ - private 轨:同一 agent_id 内 >= 2 一致证据 -> scope=private
5
+ - consensus 轨:同一 content 跨 >= 2 distinct agent_id -> scope=consensus
6
+ - 防污染:不同 agent 不互相成私有晶;跨锚点同 content 不合并;复合键 (anchor,content,scope)
7
+ """
8
+ import sys
9
+ from pathlib import Path
10
+
11
+ sys.path.insert(0, str(Path(__file__).parent.parent))
12
+
13
+ from liquid_loop.workspace import WorkspaceState
14
+
15
+
16
+ def _add(st, name, content, agent_id=""):
17
+ a = next((x for x in st.anchors if x.name == name), None)
18
+ if a is None:
19
+ a = st.add_anchor(name)
20
+ return st.add_evidence(a, content, agent_id=agent_id)
21
+
22
+
23
+ def test_private_nucleation_same_agent():
24
+ st = WorkspaceState()
25
+ _add(st, "topic", "液环是零向量记忆", agent_id="qwenpaw")
26
+ _add(st, "topic", "液环是零向量记忆", agent_id="qwenpaw")
27
+ priv = [m for m in st.memories if m.scope == "private"]
28
+ cons = [m for m in st.memories if m.scope == "consensus"]
29
+ assert len(priv) == 1
30
+ assert priv[0].contributors == ["qwenpaw"]
31
+ assert len(cons) == 0
32
+
33
+
34
+ def test_private_isolation_diff_agents():
35
+ st = WorkspaceState()
36
+ _add(st, "topic", "同一结论", agent_id="qwenpaw")
37
+ _add(st, "topic", "同一结论", agent_id="vera")
38
+ # 各 agent 内仅 1 条 -> 不 privately 成核
39
+ assert all(m.scope != "private" for m in st.memories)
40
+ # 但跨 2 distinct owner -> consensus 成核
41
+ cons = [m for m in st.memories if m.scope == "consensus"]
42
+ assert len(cons) == 1
43
+ assert set(cons[0].contributors) == {"qwenpaw", "vera"}
44
+
45
+
46
+ def test_consensus_requires_distinct_owner():
47
+ st = WorkspaceState()
48
+ _add(st, "topic", "共识结论", agent_id="qwenpaw")
49
+ _add(st, "topic", "共识结论", agent_id="qwenpaw") # 同 owner 重复
50
+ # 同 owner 2 条 -> private,但不该有 consensus(只有 1 个 owner)
51
+ cons = [m for m in st.memories if m.scope == "consensus"]
52
+ assert len(cons) == 0
53
+ priv = [m for m in st.memories if m.scope == "private"]
54
+ assert len(priv) == 1
55
+
56
+
57
+ def test_cross_anchor_no_pollution():
58
+ st = WorkspaceState()
59
+ _add(st, "A", "X", agent_id="qwenpaw")
60
+ _add(st, "A", "X", agent_id="qwenpaw")
61
+ _add(st, "B", "X", agent_id="qwenpaw")
62
+ _add(st, "B", "X", agent_id="qwenpaw")
63
+ # 两个锚点各成 1 个 private 晶,不合并
64
+ priv = [m for m in st.memories if m.scope == "private"]
65
+ assert len(priv) == 2
66
+
67
+
68
+ def test_legacy_compat_no_agent_id():
69
+ st = WorkspaceState()
70
+ _add(st, "topic", "legacy 内容", agent_id="")
71
+ _add(st, "topic", "legacy 内容", agent_id="")
72
+ priv = [m for m in st.memories if m.scope == "private"]
73
+ assert len(priv) == 1
74
+ assert priv[0].contributors == ["legacy"]
75
+
76
+
77
+ def test_dual_track_coexist():
78
+ st = WorkspaceState()
79
+ # 私有:qwenpaw 内 2 条独有结论
80
+ _add(st, "T", "qwenpaw 私有结论", agent_id="qwenpaw")
81
+ _add(st, "T", "qwenpaw 私有结论", agent_id="qwenpaw")
82
+ # 共识:qwenpaw + vera 各 1 条共享结论
83
+ _add(st, "T", "共享结论", agent_id="qwenpaw")
84
+ _add(st, "T", "共享结论", agent_id="vera")
85
+ priv = [m for m in st.memories if m.scope == "private"]
86
+ cons = [m for m in st.memories if m.scope == "consensus"]
87
+ assert len(priv) == 1 and priv[0].contributors == ["qwenpaw"]
88
+ assert len(cons) == 1 and set(cons[0].contributors) == {"qwenpaw", "vera"}
89
+
90
+
91
+ def test_no_pollution_between_agents_private():
92
+ st = WorkspaceState()
93
+ _add(st, "T", "结论A", agent_id="qwenpaw")
94
+ _add(st, "T", "结论A", agent_id="qwenpaw")
95
+ _add(st, "T", "结论A", agent_id="vera") # vera 只有 1 条 -> 不成私有
96
+ priv = [m for m in st.memories if m.scope == "private"]
97
+ cons = [m for m in st.memories if m.scope == "consensus"]
98
+ # qwenpaw 私有 1 晶;vera 仅 1 条不足私有;二者合计 2 distinct owner -> consensus 1 晶
99
+ assert len(priv) == 1 and priv[0].contributors == ["qwenpaw"]
100
+ assert len(cons) == 1 and set(cons[0].contributors) == {"qwenpaw", "vera"}
101
+
102
+
103
+ def test_storage_roundtrip_agent_id_scope(tmp_path):
104
+ """持久化往返:agent_id / scope / contributors 必须无损保存加载。"""
105
+ from liquid_loop import storage
106
+ st = WorkspaceState()
107
+ _add(st, "T", "X", agent_id="qwenpaw")
108
+ _add(st, "T", "X", agent_id="qwenpaw")
109
+ storage.save(st, tmp_path)
110
+ st2 = storage.load(tmp_path)
111
+ assert len(st2.memories) == 1
112
+ m = st2.memories[0]
113
+ assert m.scope == "private"
114
+ assert m.contributors == ["qwenpaw"]
115
+ assert st2.evidences[0].agent_id == "qwenpaw"
File without changes
File without changes