waterplane 0.1.6 → 0.1.11

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 (496) hide show
  1. package/CHANGELOG.md +92 -1
  2. package/README.md +1 -1
  3. package/SECURITY.md +11 -3
  4. package/deploy/node-version +1 -1
  5. package/node_modules/@waterplane/shared/dist/agentfiles.d.ts +17 -0
  6. package/node_modules/@waterplane/shared/dist/agentfiles.js +58 -4
  7. package/node_modules/@waterplane/shared/dist/agentfiles.js.map +1 -1
  8. package/node_modules/@waterplane/shared/dist/alwaysonwords.d.ts +83 -0
  9. package/node_modules/@waterplane/shared/dist/alwaysonwords.js +209 -0
  10. package/node_modules/@waterplane/shared/dist/alwaysonwords.js.map +1 -0
  11. package/node_modules/@waterplane/shared/dist/autocompact.js +1 -1
  12. package/node_modules/@waterplane/shared/dist/autocompact.js.map +1 -1
  13. package/node_modules/@waterplane/shared/dist/backendsources.d.ts +11 -1
  14. package/node_modules/@waterplane/shared/dist/backendsources.js.map +1 -1
  15. package/node_modules/@waterplane/shared/dist/branchmode.d.ts +27 -0
  16. package/node_modules/@waterplane/shared/dist/branchmode.js +80 -0
  17. package/node_modules/@waterplane/shared/dist/branchmode.js.map +1 -0
  18. package/node_modules/@waterplane/shared/dist/buildstamp.d.ts +37 -0
  19. package/node_modules/@waterplane/shared/dist/buildstamp.js +95 -0
  20. package/node_modules/@waterplane/shared/dist/buildstamp.js.map +1 -0
  21. package/node_modules/@waterplane/shared/dist/burn.d.ts +16 -1
  22. package/node_modules/@waterplane/shared/dist/burn.js +30 -0
  23. package/node_modules/@waterplane/shared/dist/burn.js.map +1 -1
  24. package/node_modules/@waterplane/shared/dist/changebrief.d.ts +61 -0
  25. package/node_modules/@waterplane/shared/dist/changebrief.js +70 -0
  26. package/node_modules/@waterplane/shared/dist/changebrief.js.map +1 -0
  27. package/node_modules/@waterplane/shared/dist/desktopfiles.d.ts +100 -0
  28. package/node_modules/@waterplane/shared/dist/desktopfiles.js +192 -0
  29. package/node_modules/@waterplane/shared/dist/desktopfiles.js.map +1 -0
  30. package/node_modules/@waterplane/shared/dist/exposure.d.ts +175 -0
  31. package/node_modules/@waterplane/shared/dist/exposure.js +357 -0
  32. package/node_modules/@waterplane/shared/dist/exposure.js.map +1 -0
  33. package/node_modules/@waterplane/shared/dist/exposurepush.d.ts +60 -0
  34. package/node_modules/@waterplane/shared/dist/exposurepush.js +103 -0
  35. package/node_modules/@waterplane/shared/dist/exposurepush.js.map +1 -0
  36. package/node_modules/@waterplane/shared/dist/healthindex/commits.d.ts +26 -0
  37. package/node_modules/@waterplane/shared/dist/healthindex/commits.js +57 -0
  38. package/node_modules/@waterplane/shared/dist/healthindex/commits.js.map +1 -0
  39. package/node_modules/@waterplane/shared/dist/healthindex/move.d.ts +25 -0
  40. package/node_modules/@waterplane/shared/dist/healthindex/move.js +79 -0
  41. package/node_modules/@waterplane/shared/dist/healthindex/move.js.map +1 -0
  42. package/node_modules/@waterplane/shared/dist/healthindex/readings.d.ts +53 -0
  43. package/node_modules/@waterplane/shared/dist/healthindex/readings.js +154 -0
  44. package/node_modules/@waterplane/shared/dist/healthindex/readings.js.map +1 -0
  45. package/node_modules/@waterplane/shared/dist/healthindex/repoindex.d.ts +41 -0
  46. package/node_modules/@waterplane/shared/dist/healthindex/repoindex.js +19 -0
  47. package/node_modules/@waterplane/shared/dist/healthindex/repoindex.js.map +1 -0
  48. package/node_modules/@waterplane/shared/dist/healthindex/score.d.ts +26 -0
  49. package/node_modules/@waterplane/shared/dist/healthindex/score.js +154 -0
  50. package/node_modules/@waterplane/shared/dist/healthindex/score.js.map +1 -0
  51. package/node_modules/@waterplane/shared/dist/healthindex/types.d.ts +206 -0
  52. package/node_modules/@waterplane/shared/dist/healthindex/types.js +58 -0
  53. package/node_modules/@waterplane/shared/dist/healthindex/types.js.map +1 -0
  54. package/node_modules/@waterplane/shared/dist/healthindex/vs.d.ts +26 -0
  55. package/node_modules/@waterplane/shared/dist/healthindex/vs.js +38 -0
  56. package/node_modules/@waterplane/shared/dist/healthindex/vs.js.map +1 -0
  57. package/node_modules/@waterplane/shared/dist/healthindex/words.d.ts +28 -0
  58. package/node_modules/@waterplane/shared/dist/healthindex/words.js +69 -0
  59. package/node_modules/@waterplane/shared/dist/healthindex/words.js.map +1 -0
  60. package/node_modules/@waterplane/shared/dist/healthindex.d.ts +15 -411
  61. package/node_modules/@waterplane/shared/dist/healthindex.js +8 -602
  62. package/node_modules/@waterplane/shared/dist/healthindex.js.map +1 -1
  63. package/node_modules/@waterplane/shared/dist/hints.js +5 -0
  64. package/node_modules/@waterplane/shared/dist/hints.js.map +1 -1
  65. package/node_modules/@waterplane/shared/dist/index.d.ts +29 -0
  66. package/node_modules/@waterplane/shared/dist/index.js +29 -0
  67. package/node_modules/@waterplane/shared/dist/index.js.map +1 -1
  68. package/node_modules/@waterplane/shared/dist/intent/kind.d.ts +31 -1
  69. package/node_modules/@waterplane/shared/dist/intent/kind.js +27 -3
  70. package/node_modules/@waterplane/shared/dist/intent/kind.js.map +1 -1
  71. package/node_modules/@waterplane/shared/dist/intent.d.ts +1 -1
  72. package/node_modules/@waterplane/shared/dist/intent.js +1 -1
  73. package/node_modules/@waterplane/shared/dist/intent.js.map +1 -1
  74. package/node_modules/@waterplane/shared/dist/launchmodes.d.ts +2 -0
  75. package/node_modules/@waterplane/shared/dist/launchmodes.js +12 -0
  76. package/node_modules/@waterplane/shared/dist/launchmodes.js.map +1 -1
  77. package/node_modules/@waterplane/shared/dist/ledgerspan.d.ts +59 -0
  78. package/node_modules/@waterplane/shared/dist/ledgerspan.js +99 -0
  79. package/node_modules/@waterplane/shared/dist/ledgerspan.js.map +1 -0
  80. package/node_modules/@waterplane/shared/dist/netretry.d.ts +38 -0
  81. package/node_modules/@waterplane/shared/dist/netretry.js +31 -0
  82. package/node_modules/@waterplane/shared/dist/netretry.js.map +1 -0
  83. package/node_modules/@waterplane/shared/dist/netretrycfg.d.ts +12 -0
  84. package/node_modules/@waterplane/shared/dist/netretrycfg.js +27 -0
  85. package/node_modules/@waterplane/shared/dist/netretrycfg.js.map +1 -0
  86. package/node_modules/@waterplane/shared/dist/nodemin.d.ts +6 -4
  87. package/node_modules/@waterplane/shared/dist/nodemin.js +6 -4
  88. package/node_modules/@waterplane/shared/dist/nodemin.js.map +1 -1
  89. package/node_modules/@waterplane/shared/dist/optins.d.ts +35 -1
  90. package/node_modules/@waterplane/shared/dist/optins.js +39 -1
  91. package/node_modules/@waterplane/shared/dist/optins.js.map +1 -1
  92. package/node_modules/@waterplane/shared/dist/plugin/api.d.ts +364 -0
  93. package/node_modules/@waterplane/shared/dist/plugin/api.js +2 -0
  94. package/node_modules/@waterplane/shared/dist/plugin/api.js.map +1 -0
  95. package/node_modules/@waterplane/shared/dist/plugin/backend.d.ts +197 -0
  96. package/node_modules/@waterplane/shared/dist/plugin/backend.js +9 -0
  97. package/node_modules/@waterplane/shared/dist/plugin/backend.js.map +1 -0
  98. package/node_modules/@waterplane/shared/dist/plugin/manifest.d.ts +160 -0
  99. package/node_modules/@waterplane/shared/dist/plugin/manifest.js +98 -0
  100. package/node_modules/@waterplane/shared/dist/plugin/manifest.js.map +1 -0
  101. package/node_modules/@waterplane/shared/dist/plugin/module.d.ts +98 -0
  102. package/node_modules/@waterplane/shared/dist/plugin/module.js +13 -0
  103. package/node_modules/@waterplane/shared/dist/plugin/module.js.map +1 -0
  104. package/node_modules/@waterplane/shared/dist/plugin/version.d.ts +64 -0
  105. package/node_modules/@waterplane/shared/dist/plugin/version.js +84 -0
  106. package/node_modules/@waterplane/shared/dist/plugin/version.js.map +1 -0
  107. package/node_modules/@waterplane/shared/dist/plugin.d.ts +5 -867
  108. package/node_modules/@waterplane/shared/dist/plugin.js +27 -186
  109. package/node_modules/@waterplane/shared/dist/plugin.js.map +1 -1
  110. package/node_modules/@waterplane/shared/dist/pluginlaunch.d.ts +7 -0
  111. package/node_modules/@waterplane/shared/dist/prview.d.ts +23 -0
  112. package/node_modules/@waterplane/shared/dist/prview.js +107 -0
  113. package/node_modules/@waterplane/shared/dist/prview.js.map +1 -0
  114. package/node_modules/@waterplane/shared/dist/repohealth.d.ts +4 -0
  115. package/node_modules/@waterplane/shared/dist/repohealth.js.map +1 -1
  116. package/node_modules/@waterplane/shared/dist/schedule/schedaction.d.ts +29 -0
  117. package/node_modules/@waterplane/shared/dist/schedule/schedaction.js +22 -0
  118. package/node_modules/@waterplane/shared/dist/schedule/schedaction.js.map +1 -1
  119. package/node_modules/@waterplane/shared/dist/schedule/schedclean.js +26 -0
  120. package/node_modules/@waterplane/shared/dist/schedule/schedclean.js.map +1 -1
  121. package/node_modules/@waterplane/shared/dist/schedule.d.ts +1 -1
  122. package/node_modules/@waterplane/shared/dist/schedule.js +1 -1
  123. package/node_modules/@waterplane/shared/dist/schedule.js.map +1 -1
  124. package/node_modules/@waterplane/shared/dist/sessionbudget.d.ts +20 -5
  125. package/node_modules/@waterplane/shared/dist/sessionbudget.js +42 -16
  126. package/node_modules/@waterplane/shared/dist/sessionbudget.js.map +1 -1
  127. package/node_modules/@waterplane/shared/dist/weekburn.d.ts +114 -0
  128. package/node_modules/@waterplane/shared/dist/weekburn.js +205 -0
  129. package/node_modules/@waterplane/shared/dist/weekburn.js.map +1 -0
  130. package/node_modules/@waterplane/shared/dist/wire/alwayson.d.ts +64 -0
  131. package/node_modules/@waterplane/shared/dist/wire/alwayson.js +7 -0
  132. package/node_modules/@waterplane/shared/dist/wire/alwayson.js.map +1 -0
  133. package/node_modules/@waterplane/shared/dist/wire/backend.d.ts +4 -0
  134. package/node_modules/@waterplane/shared/dist/wire/backendtokens.d.ts +6 -0
  135. package/node_modules/@waterplane/shared/dist/wire/backendtokens.js +0 -9
  136. package/node_modules/@waterplane/shared/dist/wire/backendtokens.js.map +1 -1
  137. package/node_modules/@waterplane/shared/dist/wire/costwindow.d.ts +20 -0
  138. package/node_modules/@waterplane/shared/dist/wire/messages/clienthost.d.ts +15 -1
  139. package/node_modules/@waterplane/shared/dist/wire/messages/clientsession.d.ts +10 -0
  140. package/node_modules/@waterplane/shared/dist/wire/messages/hosttools.d.ts +12 -2
  141. package/node_modules/@waterplane/shared/dist/wire/notify.d.ts +129 -1
  142. package/node_modules/@waterplane/shared/dist/wire/notify.js +79 -1
  143. package/node_modules/@waterplane/shared/dist/wire/notify.js.map +1 -1
  144. package/node_modules/@waterplane/shared/dist/wire/pullrequest.d.ts +42 -0
  145. package/node_modules/@waterplane/shared/dist/wire/pullrequest.js +2 -0
  146. package/node_modules/@waterplane/shared/dist/wire/pullrequest.js.map +1 -0
  147. package/node_modules/@waterplane/shared/dist/wire/repo.d.ts +119 -0
  148. package/node_modules/@waterplane/shared/dist/wire/repo.js +8 -3
  149. package/node_modules/@waterplane/shared/dist/wire/repo.js.map +1 -1
  150. package/node_modules/@waterplane/shared/dist/wire/sent.d.ts +3 -1
  151. package/node_modules/@waterplane/shared/dist/wire/session/contextspark.d.ts +7 -0
  152. package/node_modules/@waterplane/shared/dist/wire/session/info.d.ts +4 -1
  153. package/node_modules/@waterplane/shared/dist/wire/session/launch.d.ts +25 -0
  154. package/node_modules/@waterplane/shared/dist/wire/session.d.ts +1 -1
  155. package/node_modules/@waterplane/shared/dist/wire/telemetry.d.ts +4 -0
  156. package/node_modules/@waterplane/shared/dist/wire/work.d.ts +13 -0
  157. package/node_modules/@waterplane/shared/dist/wire/work.js.map +1 -1
  158. package/npm-shrinkwrap.json +3 -3
  159. package/package.json +2 -2
  160. package/packages/extensions/scorecard/waterplane-plugin.json +10 -0
  161. package/packages/host/dist/agentexposure.d.ts +13 -0
  162. package/packages/host/dist/agentexposure.js +90 -0
  163. package/packages/host/dist/agentexposure.js.map +1 -0
  164. package/packages/host/dist/agentintents.js +2 -2
  165. package/packages/host/dist/agentintents.js.map +1 -1
  166. package/packages/host/dist/agentwatch.d.ts +3 -7
  167. package/packages/host/dist/agentwatch.js.map +1 -1
  168. package/packages/host/dist/alwayson.d.ts +18 -0
  169. package/packages/host/dist/alwayson.js +159 -0
  170. package/packages/host/dist/alwayson.js.map +1 -0
  171. package/packages/host/dist/answergate.d.ts +3 -7
  172. package/packages/host/dist/answergate.js.map +1 -1
  173. package/packages/host/dist/attentionstore.d.ts +61 -0
  174. package/packages/host/dist/attentionstore.js +162 -0
  175. package/packages/host/dist/attentionstore.js.map +1 -0
  176. package/packages/host/dist/backends/claude.js +1 -1
  177. package/packages/host/dist/backends/claude.js.map +1 -1
  178. package/packages/host/dist/backends/derive.js +1 -0
  179. package/packages/host/dist/backends/derive.js.map +1 -1
  180. package/packages/host/dist/backends/registry.js +4 -1
  181. package/packages/host/dist/backends/registry.js.map +1 -1
  182. package/packages/host/dist/backends/types.d.ts +2 -0
  183. package/packages/host/dist/besidespend.d.ts +22 -0
  184. package/packages/host/dist/besidespend.js +65 -0
  185. package/packages/host/dist/besidespend.js.map +1 -0
  186. package/packages/host/dist/boxkit.d.ts +19 -0
  187. package/packages/host/dist/boxkit.js +38 -0
  188. package/packages/host/dist/boxkit.js.map +1 -0
  189. package/packages/host/dist/branchrules.d.ts +14 -0
  190. package/packages/host/dist/branchrules.js +47 -0
  191. package/packages/host/dist/branchrules.js.map +1 -0
  192. package/packages/host/dist/builds.d.ts +31 -1
  193. package/packages/host/dist/builds.js +55 -3
  194. package/packages/host/dist/builds.js.map +1 -1
  195. package/packages/host/dist/buildversions.d.ts +2 -0
  196. package/packages/host/dist/buildversions.js +36 -0
  197. package/packages/host/dist/buildversions.js.map +1 -0
  198. package/packages/host/dist/burnwatch.d.ts +23 -11
  199. package/packages/host/dist/burnwatch.js +51 -2
  200. package/packages/host/dist/burnwatch.js.map +1 -1
  201. package/packages/host/dist/changebrief.d.ts +37 -0
  202. package/packages/host/dist/changebrief.js +157 -0
  203. package/packages/host/dist/changebrief.js.map +1 -0
  204. package/packages/host/dist/cli/index.js +1 -1
  205. package/packages/host/dist/cli/index.js.map +1 -1
  206. package/packages/host/dist/clihealth.d.ts +2 -0
  207. package/packages/host/dist/clihealth.js +11 -2
  208. package/packages/host/dist/clihealth.js.map +1 -1
  209. package/packages/host/dist/compliance.d.ts +5 -1
  210. package/packages/host/dist/compliance.js +70 -31
  211. package/packages/host/dist/compliance.js.map +1 -1
  212. package/packages/host/dist/composer.d.ts +3 -1
  213. package/packages/host/dist/composer.js +3 -1
  214. package/packages/host/dist/composer.js.map +1 -1
  215. package/packages/host/dist/ctxlog/ctxcursor.d.ts +36 -1
  216. package/packages/host/dist/ctxlog/ctxcursor.js +96 -2
  217. package/packages/host/dist/ctxlog/ctxcursor.js.map +1 -1
  218. package/packages/host/dist/ctxlog/ctxproject.js +2 -1
  219. package/packages/host/dist/ctxlog/ctxproject.js.map +1 -1
  220. package/packages/host/dist/ctxlog/ctxupdate.js +13 -2
  221. package/packages/host/dist/ctxlog/ctxupdate.js.map +1 -1
  222. package/packages/host/dist/diskwatch.d.ts +4 -6
  223. package/packages/host/dist/diskwatch.js +3 -1
  224. package/packages/host/dist/diskwatch.js.map +1 -1
  225. package/packages/host/dist/eraseen.d.ts +6 -0
  226. package/packages/host/dist/eraseen.js +100 -0
  227. package/packages/host/dist/eraseen.js.map +1 -0
  228. package/packages/host/dist/exposure.d.ts +56 -0
  229. package/packages/host/dist/exposure.js +371 -0
  230. package/packages/host/dist/exposure.js.map +1 -0
  231. package/packages/host/dist/exposurepush.d.ts +28 -0
  232. package/packages/host/dist/exposurepush.js +136 -0
  233. package/packages/host/dist/exposurepush.js.map +1 -0
  234. package/packages/host/dist/exposurerun.d.ts +18 -0
  235. package/packages/host/dist/exposurerun.js +126 -0
  236. package/packages/host/dist/exposurerun.js.map +1 -0
  237. package/packages/host/dist/exposurewatch.d.ts +29 -0
  238. package/packages/host/dist/exposurewatch.js +127 -0
  239. package/packages/host/dist/exposurewatch.js.map +1 -0
  240. package/packages/host/dist/extensions/scorecard/host/engine.d.mts +54 -0
  241. package/packages/host/dist/extensions/scorecard/host/engine.mjs +303 -0
  242. package/packages/host/dist/extensions/scorecard/host/engine.mjs.map +1 -0
  243. package/packages/host/dist/extensions/scorecard/host/gitslug.d.mts +5 -0
  244. package/packages/host/dist/extensions/scorecard/host/gitslug.mjs +45 -0
  245. package/packages/host/dist/extensions/scorecard/host/gitslug.mjs.map +1 -0
  246. package/packages/host/dist/extensions/scorecard/host/index.d.mts +15 -0
  247. package/packages/host/dist/extensions/scorecard/host/index.mjs +47 -0
  248. package/packages/host/dist/extensions/scorecard/host/index.mjs.map +1 -0
  249. package/packages/host/dist/extensions/scorecard/host/store.d.mts +12 -0
  250. package/packages/host/dist/extensions/scorecard/host/store.mjs +91 -0
  251. package/packages/host/dist/extensions/scorecard/host/store.mjs.map +1 -0
  252. package/packages/host/dist/extensions/scorecard/shared/logic.d.mts +42 -0
  253. package/packages/host/dist/extensions/scorecard/shared/logic.mjs +170 -0
  254. package/packages/host/dist/extensions/scorecard/shared/logic.mjs.map +1 -0
  255. package/packages/host/dist/extensions/scorecard/shared/wire.d.mts +140 -0
  256. package/packages/host/dist/extensions/scorecard/shared/wire.mjs +29 -0
  257. package/packages/host/dist/extensions/scorecard/shared/wire.mjs.map +1 -0
  258. package/packages/host/dist/forge/github.d.ts +3 -0
  259. package/packages/host/dist/forge/github.js +82 -0
  260. package/packages/host/dist/forge/github.js.map +1 -0
  261. package/packages/host/dist/forge/index.d.ts +14 -0
  262. package/packages/host/dist/forge/index.js +32 -0
  263. package/packages/host/dist/forge/index.js.map +1 -0
  264. package/packages/host/dist/forge/types.d.ts +52 -0
  265. package/packages/host/dist/forge/types.js +2 -0
  266. package/packages/host/dist/forge/types.js.map +1 -0
  267. package/packages/host/dist/git.d.ts +36 -3
  268. package/packages/host/dist/git.js +119 -41
  269. package/packages/host/dist/git.js.map +1 -1
  270. package/packages/host/dist/gitnotify.d.ts +24 -0
  271. package/packages/host/dist/gitnotify.js +60 -0
  272. package/packages/host/dist/gitnotify.js.map +1 -0
  273. package/packages/host/dist/healthwatch.d.ts +2 -1
  274. package/packages/host/dist/healthwatch.js +4 -2
  275. package/packages/host/dist/healthwatch.js.map +1 -1
  276. package/packages/host/dist/intents/adapters.js +45 -14
  277. package/packages/host/dist/intents/adapters.js.map +1 -1
  278. package/packages/host/dist/intents/contract.d.ts +4 -0
  279. package/packages/host/dist/intents/contract.js.map +1 -1
  280. package/packages/host/dist/intents/fire.js +7 -1
  281. package/packages/host/dist/intents/fire.js.map +1 -1
  282. package/packages/host/dist/intents/manager.d.ts +3 -3
  283. package/packages/host/dist/intents/manager.js +2 -2
  284. package/packages/host/dist/intents/manager.js.map +1 -1
  285. package/packages/host/dist/intents/watch.d.ts +10 -2
  286. package/packages/host/dist/intents/watch.js +27 -2
  287. package/packages/host/dist/intents/watch.js.map +1 -1
  288. package/packages/host/dist/localcistatus.d.ts +22 -0
  289. package/packages/host/dist/localcistatus.js +105 -0
  290. package/packages/host/dist/localcistatus.js.map +1 -0
  291. package/packages/host/dist/main.js +40 -10
  292. package/packages/host/dist/main.js.map +1 -1
  293. package/packages/host/dist/net.d.ts +2 -0
  294. package/packages/host/dist/net.js +11 -2
  295. package/packages/host/dist/net.js.map +1 -1
  296. package/packages/host/dist/netlog.d.ts +40 -0
  297. package/packages/host/dist/netlog.js +165 -0
  298. package/packages/host/dist/netlog.js.map +1 -0
  299. package/packages/host/dist/netretrycfg.d.ts +7 -0
  300. package/packages/host/dist/netretrycfg.js +51 -0
  301. package/packages/host/dist/netretrycfg.js.map +1 -0
  302. package/packages/host/dist/notifyprefs.d.ts +6 -2
  303. package/packages/host/dist/notifyprefs.js +20 -5
  304. package/packages/host/dist/notifyprefs.js.map +1 -1
  305. package/packages/host/dist/notifytypes.d.ts +58 -0
  306. package/packages/host/dist/notifytypes.js +2 -0
  307. package/packages/host/dist/notifytypes.js.map +1 -0
  308. package/packages/host/dist/opendeliveries.js +24 -0
  309. package/packages/host/dist/opendeliveries.js.map +1 -1
  310. package/packages/host/dist/optins.d.ts +28 -1
  311. package/packages/host/dist/optins.js +96 -4
  312. package/packages/host/dist/optins.js.map +1 -1
  313. package/packages/host/dist/peers/agentpeer.js +1 -1
  314. package/packages/host/dist/peers/agentpeer.js.map +1 -1
  315. package/packages/host/dist/peers/jobs.d.ts +2 -4
  316. package/packages/host/dist/peers/jobs.js +6 -1
  317. package/packages/host/dist/peers/jobs.js.map +1 -1
  318. package/packages/host/dist/plugins/pluginapi.js +2 -0
  319. package/packages/host/dist/plugins/pluginapi.js.map +1 -1
  320. package/packages/host/dist/plugins/pluginregistry.d.ts +3 -8
  321. package/packages/host/dist/plugins/pluginregistry.js +1 -1
  322. package/packages/host/dist/plugins/pluginregistry.js.map +1 -1
  323. package/packages/host/dist/protectmain.d.ts +35 -0
  324. package/packages/host/dist/protectmain.js +73 -0
  325. package/packages/host/dist/protectmain.js.map +1 -0
  326. package/packages/host/dist/prpush.d.ts +30 -0
  327. package/packages/host/dist/prpush.js +171 -0
  328. package/packages/host/dist/prpush.js.map +1 -0
  329. package/packages/host/dist/prs.d.ts +70 -0
  330. package/packages/host/dist/prs.js +328 -0
  331. package/packages/host/dist/prs.js.map +1 -0
  332. package/packages/host/dist/push.d.ts +19 -0
  333. package/packages/host/dist/push.js.map +1 -1
  334. package/packages/host/dist/render.d.ts +57 -0
  335. package/packages/host/dist/render.js +57 -39
  336. package/packages/host/dist/render.js.map +1 -1
  337. package/packages/host/dist/repohealth.js +5 -2
  338. package/packages/host/dist/repohealth.js.map +1 -1
  339. package/packages/host/dist/repohealthapproval.d.ts +3 -0
  340. package/packages/host/dist/repohealthapproval.js +92 -2
  341. package/packages/host/dist/repohealthapproval.js.map +1 -1
  342. package/packages/host/dist/repos.js +7 -1
  343. package/packages/host/dist/repos.js.map +1 -1
  344. package/packages/host/dist/reposkill.d.ts +8 -5
  345. package/packages/host/dist/reposkill.js +16 -11
  346. package/packages/host/dist/reposkill.js.map +1 -1
  347. package/packages/host/dist/reposkilltext.d.ts +8 -1
  348. package/packages/host/dist/reposkilltext.js +72 -3
  349. package/packages/host/dist/reposkilltext.js.map +1 -1
  350. package/packages/host/dist/routes/apihost.js +26 -2
  351. package/packages/host/dist/routes/apihost.js.map +1 -1
  352. package/packages/host/dist/routes/apiprs.d.ts +2 -0
  353. package/packages/host/dist/routes/apiprs.js +45 -0
  354. package/packages/host/dist/routes/apiprs.js.map +1 -0
  355. package/packages/host/dist/routes/apirepofiles.js +12 -1
  356. package/packages/host/dist/routes/apirepofiles.js.map +1 -1
  357. package/packages/host/dist/routes/apirepowork.js +48 -24
  358. package/packages/host/dist/routes/apirepowork.js.map +1 -1
  359. package/packages/host/dist/routes/apiroutes.js +2 -1
  360. package/packages/host/dist/routes/apiroutes.js.map +1 -1
  361. package/packages/host/dist/routes/apisession.js +24 -0
  362. package/packages/host/dist/routes/apisession.js.map +1 -1
  363. package/packages/host/dist/routes/apistats.js +12 -7
  364. package/packages/host/dist/routes/apistats.js.map +1 -1
  365. package/packages/host/dist/routes/apisystem.js +23 -1
  366. package/packages/host/dist/routes/apisystem.js.map +1 -1
  367. package/packages/host/dist/routes/apitable.d.ts +10 -0
  368. package/packages/host/dist/routes/apitable.js.map +1 -1
  369. package/packages/host/dist/routes/apiweekburn.d.ts +2 -0
  370. package/packages/host/dist/routes/apiweekburn.js +30 -0
  371. package/packages/host/dist/routes/apiweekburn.js.map +1 -0
  372. package/packages/host/dist/routes/session.js +4 -0
  373. package/packages/host/dist/routes/session.js.map +1 -1
  374. package/packages/host/dist/routes/system.js +33 -6
  375. package/packages/host/dist/routes/system.js.map +1 -1
  376. package/packages/host/dist/routes/types.d.ts +29 -21
  377. package/packages/host/dist/routes/work/workbuild.js +3 -2
  378. package/packages/host/dist/routes/work/workbuild.js.map +1 -1
  379. package/packages/host/dist/routes/work/workschedule.js +33 -3
  380. package/packages/host/dist/routes/work/workschedule.js.map +1 -1
  381. package/packages/host/dist/screenlog.d.ts +20 -0
  382. package/packages/host/dist/screenlog.js +40 -0
  383. package/packages/host/dist/screenlog.js.map +1 -1
  384. package/packages/host/dist/server/clients.d.ts +14 -24
  385. package/packages/host/dist/server/clients.js +77 -11
  386. package/packages/host/dist/server/clients.js.map +1 -1
  387. package/packages/host/dist/server/ctx.d.ts +2 -0
  388. package/packages/host/dist/server/ctxseal.d.ts +1 -1
  389. package/packages/host/dist/server/ctxseal.js +6 -6
  390. package/packages/host/dist/server/ctxseal.js.map +1 -1
  391. package/packages/host/dist/server/deliveries.js +4 -2
  392. package/packages/host/dist/server/deliveries.js.map +1 -1
  393. package/packages/host/dist/server/http.js +2 -2
  394. package/packages/host/dist/server/http.js.map +1 -1
  395. package/packages/host/dist/server/intentDeps.js +4 -1
  396. package/packages/host/dist/server/intentDeps.js.map +1 -1
  397. package/packages/host/dist/server/intentEvents.js +9 -4
  398. package/packages/host/dist/server/intentEvents.js.map +1 -1
  399. package/packages/host/dist/server/scan.js +23 -1
  400. package/packages/host/dist/server/scan.js.map +1 -1
  401. package/packages/host/dist/server/sessionEvents.js +37 -10
  402. package/packages/host/dist/server/sessionEvents.js.map +1 -1
  403. package/packages/host/dist/sessions/agentpoll.d.ts +31 -0
  404. package/packages/host/dist/sessions/agentpoll.js +176 -0
  405. package/packages/host/dist/sessions/agentpoll.js.map +1 -0
  406. package/packages/host/dist/sessions/apiretry.d.ts +59 -0
  407. package/packages/host/dist/sessions/apiretry.js +240 -0
  408. package/packages/host/dist/sessions/apiretry.js.map +1 -0
  409. package/packages/host/dist/sessions/askwatch.d.ts +62 -0
  410. package/packages/host/dist/sessions/askwatch.js +169 -0
  411. package/packages/host/dist/sessions/askwatch.js.map +1 -0
  412. package/packages/host/dist/sessions/boxes.d.ts +2 -23
  413. package/packages/host/dist/sessions/boxes.js +10 -664
  414. package/packages/host/dist/sessions/boxes.js.map +1 -1
  415. package/packages/host/dist/sessions/boxread.d.ts +47 -0
  416. package/packages/host/dist/sessions/boxread.js +628 -0
  417. package/packages/host/dist/sessions/boxread.js.map +1 -0
  418. package/packages/host/dist/sessions/core.d.ts +16 -1
  419. package/packages/host/dist/sessions/ctxseries.js +3 -0
  420. package/packages/host/dist/sessions/ctxseries.js.map +1 -1
  421. package/packages/host/dist/sessions/drive.d.ts +20 -6
  422. package/packages/host/dist/sessions/drive.js +43 -8
  423. package/packages/host/dist/sessions/drive.js.map +1 -1
  424. package/packages/host/dist/sessions/knobs.d.ts +8 -0
  425. package/packages/host/dist/sessions/knobs.js +9 -0
  426. package/packages/host/dist/sessions/knobs.js.map +1 -1
  427. package/packages/host/dist/sessions/record.js +7 -2
  428. package/packages/host/dist/sessions/record.js.map +1 -1
  429. package/packages/host/dist/sessions/resume.d.ts +17 -0
  430. package/packages/host/dist/sessions/resume.js +65 -11
  431. package/packages/host/dist/sessions/resume.js.map +1 -1
  432. package/packages/host/dist/sessions/roster.js +3 -0
  433. package/packages/host/dist/sessions/roster.js.map +1 -1
  434. package/packages/host/dist/sessions/sidechannel.d.ts +1 -1
  435. package/packages/host/dist/sessions/sidechannel.js +2 -2
  436. package/packages/host/dist/sessions/turn.d.ts +15 -58
  437. package/packages/host/dist/sessions/turn.js +17 -356
  438. package/packages/host/dist/sessions/turn.js.map +1 -1
  439. package/packages/host/dist/sessions.d.ts +7 -1
  440. package/packages/host/dist/sessions.js +22 -13
  441. package/packages/host/dist/sessions.js.map +1 -1
  442. package/packages/host/dist/settle.d.ts +6 -0
  443. package/packages/host/dist/settle.js +26 -21
  444. package/packages/host/dist/settle.js.map +1 -1
  445. package/packages/host/dist/setupprefs.d.ts +26 -1
  446. package/packages/host/dist/setupprefs.js +49 -1
  447. package/packages/host/dist/setupprefs.js.map +1 -1
  448. package/packages/host/dist/sidecar/sidecarname.d.ts +2 -0
  449. package/packages/host/dist/sidecar/sidecarname.js +5 -1
  450. package/packages/host/dist/sidecar/sidecarname.js.map +1 -1
  451. package/packages/host/dist/sidecar/sidecarroute.d.ts +1 -1
  452. package/packages/host/dist/sidecar/sidecarroute.js +5 -0
  453. package/packages/host/dist/sidecar/sidecarroute.js.map +1 -1
  454. package/packages/host/dist/sidecar.d.ts +1 -1
  455. package/packages/host/dist/sidecar.js +1 -1
  456. package/packages/host/dist/sidecar.js.map +1 -1
  457. package/packages/host/dist/tokenscan.d.ts +4 -0
  458. package/packages/host/dist/tokenscan.js +6 -1
  459. package/packages/host/dist/tokenscan.js.map +1 -1
  460. package/packages/host/dist/tokenstats.js +3 -1
  461. package/packages/host/dist/tokenstats.js.map +1 -1
  462. package/packages/host/dist/transcript/transcriptparse.js +6 -1
  463. package/packages/host/dist/transcript/transcriptparse.js.map +1 -1
  464. package/packages/host/dist/transcript/transcriptturns.d.ts +29 -0
  465. package/packages/host/dist/transcript/transcriptturns.js +27 -0
  466. package/packages/host/dist/transcript/transcriptturns.js.map +1 -1
  467. package/packages/host/dist/transcript.d.ts +1 -1
  468. package/packages/host/dist/transcript.js +1 -1
  469. package/packages/host/dist/transcript.js.map +1 -1
  470. package/packages/host/dist/usagesources.d.ts +1 -1
  471. package/packages/host/dist/usagesources.js +7 -2
  472. package/packages/host/dist/usagesources.js.map +1 -1
  473. package/packages/host/dist/weekburn.d.ts +75 -0
  474. package/packages/host/dist/weekburn.js +251 -0
  475. package/packages/host/dist/weekburn.js.map +1 -0
  476. package/packages/host/dist/worktreeleftover.d.ts +9 -0
  477. package/packages/host/dist/worktreeleftover.js +17 -1
  478. package/packages/host/dist/worktreeleftover.js.map +1 -1
  479. package/packages/web/dist/assets/demo-C1GHaeTv.js +23 -0
  480. package/packages/web/dist/assets/icons-DlcvcZoo.js +1 -0
  481. package/packages/web/dist/assets/index-BBc6xwDA.css +1 -0
  482. package/packages/web/dist/assets/index-DzQKnksZ.js +169 -0
  483. package/packages/web/dist/assets/shared-Cl34umPA.js +47 -0
  484. package/packages/web/dist/assets/{sheets-Bjv2L-cG.css → sheets-DoUhPGK0.css} +1 -1
  485. package/packages/web/dist/assets/sheets-_3_SvXAx.js +220 -0
  486. package/packages/web/dist/build-id.txt +1 -1
  487. package/packages/web/dist/buildstamp.json +1 -0
  488. package/packages/web/dist/index.html +7 -7
  489. package/packages/web/dist/sw.js +14 -3
  490. package/release.json +7 -4
  491. package/packages/web/dist/assets/demo-CXlqlYE4.js +0 -23
  492. package/packages/web/dist/assets/icons-BbqDBVjw.js +0 -1
  493. package/packages/web/dist/assets/index-CgPoyb3Y.css +0 -1
  494. package/packages/web/dist/assets/index-D5JKj8DK.js +0 -169
  495. package/packages/web/dist/assets/shared-eyaskl5l.js +0 -47
  496. package/packages/web/dist/assets/sheets-BzzL2re1.js +0 -204
