云同步后端设计说明(Cloud Sync Backend Design)

August 14, 2026 · View on GitHub

配套 memory-system 技能的可选插件:把 L1/L3 记忆文件从"本地 + 手动 Git 同步"升级为"插件驱动的自动云同步"。 状态:设计草案(Design Draft) · 作者:yunyu422 · English summary

背景与目标(Background & Goals)

当前技能的三层记忆中,L3 学习画像(PREFERENCES.md)和 L1 用户档案(USER.md)位于 ${DSH_HOME}/memory/references/learned-preferences.md 已给出"手动接入 Git 私有仓库或云盘"的等效方案,但它有三个不足:

  1. 手动:需要用户自己 git init、commit、push,Agent 无法参与;
  2. 无加密:明文同步到云端有隐私风险;
  3. 无冲突策略:多台机器同时改同一个画像文件时行为未定义。

本设计定义一个 DSH 插件@dsh-contrib/memory-sync),在 Host 平面提供同步服务,在 Agent 平面提供模型面工具,把"同步"变成 Agent 日常工作流的一部分:

  • 会话开始时自动拉取远端更新(agent/pre-step 钩子);
  • 任务收尾例程写入记忆后自动推送(技能指令调用模型面工具);
  • 可选定时推送(dsh-scheduleevery 机制);
  • 可选端到端加密(AES-256-GCM,密钥走 ctx.credentials,云端只见密文);
  • 定义明确冲突策略(默认 Last-Write-Wins,画像文件用追加合并)。

架构总览(Architecture)

遵循 DSH 的 双平面规则(与 subagents 注册表 / 后端的关系同构):

┌────────────────────────── Host 平面(进程级,一次)──────────────────────────┐
│                                                                              │
│  dsh-memory-sync  (插件)                                                      │
│  ├─ ctx.memorySync 服务(同步引擎:状态机 / 冲突合并 / 加密 / 后端路由)      │
│  ├─ 后端适配器注册表(git | webdav | s3 | http —— 可插拔,类似 LLM 适配器)   │
│  └─ 消费:ctx.credentials(密钥引用)、ctx.sessions(持久化屏障)、            │
│     ctx.schedule(可选定时)、ctx.fs(本地文件)                              │
└──────────────────────────────────────────────────────────────────────────────┘
                             │ 注册工具(agent 平面)

┌────────────────────────── Agent 平面(每会话)───────────────────────────────┐
│  memory_sync_status / memory_sync_pull / memory_sync_push /                  │
│  memory_sync_configure(模型面工具,经 cordis:group + isolate realm 注册)    │
│  技能 SKILL.md 的任务收尾例程调用 memory_sync_push                           │
└──────────────────────────────────────────────────────────────────────────────┘

为什么这样分:网络 I/O、密钥解析、状态持久化必须留在 Host(一个实例服务所有会话);工具只把"模型意图"翻译成对 ctx.memorySync 的调用。与 subagents 相同——注册表在 Host,preset 只贡献工具行。

数据模型(Data Model)

同步单元

单元路径同步策略
L1 用户档案${DSH_HOME}/memory/USER.md整文件 Last-Write-Wins
L3 学习画像${DSH_HOME}/memory/PREFERENCES.md追加合并(append-merge,见冲突策略)
项目记忆(可选)<projectRoot>/.memory/MEMORY.md整文件 LWW,按项目 key 隔离

版本元数据

每个同步单元附带:

interface MemoryFileMeta {
  path: string            // 相对同步根的规范路径
  version: string         // 内容 SHA-256(16 进制)
  updatedAt: string       // RFC 3339 UTC 最后写入
  source: string          // 产生该版本的机器标识(hostname 或配置 id)
  encrypted: boolean      // 是否端到端加密
}

云端仓库(任选后端)存 { meta, blob }blob 为明文或密文。

后端适配器(Backends)

引擎对后端只依赖一个最小接口,新增后端只需实现它(对齐 LlmAdapter 模式):

interface SyncBackend {
  id: string
  // 拉取远端全部记忆单元(返回 meta 列表 + 按需 blob)
  list(): Promise<MemoryFileMeta[]>
  get(meta: MemoryFileMeta): Promise<{ blob: Uint8Array }>
  put(meta: MemoryFileMeta, blob: Uint8Array): Promise<void>
  // 可选:服务端条件写,避免竞态(后端不支持则降级为客户端合并)
  compareAndSwap?(meta: MemoryFileMeta, expected: string): Promise<boolean>
}

首期后端(M1)——Git:在 ${DSH_HOME}/memory/git init + remote add,每次同步 = add → commit → push/pull。复用用户已配好的 SSH 通道(含 ssh.github.com:443 绕行场景),零新增依赖,最适合先跑通闭环。

M2 —— WebDAV / S3:无 Git 依赖的通用存储(坚果云/OneDrive WebDAV、MinIO、R2)。密钥(密码/access key)经 ctx.credentials 引用,cordis.yml 只写 secretRef: MEMORY_SYNC_WEBDAV_PASSWORD 这类引用,绝不写值(对齐 credentials 包"配置携带引用,不携带密钥"教义)。

M3 —— HTTP 服务端(团队画像):可选的自托管服务,支持多用户/多空间,用于团队共享项目约定(类似 WorkBuddy 云端画像的协作形态)。属于远期,设计里只留接口位。

