# 路口控制标线偏移:斑马线与停止线可拖 父任务:`.trellis/tasks/08-26-direct-manipulation-road-editor`。 这是「更多元素可直接操纵」方向的第一个元素类型。 ## 为什么先做这一类 `08-26-direct-edit-map-editor` 交付了完整的直接操纵链路—— manifest → 命中 → 拖拽 → 投影 → 钳位 → ghost → 防抖 → 乱序仲裁 → 预览 → 保存 → 撤销。 这条链路**不认识具体元素**,只认 `kind + anchor + axis + value`。所以加一类元素 本应是「定义一个 kind + 一个写入器」,而不是造新子系统。 选斑马线/停止线打头,因为可行性已实测确认(2026-08-28): ```js 611 model = modelWithDirectEditProfiles(model, options.directEdit); 613 const junctionPlans = compileJunctionPlans(model, options, diagnostics); 614 applyDirectJunctionPlans(junctionPlans, options.directEdit); // 直接编辑已合并 768 const controls = compileControlMarkings(model, lanes, diagnostics, junctionPlans); 1299 const plan = junctionPlans.get(junctionNodeId); // 已按路口取到 plan ``` junction 级约束**已经能流到控制标线的生成**,管线是通的。挡路的只是模块级常量: ```js const STOP_LINE_OFFSET_METERS = 2.7; const CROSSWALK_JUNCTION_INSET_METERS = 1.5; ``` 它们全局一个值、不按进口区分。把常量换成「先查进口配置,没有再用默认」即可。 这与区间那件事性质不同:区间要求横断面**沿路变化**,是几何管线重构;这里只是 在已经拿到手的 `plan` 上多读一个字段。 ## 强制顺序:编译器优先,UI 最后 `08-26-direct-edit-map-editor` 交付了一个拖了没有任何效果的区间手柄,因为 `compileGeometry()` 从不读 `profile.interval`——UI 先于消费者建成。 见 `research/interval-not-applied.md`。 本任务反过来:**第 1 步不产出任何 UI**,只证明编译器真的消费这个参数。 第 1 步的门禁不过就停,不进入第 2、3 步。 ## 范围 ### 1. 服务端打通并证明(无 UI) - 新增两个约束 kind:`junction-crosswalk-inset`、`junction-stop-line-offset`, 锚点均为 `junction-approach`(求解器已建模该锚点)。 - `native-road-edits.js`:schema 校验与取值范围。 - `direct-edit-solver.js`:`applyJunctionConstraint()` 把值写进该进口的 plan 条目。 - `native-road.js`:`compileControlMarkings()` 读进口配置,缺省时退回既有常量。 ### 2. 手柄目标泛化 `EditHandle` 声明「一次手势写到哪里」,客户端在提交处分岔。 验收标准是:**加第 N+1 种元素时不需要修改任何已有��柄代码**。 ### 3. 手柄与拖拽 选中路口后斑马线、停止线上出现手柄,沿进口方向拖动调整其距路口的距离。 复用既有链路,不新增预览或保存机制。 ## 不做 - 不做红绿灯(属「有位姿的实体资产」,需要不同的写入器与相对锚点) - 不做箭头(需先定交互语义:拖箭头应改行驶动作,而非移动图标) - 不做区间生效,方块手柄继续隐藏 - 不改 `STOP_LINE_MAX_APPROACH_DISTANCE_METERS` 等与放置**是否成立**有关的判据, 只改放置**位置** ## 验收标准 ### 第 1 步(门禁,不过则停) - [ ] 带 `junction-crosswalk-inset` 约束编译出的斑马线坐标,与不带时**不同** - [ ] 带 `junction-stop-line-offset` 约束编译出的停止线坐标,与不带时**不同** - [ ] 无约束时输出与当前 main **逐字节相同**(fixture 基线无 diff) - [ ] 越界取值产生阻塞诊断,不静默钳制 - [ ] 约束经保存与重新加载后状态为 `exact` ### 第 2、3 步 - [ ] 选中路口后斑马线与停止线出现手柄,拖动可改变其距路口距离 - [ ] 手柄位置由钳位值反算,拖到极限停在边界 - [ ] 新增元素类型未修改既有手柄代码(以 diff 佐证) - [ ] `npm run format:check`、`npm run test`、`npm run test:client`、`npm run test:client:unit`、`npm run build` 全绿 ## 顺序依赖 无前置。后继:红绿灯位姿与箭头语义,二者都依赖第 2 步的目标泛化。