第二部分 · 演进历程  /  架构演进主线
02 第二部分 · 演进历程

架构演进主线

同步引擎、单驾驶员、门禁、文档极简等关键阶段。

阅读约 12 分钟 6 / 28 篇 源自 git log · CLAUDE.md · docs/hard-rules.md

Claude Chat Mobile 今天的系统形态来自长期的渐进式决策与真实痛点驱动,每一条主线都伴随着对假设的推翻与对不变量的坚守。

核心演进历程与分期

第一阶段

桥接层打通(2026-06)

放弃自造 LLM 编排器,通过 Agent SDK 建立双向流,确立终端等价性立场。

第二阶段

双通道与单驾驶员(2026-07)

确立「单驾驶员模型」,引入磁盘轮询镜像引擎与读写互斥锁,彻底杜绝数据分叉。

第三阶段

测试安全重构与沙箱防线(2026-08)

经历变异测试误伤数据的教训,确立容器隔离 HOME、宿主机命令白名单与 S0–S7 执行槽分层。

第四阶段

配置与网络拓扑重构(2026-08 末 ~ 2026-09)

从松散 .env 升级为结构化 ccm.config.json;确立 ACCESS_PROFILE 三候选拓扑,支持无 Cloudflare 部署。

第五阶段

SDK 升级与活体感知深化(2026-09)

升至 SDK 0.3.263,接入 applyFlagSettings 运行时调参;完善终端等待态感知与 tail attribution 归因。

近期重大关键决策与事故教训

事件与时间表象与问题根因形成的防线与架构决策
8/2 删库事故与沙箱防线mutate 测试在改坏源码时把路径函数算成空串,误打在宿主机真实 ~/.claude/projects 上造成数据清除。宿主机仅跑白名单命令guard-host-tests.js);所有可能造成破坏的测试一律在容器中跑(容器内 HOME 为一次性沙箱)。
8/14 插件化提案被否决曾提案将系统扩展插件化、允许动态加载外部模块。坚决不做插件化。插件出仓库会导致 import 边界、双向事件契约与静态门禁彻底失明,扩展全走 CLI 原生 MCP/Skills。
8/26 计数失明与长轮次模型输出数分钟无 token 刷新,被误判为卡死。确立以 transcript 字节增长作为真实死活判据;避免基于静态超时武断终止活跃长工具执行。
9/1 拓扑重构与三候选落地原网络判定过度与 Cloudflare 绑定,纯反代或局域网部署难以通过健康检查。落地 ACCESS_PROFILEcloudflare, reverse-proxy, lan),将非 Cloudflare 部署正式升为一等支持路径。
9/3 运行时 effort 动态切换历史实现认为 SDK 无法动态改 effort,切档必须重启实例。实证实测推翻旧假设:SDK 原生支持 applyFlagSettings({effortLevel}) 运行时生效,改掉低效的实例置换。
9/6-8 终端活体识别与归因修复桌面端写活体条目但不写 status;Web 续接后误将已结束的 pending 归因于桌面端。深化活体与终端等待态(terminalWaiting)感知;严格区分锁判定(宁可误锁)与列表展示(宁可少报)的相反判定方向。

组装根与代码演进约束

在历史重构中,曾考虑将组装根 app/src/server/app.js 完全拆散。但实测表明:镜像同步(Mirror)、历史追平(Catch-up)、实例调度与网络路由在业务上有极强的生命周期相关性。当前仓库要求:

  • 新状态严格受限。前端新状态进 app/public/js/app/ 域模块;后端新状态进所属领域模块,不得再向 app.js 顶层堆积全局可变状态。
  • 纯逻辑下沉 logic/。任何能够独立计算的状态判据必须写成 app/public/js/logic/ 中的纯函数,两侧共用,禁止副作用污染。
  • 决策留痕于 Commit。项目明确不保留一次性提案文档;重大决策必须通过 Git Commit Message 的结构化 Trailer(Constraint:, Rejected:, Tested:, Not-tested:)永久固化。