Recipe:持久本地状态底座¶
1. 场景与非场景¶
适用:需要持久化事件日志并保证顺序与完整性,重建或校验派生快照,以及检查或恢复协作式单写者锁。
不适用:需要在 Foundation 定义 workflow 状态机(禁止);需要抵御同权限恶意进程(fencing 不承诺该场景)。
2. 架构选择及能力 ID¶
首选能力:foundation.harness.state-store(append-only 事件、hash chain、快照与锁检查/恢复)。事件含义与 reducer 转移由调用方拥有。
3. 前置条件与信任边界¶
STATE_GENESIS_DIGEST作为链起点。- 信任边界:事件日志是唯一权威,snapshot 为派生缓存;
confirmOwnerTerminated是调用方提供的外部信任锚,不承诺抵御同权限恶意进程。
4. 最小代码¶
import { mkdtempSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import {
openStateStore,
appendEvent,
readEvents,
writeSnapshot,
readSnapshot,
inspectStateStoreLock,
recoverStateStoreLock,
} from "skill-family-harness-node";
const root = mkdtempSync(join(tmpdir(), "sf-state-"));
const store = openStateStore(root, { owner: "writer-a", expectedSchemas: [] });
appendEvent(store, { eventType: "demo", payload: { n: 1 } });
writeSnapshot(store, readEvents(store));
const snap = readSnapshot(store);
const lock = inspectStateStoreLock(root); // { owner, fencing, ageMs, recovering }
await recoverStateStoreLock(root, {
expectedOwner: lock.owner,
expectedFencing: lock.fencing,
confirmOwnerTerminated: true,
});
以上代码展示了开库、追加事件、写快照、查锁与显式恢复的顺序。
5. 预期输出与证据¶
readEvents 返回追加的事件,readSnapshot 返回派生快照,inspectStateStoreLock 返回 owner/fencing/ageMs/recovering。证据:packages/skill-family-harness-node/test/state-store.test.mjs(含 34 处断言)。
6. 安全/失败负例¶
// 负例:第二写者立即收到 store-locked
const other = openStateStore(root, { owner: "writer-b", expectedSchemas: [] });
// 抛 HarnessError:details.kind = "store-locked"
hash chain 断裂、锁 fencing 不匹配、恢复缺少 confirmOwnerTerminated 均失败关闭。
7. 可复制验证命令¶
node --test packages/skill-family-harness-node/test/state-store.test.mjs
8. 调用方继续拥有的业务逻辑¶
- 事件业务含义、reducer 转移。
confirmOwnerTerminated信任锚(Foundation 之外确认旧写者已终止)。
9. 升级与回滚注意事项¶
- 状态底座只提供机制;业务状态机/终态归 loop-agent。
- 崩溃遗留锁需外部取证后显式恢复,不自动偷锁;系统保持可诊断锁死而非静默覆盖。