重构结构化输出与投机解码的约束起点契约
值得精读,且建议按「契约 → 消费方 → 测试」的顺序读:先看 `vllm/v1/structured_output/__init__.py` 的 `_get_constraint_start()`,它是整个 PR 唯一的语义来源;再看 `scheduler.py` 三个调用点确认新契约的用法;最后看 `test_structured_output_manager.py` 的 `FlowCase` / `_run_real_flow()` 理解验证方式。重点关注四个设计决策:(1) 用 `len + 1` 哨兵而非 `None` 表达「本窗口无约束」,三个消费点的 `>=` / `>` / `<=` 各有语义,不要「顺手统一」;(2) 降序扫描把语义从「第一次边界」改成「最后一次边界」,这对交错思考模型更合理但改变了行为;(3) 断言降级为日志是刻意的(避免 engine core 被打挂),代价是失败请求要等 accept 阶段兜底;(4) 「reasoning parser 必须无状态」目前只是文档契约,落地前不建议在生产上把 stateful parser 与投机解码 + 结构化输出组合使用。