内容
# state-canon — 验证代理的可靠真相
> **一个基于可靠正统的代理会比依赖记忆的代理做得更仔细,消耗的令牌也更少。**
> `state-canon` 保持一个**权威的、协调一致的系统记录** —— 即世界状态的权威版本,每次更改都会写入,并与现实进行协调 —— 并将其置于**代理的路径中**,以便代理从可靠真相中推理,而不是从过时的记忆或昂贵的重新推导中。您可以查询、验证和治理状态。
**状态:**早期 / 探索中 —— 理论和方法已经在日常使用中经过测试;公共工具正在提取中,**令牌节省功能正在测量,而不是宣称**。完整状态见下文。仅限 Stdlib,无依赖。方法本身是单独的阅读材料: **[METHODOLOGY.md](./METHODOLOGY.md)**。
---
## 赌注
行业正在向多代理**集群**方向发展,基于**更多的代理 = 更好的工作**的假设。我们采取相反的赌注:瓶颈不在于**代理的数量**,而在于**每个决策是否基于可靠的正统**。解决这个问题,一个**单一的代理**就能走很远,令牌成本更低。
- **一个代理**,基于正统 —— 它设计、执行并**验证自己的声明是否符合可靠真相**,而不是根据自己的记忆。
- **一个人** —— 设定政策并保持上限:不可逆转的/外向的更改需要批准。
审计属性很重要 —— **验证声明的不是产生它的东西** —— 在一个代理中保持,因为**正统是外部的**,与代理的推理无关。代理不会通过重新阅读自己的记忆来检查自己的工作;它与一个权威存储进行协调,现实会写入这个存储。完整的模式 —— 单代理循环、边界、实际案例研究 —— 见 **[METHODOLOGY.md](./METHODOLOGY.md)**。
```mermaid
flowchart LR
D["代理:<br/>设计 + 规格"] --> F["框架任务<br/>带有停止点"]
F --> E["代理:<br/>构建 / 部署 / 测试"]
E --> R["声明:完成"]
R --> V{"实时验证<br/>对抗正统,<br/>而非声明"}
V -- 缺陷发现 --> C["发现<br/>写入正统"]
C --> F
V -- 验证 --> G{"爆炸半径<br/>闸门"}
G -- 试点通过 --> N["下一阶段<br/>更广泛的推广"]
G -- 人工审批 --> H["人工决策"]
```
### 为什么它有效
1. **基于正统,而不是重新推导**。系统的当前协调状态被注入代理的路径中。它不会在每个会话中重新探索世界;它会读取验证后的可靠真相。**这就是这个工具提供的内容**。
2. **对抗正统验证,而不是记忆**。代理永远不会信任**报告** —— 无论是自己的还是别人的 —— 而是相信实时状态(“服务实际上是否正在运行?”,而不是“我是否说它正在运行?”)。正统是权威;记忆是检查的线索。
3. **简洁的机器原生工件**。状态和交接是简洁的和结构化的,而不是基于文本的 —— 这是令牌成本的杠杆。
## 它是什么 —— 一个正统层,暴露在 MCP 上
一个**权威存储**,每次更改都会写入,一个**协调器**,使其与现实保持一致(漂移/孤立检测),以及一个**预置**步骤,将当前状态注入模型的上下文中。代理查询它或加载摘要 —— 无论哪种方式,它都会读取协调的可靠真相,而不是自己的记忆。
通过模型上下文协议公开,以便**任何**代理都可以插入:
| 工具 | 功能 |
|---|---|
| `state_onboard()` | 一次调用提供整个画面(服务 + 状态、开放漂移、规则、上一次决策) |
| `state_query(domain, filter)` | 按需查询特定范围 |
| `state_verify(claim)` | ★ **不要相信报告 —— 与可靠真相进行验证** → `{holds, actual, evidence}` |
| `state_reconcile(domain)` | 模型 ≡ 现实 → 漂移 / 孤立报告 |
以及资源(`state://digest`, `state://schema`, `state://rules`, `state://handoff`),供客户端提前注入上下文。前者用于**前置**(在会话开始时注入摘要);后者用于**延迟**(仅查询需要的内容)。
**它是领域无关的**。您可以注册自己的 `StateProvider`(SQLite、JSON、Git、API — 任何),以及一个 `Reconciler`(如何为每个领域观察现实)。完全抽象、参考实例、Git / VCS 实例、远程模式以及与其他上下文源的组合: **[INTERFACE.md](./INTERFACE.md)**。
**它组合得很好**。 state-canon 是一个工具,而不是整个机架:可以将它附加到 MCP 上,与您的内容 RAG、内存服务器或其他工具并排放置。保持一致性的纪律是**权威排序** —— 对于**当前**真相,协调状态优先于内存和文档。
## 安装
**要求:** Python **3.10+**。除此之外没有其他依赖 —— 服务器仅限标准库,并且没有 `pip install`。
```bash
git clone https://github.com/rm-w3kufe/state-canon-mcp.git state-canon
python3 state-canon/tests/test_state_canon.py # 可选:22 个检查,~1s
```
服务器是一个命令(标准输入输出;您的 MCP 客户端会启动它):
```bash
python3 /abs/path/state-canon/mcp_server.py --state /abs/path/your-state.json
python3 /abs/path/state-canon/mcp_server.py --sqlite /abs/path/your-state.db # 任何 SQLite 数据库
python3 /abs/path/state-canon/mcp_server.py --git /abs/path/your-repo # 一个 Git 工作树
python3 /abs/path/state-canon/mcp_server.py --microstack /abs/path/state-canon/corpus/microstack # 演示
```
> **架构说明:** 服务器**本地运行在代理旁边**(标准输入输出)。您的状态存储在**代理存储的位置**。它不是一个网络服务,不会拨打任何电话(在提供程序层支持远程状态 — 请参阅 [INTERFACE.md](./INTERFACE.md))。
### 每个客户端的配置
所有标准输入输出 MCP 客户端都需要以下三个信息: `command: python3`, `args: [launcher, --flag, path]`。
请使用**绝对路径**。
**Claude Code (CLI):**
```bash
claude mcp add state-canon -- python3 /abs/path/state-canon/mcp_server.py --state /abs/path/state.json
```
或在 `.mcp.json` / **Claude Desktop** 中的 `claude_desktop_config.json`:
```json
{ "mcpServers": { "state-canon": {
"command": "python3",
"args": ["/abs/path/state-canon/mcp_server.py", "--state", "/abs/path/state.json"] } } }
```
**OpenCode** (`opencode.json`, 0.x 格式):
```json
{ "mcp": { "state-canon": {
"type": "local",
"command": ["python3", "/abs/path/state-canon/mcp_server.py", "--state", "/abs/path/state.json"] } } }
```
**Cursor** (`.cursor/mcp.json`), **Cline** (`cline_mcp_settings.json`), **Windsurf**
(`~/.codeium/windsurf/mcp_config.json`) — 所有这些都使用与 Claude Desktop 相同的 `mcpServers` 格式。
### 验证安装(不需要客户端)
```bash
printf '%s\n' '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' \
| python3 /abs/path/state-canon/mcp_server.py --microstack /abs/path/state-canon/corpus/microstack
```
您应该会看到一行包含 `"serverInfo": {"name": "state-canon"}` 的 JSON。
## 快速入门 — 60 秒演示
代码库中提供了一个小型虚构部署 (`corpus/microstack/`),包含 **三个已知的漂移**:一个服务声明为活动但实际上已停止,一个规则冲突和一个孤立进程。
**1. 请求整个画面:**
```bash
cd state-canon
printf '%s\n' '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"state_onboard","arguments":{}}}' \
| python3 mcp_server.py --microstack corpus/microstack
```
→ 一个紧凑的摘要:9 个服务,3 个漂移(从原始文件实时重新计算,而不是从快照读取),规则,上一次决策。
**2. 捕捉一个谎言** — 声称 `cache` 正在运行,与可靠真相对抗:
```bash
printf '%s\n' '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"state_verify","arguments":{"domain":"services","filter":{"name":"cache"},"expect":{"actual":"running"}}}}' \
| python3 mcp_server.py --microstack corpus/microstack
```
→ `"holds": false` **带有证据**:声明为 `active`,观察到 `stopped`。这是整个哲学的核心:**不要相信报告 — 与状态进行验证**。
**3. 附加您的代理**,询问它:
- *"系统的当前状态是什么?有任何漂移吗?"* → 调用 `state_onboard` 一次。
- *"服务 X 是否一致?"* → 调用 `state_query` / `state_verify`。
**衡量最佳使用模式**(参见 [Measured](#measured-not-proclaimed)):**一次性注入摘要**(适用于广泛的问题),然后 **使用有针对性的 `state_query` 进行后续**(适用于狭窄的问题)。始终重新探索代价高昂。
## 使您的系统具备支持功能 — 三个步骤
### 步骤 1 — 服务器指向您的状态
**JSON(最快启动)**。任何顶级键包含记录列表的 JSON 文档:
```json
{ "system": "my-stack",
"services": [ {"name": "api", "state": "running", "version": "1.2.0"} ],
"rules": [ "api and worker versions must match" ],
"last_decision": {"id": "D-1", "text": "approved cache upgrade"} }
```
```bash
python3 mcp_server.py --state /abs/path/my-state.json
```
**SQLite.** 每张表/视图都自动成为一个可查询的领域 — 或传递显式映射(参见
`instances/sqlite_ops.py` 中的实际生产示例)。以只读方式打开 (`mode=ro`):
```python
from state_canon.sqlite_provider import SqliteStateProvider
provider = SqliteStateProvider("ops.db",
domains={"services": "services", "blockers": "v_open_blockers"},
meta={"system": "my-stack"})
```
**Git.** `--git /path/to/repo` — 工作树成为实时漂移报告(参见 [INTERFACE.md](./INTERFACE.md))。
**API / 任何.** 实现两个方法(这是**远程模式** — 服务器保留本地,提供程序跨越网络;SSH 通道具有相同的结构):
```python
from state_canon.provider import StateProvider
import json, urllib.request
class ApiStateProvider(StateProvider):
def __init__(self, base_url): self.base = base_url
def list_domains(self): return ["services", "incidents", "meta"]
def query(self, domain, filter=None):
if domain == "meta": return [{"system": "my-stack"}]
with urllib.request.urlopen(f"{self.base}/{domain}") as r: records = json.load(r)
if filter: records = [x for x in records if all(x.get(k) == v for k, v in filter.items())]
return records
```
### 步骤 2 — 确定摘要(什么对新加入者很重要)
原始转储不属于模型的上下文(我们的第一个真实正统摘要大小为 44k 字符;策略将其削减至 12k)。为每个领域声明重要内容 — 详细信息永远不会丢失,但始终可以通过 `state_query` 访问:
```python
DIGEST_POLICY = {
"services": {"fields": ["name", "state", "version"], "max": 60},
"deploys": {"fields": ["component", "result"], "max": 5, "last": True},
"audit_log": {"skip": True}, # 可查询,但不是新加入者材料
}
```
### 步骤 3(可选但推荐)— 添加协调器
这是正统发挥作用的地方:**声明 vs 观察 → 类型漂移**,实时计算。
```python
from state_canon.reconcile import Reconciler
class MyReconciler(Reconciler):
domain = "services"
def declared(self): # 模型:您的清单 / 数据库 / 配置
return load_manifest()
def observe(self): # 现实:ps, systemctl, API 探针...
return probe_running_processes()
```
泛型差异产生 `declared_but_missing`, `orphan`, 和您注册的 `rule_violation`s — 正是 demo 中植入的三种漂移类型。将它写入实例模块(`instances/microstack.py` 是 40 行的参考)。
## 用例
| 场景 | 调用模式 |
|---|---|
| 代理会话启动 — “我在哪里?” | 注入 `state://digest` 资源,或一次 `state_onboard` |
| “服务 X 是否正常?”会话中 | `state_query(services, {name: X})` — 约 80 个令牌 |
| 查看另一个代理(或人员)的报告 | `state_verify(domain, filter, expect)` → holds/mismatches + 证据 |
| 部署后检查 | `state_reconcile()` → 实时漂移列表(孤立、缺失、规则冲突) |
| CI 门控 | 在脚本中运行协调;如果漂移 ≠ 预期,则使管道失败 |
## 已测量,而不是宣称
我们拒绝提供我们尚未获得的令牌节省数。 [EXPERIMENT.md](./corpus/microstack/EXPERIMENT.md)
定义了一个可重复的实验:相同的任务**冷**(代理重新探索)vs **预置**(注入状态)vs **MCP**(查询状态),在小型受控语料库上,使用相同的模型,≥5 次试验,**正确性评分**(不合格的节省将被取消资格)。诚实的结果是**权衡** —
预置赢得广泛的任务,延迟查询赢得狭窄的任务,冷的总是失败 — 以 [RESULTS.md](./corpus/microstack/RESULTS.md) 的方式报告,附有所有注意事项。
## 状态(诚实)
| 部件 | 状态 |
|---|---|
| 理论 + 方法 | ✅ 日常使用中 |
| MCP 服务器(仅限标准库) | ✅ 22/22 检查 + 完整 stdio 烟雾测试 |
| 受控语料库 + 实验 | ✅ 权衡特性(预置赢得广泛,延迟查询赢得狭窄,冷的总是失败;正确性完整) |
| 第二个实时实例(SQLite 实际生产正统) | ✅ 14/14 结构检查;从 44k→12k 的经验教训 |
| Git/VCS 实例 | ✅ `GitStateProvider` + 协调器( `--git`);三种漂移类型从 `git status` 中落出;只读;17/17 检查 |
| 远程模式(远程状态,本地服务器) | ✅ 按设计在提供程序层;远程 MCP *传输* = 开放集成点,未发货 |
| 技能(9)+ 代理规范(1) | ✅ 纪律和单代理规范,可安装 |
| 发布令牌计数器(实际 MCP 附件 + 计费使用) | ⬜ 待验证 |
| 现实语料库 + 已发布数字 | ⬜ 验证后 |
*图例:✅ 已构建并测试 · ⬜ 已声明/路线图。 `METHODOLOGY.md`, `skills/` 和 `agents/` 是实践文档(我们每天运行的模式),不是编排代码 — 这里没有任何内容假装不是它。*
## 更深入
- **[METHODOLOGY.md](./METHODOLOGY.md)** — 基于正统的代理:角色、四个质量边界、实际四轮案例研究和诚实限制。
- **[INTERFACE.md](./INTERFACE.md)** — 扩展和集成:抽象层、参考实例、Git/VCS 实例、远程模式以及与其他上下文源的组合。
- **[skills/](./skills/)** — 九个学科作为可移植技能(每个都有疤痕)。安装到克劳德代码中。
- **[agents/](./agents/)** — 采用可采用的规范(`agent.md`)。
- **[corpus/microstack/](./corpus/microstack/)** — 测量语料库、实验设计和结果。
## 仓库布局```
state-canon/
├── README.md ← 本文(是什么 · 安装 · 用法 · 状态)
├── METHODOLOGY.md ← 基于正统的代理(工具背后的方法)
├── INTERFACE.md ← 扩展和集成(抽象 · git · 远程 · 组合)
├── skills/ ← 可移植技能(9 · 安装到 Claude Code)
├── agents/ ← 采用的规范
├── mcp_server.py ← 任何 MCP 客户端的启动文件
├── state_canon/ ← 库(stdlib):提供程序 · sqlite_provider · git_provider · reconcile · digest · server
├── instances/ ← 参考实例(microstack 演示 · 一个真实的 SQLite 正统 · git)
└── corpus/microstack/ ← 测量语料库
├── raw/ ← 冷代理面临的内容(必须合成)
├── synthesized/ ← 协调状态(正统的产品)
├── EXPERIMENT.md · RESULTS.md · GROUND_TRUTH.md · TASKS.md
```