@@ -1,403 +1,18 @@
1
1
  /**
2
- * The choice box: when to look for one, reading it off the rendered screen
3
- * (claude's numbered box and opencode's highlighted row), publishing it, the
4
- * "unparsable dialog" fallback flag, the sign-in link that rides on the same
5
- * render, and the two answer walks that place a selection before pressing
6
- * Return. Stateless — every per-session fact lives on the `Session` record.
7
- * Reasoning: `waterplane-heuristics` (`prompt.ts`, `ocprompt.ts`, `askbox.ts`,
8
- * `login.ts`) and docs/notes/host-architecture.md.
2
+ * The choice box, ANSWERED: the one answer dispatcher (`answerBox`), the two
3
+ * walks that place a selection before pressing Return (`choosePromptBox`,
4
+ * `chooseClaudeNavBox`) and the checkbox Submit row (`submitPromptBox`).
5
+ * Reading and publishing the box is `boxread.ts`. Stateless — every per-session
6
+ * fact lives on the `Session` record.
9
7
  */
10
8
  import { answerTextProblem } from "@waterplane/shared";
11
9
  import { answerSourcePlan, applySourceReply } from "../sourceanswer.js";
12
- export { sourceKeysProblem } from "../sourceanswer.js";
13
10
  import { screenReaderFor } from "../backends/readers.js";
