# 设计 技术合约不在本文重复定义。权威定义见父任务 `.trellis/tasks/08-26-direct-manipulation-road-editor/design.md` 的以下小节: - 「架构边界」— `resolveDirectEditConstraints` 在 `compileGeometry()` 之前的插入位置与数据流。 - 「约束模型」— 6 个 kind 与各自的锚点、value、单位。 - 「Handle manifest」— `HandleManifest` / `EditHandle` / `JunctionReserve` 字段。 - 「坐标与单位分层」— 服务端在局部米制框架求解,传输一律 EPSG:4326 加方位角。 - 「预览时序与延迟预算」— `previewSeq` 回显、`degraded` 标记、p95 ≤ 300ms。 - 「编辑所有权」「不变量」— 两域划分与必须验证的几何不变量。 - 「API 合约」— 5 个新端点、409 前置条件、既有端点的增量字段。 - 「编译器几何版本变更」— `recheck` 策略。 ## 本子任务的局部决定 - 求解器是纯函数,放在 `src/compile/` 下独立模块,不依赖 `fs` 与 `http`:预览、正式编译与 CLI 导出共用同一实现,这是"浏览器不维护第二套几何算法"的落点。 - 米制换算全部走 `src/geometry/lane-geometry.js` 现有的 `metersAt()` / `haversineMeters()` / `projectedDistanceAlong()` / `lateralOffsetFrom()`。禁止新增换算函数;缺能力就扩展该模块。 - handle manifest 与 diagnostics 是求解器的返回值,不是编译产物文件:预览不写盘,正式编译才落 GeoJSON。 - `axisAzimuth` 由服务端算好,客户端只做投影。这样"哪个方向可拖"是语义决定而非 UI 猜测。 - 重放匹配与求解分两个阶段:先把约束解析成 `exact` / `recheck` / `pending` / `conflicted` / `stale`,只有前两态进入求解。这样诊断与几何互不污染。 - `POST /api/edit-preview` 复用现有请求体读取与 `sendJson` 工具,不引入新的 HTTP 框架。 - 端点顺序:先 `GET /api/edit-state` 与 `POST /api/edit-preview`(只读/无写入,风险最低),再 `POST /api/edits` 与 revision 写入端点。