# reserve 内手柄在当前服务端实现下不可达 第 3 步人工验证时发现:点遍所有道路都看不到灰色(不可拖)手柄。经实测确认这是**正确行为**,不是漏测。 ## 实测数据 `test/fixtures/fengshu-er-road.osm`,24 条方向道路、32 个 reserve: ``` road handles : 126 road NOT editable : 0 with disabledReason : 0 junction handles : 96 (JunctionTools 所有,主地图已过滤) ``` ## 为什么不可达 `makeRoadHandles()` 里 `editable: false` 的唯一来源是 `unavailable`: ```js const start = Math.min(1, startReserve); const end = Math.max(0, 1 - endReserve); const unavailable = start >= end; ``` 而 `junctionReserves()` 给每端的保留区比例有硬上限: ```js const fraction = Math.min(0.45, cutback / length); ``` 于是 `startReserve ≤ 0.45`、`endReserve ≤ 0.45`,即 `start ≤ 0.45` 且 `end ≥ 0.55`。 `start >= end` 结构上永远为假,`unavailable` 分支是死代码。 实测输出里能直接看到上限生效的样子——两端都撞到 0.45 的短路段: ``` segment:way/858770822/1 window=[0.450,0.550] segment:way/117947564/0 window=[0.450,0.550] segment:way/851989492/2 window=[0.450,0.550] ``` 另外手柄的 station 取自 `(start + end) / 2`,即无保留区窗口的正中, 所以三类道路手柄的位置也永远不会落进 reserve。 ## 对验收标准的影响 prd.md 的「落在 junction reserve 内的手柄不可拖动,并提示进入 JunctionTools」 对当前三类道路手柄是**空真**:它们永远不落在 reserve 内,所以约束自动成立。 客户端一侧的置灰与原因提示路径有单测覆盖(`selection.test.ts`:disabled 手柄被保留、 `disabledReasonOf` 始终给出原因),只是服务端从不产生这种输入。因此第 3 步不需要改动。 reserve 边界真正变得用户可见是在第 4 步的**区间范围手柄**:它可以被拖向 reserve 边界, 由 `projectIntervalEnd()` 钳到 `window.minStation` / `maxStation`。届时这条边界才有可演示的行为。 ## 留给用户决定的设计问题 那个死分支暗示原作者期望「短路段应完全归 JunctionTools」。但 0.45 的上限把结果改成了: 一条几何上被两个大路口主导的短路,仍然会在正中间得到一条仅占全长 10% 的可编辑带 (上面 `[0.450,0.550]` 那几条)。 两种取向都讲得通,需要产品判断: - 保持现状:任何道路都留一条可编辑带,哪怕很窄。 - 改为:当 `cutback / length` 两端之和超过某阈值时,整条路标 `editable: false`, 引导用户进入 JunctionTools。这会让死分支复活,也让验收标准变成可演示的。 改动落在 `src/compile/direct-edit-solver.js`(属已归档的 `direct-edit-solver-api` 任务范围), 不在本任务范围内,故此处只记录不实施。