14
11
  import { derive } from "../backends/derive.js";
15
- import { detectPrompt, dialogStillUp, dialogEvidence, hasDialogFooter, isDialogFooterRow, MAX_BOX_OPTIONS, mergeBox, navToSubmit, readNavBox, sameBox, samePrompt, stripAnsi } from "../prompt.js";
16
- import { asksFromCall, descFor, pendingAskQuestions, pendingAskRecord, pickAsk, recoverHead } from "../askbox.js";
17
- import { isPlanBox, planPathFor, readPlan } from "../planbox.js";
18
- import { detectLimitText, STOP_WAIT_RE } from "../limit.js";
19
- import { detectLogin, loginCandidate, sameLogin } from "../login.js";
20
- import { logMtime, transcriptPath } from "../transcript.js";
21
- import { recordSent } from "../sentlog.js";
12
+ import { navToSubmit, readNavBox } from "../prompt.js";
22
13
  import { rememberRule, sessionAskRules } from "../answergate.js";
23
- import { PROMPT_CHECK_MS, PROMPT_MAX_STALE_MS, PROMPT_MISS_MAX, PROMPT_SETTLE_MS, RESIZE_REPAINT_MS, PROMPT_GATE_BYTES, SUBMIT_NAV_TRIES, SUBMIT_NAV_MAX_KEYS, SUBMIT_NAV_LINES, SUBMIT_NAV_SETTLE_MS, CHOOSE_NAV_TRIES, CHOOSE_NAV_SETTLE_MS, PROMPT_CELL_ROWS, IDLE_PING_MS, HEALTH_SAMPLE_ROWS, } from "./knobs.js";
24
- /**
25
- * The tail of a screen ending at the row a matcher was looking for.
26
- *
27
- * Anchored on the MATCHED row rather than sliced off the bottom, for the same
28
- * reason `deliver.ts` places its echo instead of taking the last N rows: the
29
- * bottom of a claude screen is the composer and the working line, and a sample
30
- * that shows those says nothing about the box above them.
31
- */
32
- /** How long the `askbox.enrich` fixture waits for the log to write the call: 2 min. */
33
- const ASK_RECORD_POLLS = 60;
34
- const ASK_RECORD_POLL_MS = 2_000;
35
- function healthTail(screen, anchor) {
36
- const rows = screen.split("\n");
37
- let hit = -1;
38
- for (let i = rows.length - 1; i >= 0; i--)
39
- if (anchor(rows[i])) {
40
- hit = i;
41
- break;
42
- }
43
- if (hit < 0)
44
- hit = rows.length - 1;
45
- return rows.slice(Math.max(0, hit - HEALTH_SAMPLE_ROWS + 1), hit + 1).join("\n");
46
- }
47
- export function scheduleChecks(core, s) {
48
- if (s.idleTimer)
49
- clearTimeout(s.idleTimer);
50
- s.idleTimer = setTimeout(() => core.checkIdle(s), IDLE_PING_MS);
51
- // Output on a hooked session with no turn in flight: the hooks say nothing
52
- // is running, and the CLI may be working anyway (`/compact` announces
53
- // nothing, and a `Stop` a hook blocked leaves the turn going). One armed
54
- // timer, never restarted while a pass is already pending, and it costs a
55
- // regex over ONE repaint — see `checkTurnWatch`. A session with a turn the
56
- // hooks DO own is left to them.
57
- // Not while a backend's own channel reports EXACT turns: those boundaries are
58
- // exact by definition, and `workingLine` is claude's working line — pointed
59
- // at another TUI it could only ever match something else. A channel whose
60
- // ends are requests (`verifyEnds`: claude's hook pipe) keeps the watch.
61
- const exactTurns = !!s.channel?.turnsLive && !s.backend.sources?.turns?.verifyEnds;
62
- if (s.hooksActive && !exactTurns && !s.stopVerifyTimer && !s.turnActive)
63
- core.armTurnWatch(s);
64
- // The prompt check is a debounce with a CEILING. A pure debounce never fires
65
- // while a box is up — the TUI repaints its working line every second or so,
66
- // and each repaint pushed the check out again — which is exactly the state
67
- // that needs publishing. `PROMPT_MAX_STALE_MS` since the last check that
68
- // actually ran wins over the quiet window, so a repaint storm delays
69
- // verification by a bounded amount instead of for ever.
70
- // Measured from the start of THIS burst when the last check is older than the
71
- // ceiling itself: after a quiet spell the ceiling has long expired, and taking
72
- // it at face value fired the check at 0 ms on the burst's FIRST chunk — the
73
- // first chunk of a box tmux is still painting. (`readTwice` is what keeps a
74
- // half-painted read from being published; this only stops buying it.)
75
- const now = Date.now();
76
- const since = s.promptTimer || now - s.lastPromptCheckAt < PROMPT_MAX_STALE_MS ? s.lastPromptCheckAt : now;
77
- const ceiling = since + PROMPT_MAX_STALE_MS - now;
78
- armPromptCheck(core, s, Math.max(0, Math.min(PROMPT_CHECK_MS, ceiling)));
79
- // A shell's links and codes (`shelllinks.ts`) on the same quiet tick; a
80
- // session with turns never pays for that read.
81
- if (s.backend.caps.turns === false)
82
- core.armLinksCheck(s);
83
- }
84
- /** Arm the prompt check, EARLIEST-wins: a later caller may pull the check
85
- * forward but never push a pending one back (that is what made the debounce
86
- * starve under constant output). */
87
- export function armPromptCheck(core, s, delayMs) {
88
- const due = Date.now() + delayMs;
89
- if (s.promptTimer && s.promptDueAt <= due)
90
- return;
91
- if (s.promptTimer)
92
- clearTimeout(s.promptTimer);
93
- s.promptDueAt = due;
94
- s.promptTimer = setTimeout(() => { s.promptTimer = null; checkPrompt(core, s); }, delayMs);
95
- }
96
- /**
97
- * Prompt detection runs in two stages. The cheap stage scans an ANSI-stripped
98
- * byte window — fast enough for a per-quiet-period check, but a repaint-based
99
- * TUI makes that window a shuffled, hole-punched approximation of the screen
100
- * (fragments joined across cursor jumps, words missing letters). So a hit is
101
- * only a CANDIDATE: it is re-detected against the RENDERED screen (headless VT
102
- * replay, what a user actually sees) and that result is what we publish. The
103
- * render is the expensive part, hence the gate — no candidate, no replay.
104
- *
105
- * Before this, garbled repaint fragments were surfaced verbatim as one-tap
106
- * option labels, and phantom prompts flickered in and out mid-answer.
107
- */
108
- function checkPrompt(core, s) {
109
- if (!s.info.running)
110
- return;
111
- // A backend whose TUI draws no box this detector can read is a backend this
112
- // check has nothing to say about. Not armed at all, rather than armed and
113
- // publishing null: the strict stage costs a full VT replay per quiet period,
114
- // and — the part that matters more — the only way a claude-shaped rule can
115
- // "match" a screen it was never written for is by matching something else.
116
- // The sign-in link rides on this same render, which is the right place for
117
- // it too: a claude account's sign-in screen is not a fact about a binary
118
- // that has no claude account.
119
- const reader = derive(s.backend).screen("dialogs");
120
- if (!reader)
121
- return;
122
- // The CLI's own channel is posing the dialogs: the screen reader stands down,
123
- // because two readers on one box re-key its fingerprint (a card re-opened, a
124
- // queued answer stale, a push). It comes back the moment the channel goes
125
- // down (`sidechannel.ts`), and it also stays off for a box the channel
126
- // published before it finished reconciling.
127
- if (screenReaderOff(s))
128
- return;
129
- // Named readers, not a boolean: `prompt.ts`'s rules are claude's screen and
130
- // nothing else, so a second TUI gets its own reader rather than a looser
131
- // version of this one. See `backends/types.ts`.
132
- // A reader a plugin contributed (`backends/readers.ts`) — opencode's, for one.
133
- const nav = screenReaderFor(s.backend);
134
- if (nav) {
135
- checkNavBox(core, s, nav);
136
- return;
137
- }
138
- if (reader !== "claude-numbered")
139
- return; // a contributed name whose plugin left: no reader, no box
140
- // A pane in copy-mode is showing HISTORY, not the live screen: the rendered
141
- // grid is wherever the user panned to, so an answered box scrolled back into
142
- // view would be re-detected as live — an approve bar over a dialog that no
143
- // longer exists, and an `awaitingInput` interlock on a session that is fine.
144
- // The pane is unchanged underneath; the next check after the pan back down
145
- // reads it. (`tmuxscroll.ts`.)
146
- if (s.copyMode)
147
- return;
148
- s.lastPromptCheckAt = Date.now();
149
- // Cheap stage runs LENIENT: the "❯" cursor and the Enter/Esc footer each sit
150
- // on their own row, and a repaint can leave them outside the byte window while
151
- // the option rows sit inside it. Demanding them here would drop a real prompt
152
- // before it ever reached the render — no approve bar, no push. Strictness
153
- // belongs on the rendered screen below, which is what gets published.
154
- // A dialog we could NOT parse is still a blocked session, and the reader view
155
- // has no terminal to notice it in — so the render is also paid for when the
156
- // tail merely carries a box FOOTER, and an unparsable box publishes the
157
- // weaker `awaitingInput` signal ("open the CLI") instead of nothing at all.
158
- // "esc to interrupt" is deliberately not in DIALOG_FOOTER_RE: that is the
159
- // TUI's working line, i.e. every busy session, i.e. a render per check.
160
- // The window is a few repaints wide, not one: this TUI redraws a full screen
161
- // in ~3 KB, and the footer is not the LAST thing it draws — a box whose
162
- // preview pane was painted after it fell outside a one-frame window entirely.
163
- // A regex over 12 KB every 600 ms of quiet costs nothing; missing the gate
164
- // costs the whole feature. Stale bytes here only buy a render whose STRICT
165
- // pass then publishes null, so a wide gate can't invent a phantom prompt.
166
- const rawTail = s.scrollback.slice(-PROMPT_GATE_BYTES);
167
- const tail = stripAnsi(rawTail);
168
- const candidate = !!detectPrompt(rawTail, { lenient: true });
169
- // A gate miss retires a prompt only when there is no PUBLISHED box to lose.
170
- //
171
- // "Only the strict verifier clears it" is the rule the miss counter below
172
- // exists to enforce, and this exit sat outside it. The gate reads a fixed
173
- // byte WINDOW, so a box whose own frame is a large fraction of that window —
174
- // six options with a wrapped description each — plus the repaints that follow
175
- // can push the footer out of view while the box is plainly still on screen,
176
- // and the panel vanished with no misses spent. With a box published we fall
177
- // through to the render and let the strict pass decide instead; a box that is
178
- // genuinely gone leaves a screen carrying no dialog footer, which clears it on
179
- // that same pass with no added latency.
180
- // A sign-in link opens the gate on its own shape: claude 2.1.293's sign-in
181
- // screen draws no dialog footer (`login.ts`'s `loginCandidate`).
182
- if (!candidate && !hasDialogFooter(tail) && !s.info.prompt && !s.info.login && !loginCandidate(rawTail, tail)) {
183
- s.promptGen++; // invalidates any render still in flight — the box is gone
184
- s.promptMisses = 0;
185
- s.promptPending = null;
186
- applyPrompt(core, s, null);
187
- setAwaiting(core, s, false);
188
- return;
189
- }
190
- if (s.promptRendering)
191
- return;
192
- s.promptRendering = true;
193
- const gen = s.promptGen;
194
- void core.screenText(s.info.id, 60)
195
- .then((screen) => {
196
- if (!s.info.running || s.promptGen !== gen)
197
- return;
198
- // The sign-in link rides on THIS render rather than paying for one of
199
- // its own: the gate above opens on the link's shape (`loginCandidate`),
200
- // so the replay is bought every time there is a link to find.
201
- applyLogin(core, s, detectLogin(screen, s.scrollback));
202
- const parsed = detectPrompt(screen);
203
- if (parsed) {
204
- s.promptMisses = 0;
205
- // One box stays ONE box while the TUI repaints under it. The strict
206
- // pass runs about twice a second and reads whatever is legible right
207
- // now — which the console refreshing itself, a pan, or a box taller
208
- // than the terminal all change — so a live question was re-published
209
- // several times a minute under a new fingerprint. That re-opened a
210
- // card the user had collapsed or hidden to answer at the desk, made
211
- // queued answers stale and fired a push per repaint. `sameBox` /
212
- // `mergeBox` in `prompt.ts` carry the reasoning; a box that is
213
- // genuinely different is published as itself.
214
- // The commit row's own word, off this same render — "Submit" on the
215
- // last question of an ask, "Next" on every one before it.
216
- const commit = parsed.multi ? navToSubmit(screen) : null;
217
- const read = commit ? { ...parsed, submitLabel: commit.label } : parsed;
218
- // Enriched BEFORE the comparison, not after: the enrichment is what
219
- // carries `askId`, and that is the only handle `sameBox` can trust on
220
- // the boxes that actually move.
221
- const fresh = enrichPrompt(s, read);
222
- const live = s.info.prompt;
223
- const next = live && sameBox(live, fresh) ? mergeBox(live, fresh) : fresh;
224
- // A box that is NEW, or that would change the published one, waits for
225
- // a second read that agrees — see `readTwice`. The published box (if
226
- // any) stays as it is meanwhile.
227
- if (samePrompt(next, live ?? null))
228
- s.promptPending = null;
229
- else if (!readTwice(s, read)) {
230
- armPromptCheck(core, s, PROMPT_SETTLE_MS);
231
- return;
232
- }
233
- applyPrompt(core, s, next);
234
- setAwaiting(core, s, false);
235
- return;
236
- }
237
- // Nothing parsed — but a capture taken mid-repaint is a HALF-DRAWN box:
238
- // the option rows are there and the cursor row (or a label, or the
239
- // footer) is not yet redrawn. Publishing null on that is what made a
240
- // live dialog blink: the panel unmounted, the next capture parsed it
241
- // again, and around it went, about once a second. So while the screen
242
- // still carries a dialog footer, keep the box we already published and
243
- // count the miss; a box that is genuinely gone runs the counter out (or
244
- // takes the cheap gate's exit above, which needs no misses at all).
245
- // `dialogStillUp`, not merely "a footer is somewhere on this screen".
246
- // This CLI scrolls rather than repainting an alt screen, so an answered
247
- // box stays in the rendered tail for as long as the conversation takes
248
- // to push it out — and the loose test read that corpse as a live
249
- // question, which both kept the retired box published for its full miss
250
- // budget and raised `awaitingInput` on a session sitting at an idle
251
- // composer.
252
- s.promptPending = null; // agreement is between CONSECUTIVE reads
253
- const dialog = dialogStillUp(screen);
254
- /**
255
- * **A repaint WE asked for is not evidence the box is gone.**
256
- *
257
- * The phone's answer panel takes its space from the terminal, so
258
- * publishing a box shrinks the grid, which reports new rows, which is a
259
- * SIGWINCH, which makes this TUI clear and redraw everything. The
260
- * captures taken across that redraw are half-drawn — and they were being
261
- * counted as misses, three of them at `PROMPT_CHECK_MS` apart retired the
262
- * box, the panel unmounted, the grid grew back, another SIGWINCH, the box
263
- * parsed again, and the panel came back. A ~2 Hz blink that made a live
264
- * question unanswerable, and every part of it correct in isolation.
265
- *
266
- * The miss budget is for a screen we happened to catch mid-repaint. This
267
- * is a screen we KNOW is mid-repaint, because we are the ones who asked
268
- * for it — so it costs nothing and we simply look again. `dialogStillUp`
269
- * still gates it: a box genuinely gone during a resize leaves a screen
270
- * with no footer and is retired on this same pass, exactly as before.
271
- */
272
- if (s.info.prompt && dialog && Date.now() - s.lastResizeAt < RESIZE_REPAINT_MS) {
273
- armPromptCheck(core, s, PROMPT_CHECK_MS);
274
- return;
275
- }
276
- if (s.info.prompt && dialog && s.promptMisses < PROMPT_MISS_MAX) {
277
- s.promptMisses++;
278
- // Re-arm ourselves: checks are otherwise driven by output, and a box
279
- // that was answered at the DESK leaves a quiet screen behind — the
280
- // retained prompt would then never be re-verified at all.
281
- armPromptCheck(core, s, PROMPT_CHECK_MS);
282
- return;
283
- }
284
- s.promptMisses = 0;
285
- applyPrompt(core, s, null);
286
- setAwaiting(core, s, dialog, screen);
287
- })
288
- .catch(() => { })
289
- .finally(() => { s.promptRendering = false; });
290
- }
291
- /**
292
- * Has the screen read this box TWICE IN A ROW? A box is published only then.
293
- *
294
- * tmux hands its client a screen in CHUNKS, so a render taken between two of
295
- * them is a box painted down to some row and no further: options missing, the
296
- * last label cut mid-word ("Yes, and don't a"), the question short. With a
297
- * selection cursor on row 1 that half PARSES — strictly, correctly, as what is
298
- * legible — and publishing it is publishing a wrong box: the cut label is a
299
- * one-tap button, it is in `promptFingerprint`, and `mergeBox` never rewrites a
300
- * published label, so the cut stayed for the life of the box. Measured on the
301
- * first box of a session, where the paint follows a quiet spell and the check
302
- * fired on its first chunk (`scheduleChecks`'s ceiling), but nothing about it
303
- * is specific to the first.
304
- *
305
- * Nothing on a half-painted screen says it is half-painted, so completeness is
306
- * asked of TIME instead: two consecutive strict reads, `PROMPT_SETTLE_MS`
307
- * apart, that agree field for field (`samePrompt`, on the screen's own read
308
- * BEFORE enrichment — the log is not what is being proved). A read that
309
- * disagrees becomes the new candidate; any pass that reads no box clears it.
310
- * Costs one extra render and ~`PROMPT_SETTLE_MS` on a box's first appearance,
311
- * and nothing while it sits unchanged. Degrades to publishing nothing yet,
312
- * never to a box nobody drew.
313
- */
314
- function readTwice(s, read) {
315
- const agreed = !!s.promptPending && samePrompt(s.promptPending, read);
316
- s.promptPending = agreed ? null : read;
317
- return agreed;
318
- }
319
- /** A settle between a walk's keystroke and its re-read — the box walks' one wait. */
320
- const pause = (ms) => new Promise((r) => setTimeout(r, ms));
321
- /** A contributed reader's answer, or `fallback` when it threw: a throw reads as "no box". */
322
- function safe(fn, fallback) {
323
- try {
324
- return fn();
325
- }
326
- catch {
327
- return fallback;
328
- }
329
- }
330
- /**
331
- * The same two-stage check, for a TUI that draws its dialog a different way.
332
- *
333
- * Separate from `checkPrompt()` rather than a branch inside it, because the
334
- * two share the SHAPE (cheap byte gate → expensive replay → publish, with a
335
- * miss budget so a half-drawn repaint cannot retire a live box) and not one
336
- * single rule: opencode (the first such TUI) has no numbered rows, no `❯`, no
337
- * "Enter to confirm" footer and no scrollback, and every one of `prompt.ts`'s defences is written
338
- * against one of those. Folding them together would mean loosening rules that
339
- * exist because of a measured failure on the other screen.
340
- *
341
- * What it keeps, deliberately, is the blink fix: a box that stops parsing
342
- * while the anchor is still on screen costs a MISS, not a retirement, and a
343
- * repaint the host itself caused by publishing the box (the answer panel takes
344
- * its space from the terminal, which resizes the PTY, which makes the TUI
345
- * redraw) costs nothing at all.
346
- */
347
- function checkNavBox(core, s, reader) {
348
- if (s.copyMode)
349
- return;
350
- s.lastPromptCheckAt = Date.now();
351
- const tail = stripAnsi(s.scrollback.slice(-PROMPT_GATE_BYTES));
352
- if (!safe(() => reader.candidate(tail), false)) {
353
- // Nothing that could be a dialog in the window: retire whatever was
354
- // published with no misses spent, exactly as the claude gate does.
355
- s.promptGen++;
356
- s.promptMisses = 0;
357
- applyPrompt(core, s, null);
358
- setAwaiting(core, s, false);
359
- return;
360
- }
361
- if (s.promptRendering)
362
- return;
363
- s.promptRendering = true;
364
- const gen = s.promptGen;
365
- void core.screenCells(s.info.id, PROMPT_CELL_ROWS)
366
- .then((rows) => {
367
- if (!s.info.running || s.promptGen !== gen)
368
- return;
369
- const box = safe(() => reader.read(rows), null);
370
- const prompt = box ? safe(() => reader.prompt(box), null) : null;
371
- if (prompt) {
372
- s.promptMisses = 0;
373
- applyPrompt(core, s, prompt);
374
- setAwaiting(core, s, false);
375
- return;
376
- }
377
- // Unparsed. "Is the dialog still up" is the reader's own question about
378
- // its own TUI; a dialog still drawn spends a miss rather than retiring the box.
379
- const dialog = safe(() => reader.stillUp(rows), false);
380
- if (s.info.prompt && dialog && Date.now() - s.lastResizeAt < RESIZE_REPAINT_MS) {
381
- armPromptCheck(core, s, PROMPT_CHECK_MS);
382
- return;
383
- }
384
- if (s.info.prompt && dialog && s.promptMisses < PROMPT_MISS_MAX) {
385
- s.promptMisses++;
386
- armPromptCheck(core, s, PROMPT_CHECK_MS);
387
- return;
388
- }
389
- s.promptMisses = 0;
390
- applyPrompt(core, s, null);
391
- // A dialog whose ARMED option could not be read is still a blocked
392
- // session, and the phone has no terminal open in the reader view to
393
- // notice it in. `awaitingInput` is the honest signal for it — "something
394
- // is asking; open the CLI" — and it is what the phone renders the
395
- // sentence from rather than greying out a control nobody can explain.
396
- setAwaiting(core, s, dialog);
397
- })
398
- .catch(() => { })
399
- .finally(() => { s.promptRendering = false; });
400
- }
14
+ import { healthTail, pause, safe } from "../boxkit.js";
15
+ import { SUBMIT_NAV_TRIES, SUBMIT_NAV_MAX_KEYS, SUBMIT_NAV_LINES, SUBMIT_NAV_SETTLE_MS, CHOOSE_NAV_TRIES, CHOOSE_NAV_SETTLE_MS, PROMPT_CELL_ROWS, HEALTH_SAMPLE_ROWS } from "./knobs.js";
401
16
  /**
402
17
  * Answer an unnumbered box by placing the selection on the option the user
403
18
  * named, and only then pressing Return.
@@ -500,19 +115,6 @@ async function chooseClaudeNavBox(core, id, choice) {
500
115
  }
501
116
  return core.input(id, "\r") ? { ok: true } : { ok: false, reason: "session not available" };
502
117
  }
503
- /** Is the published box the side channel's, or is the channel reconciled and
504
- * owning every box? Either way the screen has nothing to add. */
505
- export function screenReaderOff(s) {
506
- const ch = s.channel;
507
- if (!ch || ch.closed)
508
- return false;
509
- if (!!ch.published && s.info.prompt?.askId === ch.published)
510
- return true;
511
- // A dialog the channel can see but cannot pose (opencode's `question` tool, whose answer
512
- // route nobody measured) reaches the phone through the screen or not at all: the reader
513
- // keeps its duty — and so does `awaitingInput` behind it — while one is open.
514
- return ch.dialogsLive && !ch.unposed;
515
- }
516
118
  /**
517
119
  * **The one answer dispatcher** — every answer to a choice box goes through
518
120
  * here: the phone's tap (`routes/session.ts`, a digit, a `promptChoice`, typed
@@ -641,263 +243,6 @@ async function answerQuestion(q, choice, text, reply) {
641
243
  }
642
244
  return applySourceReply(r, reply);
643
245
  }
644
- /**
645
- * Put the CLI's OWN words on the box we scraped.
646
- *
647
- * `AskUserQuestion` writes its question and every option's full description
648
- * into the conversation log before anyone answers, and the screen is where
649
- * that text goes to die: descriptions are cut at the right edge and again by
650
- * the preview pane, and a box with six of them is taller than a phone's
651
- * terminal, so the question row is not on screen at all. A one-tap button
652
- * reading "A + B + C" with the paragraph explaining it nowhere on the device
653
- * is a button you cannot honestly press — which is the actual complaint
654
- * behind "I need to see the question".
655
- *
656
- * Enrichment is additive and identity-neutral: `desc`/`ask`/`truncated` are
657
- * outside `promptFingerprint` on purpose, so a description that arrives one
658
- * check late cannot invalidate an answer already queued against the box.
659
- * Matching is by LABEL, never by index — the TUI appends its own rows ("Type
660
- * something.", "Chat about this") after the tool's, and on a truncated box the
661
- * visible run starts above 1.
662
- *
663
- * Cached on the log's mtime: the strict pass runs about twice a second while a
664
- * box is up and the log does not move in that time, so this costs one `stat`
665
- * per check and a tail read per turn.
666
- */
667
- function enrichPrompt(s, p) {
668
- // The health verdict is STASHED, not recorded: this runs on every strict
669
- // pass, about twice a second while a box is up, and `applyPrompt` owns the
670
- // one edge where a box genuinely becomes published. Cleared first, so a
671
- // path that returns early below leaves no stale answer behind for that edge
672
- // to record — "the log could not be asked" is not an observation about the
673
- // matcher.
674
- s.enrich = null;
675
- const cid = s.info.claudeSessionId;
676
- if (!cid)
677
- return p;
678
- // A plan approval is never an `AskUserQuestion`, so it is done and returned
679
- // here: the card gets the plan it is asking about, or nothing extra.
680
- if (isPlanBox(p.ask ?? p.question)) {
681
- const plan = pendingPlanFor(s, cid);
682
- return plan ? { ...p, plan } : p;
683
- }
684
- let asks;
685
- try {
686
- const mtime = logMtime(transcriptPath(s.info.cwd, cid)) ?? 0;
687
- if (s.askCache && s.askCache.mtime === mtime)
688
- asks = s.askCache.asks;
689
- else {
690
- asks = pendingAskQuestions(s.info.cwd, cid);
691
- s.askCache = { mtime, asks };
692
- }
693
- // The log does not hold the call while its box is up on 2.1.304 (it is
694
- // written once answered); the `PreToolUse` hook carried it before the box.
695
- if (!asks.length && s.askHook)
696
- asks = asksFromCall(s.info.cwd, cid, s.askHook);
697
- }
698
- catch {
699
- return p;
700
- }
701
- const labels = p.options.map((o) => o.label);
702
- // The UNIQUE best match, never the first that overlaps: one
703
- // `AskUserQuestion` may carry several questions and two of them sharing a
704
- // pair of labels ("Yes"/"No") is ordinary, so `find` handed back question 1
705
- // for a screen showing question 2 — and with it question 1's `askId`, its
706
- // descriptions and its first options as a "recovered" head a digit would
707
- // select. A tie now enriches nothing. See `pickAsk`.
708
- const ask = pickAsk(asks, labels);
709
- // Only a box the log HAS a pending question for can say anything about this
710
- // matcher. A tool approval or a trust dialog carries no `AskUserQuestion` at
711
- // all, so `asks` is legitimately empty and counting that as a miss would
712
- // report the commonest box in the app as a broken parse.
713
- s.enrich = { asks: asks.length, matched: !!ask, labels: labels.join("\n") };
714
- if (!ask)
715
- return p;
716
- const options = p.options.map((o) => {
717
- const desc = descFor(ask, o.label);
718
- return desc ? { ...o, desc } : o;
719
- });
720
- // A box taller than the terminal scrolled its own first options away. The
721
- // log has them, and their indices are the TUI's own — see `recoverHead`,
722
- // which refuses unless the two lists can be proved to line up. Recovered,
723
- // the card is no longer missing buttons, so `truncated` (which SAYS options
724
- // are unreachable from here) goes with them.
725
- const head = recoverHead(ask, p.options);
726
- if (head) {
727
- const recovered = head.map((o, i) => ({ index: i + 1, label: o.label, ...(o.desc ? { desc: o.desc } : {}) }));
728
- const { truncated: _cut, ...rest } = p;
729
- // Capped like the merge, and from the same end: the recovered head is the
730
- // part nobody can see on the terminal, so the tail is what gives way.
731
- const all = [...recovered, ...options].slice(0, MAX_BOX_OPTIONS);
732
- return { ...rest, options: all, ask: ask.question, askId: ask.id };
733
- }
734
- return { ...p, options, ask: ask.question, askId: ask.id };
735
- }
736
- /**
737
- * The plan file behind a plan-approval box (`planbox.ts`), cached on the log's
738
- * mtime and the file's: the strict pass runs about twice a second while the box
739
- * is up, and neither moves in that time unless somebody edits the plan.
740
- */
741
- function pendingPlanFor(s, cid) {
742
- try {
743
- const logM = logMtime(transcriptPath(s.info.cwd, cid)) ?? 0;
744
- const c = s.planCache;
745
- const path = c && c.logMtime === logM ? c.path : planPathFor(s.info.cwd, cid);
746
- const fileM = path ? logMtime(path) ?? 0 : 0;
747
- if (c && c.logMtime === logM && c.path === path && c.fileMtime === fileM)
748
- return c.plan ?? undefined;
749
- const plan = path && fileM ? readPlan(path) : null;
750
- s.planCache = { logMtime: logM, path, fileMtime: fileM, plan };
751
- return plan ?? undefined;
752
- }
753
- catch {
754
- return undefined;
755
- }
756
- }
757
- /** Publish the "unparsable dialog on screen" fallback flag. */
758
- export function setAwaiting(core, s, on, screen) {
759
- if (!!s.info.awaitingInput === on)
760
- return;
761
- s.info.awaitingInput = on || undefined;
762
- core.emit("updated", s.info);
763
- // Same reason the parsed prompt notifies: a blocked session is silent, so
764
- // nothing else would ever tell you. Fires on the ON transition only.
765
- if (on)
766
- core.emit("awaiting", s.info.id);
767
- // …which is nearly the edge the health record wants, and the "nearly" is
768
- // the whole correction. Raising this flag means "a dialog footer is on that
769
- // screen and no box parsed above it" — but the flag is an INTERLOCK, and its
770
- // rule is deliberately loose because a false wait is cheap and typing into a
771
- // live question box is not. A CLAIM ABOUT THE DETECTOR has the opposite
772
- // error cost, so it needs the stricter question: was a box actually up?
773
- //
774
- // On the live host it was not. A claude session displaying our own prose
775
- // about this very detector put "Esc to cancel" on screen inside a sentence,
776
- // the cheap gate fired, the strict pass correctly refused to read a
777
- // paragraph as a box — and that CORRECT REFUSAL was filed as a miss. Four in
778
- // nine, i.e. a working detector reporting 44% failure, which is how a board
779
- // teaches the person reading it to stop reading it.
780
- //
781
- // So: an observation is only a miss if the primary rule was the RIGHT RULE
782
- // and failed. `dialogEvidence` is what says it was — a footer row the CLI
783
- // painted, plus a cursor or option rows above it. No box, no observation:
784
- // not a `good` either, because nothing here has been seen to work, and a
785
- // `good` per correct refusal would fill the twenty-slot window with
786
- // successes and bury the misses that matter.
787
- if (on && screen) {
788
- const ev = dialogEvidence(screen);
789
- if (ev.box) {
790
- core.noteFor(s, "prompt.box", "fallback", {
791
- via: "the weaker “something is asking you something” flag",
792
- raw: healthTail(screen, (l) => isDialogFooterRow(l)),
793
- });
794
- }
795
- }
796
- }
797
- /**
798
- * Publish (or retire) the sign-in link this session is showing.
799
- *
800
- * Same shape as `applyPrompt` and for the same reason: this runs about twice
801
- * a second while the login screen is up, and a `session.list` broadcast per
802
- * repaint would be one per repaint. `at` is stamped when the URL first
803
- * appears and kept while it is the same URL, because a login link expires and
804
- * "how old is this" is the difference between a page that signs you in and a
805
- * page that refuses.
806
- */
807
- function applyLogin(core, s, login) {
808
- const had = s.info.login ?? null;
809
- if (sameLogin(had, login))
810
- return;
811
- if (!login) {
812
- s.info.login = null;
813
- }
814
- else {
815
- s.info.login = { ...login, at: had && had.url === login.url ? had.at : Date.now() };
816
- }
817
- core.emit("updated", s.info);
818
- }
819
- export function applyPrompt(core, s, prompt) {
820
- // The usage-limit menu is owned by auto-continue, not the normal prompt
821
- // flow: take its stop-and-wait option ourselves and never surface it (no
822
- // push, no plugin event) — the scheduled continue does the rest. With
823
- // auto-continue off it stays a normal prompt (the badge still shows).
824
- const stopWait = prompt?.options.find((o) => STOP_WAIT_RE.test(o.label));
825
- if (prompt && stopWait) {
826
- const scan = stripAnsi(s.scrollback.slice(-6000));
827
- const det = detectLimitText(scan);
828
- core.markLimitBlocked(s, det.resetAt, det.weekly, scan.slice(-600));
829
- if (core.limitAuto(s)) {
830
- if (s.info.prompt) {
831
- s.info.prompt = null;
832
- core.emit("updated", s.info);
833
- }
834
- s.proc.write(String(stopWait.index) + "\r");
835
- // This menu is answered on the user's behalf and then never shown, so
836
- // the audit log is the ONLY place it is visible at all.
837
- recordSent({
838
- sessionId: s.info.id, actor: "auto", source: "limit", kind: "answer",
839
- text: String(stopWait.index), result: "written",
840
- detail: `took the usage-limit menu's "${stopWait.label}"`,
841
- });
842
- return;
843
- }
844
- }
845
- // A box IS the question, with buttons. Publishing both would put the same
846
- // ask on the row twice and in two different wordings.
847
- if (prompt)
848
- core.setAsking(s, null);
849
- // Field by field (`samePrompt`), never `JSON.stringify`: that also compares
850
- // KEY ORDER, and `mergeBox` builds its object in its own order, so the pass
851
- // after every merge reported a change for a card that had not moved — one
852
- // broadcast, one push and one plugin event per box, bought with nothing.
853
- const changed = !samePrompt(prompt, s.info.prompt ?? null);
854
- // A tick toggled on a checkbox box is the box being answered, not a new
855
- // question: the phone redraws it, nobody is pushed "needs you" per tap.
856
- const ticked = changed && samePrompt(prompt, s.info.prompt ?? null, "ignore");
857
- const had = !!s.info.prompt;
858
- if (changed) {
859
- s.info.prompt = prompt;
860
- // A numbered-choice suggestion answers THIS box; when the box goes, so
861
- // does it. (Output alone no longer clears either — see the data handler.)
862
- const sug = s.info.suggestion;
863
- if (!prompt && sug && sug.choice != null)
864
- s.info.suggestion = null;
865
- core.emit("updated", s.info);
866
- if (prompt && !ticked)
867
- core.emit("prompt", s.info.id, prompt);
868
- // A box became published where none was — the one edge on which the
869
- // choice-box detector has provably worked. Not on every `changed`: a box
870
- // whose cursor moves republishes several times while it is up, and the
871
- // question is "can this app still read a question box", asked once per
872
- // box. Not on every strict pass either, for the reason `enrichPrompt`
873
- // states.
874
- if (prompt && !had) {
875
- // The fixture is the screen the box was published off (`clifixtures.ts`).
876
- core.noteFor(s, "prompt.box", "good", { fixture: () => core.screenText(s.info.id) });
877
- // The enrichment rides on the same edge, from what the poll stashed.
878
- // `asks: 0` is not a miss (see `enrichPrompt`); the fallback is that the
879
- // phone shows the labels as the terminal cut them, with the paragraph
880
- // that explains them nowhere on the device.
881
- const e = s.enrich;
882
- if (e && e.asks > 0) {
883
- // The fixture is the LOG's record of the call, which 2.1.304 writes only
884
- // once the box is answered — so it is waited for (once per CLI version).
885
- if (e.matched)
886
- core.noteFor(s, "askbox.enrich", "good", { fixture: async () => {
887
- for (let i = 0; i < ASK_RECORD_POLLS; i++) {
888
- const rec = pendingAskRecord(s.info.cwd, s.info.claudeSessionId);
889
- if (rec)
890
- return rec;
891
- await pause(ASK_RECORD_POLL_MS);
892
- }
893
- return null;
894
- } });
895
- else
896
- core.noteFor(s, "askbox.enrich", "fallback", { via: "the labels as the terminal cut them", raw: e.labels });
897
- }
898
- }
899
- }
900
- }
901
246
  /**
902
247
  * Press Return on a checkbox box's **Submit row**, walking the selection
903
248
  * cursor there first.
@@ -956,7 +301,7 @@ export async function submitPromptBox(core, id) {
956
301
  // which is the bug this whole method exists to fix.
957
302
  // Both words the commit row is drawn with — see `prompt.ts`'s
958
303
  // `SUBMIT_ROW_RE`. Anchored, so a sentence containing "next" is not a row.
959
- const tail = healthTail(seen, (l) => /^\s*\S?\s*(Submit|Next)\s*$/.test(l));
304
+ const tail = healthTail(seen, (l) => /^\s*\S?\s*(Submit|Next)\s*$/.test(l), HEALTH_SAMPLE_ROWS);
960
305
  if (placed)
961
306
  core.noteFor(s, "prompt.submit", "good", { fixture: () => seen });
962
307
  else if (readable)
@@ -965,4 +310,5 @@ export async function submitPromptBox(core, id) {
965
310
  core.noteFor(s, "prompt.submit", "fallback", { via: "a bare Return", raw: tail });
966
311
  return { ok: core.input(id, "\r"), placed };
967
312
  }
313
+ export { sourceKeysProblem } from "../sourceanswer.js";
968
314
  //# sourceMappingURL=boxes.js.map