[{"data":1,"prerenderedAt":410},["ShallowReactive",2],{"post-en-engineering-connection-recovery-contract":3,"header-article-translation-en-engineering-connection-recovery-contract":231,"trans-engineering-connection-recovery-contract-en":232},{"id":4,"title":5,"body":6,"category":197,"date":198,"description":199,"difficulty":200,"draft":201,"duration":200,"extension":202,"featured":201,"image":203,"layout":207,"locale":208,"meta":209,"navigation":210,"path":211,"references":212,"related":200,"section":224,"seo":225,"slug":226,"status":227,"stem":228,"tags":200,"translationKey":229,"updated":200,"video":200,"__hash__":230},"content\u002Fen\u002Fengineering\u002Fconnection-recovery-contract.md","Device Connection Conflict Recovery: Proposed Engineering Contract",{"type":7,"value":8,"toc":188},"minimark",[9,18,23,26,42,45,51,55,58,69,72,76,79,109,112,117,121,124,148,151,155,158,176,181,185],[10,11,14],"cnc-warning",{"level":12,"title":13},"warning","Roadmap contract, not a shipped recovery feature",[15,16,17],"p",{},"This page describes the recovery behavior Laetoly should implement. It does not claim that automatic reconnect, position restoration, command replay, or cycle resume is currently available. The operator must follow the machine manufacturer's emergency and recovery procedure first.",[19,20,22],"h2",{"id":21},"the-failure-we-must-contain","The failure we must contain",[15,24,25],{},"A CNC connection drop is not just a networking error. The controller may still be moving, holding, alarmed, or waiting for input while the browser has lost its view of the session. A second process may also be probing the same serial device. The recovery contract must therefore fail closed:",[27,28,29,33,36,39],"ul",{},[30,31,32],"li",{},"one active application owns a controller session;",[30,34,35],{},"an uncertain command is never marked complete from a reconnect alone;",[30,37,38],{},"a reconnect never authorizes motion by itself;",[30,40,41],{},"work coordinates and modal state are re-read before any operator-approved motion.",[15,43,44],{},"Operating systems differ in how they expose serial ownership. “Single owner” is an application invariant, not a claim that every driver rejects every second open in the same way.",[46,47],"figure",{"alt":48,"caption":49,"src":50},"Schematic of Grbl alarm, hold, and recovery states","Schematic: controller state must be observed and acknowledged before a recovery path continues.","\u002Fmedia\u002Fdiagrams\u002Fconnection-recovery\u002Fgrbl-state-machine.svg",[19,52,54],{"id":53},"recovery-state-machine","Recovery state machine",[15,56,57],{},"The proposed state sequence is:",[59,60,66],"pre",{"className":61,"code":63,"language":64,"meta":65},[62],"language-text","Connected\n  -> Link stale\n  -> Motion hold \u002F operator stop\n  -> Port ownership check\n  -> Reconnect without motion\n  -> Query controller state\n  -> Compare session checkpoint\n  -> Manual approval or blocked recovery\n","text","",[67,68,63],"code",{"__ignoreMap":65},[15,70,71],{},"Each transition must produce an observable event in the driver log and a visible state in the UI. A timeout is a blocked state, not a reason to jump to the next step.",[19,73,75],{"id":74},"what-must-be-queried","What must be queried",[15,77,78],{},"After the serial session is reacquired, the driver should query the controller using the protocol supported by the target firmware. For Grbl v1.1, the interface documentation describes:",[27,80,81,87,93,99],{},[30,82,83,86],{},[67,84,85],{},"?"," for a real-time status report;",[30,88,89,92],{},[67,90,91],{},"$G"," for the current parser modal state;",[30,94,95,98],{},[67,96,97],{},"$#"," for stored coordinate parameters, including work coordinate offsets;",[30,100,101,104,105,108],{},[67,102,103],{},"!"," and ",[67,106,107],{},"~"," as real-time hold and resume controls.",[15,110,111],{},"The driver must validate the response shape and firmware identity before using any value. A response timeout, malformed report, changed firmware family, or mismatch with the saved session checkpoint keeps the job blocked.",[46,113],{"alt":114,"caption":115,"src":116},"Schematic of preserving work coordinate offsets through a reconnect","Schematic: work offsets must be re-read; a local copy is not proof of the controller's current state.","\u002Fmedia\u002Fdiagrams\u002Fconnection-recovery\u002Fcoordinate-offsets.svg",[19,118,120],{"id":119},"what-must-not-happen-automatically","What must not happen automatically",[15,122,123],{},"The first implementation must not:",[27,125,126,129,132,135,142,145],{},[30,127,128],{},"replay unknown in-flight commands;",[30,130,131],{},"assume the last acknowledged line equals the controller's physical position;",[30,133,134],{},"send a cycle start immediately after a port opens;",[30,136,137,138,141],{},"use ",[67,139,140],{},"$X"," to bypass an unresolved alarm or safety condition;",[30,143,144],{},"infer that work zero survived from browser state alone;",[30,146,147],{},"let a sample configuration file become the runtime source of truth.",[15,149,150],{},"If the machine moved while the link was unavailable, software cannot reconstruct physical position from a browser timestamp. The safe outcome is a visible checklist and operator inspection.",[19,152,154],{"id":153},"operator-approval-checklist","Operator approval checklist",[15,156,157],{},"Before an approved recovery motion, the UI should require confirmation of:",[159,160,161,164,167,170,173],"ol",{},[30,162,163],{},"the process that owns the serial port;",[30,165,166],{},"controller firmware and current state;",[30,168,169],{},"work coordinate system and offsets;",[30,171,172],{},"tool, stock, clamp, and safe-height clearance;",[30,174,175],{},"whether the operator intends to re-home, re-zero, abandon, or restart the job.",[46,177],{"alt":178,"caption":179,"src":180},"Schematic of checking workholding and clearance before recovery motion","Schematic: physical clearance is an operator check; it cannot be inferred from a reconnect event.","\u002Fmedia\u002Fdiagrams\u002Fconnection-recovery\u002Fworkholding-clearance.svg",[19,182,184],{"id":183},"implementation-boundary","Implementation boundary",[15,186,187],{},"The first milestone should ship the state model, logging, blocked recovery screen, and read-only controller queries. Command replay, resume checkpoints, and any automatic feed override require a separate protocol review and hardware test matrix. Until those exist, the correct engineering behavior is slower recovery with explicit human approval rather than a fast but untrusted resume.",{"title":65,"searchDepth":189,"depth":189,"links":190},2,[191,192,193,194,195,196],{"id":21,"depth":189,"text":22},{"id":53,"depth":189,"text":54},{"id":74,"depth":189,"text":75},{"id":119,"depth":189,"text":120},{"id":153,"depth":189,"text":154},{"id":183,"depth":189,"text":184},"Architecture","2026-09-09","A fail-closed recovery contract for serial ownership, controller state verification, and operator approval after a CNC connection drop.",null,false,"md",{"src":204,"alt":205,"caption":206},"\u002Fmedia\u002Farticle-covers\u002Fengineering\u002Fconnection-recovery.webp","Conceptual connection between a CNC controller, local driver, and browser workspace","Conceptual architecture illustration; it does not represent a shipped Laetoly UI or hardware topology.","article","en",{},true,"\u002Fen\u002Fengineering\u002Fconnection-recovery-contract",[213,217,221],{"id":214,"title":215,"url":216},"grbl-interface","Grbl v1.1 Interface Basics","https:\u002F\u002Fgithub.com\u002Fgnea\u002Fgrbl\u002Fblob\u002Fmaster\u002Fdoc\u002Fmarkdown\u002Finterface.md",{"id":218,"title":219,"url":220},"grbl-commands","Grbl v1.1 Commands","https:\u002F\u002Fgithub.com\u002Fgnea\u002Fgrbl\u002Fblob\u002Fmaster\u002Fdoc\u002Fmarkdown\u002Fcommands.md",{"id":222,"title":223},"laetoly-driver-bridge-v2","Technical Architecture Spec: Laetoly Driver WebSocket Bridge Protocol V2","engineering",{"title":5,"description":199},"connection-recovery-contract","roadmap","en\u002Fengineering\u002Fconnection-recovery-contract","engineering-connection-recovery-contract","RoYokJBFgfnyEKENfzUyNeXgy-nHS_MHcFtnevpHzBc",{"section":224,"slug":226},{"id":233,"title":234,"body":235,"category":197,"date":198,"description":396,"difficulty":200,"draft":201,"duration":200,"extension":202,"featured":201,"image":397,"layout":207,"locale":400,"meta":401,"navigation":210,"path":402,"references":403,"related":200,"section":224,"seo":407,"slug":226,"status":227,"stem":408,"tags":200,"translationKey":229,"updated":200,"video":200,"__hash__":409},"content\u002Fzh\u002Fengineering\u002Fconnection-recovery-contract.md","设备连接冲突恢复：拟议工程契约",{"type":7,"value":236,"toc":388},[237,243,246,249,263,266,270,273,276,282,285,288,291,316,319,323,326,329,352,355,358,361,378,382,385],[10,238,240],{"level":12,"title":239},"这是路线图契约，不是已经交付的恢复功能",[15,241,242],{},"本文描述 Laetoly 应实现的恢复行为，不声称自动重连、位置恢复、命令重放或续切功能已经可用。任何恢复动作都必须先遵守机器厂商的急停和故障恢复流程。",[19,244,245],{"id":245},"必须控制的故障",[15,247,248],{},"CNC 连接中断不只是网络错误。浏览器失去会话视图时，控制器可能仍处于运动、暂停、报警或等待输入状态；另一个进程也可能同时访问同一串口。因此，恢复契约必须采用失败关闭策略：",[27,250,251,254,257,260],{},[30,252,253],{},"一个控制器会话只能由一个活动应用持有；",[30,255,256],{},"未确定的命令不能因为重连就被标记为完成；",[30,258,259],{},"重连事件本身不能授权运动；",[30,261,262],{},"任何经管理员批准的运动前，都必须重新读取工作坐标和模态状态。",[15,264,265],{},"不同操作系统对串口所有权的表现不同。“单一所有者”是应用层不变量，不是声称所有驱动都会以相同方式拒绝第二次打开。",[46,267],{"alt":268,"caption":269,"src":50},"Grbl 报警、暂停和恢复状态的示意图","示意图：恢复路径继续前，必须观察并确认控制器状态。",[19,271,272],{"id":272},"恢复状态机",[15,274,275],{},"建议的状态顺序：",[59,277,280],{"className":278,"code":279,"language":64,"meta":65},[62],"已连接\n  -> 链路过期\n  -> 暂停运动 \u002F 操作员停止\n  -> 检查串口所有者\n  -> 无运动重连\n  -> 查询控制器状态\n  -> 比较会话检查点\n  -> 管理员批准或保持阻塞\n",[67,281,279],{"__ignoreMap":65},[15,283,284],{},"每次状态转换都应写入驱动日志，并在 UI 中显示。超时应保持在阻塞状态，不能作为跳过检查的理由。",[19,286,287],{"id":287},"需要查询的状态",[15,289,290],{},"重新获得串口会话后，驱动应使用目标固件支持的协议查询控制器。对于 Grbl v1.1，接口文档描述了：",[27,292,293,298,303,308],{},[30,294,295,297],{},[67,296,85],{},"：请求实时状态报告；",[30,299,300,302],{},[67,301,91],{},"：查询当前解析器模态状态；",[30,304,305,307],{},[67,306,97],{},"：查询保存的坐标参数，包括工作坐标偏移；",[30,309,310,312,313,315],{},[67,311,103],{}," 与 ",[67,314,107],{},"：实时暂停和恢复控制。",[15,317,318],{},"驱动必须在使用任何值前验证响应格式和固件身份。响应超时、报告格式错误、固件家族变化或与会话检查点不一致，都应让任务保持阻塞。",[46,320],{"alt":321,"caption":322,"src":116},"断线重连过程中保持工作坐标偏移的示意图","示意图：工作偏移必须重新读取；浏览器本地副本不能证明控制器当前状态。",[19,324,325],{"id":325},"禁止自动执行的动作",[15,327,328],{},"第一阶段实现不得自动：",[27,330,331,334,337,340,346,349],{},[30,332,333],{},"重放未知的在途命令；",[30,335,336],{},"假设最后一次确认的命令等于机器实际位置；",[30,338,339],{},"串口打开后立即发送 Cycle Start；",[30,341,342,343,345],{},"使用 ",[67,344,140],{}," 绕过未解决的报警或安全条件；",[30,347,348],{},"仅凭浏览器状态推断工作零点仍然有效；",[30,350,351],{},"把示例配置文件当作运行时真实来源。",[15,353,354],{},"如果链路中断期间机器发生了运动，软件不能通过浏览器时间戳重建真实位置。安全结果应是显示检查清单并要求操作员现场确认。",[19,356,357],{"id":357},"管理员审批清单",[15,359,360],{},"在批准恢复运动前，UI 应要求确认：",[159,362,363,366,369,372,375],{},[30,364,365],{},"当前持有串口的进程；",[30,367,368],{},"控制器固件和当前状态；",[30,370,371],{},"工作坐标系和偏移量；",[30,373,374],{},"刀具、工件、夹具和安全高度；",[30,376,377],{},"管理员选择重新回零、重新设零、放弃任务还是重新开始。",[46,379],{"alt":380,"caption":381,"src":180},"恢复运动前检查夹持和安全间隙的示意图","示意图：物理间隙必须由操作员检查，不能从重连事件自动推断。",[19,383,384],{"id":384},"实施边界",[15,386,387],{},"第一阶段应先交付状态模型、日志、阻塞恢复界面和只读控制器查询。命令重放、续切检查点和任何自动进给倍率控制，都需要单独的协议评审和真实硬件测试矩阵。在这些工作完成前，正确的工程行为是采用带人工确认的较慢恢复，而不是快速但不可信的自动续切。",{"title":65,"searchDepth":189,"depth":189,"links":389},[390,391,392,393,394,395],{"id":245,"depth":189,"text":245},{"id":272,"depth":189,"text":272},{"id":287,"depth":189,"text":287},{"id":325,"depth":189,"text":325},{"id":357,"depth":189,"text":357},{"id":384,"depth":189,"text":384},"为 CNC 断线后的串口所有权、控制器状态确认和管理员审批建立失败关闭的恢复契约。",{"src":204,"alt":398,"caption":399},"CNC 控制器、本地驱动和浏览器工作区之间的概念连接图","概念架构示意图；不代表已经发布的 Laetoly UI 或真实硬件拓扑。","zh",{},"\u002Fzh\u002Fengineering\u002Fconnection-recovery-contract",[404,405,406],{"id":214,"title":215,"url":216},{"id":218,"title":219,"url":220},{"id":222,"title":223},{"title":234,"description":396},"zh\u002Fengineering\u002Fconnection-recovery-contract","1I78KXDFyIrl-EGQXqhSA87DYRzD8y6RZuKfaoYKDAw",1789009347477]