termdock 1.4.320 → 1.4.322

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (354) hide show
  1. package/dist/client/assets/{App-BF6YvbKL.js → App-DEKo4SNL.js} +67 -67
  2. package/dist/client/assets/App-DEKo4SNL.js.br +0 -0
  3. package/dist/client/assets/App-DEKo4SNL.js.gz +0 -0
  4. package/dist/client/assets/{ArchitecturePanel-D1Jca05w.js → ArchitecturePanel-VDM6hrwp.js} +2 -2
  5. package/dist/client/assets/ArchitecturePanel-VDM6hrwp.js.br +0 -0
  6. package/dist/client/assets/ArchitecturePanel-VDM6hrwp.js.gz +0 -0
  7. package/dist/client/assets/{ChangeWalkthroughPanel-B59JwhzK.js → ChangeWalkthroughPanel-B64j3i8o.js} +1 -1
  8. package/dist/client/assets/ChangeWalkthroughPanel-B64j3i8o.js.br +0 -0
  9. package/dist/client/assets/ChangeWalkthroughPanel-B64j3i8o.js.gz +0 -0
  10. package/dist/client/assets/{CollaborationMainWorkspace-CS_o2iYt.js → CollaborationMainWorkspace-DG8TQNqo.js} +1 -1
  11. package/dist/client/assets/CollaborationMainWorkspace-DG8TQNqo.js.br +0 -0
  12. package/dist/client/assets/CollaborationMainWorkspace-DG8TQNqo.js.gz +0 -0
  13. package/dist/client/assets/CollaborationTaskContent-msQsgVaI.js +2 -0
  14. package/dist/client/assets/{ComputerControlView-CRquP12U.js → ComputerControlView-Co-TTYas.js} +2 -2
  15. package/dist/client/assets/ComputerControlView-Co-TTYas.js.br +0 -0
  16. package/dist/client/assets/ComputerControlView-Co-TTYas.js.gz +0 -0
  17. package/dist/client/assets/{DagPlayground-CAfziHw_.js → DagPlayground-kJczdJ6J.js} +1 -1
  18. package/dist/client/assets/DagPlayground-kJczdJ6J.js.br +0 -0
  19. package/dist/client/assets/DagPlayground-kJczdJ6J.js.gz +0 -0
  20. package/dist/client/assets/{DiffLab-CPlA_7PJ.js → DiffLab-BaaioC-q.js} +1 -1
  21. package/dist/client/assets/DiffLab-BaaioC-q.js.br +0 -0
  22. package/dist/client/assets/DiffLab-BaaioC-q.js.gz +0 -0
  23. package/dist/client/assets/{DiffReview-CjEi6PCy.js → DiffReview-Wfck3RIS.js} +1 -1
  24. package/dist/client/assets/DiffReview-Wfck3RIS.js.br +0 -0
  25. package/dist/client/assets/DiffReview-Wfck3RIS.js.gz +0 -0
  26. package/dist/client/assets/{DiffReviewLab-BFRqRotl.js → DiffReviewLab-Dblr3wgw.js} +1 -1
  27. package/dist/client/assets/DiffReviewLab-Dblr3wgw.js.br +0 -0
  28. package/dist/client/assets/DiffReviewLab-Dblr3wgw.js.gz +0 -0
  29. package/dist/client/assets/{DiffViewer-Bh6lvUYN.js → DiffViewer-C-utC5Ga.js} +1 -1
  30. package/dist/client/assets/DiffViewer-C-utC5Ga.js.br +0 -0
  31. package/dist/client/assets/DiffViewer-C-utC5Ga.js.gz +0 -0
  32. package/dist/client/assets/{ModelPreview-D_WFk4yX.js → ModelPreview-BBLnHWVQ.js} +1 -1
  33. package/dist/client/assets/ModelPreview-BBLnHWVQ.js.br +0 -0
  34. package/dist/client/assets/ModelPreview-BBLnHWVQ.js.gz +0 -0
  35. package/dist/client/assets/{RightSidebar-7C9-PfhA.js → RightSidebar-CUHSFkmZ.js} +3 -3
  36. package/dist/client/assets/RightSidebar-CUHSFkmZ.js.br +0 -0
  37. package/dist/client/assets/{RightSidebar-7C9-PfhA.js.gz → RightSidebar-CUHSFkmZ.js.gz} +0 -0
  38. package/dist/client/assets/{abnfDiagram-VCTEODGH-DDAdRY3H.js → abnfDiagram-VCTEODGH-DDd99QpA.js} +1 -1
  39. package/dist/client/assets/abnfDiagram-VCTEODGH-DDd99QpA.js.br +0 -0
  40. package/dist/client/assets/abnfDiagram-VCTEODGH-DDd99QpA.js.gz +0 -0
  41. package/dist/client/assets/{app-BRESmgxW.js → app-CfqF7_nh.js} +3 -3
  42. package/dist/client/assets/app-CfqF7_nh.js.br +0 -0
  43. package/dist/client/assets/app-CfqF7_nh.js.gz +0 -0
  44. package/dist/client/assets/{arc-CV9RqbOa.js → arc-C3dck_E0.js} +1 -1
  45. package/dist/client/assets/arc-C3dck_E0.js.br +0 -0
  46. package/dist/client/assets/arc-C3dck_E0.js.gz +0 -0
  47. package/dist/client/assets/{architectureDiagram-5GKGNRK7-Ct8CtmBh.js → architectureDiagram-5GKGNRK7-C3bCQc2w.js} +1 -1
  48. package/dist/client/assets/architectureDiagram-5GKGNRK7-C3bCQc2w.js.br +0 -0
  49. package/dist/client/assets/architectureDiagram-5GKGNRK7-C3bCQc2w.js.gz +0 -0
  50. package/dist/client/assets/{blockDiagram-I7D4REHJ-CVjuOZ0h.js → blockDiagram-I7D4REHJ-znMn6iCQ.js} +1 -1
  51. package/dist/client/assets/blockDiagram-I7D4REHJ-znMn6iCQ.js.br +0 -0
  52. package/dist/client/assets/blockDiagram-I7D4REHJ-znMn6iCQ.js.gz +0 -0
  53. package/dist/client/assets/{c4Diagram-7LVT6UL2-CSKcN0J-.js → c4Diagram-7LVT6UL2-C0sopIsj.js} +1 -1
  54. package/dist/client/assets/c4Diagram-7LVT6UL2-C0sopIsj.js.br +0 -0
  55. package/dist/client/assets/c4Diagram-7LVT6UL2-C0sopIsj.js.gz +0 -0
  56. package/dist/client/assets/channel-CMC8t83j.js +1 -0
  57. package/dist/client/assets/{chunk-2Q5K7J3B-CF6SP9Cv.js → chunk-2Q5K7J3B-f7USyccJ.js} +1 -1
  58. package/dist/client/assets/{chunk-5VM5RSS4-DZhLGwG4.js → chunk-5VM5RSS4-Ck2xirDs.js} +1 -1
  59. package/dist/client/assets/{chunk-F27PBJKO-CwqjUNpz.js → chunk-F27PBJKO-DaDCIj30.js} +1 -1
  60. package/dist/client/assets/chunk-F27PBJKO-DaDCIj30.js.br +0 -0
  61. package/dist/client/assets/chunk-F27PBJKO-DaDCIj30.js.gz +0 -0
  62. package/dist/client/assets/{chunk-IMKFNOWR-C9WCfeN9.js → chunk-IMKFNOWR-DEC_On5x.js} +1 -1
  63. package/dist/client/assets/chunk-IMKFNOWR-DEC_On5x.js.br +0 -0
  64. package/dist/client/assets/chunk-IMKFNOWR-DEC_On5x.js.gz +0 -0
  65. package/dist/client/assets/{chunk-JWPE2WC7-DUIVW6rN.js → chunk-JWPE2WC7-BrswC3n2.js} +1 -1
  66. package/dist/client/assets/{chunk-POPQ4Y6H-YgwJ3iH4.js → chunk-POPQ4Y6H-ClMbDV47.js} +1 -1
  67. package/dist/client/assets/{chunk-SVP7TREG-A-vVSOuv.js → chunk-SVP7TREG-D7_1VwC5.js} +1 -1
  68. package/dist/client/assets/chunk-SVP7TREG-D7_1VwC5.js.br +0 -0
  69. package/dist/client/assets/chunk-SVP7TREG-D7_1VwC5.js.gz +0 -0
  70. package/dist/client/assets/{chunk-TICWLB2K-akdXuwgx.js → chunk-TICWLB2K-D5jzVTZ8.js} +1 -1
  71. package/dist/client/assets/chunk-TICWLB2K-D5jzVTZ8.js.br +0 -0
  72. package/dist/client/assets/chunk-TICWLB2K-D5jzVTZ8.js.gz +0 -0
  73. package/dist/client/assets/{chunk-XXDRQBXY-Da273BkJ.js → chunk-XXDRQBXY-DOhaoLcX.js} +1 -1
  74. package/dist/client/assets/classDiagram-ZZMXUADV-ElMHzA-E.js +1 -0
  75. package/dist/client/assets/classDiagram-v2-VYDZK3BY-ElMHzA-E.js +1 -0
  76. package/dist/client/assets/{cose-bilkent-JH36ORCC-CGfQhg7T.js → cose-bilkent-JH36ORCC-DOsaKgiX.js} +1 -1
  77. package/dist/client/assets/cose-bilkent-JH36ORCC-DOsaKgiX.js.br +0 -0
  78. package/dist/client/assets/cose-bilkent-JH36ORCC-DOsaKgiX.js.gz +0 -0
  79. package/dist/client/assets/{cynefin-OW5HDTMX-C9RaJCMn.js → cynefin-OW5HDTMX-CMcLh_wh.js} +1 -1
  80. package/dist/client/assets/cynefin-OW5HDTMX-CMcLh_wh.js.br +0 -0
  81. package/dist/client/assets/cynefin-OW5HDTMX-CMcLh_wh.js.gz +0 -0
  82. package/dist/client/assets/{cynefinDiagram-5FMLGOSQ-C6SWqaZK.js → cynefinDiagram-5FMLGOSQ-Dd8bfq9V.js} +1 -1
  83. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-Dd8bfq9V.js.br +0 -0
  84. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-Dd8bfq9V.js.gz +0 -0
  85. package/dist/client/assets/{dagre-GXQ25YYZ-DTMtzPmS.js → dagre-GXQ25YYZ-BlW7fAi0.js} +1 -1
  86. package/dist/client/assets/dagre-GXQ25YYZ-BlW7fAi0.js.br +0 -0
  87. package/dist/client/assets/dagre-GXQ25YYZ-BlW7fAi0.js.gz +0 -0
  88. package/dist/client/assets/{diagram-S7CK7UJ4-CRalzYBW.js → diagram-S7CK7UJ4-B0-tKahG.js} +1 -1
  89. package/dist/client/assets/diagram-S7CK7UJ4-B0-tKahG.js.br +0 -0
  90. package/dist/client/assets/diagram-S7CK7UJ4-B0-tKahG.js.gz +0 -0
  91. package/dist/client/assets/{diagram-UQ7AKVKN-B5qxEH5p.js → diagram-UQ7AKVKN-BQumj4Dw.js} +1 -1
  92. package/dist/client/assets/diagram-UQ7AKVKN-BQumj4Dw.js.br +0 -0
  93. package/dist/client/assets/diagram-UQ7AKVKN-BQumj4Dw.js.gz +0 -0
  94. package/dist/client/assets/{diagram-VSXAHHWV-CPSmBWU-.js → diagram-VSXAHHWV-Zx_FLmPP.js} +1 -1
  95. package/dist/client/assets/diagram-VSXAHHWV-Zx_FLmPP.js.br +0 -0
  96. package/dist/client/assets/diagram-VSXAHHWV-Zx_FLmPP.js.gz +0 -0
  97. package/dist/client/assets/{diagram-VX7I27RA-CU8A_voC.js → diagram-VX7I27RA-CEZvatNH.js} +1 -1
  98. package/dist/client/assets/diagram-VX7I27RA-CEZvatNH.js.br +0 -0
  99. package/dist/client/assets/diagram-VX7I27RA-CEZvatNH.js.gz +0 -0
  100. package/dist/client/assets/{diagram-Z3DM3KII-CtT4QOY-.js → diagram-Z3DM3KII-CJ9IEQ8j.js} +1 -1
  101. package/dist/client/assets/diagram-Z3DM3KII-CJ9IEQ8j.js.br +0 -0
  102. package/dist/client/assets/diagram-Z3DM3KII-CJ9IEQ8j.js.gz +0 -0
  103. package/dist/client/assets/{ebnfDiagram-PWID7BFC-Cvk6Y8JV.js → ebnfDiagram-PWID7BFC-sQQMv3ea.js} +1 -1
  104. package/dist/client/assets/ebnfDiagram-PWID7BFC-sQQMv3ea.js.br +0 -0
  105. package/dist/client/assets/ebnfDiagram-PWID7BFC-sQQMv3ea.js.gz +0 -0
  106. package/dist/client/assets/{erDiagram-RLTQ6QDP-_9Ct2AHs.js → erDiagram-RLTQ6QDP-D3rMpj7M.js} +1 -1
  107. package/dist/client/assets/erDiagram-RLTQ6QDP-D3rMpj7M.js.br +0 -0
  108. package/dist/client/assets/erDiagram-RLTQ6QDP-D3rMpj7M.js.gz +0 -0
  109. package/dist/client/assets/{flowDiagram-HODETNUW-BR29aDF_.js → flowDiagram-HODETNUW-B6QZiE0-.js} +1 -1
  110. package/dist/client/assets/flowDiagram-HODETNUW-B6QZiE0-.js.br +0 -0
  111. package/dist/client/assets/flowDiagram-HODETNUW-B6QZiE0-.js.gz +0 -0
  112. package/dist/client/assets/{ganttDiagram-EL5Y4UJY-BvVG7ism.js → ganttDiagram-EL5Y4UJY-Bw9bltcu.js} +1 -1
  113. package/dist/client/assets/ganttDiagram-EL5Y4UJY-Bw9bltcu.js.br +0 -0
  114. package/dist/client/assets/ganttDiagram-EL5Y4UJY-Bw9bltcu.js.gz +0 -0
  115. package/dist/client/assets/{gestureArbiter-DalDKZKj.js → gestureArbiter-Cczz34oI.js} +1 -1
  116. package/dist/client/assets/gestureArbiter-Cczz34oI.js.br +0 -0
  117. package/dist/client/assets/gestureArbiter-Cczz34oI.js.gz +0 -0
  118. package/dist/client/assets/{gitGraphDiagram-WWUBYQGX-BHOjoasY.js → gitGraphDiagram-WWUBYQGX-mdnkxjeD.js} +1 -1
  119. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-mdnkxjeD.js.br +0 -0
  120. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-mdnkxjeD.js.gz +0 -0
  121. package/dist/client/assets/{infoDiagram-27XIBGKW-DgmnLtPV.js → infoDiagram-27XIBGKW-DyrPP3Yf.js} +1 -1
  122. package/dist/client/assets/{ishikawaDiagram-5VMMS53U-DoiUx_u1.js → ishikawaDiagram-5VMMS53U-CEPH_ePM.js} +1 -1
  123. package/dist/client/assets/ishikawaDiagram-5VMMS53U-CEPH_ePM.js.br +0 -0
  124. package/dist/client/assets/ishikawaDiagram-5VMMS53U-CEPH_ePM.js.gz +0 -0
  125. package/dist/client/assets/{journeyDiagram-3NMN7TZE-sz2KwGQ4.js → journeyDiagram-3NMN7TZE-CQ0PjBy7.js} +1 -1
  126. package/dist/client/assets/journeyDiagram-3NMN7TZE-CQ0PjBy7.js.br +0 -0
  127. package/dist/client/assets/journeyDiagram-3NMN7TZE-CQ0PjBy7.js.gz +0 -0
  128. package/dist/client/assets/{kanban-definition-UXKFOSKX-CdAnN6NF.js → kanban-definition-UXKFOSKX-BpQUXA60.js} +1 -1
  129. package/dist/client/assets/kanban-definition-UXKFOSKX-BpQUXA60.js.br +0 -0
  130. package/dist/client/assets/kanban-definition-UXKFOSKX-BpQUXA60.js.gz +0 -0
  131. package/dist/client/assets/{layout-7mCqPnQ2.js → layout-BdptC7rq.js} +1 -1
  132. package/dist/client/assets/layout-BdptC7rq.js.br +0 -0
  133. package/dist/client/assets/layout-BdptC7rq.js.gz +0 -0
  134. package/dist/client/assets/{linear-CtGxEwoA.js → linear-C2cSRCxu.js} +1 -1
  135. package/dist/client/assets/linear-C2cSRCxu.js.br +0 -0
  136. package/dist/client/assets/linear-C2cSRCxu.js.gz +0 -0
  137. package/dist/client/assets/{mermaid.core-BxJ2mx92.js → mermaid.core-ClVMFyAU.js} +5 -5
  138. package/dist/client/assets/mermaid.core-ClVMFyAU.js.br +0 -0
  139. package/dist/client/assets/mermaid.core-ClVMFyAU.js.gz +0 -0
  140. package/dist/client/assets/{mindmap-definition-YA3MSWOX-Ck2pdDVb.js → mindmap-definition-YA3MSWOX-D0AFCmsY.js} +1 -1
  141. package/dist/client/assets/mindmap-definition-YA3MSWOX-D0AFCmsY.js.br +0 -0
  142. package/dist/client/assets/mindmap-definition-YA3MSWOX-D0AFCmsY.js.gz +0 -0
  143. package/dist/client/assets/{passwordBootstrap-gTJ9KuKa.js → passwordBootstrap-R2qlU2Pq.js} +1 -1
  144. package/dist/client/assets/passwordBootstrap-R2qlU2Pq.js.br +0 -0
  145. package/dist/client/assets/passwordBootstrap-R2qlU2Pq.js.gz +0 -0
  146. package/dist/client/assets/{pegDiagram-XKGWAZYB-CYBdOhd0.js → pegDiagram-XKGWAZYB-BGAh0bwg.js} +1 -1
  147. package/dist/client/assets/pegDiagram-XKGWAZYB-BGAh0bwg.js.br +0 -0
  148. package/dist/client/assets/pegDiagram-XKGWAZYB-BGAh0bwg.js.gz +0 -0
  149. package/dist/client/assets/{pieDiagram-E7YTZNPT-IxFUaefz.js → pieDiagram-E7YTZNPT-CDOZUF44.js} +1 -1
  150. package/dist/client/assets/pieDiagram-E7YTZNPT-CDOZUF44.js.br +0 -0
  151. package/dist/client/assets/pieDiagram-E7YTZNPT-CDOZUF44.js.gz +0 -0
  152. package/dist/client/assets/{quadrantDiagram-AXDQQJYC-CSirkHeE.js → quadrantDiagram-AXDQQJYC-D_Qn6NTU.js} +1 -1
  153. package/dist/client/assets/quadrantDiagram-AXDQQJYC-D_Qn6NTU.js.br +0 -0
  154. package/dist/client/assets/quadrantDiagram-AXDQQJYC-D_Qn6NTU.js.gz +0 -0
  155. package/dist/client/assets/{railroadDiagram-O6MQD6OU-CYoi1Ctl.js → railroadDiagram-O6MQD6OU-qUVGWhJN.js} +1 -1
  156. package/dist/client/assets/railroadDiagram-O6MQD6OU-qUVGWhJN.js.br +0 -0
  157. package/dist/client/assets/railroadDiagram-O6MQD6OU-qUVGWhJN.js.gz +0 -0
  158. package/dist/client/assets/{rdpSession-BQ_xI5BI.js → rdpSession-hgCM4i-j.js} +1 -1
  159. package/dist/client/assets/rdpSession-hgCM4i-j.js.br +0 -0
  160. package/dist/client/assets/rdpSession-hgCM4i-j.js.gz +0 -0
  161. package/dist/client/assets/{referenceLongPress-DfQ5jnsk.js → referenceLongPress-BEMsP11a.js} +1 -1
  162. package/dist/client/assets/referenceLongPress-BEMsP11a.js.br +0 -0
  163. package/dist/client/assets/referenceLongPress-BEMsP11a.js.gz +0 -0
  164. package/dist/client/assets/{requirementDiagram-BXWQKSXE-BCoG9aBY.js → requirementDiagram-BXWQKSXE-BBQMQuVZ.js} +1 -1
  165. package/dist/client/assets/requirementDiagram-BXWQKSXE-BBQMQuVZ.js.br +0 -0
  166. package/dist/client/assets/requirementDiagram-BXWQKSXE-BBQMQuVZ.js.gz +0 -0
  167. package/dist/client/assets/{sankeyDiagram-P5KCCOFB-BM0bKWHQ.js → sankeyDiagram-P5KCCOFB-CeEExsqW.js} +1 -1
  168. package/dist/client/assets/sankeyDiagram-P5KCCOFB-CeEExsqW.js.br +0 -0
  169. package/dist/client/assets/sankeyDiagram-P5KCCOFB-CeEExsqW.js.gz +0 -0
  170. package/dist/client/assets/{sequenceDiagram-WJ2MYXX4-CVc-3QVK.js → sequenceDiagram-WJ2MYXX4-7ZPO-X0a.js} +1 -1
  171. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-7ZPO-X0a.js.br +0 -0
  172. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-7ZPO-X0a.js.gz +0 -0
  173. package/dist/client/assets/{sizeCapture-INFHLROL-70GusSOh.js → sizeCapture-INFHLROL-MBjz7Snm.js} +1 -1
  174. package/dist/client/assets/sizeCapture-INFHLROL-MBjz7Snm.js.br +0 -0
  175. package/dist/client/assets/sizeCapture-INFHLROL-MBjz7Snm.js.gz +0 -0
  176. package/dist/client/assets/{sparkles-DbcgKKVd.js → sparkles-C9ShmGPf.js} +1 -1
  177. package/dist/client/assets/{stateDiagram-D77RDMKH-BCw-OQPL.js → stateDiagram-D77RDMKH-DtLp89uP.js} +1 -1
  178. package/dist/client/assets/stateDiagram-D77RDMKH-DtLp89uP.js.br +0 -0
  179. package/dist/client/assets/stateDiagram-D77RDMKH-DtLp89uP.js.gz +0 -0
  180. package/dist/client/assets/stateDiagram-v2-MP3YSRHH-CIQb4Dp7.js +1 -0
  181. package/dist/client/assets/{swimlanes-42K2YHIH--yebjz0I.js → swimlanes-42K2YHIH-Bc02S1q-.js} +1 -1
  182. package/dist/client/assets/swimlanes-42K2YHIH-Bc02S1q-.js.br +0 -0
  183. package/dist/client/assets/swimlanes-42K2YHIH-Bc02S1q-.js.gz +0 -0
  184. package/dist/client/assets/swimlanesDiagram-VR7AAH4N-RiKL7eXI.js +8 -0
  185. package/dist/client/assets/{timeline-definition-24CTP7MA-B9_XXo4h.js → timeline-definition-24CTP7MA-BLLwbOm5.js} +1 -1
  186. package/dist/client/assets/timeline-definition-24CTP7MA-BLLwbOm5.js.br +0 -0
  187. package/dist/client/assets/timeline-definition-24CTP7MA-BLLwbOm5.js.gz +0 -0
  188. package/dist/client/assets/{triangle-alert-DG_BJhJY.js → triangle-alert-i_L8ws6U.js} +1 -1
  189. package/dist/client/assets/{vennDiagram-4TSXK5OY-BjYW4tQw.js → vennDiagram-4TSXK5OY-8FcrAdbk.js} +1 -1
  190. package/dist/client/assets/vennDiagram-4TSXK5OY-8FcrAdbk.js.br +0 -0
  191. package/dist/client/assets/{vennDiagram-4TSXK5OY-BjYW4tQw.js.gz → vennDiagram-4TSXK5OY-8FcrAdbk.js.gz} +0 -0
  192. package/dist/client/assets/{videoCompression-DrYmE1Ed.js → videoCompression-RIaDabW4.js} +1 -1
  193. package/dist/client/assets/videoCompression-RIaDabW4.js.br +0 -0
  194. package/dist/client/assets/videoCompression-RIaDabW4.js.gz +0 -0
  195. package/dist/client/assets/{wardleyDiagram-VM6X3IG4-DNVW8Yot.js → wardleyDiagram-VM6X3IG4-paL2wRrJ.js} +1 -1
  196. package/dist/client/assets/wardleyDiagram-VM6X3IG4-paL2wRrJ.js.br +0 -0
  197. package/dist/client/assets/wardleyDiagram-VM6X3IG4-paL2wRrJ.js.gz +0 -0
  198. package/dist/client/assets/{xychartDiagram-S5SC5T6Z-l7gJBKpK.js → xychartDiagram-S5SC5T6Z-BM5qJ4E7.js} +1 -1
  199. package/dist/client/assets/xychartDiagram-S5SC5T6Z-BM5qJ4E7.js.br +0 -0
  200. package/dist/client/assets/xychartDiagram-S5SC5T6Z-BM5qJ4E7.js.gz +0 -0
  201. package/dist/client/index.html +1 -1
  202. package/dist/client/index.html.br +0 -0
  203. package/dist/client/index.html.gz +0 -0
  204. package/dist/client/sw.js +1 -1
  205. package/dist/client/sw.js.br +0 -0
  206. package/dist/client/sw.js.gz +0 -0
  207. package/dist/server/agent/collaborationCli.js +30 -3
  208. package/dist/server/agent/collaborationDeliveryWorker.js +27 -8
  209. package/dist/server/agent/collaborationPeerTransport.js +3 -2
  210. package/dist/server/agent/collaborationRoutes.js +14 -1
  211. package/dist/server/agent/collaborationRouting.js +32 -0
  212. package/dist/server/agent/collaborationStore.js +27 -1
  213. package/dist/server/agent/collaborationTaskCli.js +1 -1
  214. package/dist/server/agent/collaborationTaskGuidance.js +2 -0
  215. package/dist/server/agent/collaborationTaskStore.js +18 -11
  216. package/dist/server/agent/collaborationTmuxDelivery.js +3 -2
  217. package/dist/server/agent/integrationCli.js +6 -0
  218. package/dist/server/agent/integrationServer.js +2 -0
  219. package/dist/server/agent/promptDelivery.js +2 -2
  220. package/dist/server/agent/sessionBindingRecovery.js +1 -1
  221. package/dist/server/agent/sessionLaunchState.js +20 -0
  222. package/dist/server/agent/terminalInput.js +17 -0
  223. package/dist/server/routes/terminal.js +125 -47
  224. package/docs/integrations.md +122 -0
  225. package/package.json +1 -1
  226. package/runtime-manifest.json +3 -3
  227. package/dist/client/assets/App-BF6YvbKL.js.br +0 -0
  228. package/dist/client/assets/App-BF6YvbKL.js.gz +0 -0
  229. package/dist/client/assets/ArchitecturePanel-D1Jca05w.js.br +0 -0
  230. package/dist/client/assets/ArchitecturePanel-D1Jca05w.js.gz +0 -0
  231. package/dist/client/assets/ChangeWalkthroughPanel-B59JwhzK.js.br +0 -0
  232. package/dist/client/assets/ChangeWalkthroughPanel-B59JwhzK.js.gz +0 -0
  233. package/dist/client/assets/CollaborationMainWorkspace-CS_o2iYt.js.br +0 -0
  234. package/dist/client/assets/CollaborationMainWorkspace-CS_o2iYt.js.gz +0 -0
  235. package/dist/client/assets/CollaborationTaskContent-WQ5CC-0d.js +0 -2
  236. package/dist/client/assets/ComputerControlView-CRquP12U.js.br +0 -0
  237. package/dist/client/assets/ComputerControlView-CRquP12U.js.gz +0 -0
  238. package/dist/client/assets/DagPlayground-CAfziHw_.js.br +0 -0
  239. package/dist/client/assets/DagPlayground-CAfziHw_.js.gz +0 -0
  240. package/dist/client/assets/DiffLab-CPlA_7PJ.js.br +0 -0
  241. package/dist/client/assets/DiffLab-CPlA_7PJ.js.gz +0 -0
  242. package/dist/client/assets/DiffReview-CjEi6PCy.js.br +0 -0
  243. package/dist/client/assets/DiffReview-CjEi6PCy.js.gz +0 -0
  244. package/dist/client/assets/DiffReviewLab-BFRqRotl.js.br +0 -0
  245. package/dist/client/assets/DiffReviewLab-BFRqRotl.js.gz +0 -0
  246. package/dist/client/assets/DiffViewer-Bh6lvUYN.js.br +0 -0
  247. package/dist/client/assets/DiffViewer-Bh6lvUYN.js.gz +0 -0
  248. package/dist/client/assets/ModelPreview-D_WFk4yX.js.br +0 -0
  249. package/dist/client/assets/ModelPreview-D_WFk4yX.js.gz +0 -0
  250. package/dist/client/assets/RightSidebar-7C9-PfhA.js.br +0 -0
  251. package/dist/client/assets/abnfDiagram-VCTEODGH-DDAdRY3H.js.br +0 -0
  252. package/dist/client/assets/abnfDiagram-VCTEODGH-DDAdRY3H.js.gz +0 -0
  253. package/dist/client/assets/app-BRESmgxW.js.br +0 -0
  254. package/dist/client/assets/app-BRESmgxW.js.gz +0 -0
  255. package/dist/client/assets/arc-CV9RqbOa.js.br +0 -0
  256. package/dist/client/assets/arc-CV9RqbOa.js.gz +0 -0
  257. package/dist/client/assets/architectureDiagram-5GKGNRK7-Ct8CtmBh.js.br +0 -0
  258. package/dist/client/assets/architectureDiagram-5GKGNRK7-Ct8CtmBh.js.gz +0 -0
  259. package/dist/client/assets/blockDiagram-I7D4REHJ-CVjuOZ0h.js.br +0 -0
  260. package/dist/client/assets/blockDiagram-I7D4REHJ-CVjuOZ0h.js.gz +0 -0
  261. package/dist/client/assets/c4Diagram-7LVT6UL2-CSKcN0J-.js.br +0 -0
  262. package/dist/client/assets/c4Diagram-7LVT6UL2-CSKcN0J-.js.gz +0 -0
  263. package/dist/client/assets/channel-BDjp8qZS.js +0 -1
  264. package/dist/client/assets/chunk-F27PBJKO-CwqjUNpz.js.br +0 -0
  265. package/dist/client/assets/chunk-F27PBJKO-CwqjUNpz.js.gz +0 -0
  266. package/dist/client/assets/chunk-IMKFNOWR-C9WCfeN9.js.br +0 -0
  267. package/dist/client/assets/chunk-IMKFNOWR-C9WCfeN9.js.gz +0 -0
  268. package/dist/client/assets/chunk-SVP7TREG-A-vVSOuv.js.br +0 -0
  269. package/dist/client/assets/chunk-SVP7TREG-A-vVSOuv.js.gz +0 -0
  270. package/dist/client/assets/chunk-TICWLB2K-akdXuwgx.js.br +0 -0
  271. package/dist/client/assets/chunk-TICWLB2K-akdXuwgx.js.gz +0 -0
  272. package/dist/client/assets/classDiagram-ZZMXUADV-CkFBQKLs.js +0 -1
  273. package/dist/client/assets/classDiagram-v2-VYDZK3BY-CkFBQKLs.js +0 -1
  274. package/dist/client/assets/cose-bilkent-JH36ORCC-CGfQhg7T.js.br +0 -0
  275. package/dist/client/assets/cose-bilkent-JH36ORCC-CGfQhg7T.js.gz +0 -0
  276. package/dist/client/assets/cynefin-OW5HDTMX-C9RaJCMn.js.br +0 -0
  277. package/dist/client/assets/cynefin-OW5HDTMX-C9RaJCMn.js.gz +0 -0
  278. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-C6SWqaZK.js.br +0 -0
  279. package/dist/client/assets/cynefinDiagram-5FMLGOSQ-C6SWqaZK.js.gz +0 -0
  280. package/dist/client/assets/dagre-GXQ25YYZ-DTMtzPmS.js.br +0 -0
  281. package/dist/client/assets/dagre-GXQ25YYZ-DTMtzPmS.js.gz +0 -0
  282. package/dist/client/assets/diagram-S7CK7UJ4-CRalzYBW.js.br +0 -0
  283. package/dist/client/assets/diagram-S7CK7UJ4-CRalzYBW.js.gz +0 -0
  284. package/dist/client/assets/diagram-UQ7AKVKN-B5qxEH5p.js.br +0 -0
  285. package/dist/client/assets/diagram-UQ7AKVKN-B5qxEH5p.js.gz +0 -0
  286. package/dist/client/assets/diagram-VSXAHHWV-CPSmBWU-.js.br +0 -0
  287. package/dist/client/assets/diagram-VSXAHHWV-CPSmBWU-.js.gz +0 -0
  288. package/dist/client/assets/diagram-VX7I27RA-CU8A_voC.js.br +0 -0
  289. package/dist/client/assets/diagram-VX7I27RA-CU8A_voC.js.gz +0 -0
  290. package/dist/client/assets/diagram-Z3DM3KII-CtT4QOY-.js.br +0 -0
  291. package/dist/client/assets/diagram-Z3DM3KII-CtT4QOY-.js.gz +0 -0
  292. package/dist/client/assets/ebnfDiagram-PWID7BFC-Cvk6Y8JV.js.br +0 -0
  293. package/dist/client/assets/ebnfDiagram-PWID7BFC-Cvk6Y8JV.js.gz +0 -0
  294. package/dist/client/assets/erDiagram-RLTQ6QDP-_9Ct2AHs.js.br +0 -0
  295. package/dist/client/assets/erDiagram-RLTQ6QDP-_9Ct2AHs.js.gz +0 -0
  296. package/dist/client/assets/flowDiagram-HODETNUW-BR29aDF_.js.br +0 -0
  297. package/dist/client/assets/flowDiagram-HODETNUW-BR29aDF_.js.gz +0 -0
  298. package/dist/client/assets/ganttDiagram-EL5Y4UJY-BvVG7ism.js.br +0 -0
  299. package/dist/client/assets/ganttDiagram-EL5Y4UJY-BvVG7ism.js.gz +0 -0
  300. package/dist/client/assets/gestureArbiter-DalDKZKj.js.br +0 -0
  301. package/dist/client/assets/gestureArbiter-DalDKZKj.js.gz +0 -0
  302. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-BHOjoasY.js.br +0 -0
  303. package/dist/client/assets/gitGraphDiagram-WWUBYQGX-BHOjoasY.js.gz +0 -0
  304. package/dist/client/assets/ishikawaDiagram-5VMMS53U-DoiUx_u1.js.br +0 -0
  305. package/dist/client/assets/ishikawaDiagram-5VMMS53U-DoiUx_u1.js.gz +0 -0
  306. package/dist/client/assets/journeyDiagram-3NMN7TZE-sz2KwGQ4.js.br +0 -0
  307. package/dist/client/assets/journeyDiagram-3NMN7TZE-sz2KwGQ4.js.gz +0 -0
  308. package/dist/client/assets/kanban-definition-UXKFOSKX-CdAnN6NF.js.br +0 -0
  309. package/dist/client/assets/kanban-definition-UXKFOSKX-CdAnN6NF.js.gz +0 -0
  310. package/dist/client/assets/layout-7mCqPnQ2.js.br +0 -0
  311. package/dist/client/assets/layout-7mCqPnQ2.js.gz +0 -0
  312. package/dist/client/assets/linear-CtGxEwoA.js.br +0 -0
  313. package/dist/client/assets/linear-CtGxEwoA.js.gz +0 -0
  314. package/dist/client/assets/mermaid.core-BxJ2mx92.js.br +0 -0
  315. package/dist/client/assets/mermaid.core-BxJ2mx92.js.gz +0 -0
  316. package/dist/client/assets/mindmap-definition-YA3MSWOX-Ck2pdDVb.js.br +0 -0
  317. package/dist/client/assets/mindmap-definition-YA3MSWOX-Ck2pdDVb.js.gz +0 -0
  318. package/dist/client/assets/passwordBootstrap-gTJ9KuKa.js.br +0 -0
  319. package/dist/client/assets/passwordBootstrap-gTJ9KuKa.js.gz +0 -0
  320. package/dist/client/assets/pegDiagram-XKGWAZYB-CYBdOhd0.js.br +0 -0
  321. package/dist/client/assets/pegDiagram-XKGWAZYB-CYBdOhd0.js.gz +0 -0
  322. package/dist/client/assets/pieDiagram-E7YTZNPT-IxFUaefz.js.br +0 -0
  323. package/dist/client/assets/pieDiagram-E7YTZNPT-IxFUaefz.js.gz +0 -0
  324. package/dist/client/assets/quadrantDiagram-AXDQQJYC-CSirkHeE.js.br +0 -0
  325. package/dist/client/assets/quadrantDiagram-AXDQQJYC-CSirkHeE.js.gz +0 -0
  326. package/dist/client/assets/railroadDiagram-O6MQD6OU-CYoi1Ctl.js.br +0 -0
  327. package/dist/client/assets/railroadDiagram-O6MQD6OU-CYoi1Ctl.js.gz +0 -0
  328. package/dist/client/assets/rdpSession-BQ_xI5BI.js.br +0 -0
  329. package/dist/client/assets/rdpSession-BQ_xI5BI.js.gz +0 -0
  330. package/dist/client/assets/referenceLongPress-DfQ5jnsk.js.br +0 -0
  331. package/dist/client/assets/referenceLongPress-DfQ5jnsk.js.gz +0 -0
  332. package/dist/client/assets/requirementDiagram-BXWQKSXE-BCoG9aBY.js.br +0 -0
  333. package/dist/client/assets/requirementDiagram-BXWQKSXE-BCoG9aBY.js.gz +0 -0
  334. package/dist/client/assets/sankeyDiagram-P5KCCOFB-BM0bKWHQ.js.br +0 -0
  335. package/dist/client/assets/sankeyDiagram-P5KCCOFB-BM0bKWHQ.js.gz +0 -0
  336. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-CVc-3QVK.js.br +0 -0
  337. package/dist/client/assets/sequenceDiagram-WJ2MYXX4-CVc-3QVK.js.gz +0 -0
  338. package/dist/client/assets/sizeCapture-INFHLROL-70GusSOh.js.br +0 -0
  339. package/dist/client/assets/sizeCapture-INFHLROL-70GusSOh.js.gz +0 -0
  340. package/dist/client/assets/stateDiagram-D77RDMKH-BCw-OQPL.js.br +0 -0
  341. package/dist/client/assets/stateDiagram-D77RDMKH-BCw-OQPL.js.gz +0 -0
  342. package/dist/client/assets/stateDiagram-v2-MP3YSRHH-C2WqSO6X.js +0 -1
  343. package/dist/client/assets/swimlanes-42K2YHIH--yebjz0I.js.br +0 -0
  344. package/dist/client/assets/swimlanes-42K2YHIH--yebjz0I.js.gz +0 -0
  345. package/dist/client/assets/swimlanesDiagram-VR7AAH4N-Cyxi7gqq.js +0 -8
  346. package/dist/client/assets/timeline-definition-24CTP7MA-B9_XXo4h.js.br +0 -0
  347. package/dist/client/assets/timeline-definition-24CTP7MA-B9_XXo4h.js.gz +0 -0
  348. package/dist/client/assets/vennDiagram-4TSXK5OY-BjYW4tQw.js.br +0 -0
  349. package/dist/client/assets/videoCompression-DrYmE1Ed.js.br +0 -0
  350. package/dist/client/assets/videoCompression-DrYmE1Ed.js.gz +0 -0
  351. package/dist/client/assets/wardleyDiagram-VM6X3IG4-DNVW8Yot.js.br +0 -0
  352. package/dist/client/assets/wardleyDiagram-VM6X3IG4-DNVW8Yot.js.gz +0 -0
  353. package/dist/client/assets/xychartDiagram-S5SC5T6Z-l7gJBKpK.js.br +0 -0
  354. package/dist/client/assets/xychartDiagram-S5SC5T6Z-l7gJBKpK.js.gz +0 -0
