nolo-cli 0.213.0 → 0.222.0-alpha.2

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 (262) hide show
  1. package/README.md +3 -2
  2. package/{_executeModel-CUJLCFWR.js → _executeModel-4GGQQHOB.js} +111 -82
  3. package/{accountResolver-4LKIHEKL.js → accountResolver-EK2S4PWF.js} +6 -6
  4. package/{action-DF5UYSJF.js → action-CK64LS6S.js} +12 -11
  5. package/{addContentAction-WERAONNY.js → addContentAction-GDHDOF4U.js} +18 -17
  6. package/{addDialogAgentAction-7VI7YRML.js → addDialogAgentAction-CAKRU3ZT.js} +21 -20
  7. package/{agentDeleteCommand-XJORXPGU.js → agentDeleteCommand-BPV2XZL7.js} +128 -119
  8. package/{agentEmailCommands-XTYYFR6Z.js → agentEmailCommands-EJOS75YL.js} +132 -124
  9. package/{agentFavoriteCommands-EDK743YA.js → agentFavoriteCommands-2LKGKSUD.js} +7 -8
  10. package/{agentGrantCommands-RQWK2TEV.js → agentGrantCommands-QQV4N4JW.js} +5 -5
  11. package/{agentListCommands-OBLRBLHS.js → agentListCommands-HIZODBF3.js} +155 -92
  12. package/{agentMachineCommands-5FMT3OT5.js → agentMachineCommands-ZMQ2CY7Y.js} +62 -54
  13. package/{agentProviderCommands-Q5O33MED.js → agentProviderCommands-WKJOAWBP.js} +5 -5
  14. package/{agentPullCommand-6EM3URVK.js → agentPullCommand-XN6ZPBUW.js} +7 -7
  15. package/agentRecordCommands-OMXVDLDX.js +176 -0
  16. package/agentRunCommand-CB34YWMV.js +206 -0
  17. package/{agentRunControl-TAMHJQSR.js → agentRunControl-JNONH3RP.js} +30 -15
  18. package/{agentRuntimeLocal-SOO2OPJG.js → agentRuntimeLocal-QZPFWMLG.js} +52 -45
  19. package/{agentSlice-CHR6KOZN.js → agentSlice-RD2CDU7T.js} +20 -19
  20. package/{appDeleteCommands-GUP6P5YE.js → appDeleteCommands-QCCFDIEQ.js} +61 -53
  21. package/{appDeployCommands-MH2FX4O5.js → appDeployCommands-V2T7TNMQ.js} +61 -53
  22. package/{appDeployStatusCommands-SUHN3HPJ.js → appDeployStatusCommands-6PGH7ZCG.js} +61 -53
  23. package/{appGetCommands-YWDEX6Z4.js → appGetCommands-3L7WWJA6.js} +61 -53
  24. package/{appListCommands-ZQVMLPAY.js → appListCommands-ENJCK4PO.js} +61 -53
  25. package/{authCommand-PWX2ZNUP.js → authCommand-6V47SYGK.js} +29 -28
  26. package/{authCommands-HV3EAU3V.js → authCommands-GAJ3NIXO.js} +14 -13
  27. package/{builtinSkillRegistry-2QETTQPM.js → builtinSkillRegistry-2ECA42FC.js} +11 -13
  28. package/{chromeCommands-REEAH4SX.js → chromeCommands-G5UDKVSV.js} +3 -3
  29. package/{chromeOpsCommands-DIVM2K3T.js → chromeOpsCommands-YKX2QX3A.js} +20 -10
  30. package/{chunk-CRHOO2ZR.js → chunk-27PCUMJI.js} +2 -2
  31. package/chunk-2CI3ZFWD.js +97 -0
  32. package/{chunk-NSAPDIN2.js → chunk-2GJKRKI6.js} +541 -31
  33. package/{chunk-SM3NSZJV.js → chunk-2UCBGYO4.js} +20 -1
  34. package/{chunk-PYRUW7XN.js → chunk-2VUZSVAS.js} +136 -54
  35. package/{chunk-YB3YZK56.js → chunk-2WZXXAQD.js} +1 -67
  36. package/chunk-2YGBI2XB.js +30 -0
  37. package/chunk-2ZKFCIJJ.js +13 -0
  38. package/{chunk-QG4AOSON.js → chunk-34J5K2YA.js} +13 -32
  39. package/{chunk-LOEO7LRC.js → chunk-3IK6ILVW.js} +4 -1
  40. package/{chunk-CTPXME7U.js → chunk-3LMUPOHG.js} +29 -6
  41. package/chunk-44X52WOJ.js +1621 -0
  42. package/{chunk-6VLJ6YA7.js → chunk-4DESLZTK.js} +9 -9
  43. package/{chunk-MYOH447Z.js → chunk-4JVNURX4.js} +1 -1
  44. package/chunk-5CHGAKRT.js +364 -0
  45. package/{chunk-YDH3FDFQ.js → chunk-5FUN7EG4.js} +1 -1
  46. package/{chunk-INUFILG6.js → chunk-5RKUPJYL.js} +1 -1
  47. package/{chunk-ZC3CMUKU.js → chunk-6OVNSQHN.js} +84 -2
  48. package/{chunk-MOIJOHA5.js → chunk-6WU5572L.js} +36 -25
  49. package/{chunk-IXNGOHV5.js → chunk-7EEZJ6BS.js} +11 -152
  50. package/{chunk-Y6ORVLSS.js → chunk-7ET2U67U.js} +1 -1
  51. package/{chunk-G7MLNNEX.js → chunk-7JLY4WYF.js} +5 -5
  52. package/{chunk-P5L7CXOC.js → chunk-7Z6EW7AH.js} +3 -2
  53. package/{chunk-NJLL224W.js → chunk-AD5EWDFD.js} +2 -2
  54. package/{chunk-J2NHJ7WX.js → chunk-AIHYNKGV.js} +4 -4
  55. package/{chunk-HPFCI4SK.js → chunk-AK5O76CC.js} +3 -3
  56. package/{chunk-Y63ZSOR6.js → chunk-AL3TYDIF.js} +1 -1
  57. package/{chunk-ALQ3657A.js → chunk-AMEOV5VZ.js} +32 -12
  58. package/chunk-AN74ON4G.js +675 -0
  59. package/{chunk-HRMJUN5J.js → chunk-AQZ6BMRK.js} +1 -1
  60. package/{chunk-XHQC4PXX.js → chunk-B4GOW4MT.js} +424 -194
  61. package/{chunk-4KB6WQUL.js → chunk-BGP2EDFG.js} +1 -1
  62. package/{chunk-NBTY7YJF.js → chunk-BR3GT6MR.js} +1 -0
  63. package/{chunk-7RFNTILS.js → chunk-BUDVRYES.js} +2 -2
  64. package/{chunk-SVYO6AO7.js → chunk-BV3FLP2L.js} +41 -1
  65. package/{chunk-RZOV7OMV.js → chunk-C4VAR65S.js} +83 -141
  66. package/{chunk-COFEN36Z.js → chunk-C4WTX5TU.js} +2 -2
  67. package/{chunk-ZL5RAEEB.js → chunk-CIRB724Q.js} +1 -1
  68. package/{chunk-F6UUQOG6.js → chunk-CKT6QUE2.js} +4 -4
  69. package/{chunk-X7SDOJUM.js → chunk-CMZ3Z5PT.js} +14 -14
  70. package/{secretCommands-LXDWOLZ6.js → chunk-D726I5AZ.js} +191 -16
  71. package/{chunk-TAKB25RM.js → chunk-DNKTQ3IN.js} +4 -4
  72. package/chunk-DVQH4BTR.js +1137 -0
  73. package/{chunk-WYDI6TGM.js → chunk-DWX2HEVC.js} +91 -132
  74. package/{chunk-5MQRBSMW.js → chunk-EIAI3PPH.js} +111 -113
  75. package/chunk-EUCFKKDM.js +247 -0
  76. package/chunk-EWQ3HGNZ.js +90 -0
  77. package/{chunk-RPQXPZZF.js → chunk-F3GRJO4Z.js} +908 -13
  78. package/{chunk-YTF4WH7J.js → chunk-FIYSMXHY.js} +1 -1
  79. package/{chunk-75XIDFBW.js → chunk-FJ23FZXF.js} +72 -28
  80. package/{chunk-INN4LTAJ.js → chunk-FJK526XH.js} +2 -2
  81. package/chunk-FS2XP5D7.js +142 -0
  82. package/{chunk-FUGMREBO.js → chunk-FYF2TONJ.js} +5 -5
  83. package/{chunk-PCLE46CE.js → chunk-GBWGPTA7.js} +2 -1
  84. package/{chunk-TX5EYMGT.js → chunk-GYVCJABP.js} +30 -254
  85. package/{chunk-3UKL3HPD.js → chunk-HOCHUZQ7.js} +8 -78
  86. package/{chunk-EHSZD5OI.js → chunk-HXER7YJF.js} +4 -4
  87. package/chunk-HYIETXA6.js +99 -0
  88. package/{chunk-H2TJUNCH.js → chunk-I4EADJ4P.js} +6 -6
  89. package/{chunk-TCZHTTUU.js → chunk-I7WBYGBP.js} +8 -8
  90. package/{chunk-6DWMYIUY.js → chunk-IILMY4W4.js} +14 -9
  91. package/chunk-JA3ICVJY.js +271 -0
  92. package/{chunk-ZRSNONOB.js → chunk-JWXITTQB.js} +8 -3
  93. package/{chunk-H4UOTUOX.js → chunk-KEN3N2TN.js} +148 -18
  94. package/{chunk-LEC5ALIN.js → chunk-KEPOVMF4.js} +1 -1
  95. package/{chunk-UHJGXRJ4.js → chunk-KQSYAIZR.js} +3 -3
  96. package/{chunk-4VJAC32I.js → chunk-L5I543VB.js} +3 -2
  97. package/chunk-LKA64WH4.js +227 -0
  98. package/{chunk-QHPRUL4O.js → chunk-LVL6GFCM.js} +4 -4
  99. package/{chunk-H5HF7TJA.js → chunk-MAIITKBT.js} +2 -2
  100. package/chunk-MBG66ZBH.js +226 -0
  101. package/{chunk-YUA6OAH5.js → chunk-MDLS23JK.js} +2 -2
  102. package/{chunk-VL5KOY2C.js → chunk-MK2Q7ZJD.js} +67 -5
  103. package/{chunk-MDB67IWP.js → chunk-MS4NZNKI.js} +10 -10
  104. package/{chunk-VO4WSAVP.js → chunk-MYHNBEXD.js} +3 -3
  105. package/{chunk-ZXOUUDCG.js → chunk-MZLE5HQ3.js} +3654 -231
  106. package/{chunk-AZMYUSVF.js → chunk-N5Z2V73W.js} +1 -1
  107. package/{chunk-V5Y3R6BT.js → chunk-NIZ2BXFD.js} +213 -210
  108. package/{chunk-KFLT5KAD.js → chunk-NWP2OYOX.js} +20 -20
  109. package/{chunk-G2BQWAVT.js → chunk-O6J3OTOP.js} +4 -4
  110. package/{chunk-VNYYOX3V.js → chunk-OB6DVWPF.js} +141 -48
  111. package/{chunk-YWSEPJ7C.js → chunk-OBWT45ZU.js} +3 -3
  112. package/{chunk-ZNWI6OVT.js → chunk-ODJ7BVSI.js} +80 -11
  113. package/{chunk-XJWWBO34.js → chunk-OJKUU3LP.js} +5 -7
  114. package/{chunk-HUBHAQK2.js → chunk-ON37YXGX.js} +29 -29
  115. package/{chunk-UYD5HQ6T.js → chunk-P5ZJRTCH.js} +5429 -1752
  116. package/{chunk-6XIE5ZGI.js → chunk-PDCV7P5W.js} +1 -1
  117. package/{chunk-WRYQ35LQ.js → chunk-PJCIP64Z.js} +859 -57
  118. package/{chunk-7QTZCMKL.js → chunk-PJVKMGPZ.js} +1089 -1639
  119. package/{chunk-A7TFUNZO.js → chunk-PPJYZRSQ.js} +6 -2
  120. package/chunk-QHEN7NZ7.js +46 -0
  121. package/{chunk-OQPKUBPB.js → chunk-QNWG52I4.js} +19 -7
  122. package/{chunk-YGILMZ7N.js → chunk-QVBXJNZ2.js} +1 -1
  123. package/{chunk-7BT37FK3.js → chunk-RDH5CQ4T.js} +648 -131
  124. package/{chunk-C6KNNXWU.js → chunk-RGQ4UUWZ.js} +25 -2
  125. package/{chunk-OWYYDMGJ.js → chunk-S2NTVGA2.js} +4 -2
  126. package/{chunk-KC4XDTT3.js → chunk-SOF4OWDM.js} +6 -4
  127. package/{chunk-RLBNLZVC.js → chunk-SQYIK6HO.js} +1 -1
  128. package/{chunk-YJAFKXMU.js → chunk-SVT62ULE.js} +50 -48
  129. package/{chunk-KIM6CLW5.js → chunk-SY3C4SQ7.js} +42 -15
  130. package/{chunk-JY5NGFFH.js → chunk-SYTHYBMI.js} +5 -5
  131. package/{chunk-WMTBPBMP.js → chunk-T6DXNI6Z.js} +52 -50
  132. package/chunk-TLE77UJ5.js +230 -0
  133. package/{chunk-4VNS5WPM.js → chunk-U67V476Y.js} +1 -8
  134. package/{chunk-F7CI2ZC5.js → chunk-UAIHKQIA.js} +2 -1
  135. package/{chunk-R5O4QAWG.js → chunk-UB3D4TRQ.js} +11 -77
  136. package/{chunk-WPORQFYN.js → chunk-UVLYNWIE.js} +2 -2
  137. package/{chunk-NOKUNJON.js → chunk-UYOICCYG.js} +29 -19
  138. package/{chunk-4I7ERB7F.js → chunk-VREDDN25.js} +1 -1
  139. package/{chunk-O2TZF4AI.js → chunk-WAE3GFCJ.js} +3 -3
  140. package/{chunk-H7PPIYWP.js → chunk-WI67URFP.js} +20 -20
  141. package/{chunk-7OCO4TDT.js → chunk-WJVYAO6P.js} +1 -1
  142. package/{chunk-T43B7LB2.js → chunk-WKGQSYTB.js} +1 -1
  143. package/{chunk-BBJ22CLB.js → chunk-WUUH4LWZ.js} +60 -30
  144. package/{chunk-4T2WNOY7.js → chunk-X7UF53VA.js} +33 -22
  145. package/{chunk-TY3TIUJK.js → chunk-XI2BWJM5.js} +65 -0
  146. package/{chunk-LLRPJECG.js → chunk-XWVCYUUU.js} +16 -159
  147. package/{chunk-J5JTMQIA.js → chunk-YFLVRVYK.js} +1 -1
  148. package/{chunk-EYLGAEB4.js → chunk-YGMBIXCF.js} +132 -0
  149. package/chunk-YL3EFYL3.js +199 -0
  150. package/{chunk-MMA3LZ3W.js → chunk-YNIYE47Z.js} +1 -1
  151. package/{chunk-W4S457LU.js → chunk-YU4ZPWVF.js} +41 -5
  152. package/{chunk-7Y4YTDQF.js → chunk-YWWDC3O7.js} +281 -159
  153. package/chunk-YZMNK53S.js +68 -0
  154. package/{chunk-RSHTSUEG.js → chunk-Z2PITYZN.js} +2060 -602
  155. package/{chunk-FY7F4Q6X.js → chunk-Z4PCXPUE.js} +2 -2
  156. package/{cliAgentConfigHelpers-WJBZQTLW.js → cliAgentConfigHelpers-TKYL43MT.js} +15 -16
  157. package/{cliAuthorityBrokerClient-PM3U6Q6J.js → cliAuthorityBrokerClient-XHH7MH2P.js} +1 -1
  158. package/{cliAuthorityStoreDriver-TKLXNNTG.js → cliAuthorityStoreDriver-6FE3BJNB.js} +1 -1
  159. package/{cliEnvHelpers-BVYTMUPJ.js → cliEnvHelpers-VPSJ4XWC.js} +3 -3
  160. package/{cliExecutor-BWBF2MTI.js → cliExecutor-4MAX3PZL.js} +2 -2
  161. package/cliLocalAgentRecordReader-MHHD4T7R.js +90 -0
  162. package/{commandRegistry-W63CYRZJ.js → commandRegistry-5DA5UP7S.js} +105 -97
  163. package/{contentThunks-U7PL5MQD.js → contentThunks-5GUQ7FWJ.js} +47 -43
  164. package/{cooldownCommands-TIGUHXTD.js → cooldownCommands-X7P5M2V5.js} +5 -4
  165. package/{createAgentAutomationAction-OLBQDD6R.js → createAgentAutomationAction-UCLTHQRI.js} +51 -49
  166. package/{createDialogAction-SVH6B3SB.js → createDialogAction-UPN774AF.js} +46 -48
  167. package/{createPageAction-F4DIWZ2Z.js → createPageAction-JRQ2TA4O.js} +50 -48
  168. package/{cursorProvider-YGGNMVWX.js → cursorProvider-2RACMEMF.js} +1 -1
  169. package/{db-HUCI5R4G.js → db-CS4ZJQKV.js} +1 -1
  170. package/{dbSlice-BVH2YZPQ.js → dbSlice-WNON7TOL.js} +17 -16
  171. package/{deleteFile-5YOEKV4U.js → deleteFile-Q3YDB4ML.js} +9 -9
  172. package/{desktopFolderProjects-SFY5EZS3.js → desktopFolderProjects-4POAMVJN.js} +2 -2
  173. package/{dialogCommands-KHIEPY3M.js → dialogCommands-VRI7VCXH.js} +64 -57
  174. package/dialogNotifyCommand-6TMCX4D2.js +36 -0
  175. package/{dialogSlice-ZCTDV2PZ.js → dialogSlice-LFNVUSAN.js} +42 -40
  176. package/{dialogUsageCommand-7KCPYGHG.js → dialogUsageCommand-HTVPR2CX.js} +11 -10
  177. package/{docCreateCommands-DPMZI7G5.js → docCreateCommands-AMPXMOX3.js} +61 -55
  178. package/{docDeleteCommands-IRQQLUBT.js → docDeleteCommands-I5WFAEHP.js} +63 -57
  179. package/{docReadCommands-LK37XH6L.js → docReadCommands-X53ELNIE.js} +61 -55
  180. package/{docStore-V2KECILA.js → docStore-2VAWVLWH.js} +21 -20
  181. package/{docUpdateCommands-O6T3HJHH.js → docUpdateCommands-6QPNDC7M.js} +64 -58
  182. package/{fetchMessages-NR4KNQLO.js → fetchMessages-TQEUZD7H.js} +8 -7
  183. package/{getPricing-2MNMXEVG.js → getPricing-MB2GBXOK.js} +6 -6
  184. package/{handleSendMessageAction-2PE25WM3.js → handleSendMessageAction-AAJOHXOB.js} +194 -302
  185. package/{hostCredentialCreate-S233UMAP.js → hostCredentialCreate-GLMJ22M6.js} +123 -114
  186. package/index.js +29 -29
  187. package/{keys-BEGDOTRL.js → keys-RWF7UCB4.js} +5 -4
  188. package/legacyMigration-TF4SYJCZ.js +19 -0
  189. package/{lib-5KKIBFIT.js → lib-OT5OTXRU.js} +7087 -6664
  190. package/{localDialogRead-7NNDVVF7.js → localDialogRead-SVTPA5GY.js} +3 -3
  191. package/{localFirstLog-DHNOY2NA.js → localFirstLog-OIETGK66.js} +1 -1
  192. package/localRecall-2J6QPOK2.js +15 -0
  193. package/{localRuntimeAdapter-KY6WXNBR.js → localRuntimeAdapter-BMP57P42.js} +119 -110
  194. package/{localRuntimeAuthority-OYH4AE4G.js → localRuntimeAuthority-IBJAT62G.js} +1 -1
  195. package/{localRuntimeDb-VBIMCWUC.js → localRuntimeDb-N7KHDXS2.js} +2 -2
  196. package/{machineCommands-Q6HA3IXF.js → machineCommands-3MLIAK5Q.js} +128 -119
  197. package/{machineInfo-UKPTZO5Y.js → machineInfo-LWHTEBHJ.js} +1 -1
  198. package/machineWsRunDispatch-FKIGROQF.js +191 -0
  199. package/{memberThunks-7EDJADWU.js → memberThunks-ZGLZ36PK.js} +29 -28
  200. package/{memoryCommands-ASCE5STX.js → memoryCommands-5WC3T66U.js} +4 -4
  201. package/models-ULVWLSQ6.js +9 -0
  202. package/{oauthTokenStore-OEERZFUC.js → oauthTokenStore-RUYNYALS.js} +1 -1
  203. package/{offlineMarxistsAgentCommand-2QTHJCHV.js → offlineMarxistsAgentCommand-4IC3Y4C6.js} +4 -4
  204. package/overlay-THLKYIWY.js +11 -0
  205. package/package.json +2 -2
  206. package/{pdf-U6KSUEZZ.js → pdf-KE3QI2V7.js} +1 -1
  207. package/{processSpawn-ZU5QFM43.js → processSpawn-6GEO77KV.js} +1 -1
  208. package/{profileConfig-KN3N2BLF.js → profileConfig-KOWK4HOG.js} +1 -1
  209. package/{projectArchive-DRTDIMEV.js → projectArchive-HK63GMF4.js} +52 -50
  210. package/{providerPresetApply-YXGV6NXB.js → providerPresetApply-OIFQ73LH.js} +19 -12
  211. package/{providerRegistry-S6UL6UNA.js → providerRegistry-KZ3SDZ3D.js} +10 -10
  212. package/{read-4V2RMG7N.js → read-MRQHJMJ2.js} +10 -10
  213. package/{readDocTool-BH6ATGQO.js → readDocTool-4BGTXTXA.js} +2 -2
  214. package/{readlineWorkspace-2W4WRCOU.js → readlineWorkspace-AKAHSCNY.js} +7982 -6274
  215. package/{removeDialogAgentAction-LYAZGNKW.js → removeDialogAgentAction-B6H7DXFM.js} +23 -22
  216. package/{runAgentClientLoop-J2VQBS2Z.js → runAgentClientLoop-UVAWGEON.js} +81 -79
  217. package/{runtimeDoctorCommands-QAI3MBKQ.js → runtimeDoctorCommands-FW6XKDUG.js} +12 -12
  218. package/{runtimeModeArgs-2Y7BALTO.js → runtimeModeArgs-X7DL7PUN.js} +1 -1
  219. package/secretCommands-LJXOOYA7.js +24 -0
  220. package/{setDialogExtraReferencesAction-OCRPGPYH.js → setDialogExtraReferencesAction-EVCY3TRW.js} +22 -21
  221. package/{setPrimaryDialogAgentAction-HFJDQIBU.js → setPrimaryDialogAgentAction-KPFVPHCJ.js} +23 -22
  222. package/{settingThunks-RAMHMTGM.js → settingThunks-ENOAK2WV.js} +97 -88
  223. package/{skillDiscovery-XKHROSH2.js → skillDiscovery-B5V23AXP.js} +4 -4
  224. package/{skillSummaryMarker-42HKSXYY.js → skillSummaryMarker-62UW7HI7.js} +1 -1
  225. package/{slateToRenderMarkdown-Y5IYN73U.js → slateToRenderMarkdown-R3X74MCX.js} +1 -1
  226. package/{slateUtils-NGV2NMKM.js → slateUtils-ESQAJ6RN.js} +1 -1
  227. package/{spaceCommands-KVJZVKVO.js → spaceCommands-DTTNAS2L.js} +61 -53
  228. package/store-JRVN62NM.js +46 -0
  229. package/{streamAgentChatTurn-GHBMJJ6S.js → streamAgentChatTurn-R5UY25VB.js} +875 -618
  230. package/{switchDialogAgentAction-EBRMW3RA.js → switchDialogAgentAction-SZ44XDRY.js} +21 -20
  231. package/{tableCommands-MP6VFSVT.js → tableCommands-HITDSLHS.js} +10 -10
  232. package/tombstones-FQQMEDOW.js +32 -0
  233. package/{toolApiClient-HGNO53TC.js → toolApiClient-OGQEBQVX.js} +4 -4
  234. package/{tools-EWKCPKMS.js → tools-HWFG6GMJ.js} +75 -74
  235. package/tuiSummaryLlmCaller-HQQZAMYF.js +44 -0
  236. package/{updateCommands-ZQYU6SCI.js → updateCommands-RJVCRSBP.js} +10 -8
  237. package/{updateDialogTitleAction-5GGMBTDF.js → updateDialogTitleAction-KNPOAMVS.js} +48 -46
  238. package/{usageCommand-F4IPVMIZ.js → usageCommand-FWZCB7AM.js} +11 -10
  239. package/{usageRebuildCommand-HAW2AD5N.js → usageRebuildCommand-SP2BLNJU.js} +12 -11
  240. package/userDataMerge-HT2ZVHBJ.js +13 -0
  241. package/{windowsSelfUpdate-257DV2T6.js → windowsSelfUpdate-KERHIAB4.js} +3 -3
  242. package/{workloadLifecycle-4C42SVBD.js → workloadLifecycle-DYNEYHV5.js} +6 -6
  243. package/agentRecordCommands-ZQ7SVYGG.js +0 -167
  244. package/agentRunCommand-WS7IGO2W.js +0 -196
  245. package/chunk-3CGG2PAL.js +0 -594
  246. package/chunk-5XBUWM6I.js +0 -89
  247. package/chunk-CJEIOP3E.js +0 -0
  248. package/chunk-EHGEOAHI.js +0 -636
  249. package/chunk-FW6YHHLI.js +0 -842
  250. package/chunk-GPVRUGGY.js +0 -115
  251. package/chunk-HSVBJRF4.js +0 -339
  252. package/chunk-WJZOQR2J.js +0 -151
  253. package/chunk-ZCWRMUWT.js +0 -89
  254. package/dist-M676ULYG.js +0 -7314
  255. package/machineWsRunDispatch-WWJQ6WR3.js +0 -182
  256. package/models-PJBE6JDV.js +0 -9
  257. package/tuiSummaryLlmCaller-ALQYUUWB.js +0 -189
  258. package/{chunk-WACI5I6V.js → chunk-2THCNKE4.js} +3 -3
  259. package/{chunk-2QHFH3DR.js → chunk-47ITIXO7.js} +6 -6
  260. package/{chunk-GOO6G4PY.js → chunk-CKG3PRZ7.js} +0 -0
  261. package/{chunk-OQHIVPG4.js → chunk-SNBZZPYH.js} +3 -3
  262. package/{chunk-AETZ7AD6.js → chunk-W6RFEDN4.js} +3 -3