冲突策略(Conflict Resolution)

  1. Last-Write-Wins(默认):比较 updatedAt(UTC,机器时钟漂移容忍 ±5 分钟,超出则回退到内容 hash 比较),新者胜。适用于 L1/L2 整文件单元。
  2. 追加合并(L3 画像专用)PREFERENCES.md 是 append-only 风格,冲突时两端各自的新增条目都保留,按日期字段重排序,重复条目(同日期同文本)去重。引擎返回合并后的文件并在当轮工具结果里告知"已合并 N 条来自另一台机器的偏好"。
  3. 自动冲突无法解决时:引擎不丢数据——把对方版本存为 <name>.conflict-<source>.md 旁路文件,并在工具结果中提示模型向用户询问。

加密(Encryption)

  • 可选端到端加密:AES-256-GCM,随机 96-bit IV 前置在密文 blob。
  • 密钥来源:ctx.credentials.resolve('MEMORY_SYNC_PASSPHRASE')——由用户在设置界面或环境变量配置,模型和工具永远拿不到明文密钥(credentials 包保证 describe 不含值)。
  • 加密开关记录在 meta.encrypted;同一仓库混用明文/密文单元是允许的(L3 建议加密,L1 可选)。

安全边界(Security Boundary)

  • 同步范围白名单:仅同步 memory/ 下的记忆文件,绝不触碰 ~/.dsh/.credentials.yamlsettings.yaml 等配置。
  • 大小上限:单个记忆文件超过阈值(默认 256 KB)拒绝 push,提示先裁剪(与技能既有的裁剪规则配合)。
  • 速率限制:每次会话 pull/push 各 ≤ N 次,防止循环触发(agent/pre-step 只在会话第一次请求前拉取一次)。
  • 模型面工具是"薄客户端":工具只触发操作、返回状态摘要;网络与密钥处理全在 Host 引擎,模型无法借工具外带密钥。

触发机制(Triggers)

时机机制动作
会话开始(每会话一次)agent/pre-step 监听器(prepend 注册,参考 dsh-plan-mode 的追加模式)拉取远端更新并合入本地记忆文件
任务收尾例程技能 SKILL.md 指令 → 调用 memory_sync_push推送本次写入的记忆单元
可选定时dsh-scheduleevery_seconds(≥300s)兜底推送,防止模型忘记调用
手动用户说"同步记忆" / /memory-system sync立即 pull+push

注意对齐 plan-mode 的实现教训:agent/pre-step 的追加必须在 downstream 接受该步骤之后进行;追加失败不能阻塞轮次。

与现有技能的关系(Relationship to the Skill)

  • 技能继续负责"何时写"(会话例程、写层触发规则、隐私红线不变);
  • 插件只负责"同步到哪"(后端、加密、冲突);
  • 升级 references/learned-preferences.md 的"可选云同步"一节:从"手动 git 命令"改为"推荐安装 memory-sync 插件,体验自动同步";
  • 插件可选:不安装时,技能行为与现在完全一致(向后兼容)。

仓库与包结构(Proposed Package Layout)

dsh-memory-sync/                    # 独立仓库(与 memory-system 技能仓库分离,便于独立发布)
├── package.json                    # name: @dsh-contrib/memory-sync
├── src/
│   ├── index.ts                    # Host 插件入口:注册 ctx.memorySync 服务
│   ├── engine.ts                   # 状态机 / 冲突合并 / 加密
│   ├── backends/
│   │   ├── git.ts                  # M1
│   │   ├── webdav.ts               # M2
│   │   └── http.ts                 # M3(预留)
│   └── tools.ts                    # 模型面工具定义(memory_sync_*)
├── agent.cordis.yml                # Agent 平面组合片段(工具行,供 preset 引用)
└── README.md

实施里程碑(Milestones)

里程碑内容验收
M1Git 后端 + 会话开始拉取 + 收尾推送 + LWW 冲突策略两台机器同步 L1/L3,无数据丢失
M2WebDAV/S3 后端 + AES-256-GCM 加密 + 追加合并策略加密推送后云端无法明文读取
M3HTTP 服务端 + 多用户空间 + 团队约定共享两人共享项目 MEMORY.md 约定

开放问题(Open Questions)

  1. 多用户共享时,L3 画像属于个人还是按空间隔离?(倾向:个人画像按用户隔离,只有项目级 MEMORY.md 共享)
  2. 加密密钥丢失的恢复路径?(倾向:提供 memory_sync_export_clear 导出未加密副本,提示用户自行保管)
  3. 是否需要观察者模式(监听本地文件变化自动同步)而非仅靠触发点?(M2 之后评估,避免与 fs/observed 机制耦合过深)

English Summary

This design defines an optional DSH plugin (@dsh-contrib/memory-sync) that upgrades the memory-system skill's L1/L3 files from manual Git syncing to automatic, encrypted, conflict-aware cloud sync:

  • Host plane: a ctx.memorySync service (engine + pluggable backends: Git → WebDAV/S3 → HTTP) consuming ctx.credentials for secrets, ctx.sessions for durability barriers, and optionally ctx.schedule.
  • Agent plane: thin model-facing tools (memory_sync_status/pull/push/configure) registered per-session, invoked by the skill's task-end routine.
  • Triggers: pull once at session start via a prepended agent/pre-step listener; push at task end; optional scheduled fallback.
  • Conflicts: Last-Write-Wins for whole files; append-merge for the L3 preferences file; sidecar files instead of data loss when unresolvable.
  • Security: optional AES-256-GCM end-to-end encryption with keys resolved through ctx.credentials (never visible to the model); whitelisted sync scope; size/rate limits.
  • Compat: the plugin is optional; without it the skill behaves exactly as today.

Milestones: M1 Git backend → M2 WebDAV/S3 + encryption + merge → M3 self-hosted HTTP server for team-shared project conventions.


设计文档 · memory-system · 与 DeepSeek 官方无关