@@ -355,7 +355,8 @@ export class CollaborationPeerTransport {
355
355
  return [];
356
356
  const facts = terminalMessage(message);
357
357
  const known = Array.isArray(packet.known) ? packet.known.find((item) => item?.id === message.id) : undefined;
358
- if (known && known.status === facts.status && known.deliveredAt === facts.deliveredAt && known.shellConfirmed === message.shellConfirmed && (known.hasSnapshot || !message.snapshot))
358
+ if (known && known.status === facts.status && known.deliveredAt === facts.deliveredAt && known.shellConfirmed === message.shellConfirmed && (known.hasSnapshot || !message.snapshot)
359
+ && known.last_error === (store.diagnostic(message.id)?.last_error ?? null))
359
360
  return [];
360
361
  const receipt = store.receipt(message.id);
361
362
  return [{ id: message.id, status: facts.status, deliveredAt: facts.deliveredAt,
@@ -447,7 +448,7 @@ export class CollaborationPeerTransport {
447
448
  for (const message of payloads) {
448
449
  const result = await client.request({ type: 'collaboration-exchange', groupId: b.groupId,
449
450
  context: mapContext(store.context(b.groupId), id => id.startsWith('remote:') ? id : remoteSession(b.localOrigin, id)),
450
- ids: batch.map(m => m.id), known: batch.map(m => ({ id: m.id, status: m.status, deliveredAt: m.deliveredAt, hasSnapshot: !!m.snapshot, shellConfirmed: m.shellConfirmed })), ...(message ? { message } : {}) });
451
+ ids: batch.map(m => m.id), known: batch.map(m => ({ id: m.id, status: m.status, deliveredAt: m.deliveredAt, hasSnapshot: !!m.snapshot, shellConfirmed: m.shellConfirmed, last_error: store.diagnostic(m.id)?.last_error ?? null })), ...(message ? { message } : {}) });
451
452
  if (Array.isArray(result.activity))
452
453
  for (const item of result.activity.slice(0, 500)) {
453
454
  if (!item || typeof item.sessionId !== 'string' || item.sessionId.startsWith('remote:'))
@@ -10,7 +10,7 @@ import { COLLAB_LIMITS, CollaborationError, MIN_ID_PREFIX_LENGTH, ambiguousIdMes
10
10
  export function cleanMemberName(value) {
11
11
  return value.replace(/[\u0000-\u001f\u007f]/g, ' ').replace(/\s+/g, ' ').trim().slice(0, 80);
12
12
  }
13
- export function collaborationRoutes({ store, resolveSession, deliver, rebind, resolveNames, renameSession }) {
13
+ export function collaborationRoutes({ store, resolveSession, deliver, rebind, diagnoseRoute, resolveNames, renameSession }) {
14
14
  const router = Router();
15
15
  const run = (handler) => async (req, res) => {
16
16
  try {
@@ -96,6 +96,16 @@ export function collaborationRoutes({ store, resolveSession, deliver, rebind, re
96
96
  }
97
97
  res.json({ ok: true, route: await rebind(sessionId, pane ?? null) });
98
98
  }));
99
+ router.get('/route/:id', run(async (req, res, sessionId) => {
100
+ const id = String(req.params.id);
101
+ if (id !== sessionId && !store.groupsForSession(sessionId).some(group => group.sessionIds.includes(id)))
102
+ throw new CollaborationError('NOT_A_GROUP_MEMBER', 'Route diagnostics require a shared group', 403);
103
+ if (id.startsWith('remote:'))
104
+ throw new CollaborationError('REMOTE_ROUTE_DIAGNOSTICS_UNSUPPORTED', 'Query the owning service for the current runtime evidence', 409);
105
+ if (!diagnoseRoute)
106
+ throw new CollaborationError('ROUTE_DIAGNOSTICS_UNAVAILABLE', 'The running service does not support route diagnostics (minimum 1.4.321)', 409);
107
+ res.json({ ok: true, route: await diagnoseRoute(id) });
108
+ }));
99
109
  /** Accepts the short id a terminal shows as well as the full one; an
100
110
  * ambiguous prefix is refused rather than guessed, so a reply can never
101
111
  * land on the wrong thread. */
@@ -152,6 +162,9 @@ export function collaborationRoutes({ store, resolveSession, deliver, rebind, re
152
162
  };
153
163
  router.get('/capabilities', run((_req, res) => {
154
164
  res.json({ protocol_version: 2, server_version: getTermdockVersion(), limits: COLLAB_LIMITS,
165
+ route_diagnostics: !!diagnoseRoute, route_identity_recovery: !!diagnoseRoute, route_identity_recovery_min_version: '1.4.321',
166
+ agent_launch_generation_consistency: true, agent_launch_generation_consistency_min_version: '1.4.322',
167
+ terminal_input_check_diagnostics: true,
155
168
  task_workflow: { version: 2, command: 'td collab task', single_authority: true, explicit_reports: true,
156
169
  managed_goals: true, automatic_review: true, dependency_dispatch: true, isolated_worktrees: true, encrypted_commit_transfer: true,
157
170
  durable_questions: true, user_acceptance: true, versioned_artifacts: true, independent_reviews: true,
@@ -17,6 +17,11 @@ export class CollaborationRoutingStore {
17
17
  || !/^%\d+$/.test(binding.pane.paneId) || !/^\$\d+$/.test(binding.pane.sessionId) || typeof binding.pane.agentSlug !== 'string'))) {
18
18
  throw new Error('Invalid collaboration binding');
19
19
  }
20
+ if (binding.routeRevision !== undefined && (typeof binding.routeRevision !== 'string' || !/^[a-zA-Z0-9-]{1,80}$/.test(binding.routeRevision)))
21
+ throw new Error('Invalid route revision');
22
+ if (binding.lastRecovery !== undefined && (!binding.lastRecovery || !['native-identity', 'owner-confirmed'].includes(binding.lastRecovery.kind)
23
+ || !Number.isSafeInteger(binding.lastRecovery.at)))
24
+ throw new Error('Invalid route recovery record');
20
25
  this.bindings.set(binding.sessionId, binding);
21
26
  }
22
27
  }
@@ -38,6 +43,10 @@ export class CollaborationRoutingStore {
38
43
  ownerOfBackend(id) {
39
44
  return [...this.bindings.values()].find((binding) => binding.backendSessionId === id)?.sessionId ?? null;
40
45
  }
46
+ hasOtherPaneOwner(id, pane) {
47
+ return [...this.bindings.values()].some(binding => binding.sessionId !== id && binding.pane
48
+ && binding.pane.serverPid === pane.serverPid && binding.pane.sessionId === pane.sessionId && binding.pane.paneId === pane.paneId);
49
+ }
41
50
  bind(binding) {
42
51
  this.assertReadable();
43
52
  const owner = binding.backendSessionId ? this.ownerOfBackend(binding.backendSessionId) : null;
@@ -65,6 +74,29 @@ export class CollaborationRoutingStore {
65
74
  this.bindings = next;
66
75
  }
67
76
  }
77
+ export function assessCollaborationRouteIdentity(binding, panes, ownershipConfirmed, unconfirmedWrite) {
78
+ const selected = selectCollaborationPane(binding, panes);
79
+ const metadata = (pane) => ({ serverPid: pane.serverPid, sessionId: pane.sessionId,
80
+ paneId: pane.paneId, panePid: pane.panePid, agentSlug: pane.agentSlug, nativeSessionId: pane.nativeSessionId });
81
+ const diagnostics = { expected: binding.pane ? { ...binding.pane } : null,
82
+ observed: panes.slice(0, 20).map(pane => ({ ...metadata(pane), nativeIdentitySource: pane.nativeIdentitySource ?? null, nativeIdentityFailure: pane.nativeIdentityFailure ?? null, nativeIdentityVerified: pane.nativeIdentityVerified === true })),
83
+ truncated: panes.length > 20, recovery: 'unchanged', reason: null,
84
+ rebind_command: `td collab --session ${binding.sessionId} rebind${panes.length === 1 ? ` --pane ${panes[0].paneId}` : ''}` };
85
+ if (selected.state !== 'identity-mismatch')
86
+ return { ...selected, diagnostics };
87
+ const nativeId = binding.pane?.nativeSessionId ?? binding.nativeSessionId;
88
+ const slug = binding.pane?.agentSlug || binding.agentSlug;
89
+ const matching = panes.filter(pane => !pane.isShell && pane.agentSlug === slug && pane.nativeSessionId === nativeId
90
+ && !pane.nativeIdentityFailure && pane.nativeIdentityVerified === true);
91
+ diagnostics.recovery = 'confirmation-required';
92
+ diagnostics.reason = unconfirmedWrite ? 'DELIVERY_OUTCOME_UNCONFIRMED' : !ownershipConfirmed ? 'ROUTE_OWNERSHIP_UNCONFIRMED'
93
+ : !nativeId || !slug ? 'NATIVE_IDENTITY_UNCONFIRMED' : matching.length > 1 ? 'MULTIPLE_NATIVE_IDENTITY_MATCHES'
94
+ : matching.length !== 1 ? 'NATIVE_IDENTITY_UNCONFIRMED' : null;
95
+ if (diagnostics.reason)
96
+ return { ...selected, diagnostics };
97
+ diagnostics.recovery = 'automatic';
98
+ return { state: 'ready', pane: matching[0], diagnostics };
99
+ }
68
100
  // Once pinned, changing the active pane cannot change the recipient. A reused
69
101
  // tmux name/pane after a server restart must not inherit an old peer's inbox.
70
102
  export function selectCollaborationPane(binding, panes) {
@@ -584,6 +584,10 @@ export class CollaborationStore {
584
584
  this.expire();
585
585
  return [...new Set(this.document.messages.filter((message) => message.status === 'pending').map((message) => message.toSessionId))];
586
586
  }
587
+ hasUnconfirmedDelivery(sessionId) {
588
+ return this.document.messages.some(message => message.toSessionId === sessionId && message.status === 'pending'
589
+ && (this.document.transport?.[message.id]?.attempt_count ?? 0) > 0);
590
+ }
587
591
  confirmShell(messageId) {
588
592
  const message = this.getMessage(messageId);
589
593
  if (!message || message.status !== 'pending')
@@ -773,6 +777,25 @@ export class CollaborationStore {
773
777
  (this.document.transport ??= {})[id] = diagnostic;
774
778
  this.persist();
775
779
  }
780
+ /** A route blocks the whole recipient queue, not just its first message. */
781
+ recordRecipientTransport(sessionId, patch) {
782
+ let changed = false;
783
+ for (const message of this.document.messages) {
784
+ if (message.toSessionId !== sessionId || message.status !== 'pending')
785
+ continue;
786
+ const previous = this.document.transport?.[message.id];
787
+ if ((previous?.checked_at ?? 0) > patch.checked_at)
788
+ continue;
789
+ const next = { relay_online: null, peer_reachable: null, next_retry_at: null, last_error: null,
790
+ ...previous, ...patch, attempt_count: previous?.attempt_count ?? 0 };
791
+ if (JSON.stringify(previous) === JSON.stringify(next))
792
+ continue;
793
+ (this.document.transport ??= {})[message.id] = next;
794
+ changed = true;
795
+ }
796
+ if (changed)
797
+ this.persist();
798
+ }
776
799
  receipt(id, raw = false) {
777
800
  const message = this.getMessage(id);
778
801
  if (!message)
@@ -788,7 +811,10 @@ export class CollaborationStore {
788
811
  failure_reason: message.failureReason ?? null, delivery_semantics: message.status === 'stored' ? 'durable_storage' : facts.deliverySource ?? (facts.deliveredAt === null ? 'not_delivered' : 'legacy_or_unspecified'),
789
812
  snapshot: message.snapshot ? (raw ? message.snapshot : plainCollaborationSnapshot(message.snapshot)) : null,
790
813
  delivery: { status: facts.status,
791
- stage: message.status === 'stored' ? 'stored' : facts.deliveredAt !== null ? 'terminal_written' : diagnostic?.remote_received_at ? 'remote_received' : 'queued',
814
+ stage: message.status === 'stored' ? 'stored' : facts.deliveredAt !== null ? 'terminal_written' : diagnostic?.route_state === 'identity-mismatch' || diagnostic?.last_error === 'TMUX_PANE_CHANGED' ? 'blocked' : diagnostic?.remote_received_at ? 'remote_received' : 'queued',
815
+ ...(!diagnostic?.route_diagnostics && diagnostic?.last_error === 'TMUX_PANE_CHANGED' ? { requires_confirmation: true } : {}),
816
+ ...(diagnostic?.route_diagnostics ? { route: diagnostic.route_diagnostics, route_state: diagnostic.route_state,
817
+ requires_confirmation: diagnostic.route_diagnostics.recovery === 'confirmation-required' } : {}),
792
818
  remote_received_at: diagnostic?.remote_received_at ?? null, delivered_at: facts.deliveredAt, error: message.failureReason ?? diagnostic?.last_error ?? null },
793
819
  reply: { status: replies.length ? 'received' : 'pending', ack_at: replies.find(reply => reply.responseKind === 'ack')?.createdAt ?? null, reply_ids: replies.map(reply => reply.id) },
794
820
  idempotency_key: message.idempotencyKey ?? null,
@@ -15,7 +15,7 @@ export async function executeTaskCommand(command, request, io) {
15
15
  plan: [...bodyOptions, 'attempt', 'evidence'], review: [...bodyOptions, 'artifact', 'evidence', 'verdict'], comment: bodyOptions,
16
16
  'request-review': [...bodyOptions, 'artifact', 'assignee', 'revision'],
17
17
  revise: [...bodyOptions, 'revision'], close: [...bodyOptions, 'revision'], reopen: [...bodyOptions, 'revision'],
18
- coordinate: [...bodyOptions, 'revision'], pause: [...bodyOptions, 'revision'], resume: [...bodyOptions, 'revision'], retry: [...bodyOptions, 'revision'],
18
+ coordinate: [...bodyOptions, 'revision', 'summary'], pause: [...bodyOptions, 'revision'], resume: [...bodyOptions, 'revision'], retry: [...bodyOptions, 'revision'],
19
19
  };
20
20
  for (const flag of Object.keys(o))
21
21
  if (![...allowed[operation], ...(o.principal ? originOptions : []), 'principal', 'session', 'json', 'jsonl', 'text', 'help'].includes(flag))
@@ -0,0 +1,2 @@
1
+ /** Shared across first dispatch and subsequent coordination wakes. */
2
+ export const GOAL_EXPERIENCE_GUIDE = "用户可理解的拆分与更新:一个用户目标保留一张主卡片,所有执行工作都挂在这个目标下;跟进与返工沿用原目标,不用新的顶层目标表达同一件事。子任务按可验收成果划分,一项有明确产物、负责人、完成标准和必要依赖;标题用简短动词加成果名称,不用角色名、过程日志、ID或‘好的/按计划’。简单问题只安排一个必要执行任务;复杂任务仅在产物或负责人可独立验收时拆分,不为采集、复述、重复汇总制造多份卡片。首次拆分后、范围或依赖变化、明确里程碑或受阻时,用 task coordinate --revision <最新版本> --summary '已完成什么;当前推进什么;下一步或需要用户什么' --content '工作划分、各项产物、依赖顺序和依据' 更新当前目标。摘要面向用户,简短说明变化和下一步,不堆哈希、路径、版本号和验证日志;完整证据保留正文。执行成员用 report --attempt <当前尝试> --status working|blocked|failed --summary '当前明确进展或缺少的条件';没有新事实不要重复发报告,不报告百分比、预估剩余时间或无法观测的内部活动。只有存在必要的人类决定时用 task ask,普通安排说明不要求用户确认方案。";
@@ -1,3 +1,4 @@
1
+ import { GOAL_EXPERIENCE_GUIDE } from './collaborationTaskGuidance.js';
1
2
  import { randomBytes, createHash } from 'node:crypto';
2
3
  import { readFileSync, writeFileSync, mkdirSync, renameSync } from 'node:fs';
3
4
  import { dirname } from 'node:path';
@@ -186,15 +187,17 @@ export class CollaborationTaskStore {
186
187
  const current = task.attempts.find(a => a.id === task.activeAttemptId);
187
188
  const result = task.artifacts.filter(a => a.kind === 'result' && a.attemptId === task.activeAttemptId).at(-1);
188
189
  const plan = task.artifacts.filter(a => a.kind === 'plan' && a.attemptId === task.activeAttemptId).at(-1);
189
- const reportSummary = current?.report?.content.split(/\n\s*\n/).map(paragraph => paragraph.split('\n').filter(line => !/^#{1,6}\s/.test(line)).join('\n').trim()).find(Boolean)?.slice(0, 512);
190
+ const reportSummary = (current?.report?.summary || current?.report?.content.split(/\n\s*\n/).map(paragraph => paragraph.split('\n').filter(line => !/^#{1,6}\s/.test(line)).join('\n').trim()).find(Boolean))?.slice(0, 512);
191
+ const coordination = task.events.filter(e => e.kind === 'coordinate' && e.attemptId === task.activeAttemptId).at(-1);
190
192
  const automationIssueSource = task.automationIssue ? current?.report && ['blocked', 'failed'].includes(current.report.status)
191
193
  && task.automationIssue === current.report.content.slice(0, 1000) ? 'member-report' : 'system' : undefined;
192
- return { ...task, ...(task.purpose === 'automation' ? { execution: taskExecution(task) } : {}), automationIssueSource, spec: task.spec.slice(0, 512), constraints: '', acceptance: '',
194
+ return { ...task, ...(task.purpose === 'automation' ? { execution: taskExecution(task) } : {}), automationIssueSource, spec: task.spec.slice(0, 512), constraints: '', acceptance: task.acceptance.slice(0, 512),
193
195
  deliveries: task.deliveries.filter(d => d.attemptId === task.activeAttemptId && d.error).slice(-1),
194
- attempts: current ? [{ ...current, report: current.report ? { ...current.report, summary: reportSummary, content: '', evidence: undefined } : undefined }] : [],
196
+ attempts: current ? [{ ...current, report: current.report ? { ...current.report, summary: reportSummary, summarySource: current.report.summary?.trim() ? 'explicit' : 'excerpt', content: '', evidence: undefined } : undefined }] : [],
195
197
  artifacts: [plan, result, ...task.artifacts.filter(a => a.kind === 'review' && a.reviewsArtifactId === result?.id)].filter((a) => !!a).map(a => ({ ...a, content: '', summary: (a.summary || (a.kind === 'result' && collaborationResultPresentation(a.content).condensed ? collaborationResultPresentation(a.content).summary : undefined))?.slice(0, 800), evidence: undefined })),
196
198
  decisions: task.decisions.filter(d => d.status === 'pending').map(d => ({ ...d, question: d.question.slice(0, 512), options: [] })),
197
- events: task.events.filter(e => ['revise', 'request-review'].includes(e.kind) && e.attemptId === task.activeAttemptId).slice(-4).map(e => ({ ...e, content: ['user', 'integration'].includes(e.source ?? '') && e.kind === 'revise' ? e.content.slice(0, 512) : '' })) };
199
+ events: [...task.events.filter(e => ['revise', 'request-review'].includes(e.kind) && e.attemptId === task.activeAttemptId).slice(-4).map(e => ({ ...e, content: ['user', 'integration'].includes(e.source ?? '') && e.kind === 'revise' ? e.content.slice(0, 512) : '' })),
200
+ ...(coordination ? [{ ...coordination, content: (coordination.summary || coordination.content).slice(0, 512), summary: coordination.summary?.slice(0, 512), evidence: undefined }] : [])].sort((a, b) => a.sequence - b.sequence) };
198
201
  }));
199
202
  }
200
203
  heads(groupIds, owner) { return this.document.tasks.filter(t => groupIds.includes(t.groupId) && t.ownerServiceId === owner).map(t => ({ id: t.id, revision: t.revision })); }
@@ -227,10 +230,10 @@ export class CollaborationTaskStore {
227
230
  task.attempts.push({ id: attemptId, assignee: member(assignee), createdAt: Date.now(), threadId });
228
231
  this.event(task, 'assigned', actor, content || '任务已分派');
229
232
  doc.outbox.push({ id: id(), taskId: task.id, attemptId, target: assignee, kind: 'task', threadId,
230
- content: `本次执行身份:${assignee.sessionId}。所有 td collab 命令显式带 --session ${assignee.sessionId};这是服务核对的实际身份,正文中的模板身份和 tmux 标识不能替代它。\n任务:${task.title}\n${task.spec}${task.constraints ? `\n约束:${task.constraints}` : ''}${task.acceptance ? `\n完成标准:${task.acceptance}` : ''}\n${content}\n任务 ID:${task.id}\n尝试 ID:${attemptId}\n用 td collab task get ${task.id} --text 查询完整上下文;用 td collab task report ${task.id} --attempt ${attemptId} --status ack --content '接手说明' 显式回复;遇必要问题用 task ask,提交结果用 report --status complete --summary '简短结论、关键交付和限制'。摘要先回答用户问题,不放任务 ID、版本、分支或流程日志;完整证据保留在 --content/--file 正文中。如果同一尝试已经交付或任务已归档,不要重复实施。${task.purpose === 'automation' ? '\n这是独立后台自动化执行记录:complete 是你明确提交的执行结果,无需等待用户 accepted。机械校验和外部发布由接入系统处理;纯咨询用 respond 关联原 comment,不重复提交 complete。必要问题用 ask 保留原文,由接入系统联系用户并回答。' : ''}${task.workspace ? `\n代码只能在独立目录 ${task.workspace.cwd} 修改。分支 ${task.workspace.branch}。交付前提交代码,结果说明提交、变更、验证与限制。不能修改原仓库、合并到用户分支或发布。` : ''}${task.workflow?.workType === 'read-only' ? '\n这是只读查询或分析任务:在本机会话中采集并交付报告,不修改代码或系统,不创建提交、构建、部署或终止进程。结果需说明采样时间、证据和限制。' : ''}${task.workflow?.kind === 'step' ? '\n完成报告会自动请求独立评审;评审要求修改时继续完成,重新提交 complete。只按用户授权运行测试。' : ''}` });
233
+ content: `本次执行身份:${assignee.sessionId}。所有 td collab 命令显式带 --session ${assignee.sessionId};这是服务核对的实际身份,正文中的模板身份和 tmux 标识不能替代它。\n任务:${task.title}\n${task.spec}${task.constraints ? `\n约束:${task.constraints}` : ''}${task.acceptance ? `\n完成标准:${task.acceptance}` : ''}\n${content}\n任务 ID:${task.id}\n尝试 ID:${attemptId}\n用 td collab task get ${task.id} --text 查询完整上下文;用 td collab task report ${task.id} --attempt ${attemptId} --status ack --content '接手说明' 显式回复;遇必要问题用 task ask,提交结果用 report --status complete --summary '简短结论、关键交付和限制'。摘要先回答用户问题,不放任务 ID、版本、分支或流程日志;完整证据保留在 --content/--file 正文中。明确里程碑、交付范围变化或遇到阻塞时,可用 report --status working|blocked|failed --summary '用户能理解的当前进展与下一步' --content '原始说明与证据' 更新,不以终端有输出代替报告,不重复无变化的进展。如果同一尝试已经交付或任务已归档,不要重复实施。${task.purpose === 'automation' ? '\n这是独立后台自动化执行记录:complete 是你明确提交的执行结果,无需等待用户 accepted。机械校验和外部发布由接入系统处理;纯咨询用 respond 关联原 comment,不重复提交 complete。必要问题用 ask 保留原文,由接入系统联系用户并回答。' : ''}${task.workspace ? `\n代码只能在独立目录 ${task.workspace.cwd} 修改。分支 ${task.workspace.branch}。交付前提交代码,结果说明提交、变更、验证与限制。不能修改原仓库、合并到用户分支或发布。` : ''}${task.workflow?.workType === 'read-only' ? '\n这是只读查询或分析任务:在本机会话中采集并交付报告,不修改代码或系统,不创建提交、构建、部署或终止进程。结果需说明采样时间、证据和限制。' : ''}${task.workflow?.kind === 'step' ? '\n完成报告会自动请求独立评审;评审要求修改时继续完成,重新提交 complete。代码交付前运行受影响的测试和必要构建;查询交付核对数据来源、采样时间和限制。未实际验收的路径必须明确说明。' : ''}` });
231
234
  }
232
235
  goalInstructions(task) {
233
- return `${this.baseGoalInstructions(task)}\n启动 Agent 前,读取 task get 返回的 launchProfiles、defaultLaunchProfileId 和 roster.launchProfile。根据用户填写的 notes 判断适用任务;这些是选用建议,不是能力或性能保证。需要另一种模型或参数时,用 td collab spawn ${task.groupId} <agentSlug> --launch-profile <方案id> --cwd <项目目录> --session ${task.coordinator?.sessionId} 创建对应执行成员,再把子任务分派给它。已有成员及其代码执行会话保留创建时的启动方案,不因默认方案变更而更换模型。`;
236
+ return `${this.baseGoalInstructions(task)}\n${GOAL_EXPERIENCE_GUIDE}\n启动 Agent 前,读取 task get 返回的 launchProfiles、defaultLaunchProfileId 和 roster.launchProfile。根据用户填写的 notes 判断适用任务;这些是选用建议,不是能力或性能保证。需要另一种模型或参数时,用 td collab spawn ${task.groupId} <agentSlug> --launch-profile <方案id> --cwd <项目目录> --session ${task.coordinator?.sessionId} 创建对应执行成员,再把子任务分派给它。已有成员及其代码执行会话保留创建时的启动方案,不因默认方案变更而更换模型。`;
234
237
  }
235
238
  baseGoalInstructions(task) {
236
239
  return `你是此目标的协调者,负责把目标推进到可验收交付,不亲自实施子任务。\n目标:${task.spec}\n约束:${task.constraints || '未补充'}\n完成标准:${task.acceptance || '满足用户目标,说明交付与限制'}\n任务 ID:${task.id}\n当前协调身份:${task.coordinator?.sessionId};所有命令显式带 --session ${task.coordinator?.sessionId},不使用 tmux 标识。\n用 td collab task get ${task.id} --json 读取 roster、子任务、完整记录和 revision。\n先报告 ack;拆分为可交付子任务,用 td collab task create --group ${task.groupId} --parent ${task.id} --title '标题' --content '完整要求' --assignee <roster里的成员sessionId> --acceptance '明确标准' --work-type read-only|code。先按目标明确分类:查询、检查、研究、分析用 read-only,复用现有执行成员会话,不创建 Git 目录;修改代码用 code,才创建独立目录。简单问题只建一个必要任务,不为了形式拆成采集、复述、汇总多份任务。子任务继承自动评审与协调者。依赖任务用 --depends-on id,id,服务在依赖评审通过后自动分派。保持分工合理,不根据终端输出推断谁有空。\n每次收到明确更新后读取最新记录,处理失败与交接。服务自动安排独立评审、返工和依赖接续;不要重复请求评审或催促正在等待回复的成员。必要的人类决策用 task ask --attempt <本轮id>;方案需要用户确认时提交 task plan,不把普通回复当授权。\n只有已交付代码任务实际包含相对 base 的提交变化时,才需创建 --work-type code --integration 的最终集成子任务,--depends-on 依赖全部代码实施任务;独立目录会包含依赖的提交。不得在原仓库自动合并或发布。\n结束本次协调用 td collab task coordinate ${task.id} --revision <最新版本> --content '已安排的工作和下一步';有新事件服务会再次唤起你。所有子任务评审通过后报告 complete --summary '直接回答用户的简短结果和限制';只读目标直接汇总已核对结果,不创建集成或重复汇总任务。正文保留证据、评审结论和限制,仅代码目标补充目录、分支和提交,等待用户最终验收。任何异常都要留下明确说明,不伪造完成或进度。`;
@@ -354,8 +357,8 @@ export class CollaborationTaskStore {
354
357
  taskPurpose(input.purpose);
355
358
  const content = text(input.content, '内容');
356
359
  const summary = text(input.summary, '结果摘要', 2400);
357
- if (summary && (input.kind !== 'report' || input.status !== 'complete'))
358
- throw new CollaborationError('INVALID_SUMMARY', '摘要只能随完成结果提交');
360
+ if (summary && input.kind !== 'coordinate' && (input.kind !== 'report' || !['working', 'blocked', 'failed', 'complete'].includes(input.status ?? '')))
361
+ throw new CollaborationError('INVALID_SUMMARY', '摘要只能用于进展、阻塞、失败、结果或协调说明');
359
362
  if (input.verdict !== undefined && !['pass', 'changes', 'blocked'].includes(input.verdict))
360
363
  throw new CollaborationError('INVALID_VERDICT', '评审结论无效');
361
364
  if (input.evidence !== undefined && Buffer.byteLength(JSON.stringify(input.evidence)) > 16_384)
@@ -470,10 +473,12 @@ export class CollaborationTaskStore {
470
473
  if (plan && task.approvedPlanArtifactId !== plan.id)
471
474
  throw new CollaborationError('PLAN_PENDING', '方案尚未由用户确认,请先等待决定', 409);
472
475
  }
473
- attempt.report = { status: input.status, content, evidence: input.evidence, createdAt: Date.now() };
476
+ attempt.report = { status: input.status, content, ...(summary ? { summary } : {}), evidence: input.evidence, createdAt: Date.now() };
474
477
  const event = this.event(task, 'report', actor, content, attempt.id);
475
478
  event.reportStatus = input.status;
476
479
  event.evidence = input.evidence;
480
+ if (summary)
481
+ event.summary = summary;
477
482
  if (input.status === 'complete' && attempt.id === task.activeAttemptId && task.status === 'accepted') {
478
483
  task.status = 'open';
479
484
  delete task.acceptedArtifactId;
@@ -631,7 +636,9 @@ export class CollaborationTaskStore {
631
636
  else if (input.kind === 'coordinate') {
632
637
  if (task.workflow?.kind !== 'goal' || !sameMember(actor, task.coordinator) || !content)
633
638
  throw new CollaborationError('COORDINATOR_REQUIRED', '请由目标协调者提交本次协调说明', 403);
634
- this.event(task, 'coordinate', actor, content);
639
+ const event = this.event(task, 'coordinate', actor, content);
640
+ if (summary)
641
+ event.summary = summary;
635
642
  task.coordination = { notifiedSequence: task.events.at(-1).sequence, acknowledgedSequence: task.events.at(-1).sequence, notifiedAt: Date.now() };
636
643
  delete task.automationIssue;
637
644
  }
@@ -807,7 +814,7 @@ export class CollaborationTaskStore {
807
814
  else if (action === 'wake') {
808
815
  const updates = task.events.filter(e => e.sequence > task.coordination.notifiedSequence && e.kind !== 'coordinate');
809
816
  doc.outbox.push({ id: id(), taskId: task.id, attemptId: task.activeAttemptId, target: task.coordinator, kind: 'message', threadId: task.id,
810
- content: `当前协调身份:${task.coordinator.sessionId};命令带 --session ${task.coordinator.sessionId}。\n目标「${task.title}」有新的明确事件,请继续协调:\n${updates.slice(-8).map(e => `${new Date(e.createdAt).toISOString()} ${e.content.slice(0, 1200)}`).join('\n')}\n用 td collab task get ${task.id} --json 读取完整上下文与子任务;安排必要下一步后 task coordinate ${task.id} --revision <最新版本> --content '协调说明'。自动评审和依赖已由服务接续,不要重复分派。\n当前流程指南:查询、检查、分析必须 --work-type read-only,复用 roster 现有执行成员;只有修改代码才用 code 和独立目录。只读报告由你直接汇总,不新增仅转述的汇总子任务。已评审且 HEAD 等于 base 的交付没有代码变化,不需要集成;有代码变化才安排必要集成。用户有新要求时继续本目标,交付新版本,不重做已有采样。最终汇总通过评审且无新要求时等待用户验收,不重复提交相同结果。` });
817
+ content: `当前协调身份:${task.coordinator.sessionId};命令带 --session ${task.coordinator.sessionId}。\n目标「${task.title}」有新的明确事件,请继续协调:\n${updates.slice(-8).map(e => `${new Date(e.createdAt).toISOString()} ${e.content.slice(0, 1200)}`).join('\n')}\n用 td collab task get ${task.id} --json 读取完整上下文与子任务;安排必要下一步后 task coordinate ${task.id} --revision <最新版本> --content '协调说明'。自动评审和依赖已由服务接续,不要重复分派。\n当前流程指南:查询、检查、分析必须 --work-type read-only,复用 roster 现有执行成员;只有修改代码才用 code 和独立目录。只读报告由你直接汇总,不新增仅转述的汇总子任务。已评审且 HEAD 等于 base 的交付没有代码变化,不需要集成;有代码变化才安排必要集成。用户有新要求时继续本目标,交付新版本,不重做已有采样。最终汇总通过评审且无新要求时等待用户验收,不重复提交相同结果。\n${GOAL_EXPERIENCE_GUIDE}` });
811
818
  task.coordination.notifiedSequence = task.events.at(-1).sequence;
812
819
  task.coordination.notifiedAt = Date.now();
813
820
  }
@@ -40,6 +40,7 @@ export function writeCollaborationTmuxPane(run, pane, prompt, stdin, assertCurre
40
40
  progress?.('queue_wait');
41
41
  return serializeTerminalInput(paneInputKey(pane), () => {
42
42
  progress?.('queue_acquired');
43
+ assertCurrent?.('queue_acquired');
43
44
  return writeTmuxPrompt(run, pane, prompt, stdin, assertCurrent, progress);
44
45
  });
45
46
  }
@@ -47,7 +48,7 @@ async function writeTmuxPrompt(run, pane, prompt,
47
48
  /** Body travels on stdin so tmux cannot parse its semicolons/backslashes. */
48
49
  stdin, assertCurrent, progress) {
49
50
  await assertSamePane(run, pane);
50
- assertCurrent?.();
51
+ assertCurrent?.('before_paste');
51
52
  // A fixed pane target is independent of the current window, keyboard focus
52
53
  // and browser presence. Delivery goes through a named tmux buffer rather
53
54
  // than `send-keys -l`: while a pane is in copy-mode, literal bytes are
@@ -81,7 +82,7 @@ stdin, assertCurrent, progress) {
81
82
  progress?.('paste_written');
82
83
  await waitForPromptSubmit();
83
84
  await assertSamePane(run, pane);
84
- assertCurrent?.();
85
+ assertCurrent?.('before_submit');
85
86
  progress?.('submit_attempted');
86
87
  await run([
87
88
  // The submit key rides outside the paste block: inside it, an editor
@@ -61,6 +61,12 @@ export const INTEGRATION_HELP = `td integration — local scoped integration adm
61
61
  diagnostics <TD-session-id> (read stored launch/restore diagnostics; administrator only)
62
62
  1.4.314 adds phase/timestamps, paste/submit write facts and target-change
63
63
  evidence; no argv/environment/credentials or application readiness claim.
64
+ 1.4.322 adds guard_captured/runtime_resolving/runtime_resolved stages and
65
+ target_change.check_phase/guard_captured_at/checked_at, launch IDs and route revisions.
66
+ Check actual server agent_launch_generation_consistency=true (minimum 1.4.322),
67
+ terminal_input_check_diagnostics=true; upgrading only the CLI does not fix a running service.
68
+ TERMINAL_INPUT_TARGET_CHANGED still rejects an actually replaced target.
69
+ create never auto-retries; retry-cold remains a separate, explicitly authorized operation.
64
70
  Prior versions cannot reconstruct missing launch evidence retroactively.
65
71
  create --file <policy.json> --credential-file <private-output.json>
66
72
  update --file <policy.json> (same identity/group; preserves the credential)
@@ -246,6 +246,8 @@ export class IntegrationRuntime {
246
246
  session_startup_input_clear: true, session_startup_input_clear_min_version: '1.4.310',
247
247
  agent_launch_process_check: true, agent_launch_process_check_min_version: '1.4.312',
248
248
  terminal_input_runtime_fence: true, terminal_input_runtime_fence_min_version: '1.4.313',
249
+ agent_launch_generation_consistency: true, agent_launch_generation_consistency_min_version: '1.4.322',
250
+ terminal_input_check_diagnostics: true,
249
251
  session_launch_diagnostics: true, session_launch_diagnostics_min_version: '1.4.314',
250
252
  session_cold_retry: true, session_cold_retry_min_version: '1.4.314',
251
253
  session_rename: true, session_rename_min_version: '1.4.315',
@@ -22,12 +22,12 @@ export function writeBracketedPrompt(target, prompt, assertCurrent, progress) {
22
22
  progress?.('queue_wait');
23
23
  return serializeTerminalInput(target, async () => {
24
24
  progress?.('queue_acquired');
25
- assertCurrent?.();
25
+ assertCurrent?.('queue_acquired');
26
26
  progress?.('paste_attempted');
27
27
  target.write(buildBracketedPasteBytes(prompt));
28
28
  progress?.('paste_written');
29
29
  await waitForPromptSubmit();
30
- assertCurrent?.();
30
+ assertCurrent?.('before_submit');
31
31
  progress?.('submit_attempted');
32
32
  target.write('\r');
33
33
  progress?.('submit_written');
@@ -39,7 +39,7 @@ export function resolveCollaborationBackend(record, records, backends, routing)
39
39
  return null;
40
40
  if (records.some((other) => other.sessionId !== record.sessionId && other.backendSessionId === id))
41
41
  return null;
42
- routing.bind({ sessionId: record.sessionId, backendSessionId: id, mode: backend.mode,
42
+ routing.bind({ ...binding, sessionId: record.sessionId, backendSessionId: id, mode: backend.mode,
43
43
  tmuxSessionName: backend.tmuxSessionName,
44
44
  agentSlug: binding?.agentSlug ?? backend.agent?.slug ?? record.agentResume?.slug ?? null,
45
45
  nativeSessionId: binding?.nativeSessionId ?? backend.agentSession?.sessionId ?? record.agentResume?.sessionId ?? null,
@@ -0,0 +1,20 @@
1
+ import { TerminalInputTargetChangedError } from './terminalInput.js';
2
+ /** Display/identity metadata may have crossed an await with an old snapshot.
3
+ * Only the launch lifecycle can change these server-owned control fields. */
4
+ export function mergeSessionLaunchState(candidate, current, change) {
5
+ if (!change)
6
+ return current ? { ...candidate,
7
+ agentLaunchGeneration: current.agentLaunchGeneration ?? null,
8
+ agentLaunchCheck: current.agentLaunchCheck ?? null,
9
+ } : candidate;
10
+ if (!current || (current.agentLaunchGeneration ?? null) !== change.expectedGeneration
11
+ || (current.agentLaunchCheck?.id ?? null) !== change.expectedCheckId) {
12
+ throw new TerminalInputTargetChangedError({
13
+ expected_backend_session_id: candidate.backendSessionId, current_backend_session_id: current?.backendSessionId ?? null,
14
+ expected_launch_id: change.expectedGeneration, current_launch_id: current?.agentLaunchGeneration ?? null,
15
+ backend_instance_matches: !!current && candidate.backendSessionId === current.backendSessionId,
16
+ check_phase: 'launch_state_commit', checked_at: Date.now(),
17
+ });
18
+ }
19
+ return { ...candidate, agentLaunchGeneration: change.generation, agentLaunchCheck: change.check };
20
+ }
@@ -22,6 +22,23 @@ export class TerminalInputTargetChangedError extends Error {
22
22
  this.evidence = evidence;
23
23
  }
24
24
  }
25
+ /** Capture once, including for a launch's own command. Never adopt a newer
26
+ * generation simply because the physical backend has stayed the same. */
27
+ export function captureRuntimeInputGuard(current, expected = current()) {
28
+ const capturedAt = Date.now();
29
+ return (phase = 'guard_capture') => {
30
+ const actual = current();
31
+ const matches = actual.backendInstance === expected.backendInstance;
32
+ if (actual.backendSessionId !== expected.backendSessionId || !matches
33
+ || actual.launchId !== expected.launchId || actual.routeRevision !== expected.routeRevision) {
34
+ throw new TerminalInputTargetChangedError({ expected_backend_session_id: expected.backendSessionId,
35
+ current_backend_session_id: actual.backendSessionId, expected_launch_id: expected.launchId,
36
+ current_launch_id: actual.launchId, backend_instance_matches: matches, check_phase: phase,
37
+ guard_captured_at: capturedAt, checked_at: Date.now(), expected_route_revision: expected.routeRevision,
38
+ current_route_revision: actual.routeRevision });
39
+ }
40
+ };
41
+ }
25
42
  /** Clearing a one-time launch check does not change the runtime generation. */
26
43
  export function captureTerminalInputGuard(current, expected = current()) {
27
44
  return () => {