@@ -1,21 +1,25 @@
1
1
  import {
2
2
  resolveRuntimeAuthToken,
3
3
  resolveRuntimeServerUrl
4
- } from "./chunk-HRMJUN5J.js";
4
+ } from "./chunk-AQZ6BMRK.js";
5
5
  import {
6
6
  isAgentRunTerminalStatus,
7
- normalizeRunTitle
8
- } from "./chunk-ALQ3657A.js";
7
+ normalizeRunTitle,
8
+ shortAgentKey
9
+ } from "./chunk-AMEOV5VZ.js";
9
10
  import {
10
11
  findPowerShellExecutable
11
- } from "./chunk-H4UOTUOX.js";
12
+ } from "./chunk-KEN3N2TN.js";
13
+ import {
14
+ AUTH_ERROR_PATTERNS
15
+ } from "./chunk-EWQ3HGNZ.js";
12
16
  import {
13
17
  isRecord
14
18
  } from "./chunk-KUG52IAP.js";
15
19
  import {
16
20
  isCompiledBinary,
17
21
  resolveCliEntrypointPath
18
- } from "./chunk-WACI5I6V.js";
22
+ } from "./chunk-2THCNKE4.js";
19
23
 
20
24
  // packages/cli/client/originShellApprovalTransport.ts
21
25
  import { realpathSync } from "node:fs";
@@ -444,9 +448,10 @@ function redactLogLines(lines, options = {}) {
444
448
  }
445
449
 
446
450
  // packages/cli/agentRunControl.ts
447
- import { homedir as nodeHomedir } from "node:os";
451
+ import { hostname as nodeHostname, homedir as nodeHomedir } from "node:os";
448
452
  import { dirname, isAbsolute as isAbsolute2, join as join2, resolve } from "node:path";
449
453
  import * as nodeFs2 from "node:fs";
454
+ import { randomUUID as randomUUID2, createHash } from "node:crypto";
450
455
  import { execFileSync as nodeExecFileSync, spawn as nodeSpawn } from "node:child_process";
451
456
 
452
457
  // packages/cli/client/hostMemory.ts
@@ -1090,6 +1095,7 @@ function resolveResultServerMeta(input) {
1090
1095
  var resultHeaderMeta = /* @__PURE__ */ new WeakMap();
1091
1096
  function recordRunResultHeaderMeta(result, meta) {
1092
1097
  const clean = {};
1098
+ if (meta.commandObservations?.length) clean.commandObservations = meta.commandObservations;
1093
1099
  if (meta.model) clean.model = meta.model;
1094
1100
  if (meta.dialogServer) clean.dialogServer = meta.dialogServer;
1095
1101
  if (meta.serverSync) clean.serverSync = meta.serverSync;
@@ -1134,7 +1140,8 @@ function buildResultFrontMatter(input) {
1134
1140
  ["server", input.server],
1135
1141
  ["serverSync", input.serverSync],
1136
1142
  ["cwd", input.cwd],
1137
- ["continuedFrom", input.continuedFrom]
1143
+ ["continuedFrom", input.continuedFrom],
1144
+ ["acceptance", input.acceptance ? JSON.stringify(input.acceptance) : void 0]
1138
1145
  ];
1139
1146
  const lines = entries.filter(([, v]) => v !== void 0 && v !== "").map(([k, v]) => `${k}: ${yamlScalar(v)}`);
1140
1147
  return `---
@@ -1145,9 +1152,18 @@ ${lines.join("\n")}
1145
1152
  function buildResultFileContent(input, body) {
1146
1153
  return `${buildResultFrontMatter(input)}${body}`;
1147
1154
  }
1155
+ var RESULT_FRONT_MATTER_RE = /^---\nrunId: [^\n]*\n(?:[^\n]*\n)*?---\n/;
1156
+ function stripResultFrontMatter(text) {
1157
+ const match = RESULT_FRONT_MATTER_RE.exec(text);
1158
+ return match ? text.slice(match[0].length) : text;
1159
+ }
1148
1160
 
1149
1161
  // packages/ai/tools/agent/runFailureClass.ts
1150
- var RATE_LIMIT_PATTERN = /429|rate.?limit|quota|insufficient.?balance|UPSTREAM_402|cooling|冷却/i;
1162
+ function isHistoryIntegrityFailure(message) {
1163
+ return /^Strict continuation history load failed for [^\r\n]+:/i.test(message.trim());
1164
+ }
1165
+ var BALANCE_PATTERN = /\bUPSTREAM_402\b|\b402\b|insufficient[_\s-]+balance|余额不足|wallet\s+balance\s+is\s+insufficient|top\s+up\s+your\s+wallet|payment[_ ]required/i;
1166
+ var RATE_LIMIT_PATTERN = /429|rate.?limit|quota|cooling|冷却/i;
1151
1167
  var PROVIDER_ERROR_PATTERN = /provider|upstream|5\d\d|bad.?gateway|service.?unavailable|overloaded/i;
1152
1168
  var MALFORMED_PATTERN = /MALFORMED_FUNCTION_CALL|malformed|invalid.?function.?call|invalid.?tool.?call/i;
1153
1169
  var STALLED_PATTERN = /stall|no.?progress|repetition|stagnant|无进展|卡死/i;
@@ -1159,6 +1175,20 @@ function classifyRunFailure(input) {
1159
1175
  }
1160
1176
  const reason = typeof input.failureReason === "string" ? input.failureReason : "";
1161
1177
  const message = typeof input.errorMessage === "string" ? input.errorMessage : "";
1178
+ if (reason === "history_integrity" || isHistoryIntegrityFailure(message)) {
1179
+ return { failureClass: "history_integrity", retryable: false };
1180
+ }
1181
+ if (!reason || reason === "provider_rate_limited" || reason === "provider_error") {
1182
+ if (BALANCE_PATTERN.test(message)) {
1183
+ return { failureClass: "balance_exhausted", retryable: false };
1184
+ }
1185
+ if (AUTH_ERROR_PATTERNS.some((pattern) => pattern.test(message))) {
1186
+ return { failureClass: "auth", retryable: false };
1187
+ }
1188
+ if (reason === "provider_error" && RATE_LIMIT_PATTERN.test(message)) {
1189
+ return { failureClass: "rate_limited", retryable: true };
1190
+ }
1191
+ }
1162
1192
  switch (reason) {
1163
1193
  case "provider_rate_limited":
1164
1194
  return { failureClass: "rate_limited", retryable: true };
@@ -1552,7 +1582,9 @@ function withRunRecordLock(runId, deps, fn, opts = {}) {
1552
1582
  try {
1553
1583
  const stat = fs.statSync?.(lockPath);
1554
1584
  const ageMs = stat ? now().getTime() - stat.mtimeMs : Number.POSITIVE_INFINITY;
1555
- if (ageMs > LOCK_STALE_MS) {
1585
+ const ownerPid = opts.requireDeadOwner ? Number(String(fs.readFileSync(lockPath, "utf8"))) : void 0;
1586
+ const ownerGone = !opts.requireDeadOwner || Number.isSafeInteger(ownerPid) && ownerPid > 0 && isPidGone(ownerPid, deps);
1587
+ if (ageMs > LOCK_STALE_MS && ownerGone) {
1556
1588
  fs.unlinkSync(lockPath);
1557
1589
  fs.writeFileSync(lockPath, String(process.pid), { flag: "wx" });
1558
1590
  held = true;
@@ -1582,13 +1614,15 @@ function writeRunRecord(record, deps = {}) {
1582
1614
  fs.writeFileSync(tmp, payload);
1583
1615
  fs.renameSync(tmp, path);
1584
1616
  return;
1585
- } catch {
1617
+ } catch (error) {
1586
1618
  try {
1587
1619
  fs.unlinkSync(tmp);
1588
1620
  } catch {
1589
1621
  }
1622
+ if (record.writerLaunch) throw error;
1590
1623
  }
1591
1624
  }
1625
+ if (record.writerLaunch) throw new Error("[local-writer-resource] fenced launch requires atomic rename");
1592
1626
  fs.writeFileSync(path, payload);
1593
1627
  }
1594
1628
  function reportRunProcessIdentity(runId, deps = {}) {
@@ -2054,9 +2088,18 @@ async function gcRunRecords(deps = {}, options = {}) {
2054
2088
  const failedIds = [];
2055
2089
  for (const record of records) {
2056
2090
  if (!isRunTerminalStatus(record.status)) continue;
2091
+ if (localWriterStillOwns(record, deps)) continue;
2092
+ if (!/^[A-Za-z0-9._-]{1,128}$/.test(record.runId) || record.runId === "." || record.runId === "..") {
2093
+ failedIds.push(record.runId);
2094
+ continue;
2095
+ }
2057
2096
  const ts = record.reconciledAt ?? record.endedAt ?? record.startedAt;
2058
2097
  const ageMs = nowMs - new Date(ts).getTime();
2059
2098
  if (!Number.isFinite(ageMs) || ageMs < retentionMs) continue;
2099
+ if (fs.existsSync(`${resolveRunRecordPath(record.runId, deps.env, deps.homedir)}.lock`)) {
2100
+ failedIds.push(record.runId);
2101
+ continue;
2102
+ }
2060
2103
  const jsonPath = resolveRunRecordPath(record.runId, deps.env, deps.homedir);
2061
2104
  const logPath = resolveRunLogPath(record.runId, deps.env, deps.homedir);
2062
2105
  const queuePath = record.queuePath ?? resolveRunQueuePath(record.runId, deps.env, deps.homedir);
@@ -2076,8 +2119,30 @@ async function gcRunRecords(deps = {}, options = {}) {
2076
2119
  const runsDirForLegacy = resolveRunsDir(deps.env, deps.homedir);
2077
2120
  tryUnlinkFile(fs, join2(runsDirForLegacy, `${record.runId}.report.md`));
2078
2121
  tryUnlinkFile(fs, join2(runsDirForLegacy, `${record.runId}.report.json`));
2079
- tryUnlinkFile(fs, record.resultFile ?? join2(runsDirForLegacy, `${record.runId}.result.md`));
2080
- if (!logOk || !msgOk || !queueOk) {
2122
+ let resultOk = false;
2123
+ let artifactsOk = true;
2124
+ const artifactSweep = withRunRecordLock(record.runId, deps, () => {
2125
+ resultOk = tryUnlinkFile(fs, join2(runsDirForLegacy, `${record.runId}.result.md`));
2126
+ for (const artifact of record.resultArtifacts ?? []) {
2127
+ try {
2128
+ const prefix = `${record.runId}.result.md.`;
2129
+ const name = artifact.path.slice(join2(runsDirForLegacy, prefix).length);
2130
+ const uuid = "[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}";
2131
+ if (artifact.publisher !== "run-result-v1" || !/^[A-Za-z0-9._-]+$/.test(record.runId) || !["pending", "bak"].includes(artifact.kind) || !new RegExp(`^${uuid}\\.${artifact.kind}$`).test(name) || artifact.path !== join2(runsDirForLegacy, prefix + name)) throw new Error("unsafe artifact ownership");
2132
+ if (!fs.existsSync(artifact.path)) continue;
2133
+ const stat = fs.lstatSync?.(artifact.path);
2134
+ if (!stat || !stat.isFile() || stat.isSymbolicLink() || fs.realpathSync?.(artifact.path) !== resolve(artifact.path) || String(stat.dev) !== artifact.dev || String(stat.ino) !== artifact.ino || createHash("sha256").update(fs.readFileSync(artifact.path)).digest("hex") !== artifact.sha256) {
2135
+ throw new Error("artifact identity changed");
2136
+ }
2137
+ if (!tryUnlinkFile(fs, artifact.path)) artifactsOk = false;
2138
+ } catch {
2139
+ artifactsOk = false;
2140
+ }
2141
+ }
2142
+ return true;
2143
+ }, { strict: true });
2144
+ if (!artifactSweep) artifactsOk = false;
2145
+ if (!logOk || !msgOk || !queueOk || !resultOk || !artifactsOk) {
2081
2146
  failedIds.push(record.runId);
2082
2147
  continue;
2083
2148
  }
@@ -2090,12 +2155,12 @@ async function gcRunRecords(deps = {}, options = {}) {
2090
2155
  }
2091
2156
  try {
2092
2157
  const dir = resolveRunsDir(deps.env, deps.homedir);
2093
- const statSync = fs.statSync;
2158
+ const statSync2 = fs.statSync;
2094
2159
  for (const entry of fs.readdirSync(dir)) {
2095
2160
  if (typeof entry !== "string" || !entry.endsWith(".tmp")) continue;
2096
2161
  const tmpPath = join2(dir, entry);
2097
2162
  try {
2098
- const stat = statSync?.(tmpPath);
2163
+ const stat = statSync2?.(tmpPath);
2099
2164
  if (stat && nowMs - stat.mtimeMs <= TMP_STALE_MS) continue;
2100
2165
  } catch {
2101
2166
  continue;
@@ -2210,6 +2275,270 @@ function emitHostMemoryNotice(mem, output) {
2210
2275
  }
2211
2276
  return notice;
2212
2277
  }
2278
+ function trustedLocalWorktree(cwd, deps) {
2279
+ const fs = deps.fs ?? nodeFs2;
2280
+ try {
2281
+ const env = { ...process.env, ...deps.env };
2282
+ for (const key of Object.keys(env)) if (key.startsWith("GIT_")) delete env[key];
2283
+ const exec = deps.execFileSync ?? nodeExecFileSync;
2284
+ const git = (args) => exec("git", args, {
2285
+ cwd,
2286
+ env,
2287
+ encoding: "utf8",
2288
+ stdio: ["ignore", "pipe", "ignore"],
2289
+ timeout: 3e3
2290
+ }).trim();
2291
+ const real = (path) => String((fs.realpathSync ?? nodeFs2.realpathSync)(path));
2292
+ const [dir, top, common] = git(["rev-parse", "--path-format=absolute", "--git-dir", "--show-toplevel", "--git-common-dir"]).split("\n");
2293
+ if (!dir || !top || !common || ![dir, top, common].every(isAbsolute2)) return;
2294
+ const root = real(top), gitDir = real(dir), commonDir = real(common);
2295
+ const marker = join2(root, ".git");
2296
+ const stat = (path) => (fs.lstatSync ?? nodeFs2.lstatSync)(path);
2297
+ if (stat(marker).isSymbolicLink() || stat(commonDir).isSymbolicLink()) return;
2298
+ if (gitDir === commonDir) {
2299
+ if (!stat(marker).isDirectory() || real(marker) !== commonDir) return;
2300
+ } else {
2301
+ const registry = join2(commonDir, "worktrees");
2302
+ if (stat(registry).isSymbolicLink() || dirname(gitDir) !== real(registry) || !stat(gitDir).isDirectory() || stat(gitDir).isSymbolicLink() || !stat(marker).isFile()) return;
2303
+ const text = String(fs.readFileSync(marker, "utf8")).trim();
2304
+ if (!text.startsWith("gitdir: ") || real(resolve(root, text.slice(8))) !== gitDir) return;
2305
+ const back = String(fs.readFileSync(join2(gitDir, "gitdir"), "utf8")).trim();
2306
+ const commonBack = String(fs.readFileSync(join2(gitDir, "commondir"), "utf8")).trim();
2307
+ if (real(resolve(gitDir, back)) !== real(marker) || real(resolve(gitDir, commonBack)) !== commonDir) return;
2308
+ }
2309
+ const registered = git(["worktree", "list", "--porcelain"]).split("\n").filter((line) => line.startsWith("worktree ")).map((line) => line.slice(9));
2310
+ if (!registered.some((path) => real(path) === root)) return;
2311
+ const mainMarker = registered[0] && join2(registered[0], ".git");
2312
+ if (!mainMarker || stat(mainMarker).isSymbolicLink() || !stat(mainMarker).isDirectory() || real(mainMarker) !== commonDir) return;
2313
+ return { root, gitDir, commonDir };
2314
+ } catch {
2315
+ return;
2316
+ }
2317
+ }
2318
+ function localWriterRecovery(record) {
2319
+ if (record.localWriterClaim?.state !== "held" || typeof record.pid === "number" && record.pid > 0) return;
2320
+ return {
2321
+ state: "required",
2322
+ reason: "owner-unpublished",
2323
+ automaticReleaseAllowed: false,
2324
+ runId: record.runId,
2325
+ canonicalCwd: record.localWriterClaim.cwd,
2326
+ requiredEvidence: "native launch receipt proving no live child; parent death/timeouts/process-name search are insufficient"
2327
+ };
2328
+ }
2329
+ function revokePreparedWriterLaunch(runId, attemptId, deps = {}) {
2330
+ if (!/^[A-Za-z0-9_-]+$/.test(runId) || !attemptId) return "blocked";
2331
+ return withRunRecordLock("local-writer-admission", deps, () => {
2332
+ const snapshot = readRunRecord(runId, deps);
2333
+ if (!snapshot) return "blocked";
2334
+ return withRunRecordLock(runId, deps, () => {
2335
+ const latest = readRunRecord(runId, deps);
2336
+ if (!latest || JSON.stringify(latest) !== JSON.stringify(snapshot)) return "blocked";
2337
+ const launch = latest.writerLaunch;
2338
+ if (launch?.protocol !== "fenced-launch-v1" || launch.attemptId !== attemptId) return "blocked";
2339
+ if (launch.phase === "revoked") return latest.localWriterClaim?.state === "released" ? "already-revoked" : "blocked";
2340
+ if (launch.phase !== "prepared" || latest.localWriterClaim?.state !== "held" || latest.execution?.state !== "known" || latest.execution.owner.state !== "unknown" || latest.execution.canonicalCwd !== latest.localWriterClaim.cwd || latest.pid !== void 0 || latest.cwd !== latest.localWriterClaim.cwd || latest.execution.kind !== "host-local" || latest.execution.permissions.readOnly || !latest.execution.permissions.hostWritesAuthorized) return "blocked";
2341
+ launch.phase = "revoked";
2342
+ latest.localWriterClaim.state = "released";
2343
+ writeRunRecord(latest, deps);
2344
+ return "revoked";
2345
+ }, { strict: true, requireDeadOwner: true }) ?? "blocked";
2346
+ }, { strict: true, requireDeadOwner: true }) ?? "blocked";
2347
+ }
2348
+ function localWriterStillOwns(record, deps) {
2349
+ if (record.localWriterClaim?.state !== "held") return false;
2350
+ if (typeof record.pid !== "number" || record.pid <= 0) return true;
2351
+ const e = record.execution;
2352
+ const observed = e?.state === "known" && e.owner.state === "verified" ? nativeOwner(record.pid, deps) : void 0;
2353
+ const reused = observed?.state === "verified" && e?.state === "known" && e.owner.state === "verified" && (observed.startedAt !== e.owner.startedAt || (observed.linux?.bootId !== e.owner.linux?.bootId || observed.linux?.startTicks !== e.owner.linux?.startTicks));
2354
+ if (!isPidGone(record.pid, deps) && !reused) return true;
2355
+ const snapshot = JSON.stringify(record);
2356
+ const released = withRunRecordLock(record.runId, deps, () => {
2357
+ const latest = readRunRecord(record.runId, deps);
2358
+ if (!latest || JSON.stringify(latest) !== snapshot) return false;
2359
+ latest.localWriterClaim.state = "released";
2360
+ writeRunRecord(latest, deps);
2361
+ return true;
2362
+ }, { strict: true });
2363
+ return released !== true;
2364
+ }
2365
+ function acquireLocalWriterClaim(runId, cwd, deps) {
2366
+ const fs = deps.fs ?? nodeFs2;
2367
+ const canonical = String((fs.realpathSync ?? nodeFs2.realpathSync)(cwd));
2368
+ const worktree = trustedLocalWorktree(canonical, deps);
2369
+ const acquired = withRunRecordLock("local-writer-admission", deps, () => {
2370
+ const updated = withRunRecordLock(runId, deps, () => {
2371
+ const record = readRunRecord(runId, deps);
2372
+ if (!record) throw new Error(`[local-writer-resource] missing run ${runId}`);
2373
+ if (record.writerLaunch?.phase === "revoked") throw new Error("[local-writer-resource] claim attempt revoked");
2374
+ record.localWriterClaim = { cwd: canonical, ...worktree ? { worktree } : {}, state: "held" };
2375
+ if (record.writerLaunch && record.execution?.state === "known" && record.execution.owner.state === "verified" && record.pid === process.pid) {
2376
+ record.writerLaunch.phase = "granted";
2377
+ }
2378
+ writeRunRecord(record, deps);
2379
+ return true;
2380
+ }, { strict: true });
2381
+ if (!updated) throw new Error(`[local-writer-resource] run lock busy: ${runId}`);
2382
+ return true;
2383
+ }, { strict: true, requireDeadOwner: true });
2384
+ if (!acquired) throw new Error("[local-writer-resource] admission lock busy; no child spawned");
2385
+ return canonical;
2386
+ }
2387
+ function nativeOwner(pid, deps) {
2388
+ const first = probeProcessStartTime(pid, deps);
2389
+ let linux;
2390
+ if ((deps.platform ?? process.platform) === "linux") {
2391
+ try {
2392
+ const stat = nodeFs2.readFileSync(`/proc/${pid}/stat`, "utf8");
2393
+ const startTicks = stat.slice(stat.lastIndexOf(")") + 2).split(/\s+/)[19];
2394
+ const bootId = nodeFs2.readFileSync("/proc/sys/kernel/random/boot_id", "utf8").trim();
2395
+ if (/^\d+$/.test(startTicks) && bootId) linux = { startTicks, bootId };
2396
+ } catch {
2397
+ return { state: "unknown" };
2398
+ }
2399
+ }
2400
+ const second = probeProcessStartTime(pid, deps);
2401
+ if (!first || !second || first.getTime() !== second.getTime() || isPidGone(pid, deps) || (deps.platform ?? process.platform) === "linux" && !linux) return { state: "unknown" };
2402
+ return { state: "verified", pid, startedAt: first.toISOString(), source: "parent-native", ...linux ? { linux } : {} };
2403
+ }
2404
+ function validateLocalWriterChild(runId, cwd, policy, deps = {}) {
2405
+ const fail = (reason = "facts") => {
2406
+ throw new Error(`[local-writer-resource] child binding unknown or mismatched: ${reason}`);
2407
+ };
2408
+ if (!/^[A-Za-z0-9_-]+$/.test(runId)) fail();
2409
+ const validated = withRunRecordLock(runId, deps, () => {
2410
+ const r = readRunRecord(runId, deps), e = r?.execution;
2411
+ const launch = r?.writerLaunch;
2412
+ if (launch && (launch.protocol !== "fenced-launch-v1" || launch.phase !== "granted" || launch.attemptId !== deps.env?.NOLO_WRITER_LAUNCH_ATTEMPT)) fail("launch grant missing/revoked");
2413
+ const native = nativeOwner(process.pid, deps);
2414
+ const real = String((deps.fs?.realpathSync ?? nodeFs2.realpathSync)(cwd));
2415
+ if (!r || r.runId !== runId || r.pid !== process.pid || r.status !== "running" || e?.state !== "known" || e.kind !== "host-local" || e.runtimeKey !== "local" || e.device.kind !== "localhost" || e.device.hostname !== nodeHostname() || e.device.platform !== process.platform || !["cli-command-authorized", "cli-tool-dispatch-authorized"].includes(e.provenance) || e.owner.state !== "verified" || native.state !== "verified" || e.owner.pid !== process.pid || e.owner.startedAt !== native.startedAt || (e.owner.linux?.bootId !== native.linux?.bootId || e.owner.linux?.startTicks !== native.linux?.startTicks) || r.processIdentity !== "verified" || r.processStartedAt !== e.owner.startedAt || e.canonicalCwd !== real || r.cwd !== real || e.permissions.hostWritesAuthorized !== policy.hostWritesAuthorized || e.permissions.readOnly !== policy.readOnly) fail("native identity/authorization");
2416
+ if (e?.state !== "known") return fail();
2417
+ const set = (v) => JSON.stringify(v === void 0 ? null : [...new Set(v)].sort());
2418
+ if (set(e.permissions.allowedToolNames) !== set(policy.allowedToolNames) || set(e.permissions.blockedToolNames) !== set(policy.blockedToolNames) || JSON.stringify(e.worktree) !== JSON.stringify(trustedLocalWorktree(real, deps))) fail("scope/worktree");
2419
+ if (!policy.readOnly && (!policy.hostWritesAuthorized || r?.localWriterClaim?.state !== "held" || r.localWriterClaim.cwd !== real || e.worktree && (r.localWriterClaim.worktree?.root !== e.worktree.root || r.localWriterClaim.worktree.gitDir !== e.worktree.gitDir))) fail();
2420
+ return true;
2421
+ }, { strict: true, requireDeadOwner: true });
2422
+ if (!validated) fail("registry lock busy");
2423
+ }
2424
+ async function awaitLocalWriterChild(runId, cwd, policy, deps = {}) {
2425
+ if (!/^[A-Za-z0-9_-]+$/.test(runId)) throw new Error("[local-writer-resource] child binding invalid id");
2426
+ const deadline = Date.now() + 2e3;
2427
+ for (; ; ) {
2428
+ const r = readRunRecord(runId, deps);
2429
+ const publication = r?.ownerPublication;
2430
+ if (r?.writerLaunch && (r.writerLaunch.phase === "revoked" || r.writerLaunch.attemptId !== deps.env?.NOLO_WRITER_LAUNCH_ATTEMPT)) {
2431
+ throw new Error("[local-writer-resource] child binding launch revoked/mismatched");
2432
+ }
2433
+ const native = publication ? nativeOwner(publication.parent.pid, deps) : { state: "unknown" };
2434
+ const parentLive = publication && native.state === "verified" && publication.parent.startedAt === native.startedAt && publication.parent.linux?.bootId === native.linux?.bootId && publication.parent.linux?.startTicks === native.linux?.startTicks;
2435
+ try {
2436
+ validateLocalWriterChild(runId, cwd, policy, deps);
2437
+ return;
2438
+ } catch (error) {
2439
+ const lockBusy = String(error).includes("registry lock busy");
2440
+ const pending = publication?.state === "pending" && r?.execution?.state === "known" && r.execution.owner.state === "unknown";
2441
+ if (!parentLive || !pending && !lockBusy || Date.now() >= deadline) throw error;
2442
+ await new Promise((resolve2) => setTimeout(resolve2, 20));
2443
+ }
2444
+ }
2445
+ }
2446
+ function resolveLocalContinuation(record, deps = {}) {
2447
+ const fail = (why) => {
2448
+ throw new Error(`[local-continuation] ${why}; dispatch a fresh explicitly authorized run`);
2449
+ };
2450
+ const e = record.execution;
2451
+ if (e?.state !== "known" || e.kind !== "host-local" || e.runtimeKey !== "local" || e.device?.kind !== "localhost" || e.device.hostname !== nodeHostname() || e.device.platform !== process.platform || !["cli-command-authorized", "cli-tool-dispatch-authorized"].includes(e.provenance) || typeof e.permissions?.readOnly !== "boolean" || typeof e.permissions.hostWritesAuthorized !== "boolean" || !e.permissions.readOnly && !e.permissions.hostWritesAuthorized) return fail("execution unknown or unsupported");
2452
+ const lists = [e.permissions.allowedToolNames, e.permissions.blockedToolNames];
2453
+ if (lists.some((v) => v !== void 0 && (!Array.isArray(v) || v.some((t) => typeof t !== "string" || !t || t.startsWith("--"))))) return fail("tool scope invalid");
2454
+ let cwd;
2455
+ try {
2456
+ if (!e.canonicalCwd || !isAbsolute2(e.canonicalCwd) || record.cwd !== e.canonicalCwd) return fail("cwd identity missing");
2457
+ const fs = deps.fs ?? nodeFs2;
2458
+ cwd = String((fs.realpathSync ?? nodeFs2.realpathSync)(e.canonicalCwd));
2459
+ if (cwd !== e.canonicalCwd || !(fs.statSync ?? nodeFs2.statSync)(cwd).isDirectory()) return fail("cwd drift");
2460
+ if (JSON.stringify(e.worktree) !== JSON.stringify(trustedLocalWorktree(cwd, deps))) return fail("cwd worktree changed");
2461
+ } catch {
2462
+ return fail("cwd missing or moved");
2463
+ }
2464
+ const death = record.ownerDeath;
2465
+ const hasDeath = !record.pid && death && death.pid > 0 && JSON.stringify(death.executionOwner) === JSON.stringify(e.owner) && (!record.localWriterClaim || record.localWriterClaim.state === "released");
2466
+ if (!hasDeath && (typeof record.pid !== "number" || record.pid <= 0)) return fail("old owner unknown");
2467
+ const current = hasDeath ? { state: "unknown" } : nativeOwner(record.pid, deps);
2468
+ const old = e.owner;
2469
+ const reused = old?.state === "verified" && current.state === "verified" && (old.pid !== current.pid || old.startedAt !== current.startedAt || old.linux?.bootId !== current.linux?.bootId || old.linux?.startTicks !== current.linux?.startTicks);
2470
+ if (!hasDeath && !isPidGone(record.pid, deps) && !reused) return fail("old owner live or unknown");
2471
+ if (!e.permissions.readOnly && (record.localWriterClaim?.cwd !== cwd || !["held", "released"].includes(record.localWriterClaim.state))) return fail("writer claim unknown");
2472
+ const policy = { runtimeKey: "local", ...e.permissions, provenance: "cli-tool-dispatch-authorized" };
2473
+ const rawArgs = [
2474
+ "--runtime-key",
2475
+ "local",
2476
+ ...policy.hostWritesAuthorized ? ["--allow-host-writes"] : [],
2477
+ ...policy.readOnly ? ["--read-only"] : [],
2478
+ ...(policy.allowedToolNames ?? []).flatMap((t) => ["--allowed-tool", t]),
2479
+ ...(policy.blockedToolNames ?? []).flatMap((t) => ["--blocked-tool", t])
2480
+ ];
2481
+ return { cwd, policy, rawArgs };
2482
+ }
2483
+ function registerLocalForegroundWriter(cwd, policy, agentKey, deps = {}) {
2484
+ const fs = deps.fs ?? nodeFs2;
2485
+ const canonical = String((fs.realpathSync ?? nodeFs2.realpathSync)(cwd));
2486
+ const owner = nativeOwner(process.pid, deps);
2487
+ if (owner.state !== "verified" || policy.readOnly || !policy.hostWritesAuthorized) {
2488
+ throw new Error("[local-writer-resource] foreground native identity/authorization unknown");
2489
+ }
2490
+ const runId = defaultGenerateRunId();
2491
+ fs.mkdirSync(resolveRunsDir(deps.env, deps.homedir), { recursive: true });
2492
+ const worktree = trustedLocalWorktree(canonical, deps);
2493
+ const record = {
2494
+ runId,
2495
+ agentKey,
2496
+ writerLaunch: { protocol: "fenced-launch-v1", attemptId: randomUUID2(), phase: "prepared" },
2497
+ cwd: canonical,
2498
+ startedAt: (deps.now?.() ?? /* @__PURE__ */ new Date()).toISOString(),
2499
+ status: "running",
2500
+ logPath: resolveRunLogPath(runId, deps.env, deps.homedir),
2501
+ pid: process.pid,
2502
+ processStartedAt: owner.startedAt,
2503
+ processIdentity: "verified",
2504
+ execution: {
2505
+ state: "known",
2506
+ kind: "host-local",
2507
+ runtimeKey: "local",
2508
+ canonicalCwd: canonical,
2509
+ device: { kind: "localhost", hostname: nodeHostname(), platform: process.platform },
2510
+ ...worktree ? { worktree } : {},
2511
+ permissions: {
2512
+ hostWritesAuthorized: policy.hostWritesAuthorized,
2513
+ readOnly: policy.readOnly,
2514
+ ...policy.allowedToolNames ? { allowedToolNames: [...policy.allowedToolNames] } : {},
2515
+ ...policy.blockedToolNames ? { blockedToolNames: [...policy.blockedToolNames] } : {}
2516
+ },
2517
+ provenance: policy.provenance,
2518
+ owner
2519
+ }
2520
+ };
2521
+ writeRunRecord(record, deps);
2522
+ try {
2523
+ acquireLocalWriterClaim(runId, canonical, deps);
2524
+ } catch (error) {
2525
+ finalizeRunRecord(runId, { status: "failed", exitCode: 1, note: String(error) }, deps);
2526
+ throw error;
2527
+ }
2528
+ return runId;
2529
+ }
2530
+ function releaseUnspawnedLocalWriterClaim(runId, deps) {
2531
+ const released = withRunRecordLock(runId, deps, () => {
2532
+ const record = readRunRecord(runId, deps);
2533
+ if (record?.localWriterClaim) {
2534
+ if (record.writerLaunch?.phase === "prepared") record.writerLaunch.phase = "revoked";
2535
+ record.localWriterClaim.state = "released";
2536
+ writeRunRecord(record, deps);
2537
+ }
2538
+ return true;
2539
+ }, { strict: true });
2540
+ if (!released) throw new Error(`[local-writer-resource] release lock busy: ${runId}`);
2541
+ }
2213
2542
  async function spawnLocalBackgroundRun(input, deps = {}) {
2214
2543
  const homedir = deps.homedir ?? nodeHomedir;
2215
2544
  const env = deps.env ?? (deps.homedir ? { ...process.env, NOLO_HOME: join2(homedir(), ".nolo") } : process.env);
@@ -2255,13 +2584,43 @@ async function spawnLocalBackgroundRun(input, deps = {}) {
2255
2584
  }
2256
2585
  } catch {
2257
2586
  }
2587
+ const executionRequest = input.localExecution;
2588
+ if (executionRequest && (executionRequest.runtimeKey !== "local" || typeof executionRequest.readOnly !== "boolean" || typeof executionRequest.hostWritesAuthorized !== "boolean" || !executionRequest.readOnly && !executionRequest.hostWritesAuthorized)) {
2589
+ throw new Error("Invalid authorized local execution facts");
2590
+ }
2591
+ const canonicalCwd = executionRequest ? String((fs.realpathSync ?? nodeFs2.realpathSync)(targetCwd)) : void 0;
2592
+ const executionWorktree = canonicalCwd ? trustedLocalWorktree(canonicalCwd, resolvedDeps) : void 0;
2593
+ const execution = executionRequest ? {
2594
+ state: "known",
2595
+ kind: "host-local",
2596
+ runtimeKey: "local",
2597
+ device: { kind: "localhost", hostname: nodeHostname(), platform: deps.platform ?? process.platform },
2598
+ canonicalCwd,
2599
+ ...executionWorktree ? { worktree: executionWorktree } : {},
2600
+ permissions: {
2601
+ hostWritesAuthorized: executionRequest.hostWritesAuthorized,
2602
+ readOnly: executionRequest.readOnly,
2603
+ ...executionRequest.allowedToolNames ? { allowedToolNames: [...executionRequest.allowedToolNames] } : {},
2604
+ ...executionRequest.blockedToolNames ? { blockedToolNames: [...executionRequest.blockedToolNames] } : {}
2605
+ },
2606
+ provenance: executionRequest.provenance,
2607
+ owner: { state: "unknown" }
2608
+ } : { state: "unknown", reason: "missing-host-facts" };
2258
2609
  const title = normalizeRunTitle(input.title);
2259
2610
  const record = {
2611
+ ...input.evidenceScope ? { evidenceScope: input.evidenceScope } : {},
2612
+ ...input.dispatchSpeedProvenance ? { dispatchSpeedProvenance: input.dispatchSpeedProvenance } : {},
2260
2613
  runId,
2261
2614
  agentKey: input.agentKey,
2262
- ...typeof input.agentName === "string" && input.agentName.trim() ? { agentName: input.agentName.trim() } : {},
2615
+ agentName: input.agentName?.trim() || shortAgentKey(input.agentKey),
2263
2616
  ...title ? { title } : {},
2264
- cwd: input.cwd,
2617
+ cwd: canonicalCwd ?? input.cwd,
2618
+ execution,
2619
+ ...executionRequest ? { writerLaunch: { protocol: "fenced-launch-v1", attemptId: randomUUID2(), phase: "prepared" } } : {},
2620
+ ...executionRequest ? (() => {
2621
+ const parent = nativeOwner(process.pid, resolvedDeps);
2622
+ return parent.state === "verified" ? { ownerPublication: { state: "pending", parent } } : {};
2623
+ })() : {},
2265
2624
  ...messagePath ? { msgFile: messagePath } : input.msgFile ? { msgFile: input.msgFile } : {},
2266
2625
  startedAt: now().toISOString(),
2267
2626
  ...typeof input.timeoutMs === "number" ? { timeoutMs: input.timeoutMs } : {},
@@ -2269,6 +2628,7 @@ async function spawnLocalBackgroundRun(input, deps = {}) {
2269
2628
  logPath,
2270
2629
  queuePath,
2271
2630
  batchId,
2631
+ ...input.selectionCheck ? { selectionCheck: input.selectionCheck } : {},
2272
2632
  ...typeof input.credentialGroup === "string" && input.credentialGroup.trim() ? { credentialGroup: input.credentialGroup.trim() } : {},
2273
2633
  ...typeof input.parentDialogId === "string" && input.parentDialogId.trim() ? { parentDialogId: input.parentDialogId.trim() } : {},
2274
2634
  ...typeof input.dialogId === "string" && input.dialogId.trim() ? { dialogId: input.dialogId.trim() } : {},
@@ -2294,11 +2654,11 @@ async function spawnLocalBackgroundRun(input, deps = {}) {
2294
2654
  ...env,
2295
2655
  NOLO_AGENT_RUN_CHILD: "1",
2296
2656
  NOLO_AGENT_RUN_ID: runId,
2297
- ...input.subtaskBudgetLimits ? {
2298
- NOLO_SUBTASK_MAX_TOOL_CALLS: String(input.subtaskBudgetLimits.maxToolCalls),
2299
- NOLO_SUBTASK_MAX_WALL_CLOCK_MS: String(input.subtaskBudgetLimits.maxWallClockMs)
2300
- } : {}
2657
+ ...record.writerLaunch ? { NOLO_WRITER_LAUNCH_ATTEMPT: record.writerLaunch.attemptId } : {}
2301
2658
  };
2659
+ if (!record.writerLaunch) delete childEnv.NOLO_WRITER_LAUNCH_ATTEMPT;
2660
+ delete childEnv.NOLO_SUBTASK_MAX_TOOL_CALLS;
2661
+ delete childEnv.NOLO_SUBTASK_MAX_WALL_CLOCK_MS;
2302
2662
  let hostMemory = null;
2303
2663
  let reservation;
2304
2664
  const logFd = fs.openSync(logPath, "a");
@@ -2312,6 +2672,8 @@ async function spawnLocalBackgroundRun(input, deps = {}) {
2312
2672
  ...fs.statSync ? { statSync: (path) => ({ mtimeMs: fs.statSync(path).mtimeMs }) } : {}
2313
2673
  };
2314
2674
  let proc;
2675
+ let preparedScope;
2676
+ const launchScope = (r) => JSON.stringify({ cwd: r.cwd, execution: r.execution, claim: r.localWriterClaim, publication: r.ownerPublication });
2315
2677
  try {
2316
2678
  reservation = reserveHostMemory({
2317
2679
  runsDir,
@@ -2323,8 +2685,14 @@ async function spawnLocalBackgroundRun(input, deps = {}) {
2323
2685
  getProcessStartTime: () => null,
2324
2686
  withLock: (id, fn, opts) => withRunRecordLock(id, resolvedDeps, fn, opts)
2325
2687
  });
2688
+ const spawnCwd = input.claimLocalWrites ? acquireLocalWriterClaim(runId, input.cwd ?? process.cwd(), resolvedDeps) : canonicalCwd ?? input.cwd;
2689
+ if (record.writerLaunch) {
2690
+ const prepared = readRunRecord(runId, resolvedDeps);
2691
+ if (!prepared || prepared.writerLaunch?.phase !== "prepared" || prepared.writerLaunch.attemptId !== record.writerLaunch.attemptId) throw new Error("[local-writer-resource] launch attempt revoked before spawn");
2692
+ preparedScope = launchScope(prepared);
2693
+ }
2326
2694
  proc = spawn(execPath, childArgs, {
2327
- cwd: input.cwd,
2695
+ cwd: spawnCwd,
2328
2696
  env: childEnv,
2329
2697
  detached: true,
2330
2698
  // Detached on Windows means no console; hide the one its children would create.
@@ -2334,6 +2702,7 @@ async function spawnLocalBackgroundRun(input, deps = {}) {
2334
2702
  } catch (error) {
2335
2703
  try {
2336
2704
  reservation?.release("spawn_sync_failed");
2705
+ if (input.claimLocalWrites) releaseUnspawnedLocalWriterClaim(runId, resolvedDeps);
2337
2706
  } finally {
2338
2707
  finalizeRunRecord(runId, { status: "failed", exitCode: 1, note: String(error) }, resolvedDeps);
2339
2708
  }
@@ -2356,13 +2725,56 @@ async function spawnLocalBackgroundRun(input, deps = {}) {
2356
2725
  });
2357
2726
  const hostMemoryNotice = emitHostMemoryNotice(hostMemory, input.output);
2358
2727
  if (typeof proc.pid === "number") {
2359
- withRunRecordLock(runId, resolvedDeps, () => {
2360
- const latest = readRunRecord(runId, resolvedDeps) ?? record;
2728
+ const nativeStartedAt = executionRequest ? probeProcessStartTime(proc.pid, resolvedDeps) : null;
2729
+ let linuxIdentity;
2730
+ if (executionRequest && (deps.platform ?? process.platform) === "linux") {
2731
+ try {
2732
+ const stat = String(nodeFs2.readFileSync(`/proc/${proc.pid}/stat`, "utf8"));
2733
+ const startTicks = stat.slice(stat.lastIndexOf(")") + 2).split(/\s+/)[19];
2734
+ const bootId = nodeFs2.readFileSync("/proc/sys/kernel/random/boot_id", "utf8").trim();
2735
+ if (/^\d+$/.test(startTicks) && bootId) linuxIdentity = { bootId, startTicks };
2736
+ } catch {
2737
+ }
2738
+ }
2739
+ const confirmedStart = executionRequest ? probeProcessStartTime(proc.pid, resolvedDeps) : null;
2740
+ const stableNativeIdentity = nativeStartedAt && confirmedStart && nativeStartedAt.getTime() === confirmedStart.getTime() && !isPidGone(proc.pid, resolvedDeps);
2741
+ const publishOwner = () => withRunRecordLock(runId, resolvedDeps, () => {
2742
+ const latest = readRunRecord(runId, resolvedDeps);
2743
+ if (!latest) throw new Error("[local-writer-resource] publication record missing");
2744
+ if (record.writerLaunch) {
2745
+ const launch = latest.writerLaunch;
2746
+ if (launch?.protocol !== "fenced-launch-v1" || launch.attemptId !== record.writerLaunch.attemptId || launch.phase !== "prepared") {
2747
+ throw new Error("[local-writer-resource] publication attempt revoked/mismatched");
2748
+ }
2749
+ if (launchScope(latest) !== preparedScope) throw new Error("[local-writer-resource] publication scope changed");
2750
+ }
2361
2751
  latest.pid = proc.pid;
2362
- latest.processIdentity ??= "unverified";
2752
+ if (latest.execution?.state === "known") {
2753
+ const verified = stableNativeIdentity && ((deps.platform ?? process.platform) !== "linux" || linuxIdentity);
2754
+ latest.execution.owner = verified ? {
2755
+ state: "verified",
2756
+ pid: proc.pid,
2757
+ startedAt: nativeStartedAt.toISOString(),
2758
+ source: "parent-native",
2759
+ ...linuxIdentity ? { linux: linuxIdentity } : {}
2760
+ } : { state: "unknown" };
2761
+ latest.processIdentity = verified ? "verified" : "unverified";
2762
+ latest.processStartedAt = verified ? nativeStartedAt.toISOString() : void 0;
2763
+ } else {
2764
+ latest.processIdentity ??= "unverified";
2765
+ }
2766
+ if (latest.writerLaunch && latest.execution?.state === "known" && latest.execution.owner.state === "verified") {
2767
+ latest.writerLaunch.phase = "granted";
2768
+ }
2769
+ if (latest.ownerPublication) latest.ownerPublication.state = "complete";
2363
2770
  writeRunRecord(latest, resolvedDeps);
2364
2771
  return true;
2365
- }, { strict: true });
2772
+ }, { strict: true, requireDeadOwner: true });
2773
+ const publicationDeadline = Date.now() + 2e3;
2774
+ while (!publishOwner()) {
2775
+ if (Date.now() >= publicationDeadline) throw new Error("[local-writer-resource] parent owner publication lock busy");
2776
+ await new Promise((resolve2) => setTimeout(resolve2, 20));
2777
+ }
2366
2778
  try {
2367
2779
  const persisted = readRunRecord(runId, resolvedDeps);
2368
2780
  reservation.associate({ runId, pid: proc.pid, processStartedAt: persisted?.processStartedAt });
@@ -2387,6 +2799,8 @@ async function spawnLocalBackgroundRun(input, deps = {}) {
2387
2799
  logPath,
2388
2800
  queuePath,
2389
2801
  batchId,
2802
+ agentName: record.agentName ?? shortAgentKey(input.agentKey),
2803
+ ...input.selectionCheck ? { selectionCheck: input.selectionCheck } : {},
2390
2804
  ...hostMemoryNotice ? { hostMemoryNotice } : {}
2391
2805
  };
2392
2806
  }
@@ -2495,8 +2909,31 @@ function transitionRunToTerminal(runId, update, deps = {}, options = {}) {
2495
2909
  if (typeof update.lastAssistantText === "string" && update.lastAssistantText) {
2496
2910
  record2.lastAssistantText = update.lastAssistantText.slice(0, 2e3);
2497
2911
  }
2912
+ if (update.cacheUsage) {
2913
+ record2.cacheHitRatio = update.cacheUsage.cache_hit_ratio;
2914
+ record2.cacheCachedTokens = update.cacheUsage.cached_tokens;
2915
+ }
2498
2916
  record2.endedAt = now().toISOString();
2499
- if (typeof update.lastAssistantText === "string" && update.lastAssistantText) {
2917
+ let resultWriteFailed = false;
2918
+ let pendingResultFile;
2919
+ let stagingComplete = false;
2920
+ let backupFile;
2921
+ let backupVerified = false;
2922
+ const registerArtifact = (path, kind) => {
2923
+ const fs = deps.fs ?? nodeFs2;
2924
+ const stat = fs.lstatSync?.(path);
2925
+ if (!stat || !stat.isFile() || stat.isSymbolicLink()) return;
2926
+ const artifact = {
2927
+ publisher: "run-result-v1",
2928
+ path,
2929
+ kind,
2930
+ dev: String(stat.dev),
2931
+ ino: String(stat.ino),
2932
+ sha256: createHash("sha256").update(fs.readFileSync(path)).digest("hex")
2933
+ };
2934
+ record2.resultArtifacts = [...(record2.resultArtifacts ?? []).filter((a) => a.path !== path), artifact];
2935
+ };
2936
+ if (typeof update.lastAssistantText === "string" && update.lastAssistantText || update.acceptance?.checks.observations?.length) {
2500
2937
  try {
2501
2938
  const fs = deps.fs ?? nodeFs2;
2502
2939
  const resultFile = join2(resolveRunsDir(deps.env, deps.homedir), `${runId}.result.md`);
@@ -2505,6 +2942,7 @@ function transitionRunToTerminal(runId, update, deps = {}, options = {}) {
2505
2942
  const content = buildResultFileContent(
2506
2943
  {
2507
2944
  runId,
2945
+ acceptance: update.acceptance,
2508
2946
  status: record2.status,
2509
2947
  agentName: record2.agentName,
2510
2948
  model: update.model,
@@ -2519,16 +2957,54 @@ function transitionRunToTerminal(runId, update, deps = {}, options = {}) {
2519
2957
  continuedFrom: record2.continuedFrom,
2520
2958
  ...update.cacheUsage ? { cacheUsage: update.cacheUsage } : {}
2521
2959
  },
2522
- update.lastAssistantText
2960
+ update.lastAssistantText ?? ""
2523
2961
  );
2524
- fs.writeFileSync(resultFile, content, "utf8");
2962
+ if (typeof fs.renameSync !== "function") throw new Error("atomic result publication requires renameSync");
2963
+ pendingResultFile = `${resultFile}.${randomUUID2()}.pending`;
2964
+ try {
2965
+ fs.writeFileSync(pendingResultFile, content, { encoding: "utf8", flag: "wx" });
2966
+ stagingComplete = true;
2967
+ } finally {
2968
+ if (fs.existsSync(pendingResultFile)) registerArtifact(pendingResultFile, "pending");
2969
+ }
2970
+ if (fs.existsSync(resultFile)) {
2971
+ const previous = fs.readFileSync(resultFile);
2972
+ const backup = `${resultFile}.${randomUUID2()}.bak`;
2973
+ backupFile = backup;
2974
+ try {
2975
+ fs.writeFileSync(backup, previous, { flag: "wx" });
2976
+ } finally {
2977
+ if (fs.existsSync(backup)) registerArtifact(backup, "bak");
2978
+ }
2979
+ const sameBytes = (a, b) => Buffer.from(a).equals(Buffer.from(b));
2980
+ if (!sameBytes(previous, fs.readFileSync(backup)) || !sameBytes(previous, fs.readFileSync(resultFile))) {
2981
+ throw new Error("previous result backup verification failed");
2982
+ }
2983
+ backupVerified = true;
2984
+ }
2985
+ fs.renameSync(pendingResultFile, resultFile);
2986
+ record2.resultArtifacts = record2.resultArtifacts?.filter((a) => a.path !== pendingResultFile);
2987
+ pendingResultFile = void 0;
2525
2988
  record2.resultFile = resultFile;
2526
2989
  } catch {
2990
+ resultWriteFailed = true;
2991
+ delete record2.resultFile;
2992
+ if (record2.status === "done") {
2993
+ record2.status = "failed";
2994
+ record2.exitCode = 1;
2995
+ }
2527
2996
  }
2528
2997
  }
2529
2998
  if (typeof update.note === "string" && update.note.trim()) {
2530
2999
  record2.note = update.note.trim();
2531
3000
  }
3001
+ if (resultWriteFailed) {
3002
+ if (record2.note?.startsWith("orphaned:")) record2.note = void 0;
3003
+ const fs = deps.fs ?? nodeFs2;
3004
+ const stagingNote = pendingResultFile ? fs.existsSync(pendingResultFile) ? `${stagingComplete ? "complete staging copy" : "incomplete staging fragment"}: ${pendingResultFile}` : `staging not created: ${pendingResultFile}` : "staging not created";
3005
+ const backupNote = backupFile ? `${fs.existsSync(backupFile) ? backupVerified ? "full verified backup" : "partial backup" : "backup not created"}: ${backupFile}` : "backup not created";
3006
+ record2.note = [record2.note, `result file write failed; complete final report was not saved; ${stagingNote}; ${backupNote}`].filter(Boolean).join("; ");
3007
+ }
2532
3008
  if (record2.note?.startsWith("orphaned:")) record2.note = void 0;
2533
3009
  writeRunRecord(record2, deps);
2534
3010
  return { kind: "transitioned", record: record2 };
@@ -2604,10 +3080,10 @@ function defaultGetProcessStartTime(pid, deps = {}) {
2604
3080
  // 这会让 isPidReused 的结论依赖调用者环境:同一条 run 记录在英文
2605
3081
  // locale 下被判 pid reused → orphaned,中文 locale 下不判。强制 C
2606
3082
  // locale 让输出恒为可解析的英文格式,结果与 locale 无关。
2607
- env: { ...process.env, LC_ALL: "C", LANG: "C" }
3083
+ env: { ...process.env, LC_ALL: "C", LANG: "C", TZ: "UTC" }
2608
3084
  }).trim();
2609
3085
  if (!output) return null;
2610
- const d = new Date(output);
3086
+ const d = new Date(output.endsWith("Z") || /[+-]\d\d:\d\d$/.test(output) ? output : `${output} UTC`);
2611
3087
  return isNaN(d.getTime()) ? null : d;
2612
3088
  } catch {
2613
3089
  return null;
@@ -2659,6 +3135,7 @@ function checkStaleRun(runId, deps = {}) {
2659
3135
  const latest = readRunRecord(runId, deps);
2660
3136
  if (!latest) return record;
2661
3137
  if (latest.status !== "running") return latest;
3138
+ if (latest.pid !== record.pid || latest.processStartedAt !== record.processStartedAt || latest.processIdentity !== record.processIdentity) return latest;
2662
3139
  if (latest.activity?.updatedAt !== record.activity?.updatedAt) return latest;
2663
3140
  const at = now().toISOString();
2664
3141
  latest.status = "orphaned";
@@ -2674,6 +3151,16 @@ function checkStaleRun(runId, deps = {}) {
2674
3151
  }
2675
3152
  latest.endedAt = at;
2676
3153
  latest.reconciledAt = at;
3154
+ if ((pidGone || pidReused) && latest.localWriterClaim?.state === "held") {
3155
+ latest.localWriterClaim.state = "released";
3156
+ }
3157
+ latest.ownerDeath = {
3158
+ pid: latest.pid,
3159
+ processStartedAt: latest.processStartedAt,
3160
+ processIdentity: latest.processIdentity,
3161
+ ...latest.execution?.state === "known" ? { executionOwner: latest.execution.owner } : {},
3162
+ confirmedAt: at
3163
+ };
2677
3164
  latest.pid = void 0;
2678
3165
  writeRunRecord(latest, deps);
2679
3166
  return latest;
@@ -2844,6 +3331,7 @@ async function runAgentStatusCommand(args, deps) {
2844
3331
  const { partialCheckpoint, ...summary } = record;
2845
3332
  deps.output.write(JSON.stringify({
2846
3333
  ...summary,
3334
+ ...localWriterRecovery(record) ? { writerRecovery: localWriterRecovery(record) } : {},
2847
3335
  ...includeCheckpoint ? { checkpoint: partialCheckpoint ? { ...partialCheckpoint, available: true } : { available: false, final: false, reason: "checkpoint_missing" } } : {}
2848
3336
  }) + "\n");
2849
3337
  return 0;
@@ -2878,6 +3366,9 @@ function printStatusOnce(record, deps) {
2878
3366
  deps.output.write(`status: ${record.status}
2879
3367
  `);
2880
3368
  deps.output.write(`pid: ${record.pid ?? "-"}
3369
+ `);
3370
+ const recovery = localWriterRecovery(record);
3371
+ if (recovery) deps.output.write(`writerRecovery: required (${recovery.reason}); automatic release forbidden; native launch evidence required
2881
3372
  `);
2882
3373
  deps.output.write(`agent: ${record.agentKey}
2883
3374
  `);
@@ -3135,6 +3626,16 @@ async function runAgentStopCommand(args, deps) {
3135
3626
  async function runAgentKillCommand(args, deps) {
3136
3627
  return runSignalCommand(args, "SIGKILL", "kill", deps);
3137
3628
  }
3629
+ async function runAgentRecoverPreparedWriterCommand(args, deps) {
3630
+ if (args.length !== 3 || args[1] !== "--attempt-id" || !/^[A-Za-z0-9_-]+$/.test(args[0] ?? "") || !args[2] || args[2].startsWith("-")) {
3631
+ deps.output.write("Usage: nolo agent recover-prepared-writer <runId> --attempt-id <attemptId>\n");
3632
+ return 1;
3633
+ }
3634
+ const [runId, , attemptId] = args;
3635
+ const outcome = revokePreparedWriterLaunch(runId, attemptId, deps);
3636
+ deps.output.write(JSON.stringify({ action: "recoverPreparedWriter", runId, attemptId, outcome }) + "\n");
3637
+ return outcome === "blocked" ? 1 : 0;
3638
+ }
3138
3639
 
3139
3640
  export {
3140
3641
  createShellApprovalChild,
@@ -3145,6 +3646,8 @@ export {
3145
3646
  recordRunResultHeaderMeta,
3146
3647
  getRunResultHeaderMeta,
3147
3648
  serverOriginForDialog,
3649
+ stripResultFrontMatter,
3650
+ isHistoryIntegrityFailure,
3148
3651
  RUN_TERMINAL_STATUSES,
3149
3652
  isRunTerminalStatus,
3150
3653
  resolveNoloHome,
@@ -3192,6 +3695,12 @@ export {
3192
3695
  absolutizeSkillArgs,
3193
3696
  rewriteMsgFileArg,
3194
3697
  buildAgentRunChildCommand,
3698
+ localWriterRecovery,
3699
+ revokePreparedWriterLaunch,
3700
+ validateLocalWriterChild,
3701
+ awaitLocalWriterChild,
3702
+ resolveLocalContinuation,
3703
+ registerLocalForegroundWriter,
3195
3704
  spawnLocalBackgroundRun,
3196
3705
  ackRunRecord,
3197
3706
  DEFAULT_ACK_LEASE_TTL_MS,
@@ -3219,5 +3728,6 @@ export {
3219
3728
  TERMINATE_KILL_GRACE_MS,
3220
3729
  terminateRunProcess,
3221
3730
  runAgentStopCommand,
3222
- runAgentKillCommand
3731
+ runAgentKillCommand,
3732
+ runAgentRecoverPreparedWriterCommand
3223
3733
  };