charness 3.6.1 → 3.7.0

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 (578) hide show
  1. package/CHANGELOG.md +267 -0
  2. package/DEVELOPMENT.md +31 -5
  3. package/MIGRATION_RENAME_TO_CHARNESS.md +3 -2
  4. package/README.md +84 -782
  5. package/SETUP.md +37 -10
  6. package/agent-plugin/.claude-plugin/plugin.json +7 -0
  7. package/agent-plugin/README.md +35 -0
  8. package/agent-plugin/skills/charness-delegate-claude/SKILL.md +85 -0
  9. package/agent-plugin/skills/charness-delegate-claude/summarize-events.py +90 -0
  10. package/agent-plugin/skills/charness-delegate-opencode/SKILL.md +68 -0
  11. package/agent-plugin/skills/charness-manager/SKILL.md +152 -0
  12. package/dist/adapters/adapterNames.d.ts +6 -0
  13. package/dist/adapters/adapterNames.d.ts.map +1 -1
  14. package/dist/adapters/adapterNames.js +8 -2
  15. package/dist/adapters/adapterNames.js.map +1 -1
  16. package/dist/adapters/claudeCliAdapter.d.ts +8 -0
  17. package/dist/adapters/claudeCliAdapter.d.ts.map +1 -1
  18. package/dist/adapters/claudeCliAdapter.js +42 -5
  19. package/dist/adapters/claudeCliAdapter.js.map +1 -1
  20. package/dist/adapters/claudeJsonStreamAdapter.d.ts +10 -9
  21. package/dist/adapters/claudeJsonStreamAdapter.d.ts.map +1 -1
  22. package/dist/adapters/claudeJsonStreamAdapter.js +53 -55
  23. package/dist/adapters/claudeJsonStreamAdapter.js.map +1 -1
  24. package/dist/adapters/createAdapter.d.ts +8 -0
  25. package/dist/adapters/createAdapter.d.ts.map +1 -1
  26. package/dist/adapters/createAdapter.js +14 -2
  27. package/dist/adapters/createAdapter.js.map +1 -1
  28. package/dist/adapters/openCodeAdapter.d.ts +43 -6
  29. package/dist/adapters/openCodeAdapter.d.ts.map +1 -1
  30. package/dist/adapters/openCodeAdapter.js +95 -6
  31. package/dist/adapters/openCodeAdapter.js.map +1 -1
  32. package/dist/agentLogin/agentLogin.d.ts +1 -1
  33. package/dist/agentLogin/agentLogin.d.ts.map +1 -1
  34. package/dist/apiRetryKick.d.ts +4 -3
  35. package/dist/apiRetryKick.d.ts.map +1 -1
  36. package/dist/apiRetryKick.js +16 -9
  37. package/dist/apiRetryKick.js.map +1 -1
  38. package/dist/bot.d.ts.map +1 -1
  39. package/dist/bot.js +1313 -381
  40. package/dist/bot.js.map +1 -1
  41. package/dist/cli/claudeProfiles.d.ts +11 -6
  42. package/dist/cli/claudeProfiles.d.ts.map +1 -1
  43. package/dist/cli/claudeProfiles.js +50 -22
  44. package/dist/cli/claudeProfiles.js.map +1 -1
  45. package/dist/cli/hot.d.ts +5 -0
  46. package/dist/cli/hot.d.ts.map +1 -1
  47. package/dist/cli/hot.js +71 -25
  48. package/dist/cli/hot.js.map +1 -1
  49. package/dist/cli/tscWatchGuard.d.ts +95 -0
  50. package/dist/cli/tscWatchGuard.d.ts.map +1 -0
  51. package/dist/cli/tscWatchGuard.js +295 -0
  52. package/dist/cli/tscWatchGuard.js.map +1 -0
  53. package/dist/cli.js +12 -1
  54. package/dist/cli.js.map +1 -1
  55. package/dist/connectors/jira/answerSink.d.ts +10 -0
  56. package/dist/connectors/jira/answerSink.d.ts.map +1 -1
  57. package/dist/connectors/jira/answerSink.js +13 -0
  58. package/dist/connectors/jira/answerSink.js.map +1 -1
  59. package/dist/connectors/jira/config.d.ts +2 -0
  60. package/dist/connectors/jira/config.d.ts.map +1 -1
  61. package/dist/connectors/jira/config.js +9 -1
  62. package/dist/connectors/jira/config.js.map +1 -1
  63. package/dist/connectors/jira/connector.d.ts +11 -1
  64. package/dist/connectors/jira/connector.d.ts.map +1 -1
  65. package/dist/connectors/jira/connector.js +7 -0
  66. package/dist/connectors/jira/connector.js.map +1 -1
  67. package/dist/connectors/jira/inbound.d.ts +27 -4
  68. package/dist/connectors/jira/inbound.d.ts.map +1 -1
  69. package/dist/connectors/jira/inbound.js +69 -8
  70. package/dist/connectors/jira/inbound.js.map +1 -1
  71. package/dist/connectors/jira/issueBlocks.d.ts +5 -0
  72. package/dist/connectors/jira/issueBlocks.d.ts.map +1 -1
  73. package/dist/connectors/jira/issueBlocks.js +11 -0
  74. package/dist/connectors/jira/issueBlocks.js.map +1 -1
  75. package/dist/connectors/telegram/bindPicker.d.ts +5 -0
  76. package/dist/connectors/telegram/bindPicker.d.ts.map +1 -1
  77. package/dist/connectors/telegram/bindPicker.js +18 -1
  78. package/dist/connectors/telegram/bindPicker.js.map +1 -1
  79. package/dist/connectors/telegram/bindPickerClaims.d.ts +46 -0
  80. package/dist/connectors/telegram/bindPickerClaims.d.ts.map +1 -0
  81. package/dist/connectors/telegram/bindPickerClaims.js +83 -0
  82. package/dist/connectors/telegram/bindPickerClaims.js.map +1 -0
  83. package/dist/connectors/telegram/bindSweep.d.ts +32 -0
  84. package/dist/connectors/telegram/bindSweep.d.ts.map +1 -0
  85. package/dist/connectors/telegram/bindSweep.js +47 -0
  86. package/dist/connectors/telegram/bindSweep.js.map +1 -0
  87. package/dist/connectors/telegram/bindingWelcome.d.ts +23 -0
  88. package/dist/connectors/telegram/bindingWelcome.d.ts.map +1 -0
  89. package/dist/connectors/telegram/bindingWelcome.js +26 -0
  90. package/dist/connectors/telegram/bindingWelcome.js.map +1 -0
  91. package/dist/connectors/telegram/botApiConnection.d.ts +74 -0
  92. package/dist/connectors/telegram/botApiConnection.d.ts.map +1 -0
  93. package/dist/connectors/telegram/botApiConnection.js +201 -0
  94. package/dist/connectors/telegram/botApiConnection.js.map +1 -0
  95. package/dist/connectors/telegram/commands/botCore.d.ts +8 -2
  96. package/dist/connectors/telegram/commands/botCore.d.ts.map +1 -1
  97. package/dist/connectors/telegram/commands/botSkills.d.ts +21 -0
  98. package/dist/connectors/telegram/commands/botSkills.d.ts.map +1 -0
  99. package/dist/connectors/telegram/commands/botSkills.js +133 -0
  100. package/dist/connectors/telegram/commands/botSkills.js.map +1 -0
  101. package/dist/connectors/telegram/commands/callbackMessage.d.ts +5 -0
  102. package/dist/connectors/telegram/commands/callbackMessage.d.ts.map +1 -1
  103. package/dist/connectors/telegram/commands/callbackMessage.js +9 -0
  104. package/dist/connectors/telegram/commands/callbackMessage.js.map +1 -1
  105. package/dist/connectors/telegram/commands/compaction.d.ts +65 -3
  106. package/dist/connectors/telegram/commands/compaction.d.ts.map +1 -1
  107. package/dist/connectors/telegram/commands/compaction.js +512 -94
  108. package/dist/connectors/telegram/commands/compaction.js.map +1 -1
  109. package/dist/connectors/telegram/commands/displayModes.d.ts +1 -1
  110. package/dist/connectors/telegram/commands/displayModes.d.ts.map +1 -1
  111. package/dist/connectors/telegram/commands/displayModes.js +6 -18
  112. package/dist/connectors/telegram/commands/displayModes.js.map +1 -1
  113. package/dist/connectors/telegram/commands/fallbackChain.js +5 -5
  114. package/dist/connectors/telegram/commands/fallbackChain.js.map +1 -1
  115. package/dist/connectors/telegram/commands/reminders.d.ts +1 -1
  116. package/dist/connectors/telegram/commands/reminders.d.ts.map +1 -1
  117. package/dist/connectors/telegram/commands/reminders.js +4 -15
  118. package/dist/connectors/telegram/commands/reminders.js.map +1 -1
  119. package/dist/connectors/telegram/commands/selfUpdate.d.ts.map +1 -1
  120. package/dist/connectors/telegram/commands/selfUpdate.js +1 -11
  121. package/dist/connectors/telegram/commands/selfUpdate.js.map +1 -1
  122. package/dist/connectors/telegram/commands/taskAgents.d.ts +22 -0
  123. package/dist/connectors/telegram/commands/taskAgents.d.ts.map +1 -0
  124. package/dist/connectors/telegram/commands/taskAgents.js +104 -0
  125. package/dist/connectors/telegram/commands/taskAgents.js.map +1 -0
  126. package/dist/connectors/telegram/commands/todo.d.ts +82 -0
  127. package/dist/connectors/telegram/commands/todo.d.ts.map +1 -0
  128. package/dist/connectors/telegram/commands/todo.js +384 -0
  129. package/dist/connectors/telegram/commands/todo.js.map +1 -0
  130. package/dist/connectors/telegram/commands/topicCommand.d.ts +6 -2
  131. package/dist/connectors/telegram/commands/topicCommand.d.ts.map +1 -1
  132. package/dist/connectors/telegram/commands/topicCommand.js +6 -9
  133. package/dist/connectors/telegram/commands/topicCommand.js.map +1 -1
  134. package/dist/connectors/telegram/openBindMessages.d.ts +45 -0
  135. package/dist/connectors/telegram/openBindMessages.d.ts.map +1 -0
  136. package/dist/connectors/telegram/openBindMessages.js +67 -0
  137. package/dist/connectors/telegram/openBindMessages.js.map +1 -0
  138. package/dist/connectors/telegram/outputFlushPlan.d.ts +49 -0
  139. package/dist/connectors/telegram/outputFlushPlan.d.ts.map +1 -1
  140. package/dist/connectors/telegram/outputFlushPlan.js +46 -0
  141. package/dist/connectors/telegram/outputFlushPlan.js.map +1 -1
  142. package/dist/connectors/telegram/pendingTopicName.d.ts +26 -0
  143. package/dist/connectors/telegram/pendingTopicName.d.ts.map +1 -0
  144. package/dist/connectors/telegram/pendingTopicName.js +27 -0
  145. package/dist/connectors/telegram/pendingTopicName.js.map +1 -0
  146. package/dist/connectors/test/connector.d.ts.map +1 -1
  147. package/dist/connectors/test/connector.js +6 -1
  148. package/dist/connectors/test/connector.js.map +1 -1
  149. package/dist/i18n/de.d.ts.map +1 -1
  150. package/dist/i18n/de.js +90 -7
  151. package/dist/i18n/de.js.map +1 -1
  152. package/dist/i18n/en.d.ts.map +1 -1
  153. package/dist/i18n/en.js +90 -7
  154. package/dist/i18n/en.js.map +1 -1
  155. package/dist/i18n/es.d.ts.map +1 -1
  156. package/dist/i18n/es.js +90 -7
  157. package/dist/i18n/es.js.map +1 -1
  158. package/dist/i18n/fr.d.ts.map +1 -1
  159. package/dist/i18n/fr.js +90 -7
  160. package/dist/i18n/fr.js.map +1 -1
  161. package/dist/i18n/hi.d.ts.map +1 -1
  162. package/dist/i18n/hi.js +90 -7
  163. package/dist/i18n/hi.js.map +1 -1
  164. package/dist/i18n/ja.d.ts.map +1 -1
  165. package/dist/i18n/ja.js +90 -7
  166. package/dist/i18n/ja.js.map +1 -1
  167. package/dist/i18n/ka.d.ts.map +1 -1
  168. package/dist/i18n/ka.js +90 -7
  169. package/dist/i18n/ka.js.map +1 -1
  170. package/dist/i18n/pt.d.ts.map +1 -1
  171. package/dist/i18n/pt.js +90 -7
  172. package/dist/i18n/pt.js.map +1 -1
  173. package/dist/i18n/ru.d.ts.map +1 -1
  174. package/dist/i18n/ru.js +90 -7
  175. package/dist/i18n/ru.js.map +1 -1
  176. package/dist/i18n/uk.d.ts.map +1 -1
  177. package/dist/i18n/uk.js +90 -7
  178. package/dist/i18n/uk.js.map +1 -1
  179. package/dist/i18n/uz.d.ts.map +1 -1
  180. package/dist/i18n/uz.js +90 -7
  181. package/dist/i18n/uz.js.map +1 -1
  182. package/dist/i18n/zh.d.ts.map +1 -1
  183. package/dist/i18n/zh.js +90 -7
  184. package/dist/i18n/zh.js.map +1 -1
  185. package/dist/i18n.d.ts +1 -1
  186. package/dist/i18n.js +1 -1
  187. package/dist/installManager.d.ts +13 -0
  188. package/dist/installManager.d.ts.map +1 -1
  189. package/dist/installManager.js +38 -4
  190. package/dist/installManager.js.map +1 -1
  191. package/dist/instanceSettings.d.ts +40 -1
  192. package/dist/instanceSettings.d.ts.map +1 -1
  193. package/dist/instanceSettings.js +105 -26
  194. package/dist/instanceSettings.js.map +1 -1
  195. package/dist/openCodeQuestionFlow.d.ts +30 -0
  196. package/dist/openCodeQuestionFlow.d.ts.map +1 -1
  197. package/dist/openCodeQuestionFlow.js +43 -0
  198. package/dist/openCodeQuestionFlow.js.map +1 -1
  199. package/dist/postToSession.d.ts +20 -5
  200. package/dist/postToSession.d.ts.map +1 -1
  201. package/dist/postToSession.js +38 -7
  202. package/dist/postToSession.js.map +1 -1
  203. package/dist/remoteRun/cliArgs.d.ts +73 -0
  204. package/dist/remoteRun/cliArgs.d.ts.map +1 -0
  205. package/dist/remoteRun/cliArgs.js +197 -0
  206. package/dist/remoteRun/cliArgs.js.map +1 -0
  207. package/dist/remoteRun/commands.d.ts +56 -0
  208. package/dist/remoteRun/commands.d.ts.map +1 -0
  209. package/dist/remoteRun/commands.js +306 -0
  210. package/dist/remoteRun/commands.js.map +1 -0
  211. package/dist/remoteRun/depsPlan.d.ts +16 -0
  212. package/dist/remoteRun/depsPlan.d.ts.map +1 -0
  213. package/dist/remoteRun/depsPlan.js +82 -0
  214. package/dist/remoteRun/depsPlan.js.map +1 -0
  215. package/dist/remoteRun/exitCodes.d.ts +34 -0
  216. package/dist/remoteRun/exitCodes.d.ts.map +1 -0
  217. package/dist/remoteRun/exitCodes.js +38 -0
  218. package/dist/remoteRun/exitCodes.js.map +1 -0
  219. package/dist/remoteRun/foreground.d.ts +29 -0
  220. package/dist/remoteRun/foreground.d.ts.map +1 -0
  221. package/dist/remoteRun/foreground.js +159 -0
  222. package/dist/remoteRun/foreground.js.map +1 -0
  223. package/dist/remoteRun/interrupts.d.ts +17 -0
  224. package/dist/remoteRun/interrupts.d.ts.map +1 -0
  225. package/dist/remoteRun/interrupts.js +41 -0
  226. package/dist/remoteRun/interrupts.js.map +1 -0
  227. package/dist/remoteRun/jobFiles.d.ts +31 -0
  228. package/dist/remoteRun/jobFiles.d.ts.map +1 -0
  229. package/dist/remoteRun/jobFiles.js +84 -0
  230. package/dist/remoteRun/jobFiles.js.map +1 -0
  231. package/dist/remoteRun/jobFormat.d.ts +16 -0
  232. package/dist/remoteRun/jobFormat.d.ts.map +1 -0
  233. package/dist/remoteRun/jobFormat.js +130 -0
  234. package/dist/remoteRun/jobFormat.js.map +1 -0
  235. package/dist/remoteRun/jobId.d.ts +15 -0
  236. package/dist/remoteRun/jobId.d.ts.map +1 -0
  237. package/dist/remoteRun/jobId.js +85 -0
  238. package/dist/remoteRun/jobId.js.map +1 -0
  239. package/dist/remoteRun/jobMeta.d.ts +18 -0
  240. package/dist/remoteRun/jobMeta.d.ts.map +1 -0
  241. package/dist/remoteRun/jobMeta.js +33 -0
  242. package/dist/remoteRun/jobMeta.js.map +1 -0
  243. package/dist/remoteRun/jobQuery.d.ts +12 -0
  244. package/dist/remoteRun/jobQuery.d.ts.map +1 -0
  245. package/dist/remoteRun/jobQuery.js +22 -0
  246. package/dist/remoteRun/jobQuery.js.map +1 -0
  247. package/dist/remoteRun/jobRecords.d.ts +22 -0
  248. package/dist/remoteRun/jobRecords.d.ts.map +1 -0
  249. package/dist/remoteRun/jobRecords.js +145 -0
  250. package/dist/remoteRun/jobRecords.js.map +1 -0
  251. package/dist/remoteRun/jobState.d.ts +62 -0
  252. package/dist/remoteRun/jobState.d.ts.map +1 -0
  253. package/dist/remoteRun/jobState.js +132 -0
  254. package/dist/remoteRun/jobState.js.map +1 -0
  255. package/dist/remoteRun/leaseTiming.d.ts +18 -0
  256. package/dist/remoteRun/leaseTiming.d.ts.map +1 -0
  257. package/dist/remoteRun/leaseTiming.js +43 -0
  258. package/dist/remoteRun/leaseTiming.js.map +1 -0
  259. package/dist/remoteRun/output.d.ts +35 -0
  260. package/dist/remoteRun/output.d.ts.map +1 -0
  261. package/dist/remoteRun/output.js +82 -0
  262. package/dist/remoteRun/output.js.map +1 -0
  263. package/dist/remoteRun/pathPatterns.d.ts +33 -0
  264. package/dist/remoteRun/pathPatterns.d.ts.map +1 -0
  265. package/dist/remoteRun/pathPatterns.js +115 -0
  266. package/dist/remoteRun/pathPatterns.js.map +1 -0
  267. package/dist/remoteRun/probe.d.ts +56 -0
  268. package/dist/remoteRun/probe.d.ts.map +1 -0
  269. package/dist/remoteRun/probe.js +123 -0
  270. package/dist/remoteRun/probe.js.map +1 -0
  271. package/dist/remoteRun/project.d.ts +26 -0
  272. package/dist/remoteRun/project.d.ts.map +1 -0
  273. package/dist/remoteRun/project.js +159 -0
  274. package/dist/remoteRun/project.js.map +1 -0
  275. package/dist/remoteRun/projectConfig.d.ts +38 -0
  276. package/dist/remoteRun/projectConfig.d.ts.map +1 -0
  277. package/dist/remoteRun/projectConfig.js +87 -0
  278. package/dist/remoteRun/projectConfig.js.map +1 -0
  279. package/dist/remoteRun/remoteRunCli.d.ts +15 -0
  280. package/dist/remoteRun/remoteRunCli.d.ts.map +1 -0
  281. package/dist/remoteRun/remoteRunCli.js +144 -0
  282. package/dist/remoteRun/remoteRunCli.js.map +1 -0
  283. package/dist/remoteRun/remoteRunError.d.ts +14 -0
  284. package/dist/remoteRun/remoteRunError.d.ts.map +1 -0
  285. package/dist/remoteRun/remoteRunError.js +28 -0
  286. package/dist/remoteRun/remoteRunError.js.map +1 -0
  287. package/dist/remoteRun/rsync.d.ts +17 -0
  288. package/dist/remoteRun/rsync.d.ts.map +1 -0
  289. package/dist/remoteRun/rsync.js +39 -0
  290. package/dist/remoteRun/rsync.js.map +1 -0
  291. package/dist/remoteRun/runnerClient.d.ts +50 -0
  292. package/dist/remoteRun/runnerClient.d.ts.map +1 -0
  293. package/dist/remoteRun/runnerClient.js +139 -0
  294. package/dist/remoteRun/runnerClient.js.map +1 -0
  295. package/dist/remoteRun/runners.d.ts +57 -0
  296. package/dist/remoteRun/runners.d.ts.map +1 -0
  297. package/dist/remoteRun/runners.js +181 -0
  298. package/dist/remoteRun/runners.js.map +1 -0
  299. package/dist/remoteRun/runnersConfig.d.ts +44 -0
  300. package/dist/remoteRun/runnersConfig.d.ts.map +1 -0
  301. package/dist/remoteRun/runnersConfig.js +107 -0
  302. package/dist/remoteRun/runnersConfig.js.map +1 -0
  303. package/dist/remoteRun/safeCopy.d.ts +31 -0
  304. package/dist/remoteRun/safeCopy.d.ts.map +1 -0
  305. package/dist/remoteRun/safeCopy.js +137 -0
  306. package/dist/remoteRun/safeCopy.js.map +1 -0
  307. package/dist/remoteRun/sendPlan.d.ts +67 -0
  308. package/dist/remoteRun/sendPlan.d.ts.map +1 -0
  309. package/dist/remoteRun/sendPlan.js +139 -0
  310. package/dist/remoteRun/sendPlan.js.map +1 -0
  311. package/dist/remoteRun/ssh.d.ts +62 -0
  312. package/dist/remoteRun/ssh.d.ts.map +1 -0
  313. package/dist/remoteRun/ssh.js +202 -0
  314. package/dist/remoteRun/ssh.js.map +1 -0
  315. package/dist/remoteRun/submit.d.ts +29 -0
  316. package/dist/remoteRun/submit.d.ts.map +1 -0
  317. package/dist/remoteRun/submit.js +142 -0
  318. package/dist/remoteRun/submit.js.map +1 -0
  319. package/dist/requests/answerRequest.d.ts +5 -0
  320. package/dist/requests/answerRequest.d.ts.map +1 -1
  321. package/dist/requests/answerRequest.js +16 -1
  322. package/dist/requests/answerRequest.js.map +1 -1
  323. package/dist/requests/requestLedger.d.ts +13 -0
  324. package/dist/requests/requestLedger.d.ts.map +1 -1
  325. package/dist/requests/requestLedger.js +9 -0
  326. package/dist/requests/requestLedger.js.map +1 -1
  327. package/dist/requests/topicRequestSettle.d.ts +30 -0
  328. package/dist/requests/topicRequestSettle.d.ts.map +1 -0
  329. package/dist/requests/topicRequestSettle.js +23 -0
  330. package/dist/requests/topicRequestSettle.js.map +1 -0
  331. package/dist/requests/wakeUpEngine.d.ts +4 -0
  332. package/dist/requests/wakeUpEngine.d.ts.map +1 -1
  333. package/dist/requests/wakeUpEngine.js +5 -1
  334. package/dist/requests/wakeUpEngine.js.map +1 -1
  335. package/dist/scheduler/delivery.d.ts +2 -0
  336. package/dist/scheduler/delivery.d.ts.map +1 -1
  337. package/dist/scheduler/delivery.js +8 -4
  338. package/dist/scheduler/delivery.js.map +1 -1
  339. package/dist/scheduler/mcpSurface.d.ts +59 -10
  340. package/dist/scheduler/mcpSurface.d.ts.map +1 -1
  341. package/dist/scheduler/mcpSurface.js +276 -79
  342. package/dist/scheduler/mcpSurface.js.map +1 -1
  343. package/dist/scheduler/recurrence.d.ts +5 -0
  344. package/dist/scheduler/recurrence.d.ts.map +1 -1
  345. package/dist/scheduler/recurrence.js +12 -2
  346. package/dist/scheduler/recurrence.js.map +1 -1
  347. package/dist/scheduler/strictToolInput.d.ts +45 -0
  348. package/dist/scheduler/strictToolInput.d.ts.map +1 -0
  349. package/dist/scheduler/strictToolInput.js +155 -0
  350. package/dist/scheduler/strictToolInput.js.map +1 -0
  351. package/dist/scheduler/types.d.ts +5 -0
  352. package/dist/scheduler/types.d.ts.map +1 -1
  353. package/dist/scheduler/workerWatch.d.ts +23 -0
  354. package/dist/scheduler/workerWatch.d.ts.map +1 -0
  355. package/dist/scheduler/workerWatch.js +26 -0
  356. package/dist/scheduler/workerWatch.js.map +1 -0
  357. package/dist/selfUpdate/emittedSource.d.ts +11 -0
  358. package/dist/selfUpdate/emittedSource.d.ts.map +1 -0
  359. package/dist/selfUpdate/emittedSource.js +24 -0
  360. package/dist/selfUpdate/emittedSource.js.map +1 -0
  361. package/dist/selfUpdate/gitSource.d.ts +0 -6
  362. package/dist/selfUpdate/gitSource.d.ts.map +1 -1
  363. package/dist/selfUpdate/gitSource.js +2 -18
  364. package/dist/selfUpdate/gitSource.js.map +1 -1
  365. package/dist/selfUpdate/updatePending.d.ts +1 -1
  366. package/dist/sendErrorClassifier.d.ts +10 -0
  367. package/dist/sendErrorClassifier.d.ts.map +1 -1
  368. package/dist/sendErrorClassifier.js +22 -0
  369. package/dist/sendErrorClassifier.js.map +1 -1
  370. package/dist/state.d.ts +78 -7
  371. package/dist/state.d.ts.map +1 -1
  372. package/dist/state.js +125 -8
  373. package/dist/state.js.map +1 -1
  374. package/dist/stateFile.d.ts +9 -0
  375. package/dist/stateFile.d.ts.map +1 -0
  376. package/dist/stateFile.js +57 -0
  377. package/dist/stateFile.js.map +1 -0
  378. package/dist/stt/sttInstall.d.ts +7 -3
  379. package/dist/stt/sttInstall.d.ts.map +1 -1
  380. package/dist/stt/sttInstall.js +8 -4
  381. package/dist/stt/sttInstall.js.map +1 -1
  382. package/dist/stt/sttSettings.d.ts +2 -1
  383. package/dist/stt/sttSettings.d.ts.map +1 -1
  384. package/dist/stt/sttSettings.js +3 -2
  385. package/dist/stt/sttSettings.js.map +1 -1
  386. package/dist/stt/transcribeChain.js +2 -0
  387. package/dist/stt/transcribeChain.js.map +1 -1
  388. package/dist/testTimings.d.ts +13 -3
  389. package/dist/testTimings.d.ts.map +1 -1
  390. package/dist/testTimings.js +26 -2
  391. package/dist/testTimings.js.map +1 -1
  392. package/dist/todos/board.d.ts +83 -0
  393. package/dist/todos/board.d.ts.map +1 -0
  394. package/dist/todos/board.js +227 -0
  395. package/dist/todos/board.js.map +1 -0
  396. package/dist/todos/format.d.ts +33 -0
  397. package/dist/todos/format.d.ts.map +1 -0
  398. package/dist/todos/format.js +90 -0
  399. package/dist/todos/format.js.map +1 -0
  400. package/dist/todos/merge.d.ts +46 -0
  401. package/dist/todos/merge.d.ts.map +1 -0
  402. package/dist/todos/merge.js +137 -0
  403. package/dist/todos/merge.js.map +1 -0
  404. package/dist/todos/midTurn.d.ts +75 -0
  405. package/dist/todos/midTurn.d.ts.map +1 -0
  406. package/dist/todos/midTurn.js +214 -0
  407. package/dist/todos/midTurn.js.map +1 -0
  408. package/dist/todos/nag.d.ts +85 -0
  409. package/dist/todos/nag.d.ts.map +1 -0
  410. package/dist/todos/nag.js +103 -0
  411. package/dist/todos/nag.js.map +1 -0
  412. package/dist/todos/order.d.ts +25 -0
  413. package/dist/todos/order.d.ts.map +1 -0
  414. package/dist/todos/order.js +61 -0
  415. package/dist/todos/order.js.map +1 -0
  416. package/dist/todos/projects.d.ts +102 -0
  417. package/dist/todos/projects.d.ts.map +1 -0
  418. package/dist/todos/projects.js +342 -0
  419. package/dist/todos/projects.js.map +1 -0
  420. package/dist/todos/registry.d.ts +64 -0
  421. package/dist/todos/registry.d.ts.map +1 -0
  422. package/dist/todos/registry.js +116 -0
  423. package/dist/todos/registry.js.map +1 -0
  424. package/dist/todos/reminderEngine.d.ts +78 -0
  425. package/dist/todos/reminderEngine.d.ts.map +1 -0
  426. package/dist/todos/reminderEngine.js +162 -0
  427. package/dist/todos/reminderEngine.js.map +1 -0
  428. package/dist/todos/store.d.ts +34 -0
  429. package/dist/todos/store.d.ts.map +1 -0
  430. package/dist/todos/store.js +208 -0
  431. package/dist/todos/store.js.map +1 -0
  432. package/dist/todos/tools.d.ts +26 -0
  433. package/dist/todos/tools.d.ts.map +1 -0
  434. package/dist/todos/tools.js +25 -0
  435. package/dist/todos/tools.js.map +1 -0
  436. package/dist/todos/types.d.ts +85 -0
  437. package/dist/todos/types.d.ts.map +1 -0
  438. package/dist/todos/types.js +30 -0
  439. package/dist/todos/types.js.map +1 -0
  440. package/dist/trackers/taskAgentLimit.d.ts +58 -0
  441. package/dist/trackers/taskAgentLimit.d.ts.map +1 -0
  442. package/dist/trackers/taskAgentLimit.js +62 -0
  443. package/dist/trackers/taskAgentLimit.js.map +1 -0
  444. package/dist/trackers/taskAgentSlots.d.ts +109 -0
  445. package/dist/trackers/taskAgentSlots.d.ts.map +1 -0
  446. package/dist/trackers/taskAgentSlots.js +227 -0
  447. package/dist/trackers/taskAgentSlots.js.map +1 -0
  448. package/dist/trackers/types.d.ts +14 -0
  449. package/dist/trackers/types.d.ts.map +1 -0
  450. package/dist/trackers/types.js +3 -0
  451. package/dist/trackers/types.js.map +1 -0
  452. package/dist/types.d.ts +80 -4
  453. package/dist/types.d.ts.map +1 -1
  454. package/dist/utils/adoptReplayGate.d.ts +16 -0
  455. package/dist/utils/adoptReplayGate.d.ts.map +1 -0
  456. package/dist/utils/adoptReplayGate.js +35 -0
  457. package/dist/utils/adoptReplayGate.js.map +1 -0
  458. package/dist/utils/agentPlugin.d.ts +113 -0
  459. package/dist/utils/agentPlugin.d.ts.map +1 -0
  460. package/dist/utils/agentPlugin.js +192 -0
  461. package/dist/utils/agentPlugin.js.map +1 -0
  462. package/dist/utils/autoContinueOnLimit.d.ts +7 -4
  463. package/dist/utils/autoContinueOnLimit.d.ts.map +1 -1
  464. package/dist/utils/autoContinueOnLimit.js +8 -5
  465. package/dist/utils/autoContinueOnLimit.js.map +1 -1
  466. package/dist/utils/botSkills.d.ts +62 -0
  467. package/dist/utils/botSkills.d.ts.map +1 -0
  468. package/dist/utils/botSkills.js +53 -0
  469. package/dist/utils/botSkills.js.map +1 -0
  470. package/dist/utils/botSkillsSetting.d.ts +7 -0
  471. package/dist/utils/botSkillsSetting.d.ts.map +1 -0
  472. package/dist/utils/botSkillsSetting.js +9 -0
  473. package/dist/utils/botSkillsSetting.js.map +1 -0
  474. package/dist/utils/claudeCodeVersion.d.ts +7 -0
  475. package/dist/utils/claudeCodeVersion.d.ts.map +1 -1
  476. package/dist/utils/claudeCodeVersion.js +14 -1
  477. package/dist/utils/claudeCodeVersion.js.map +1 -1
  478. package/dist/utils/claudeCompactHook.d.ts +33 -15
  479. package/dist/utils/claudeCompactHook.d.ts.map +1 -1
  480. package/dist/utils/claudeCompactHook.js +36 -17
  481. package/dist/utils/claudeCompactHook.js.map +1 -1
  482. package/dist/utils/claudeCompactSummary.d.ts +15 -0
  483. package/dist/utils/claudeCompactSummary.d.ts.map +1 -0
  484. package/dist/utils/claudeCompactSummary.js +96 -0
  485. package/dist/utils/claudeCompactSummary.js.map +1 -0
  486. package/dist/utils/claudeLimitSwitch.d.ts +11 -9
  487. package/dist/utils/claudeLimitSwitch.d.ts.map +1 -1
  488. package/dist/utils/claudeLimitSwitch.js +18 -16
  489. package/dist/utils/claudeLimitSwitch.js.map +1 -1
  490. package/dist/utils/claudeProfiles.d.ts +5 -0
  491. package/dist/utils/claudeProfiles.d.ts.map +1 -1
  492. package/dist/utils/claudeProfiles.js +14 -0
  493. package/dist/utils/claudeProfiles.js.map +1 -1
  494. package/dist/utils/claudeSessionTitle.d.ts +2 -1
  495. package/dist/utils/claudeSessionTitle.d.ts.map +1 -1
  496. package/dist/utils/claudeSessionTitle.js +14 -14
  497. package/dist/utils/claudeSessionTitle.js.map +1 -1
  498. package/dist/utils/claudeUsage.d.ts +95 -15
  499. package/dist/utils/claudeUsage.d.ts.map +1 -1
  500. package/dist/utils/claudeUsage.js +241 -41
  501. package/dist/utils/claudeUsage.js.map +1 -1
  502. package/dist/utils/claudeUsageRefresher.d.ts +10 -0
  503. package/dist/utils/claudeUsageRefresher.d.ts.map +1 -1
  504. package/dist/utils/claudeUsageRefresher.js +11 -0
  505. package/dist/utils/claudeUsageRefresher.js.map +1 -1
  506. package/dist/utils/claudeUserEntry.d.ts +50 -0
  507. package/dist/utils/claudeUserEntry.d.ts.map +1 -0
  508. package/dist/utils/claudeUserEntry.js +120 -0
  509. package/dist/utils/claudeUserEntry.js.map +1 -0
  510. package/dist/utils/clearThreadOutputQueues.d.ts +4 -3
  511. package/dist/utils/clearThreadOutputQueues.d.ts.map +1 -1
  512. package/dist/utils/clearThreadOutputQueues.js +1 -1
  513. package/dist/utils/clearThreadOutputQueues.js.map +1 -1
  514. package/dist/utils/compactOnIdle.d.ts +33 -13
  515. package/dist/utils/compactOnIdle.d.ts.map +1 -1
  516. package/dist/utils/compactOnIdle.js +35 -15
  517. package/dist/utils/compactOnIdle.js.map +1 -1
  518. package/dist/utils/fallbackBridge.d.ts +5 -0
  519. package/dist/utils/fallbackBridge.d.ts.map +1 -1
  520. package/dist/utils/fallbackBridge.js +19 -3
  521. package/dist/utils/fallbackBridge.js.map +1 -1
  522. package/dist/utils/fallbackChain.d.ts +9 -3
  523. package/dist/utils/fallbackChain.d.ts.map +1 -1
  524. package/dist/utils/fallbackChain.js +21 -3
  525. package/dist/utils/fallbackChain.js.map +1 -1
  526. package/dist/utils/fileSendPlan.d.ts +6 -0
  527. package/dist/utils/fileSendPlan.d.ts.map +1 -1
  528. package/dist/utils/fileSendPlan.js +11 -0
  529. package/dist/utils/fileSendPlan.js.map +1 -1
  530. package/dist/utils/fileSendService.d.ts +7 -1
  531. package/dist/utils/fileSendService.d.ts.map +1 -1
  532. package/dist/utils/fileSendService.js +6 -2
  533. package/dist/utils/fileSendService.js.map +1 -1
  534. package/dist/utils/groupFinalizePlan.d.ts +8 -10
  535. package/dist/utils/groupFinalizePlan.d.ts.map +1 -1
  536. package/dist/utils/groupFinalizePlan.js +8 -12
  537. package/dist/utils/groupFinalizePlan.js.map +1 -1
  538. package/dist/utils/jsonStreamHost.d.ts +13 -0
  539. package/dist/utils/jsonStreamHost.d.ts.map +1 -1
  540. package/dist/utils/jsonStreamHost.js +13 -0
  541. package/dist/utils/jsonStreamHost.js.map +1 -1
  542. package/dist/utils/messageSendService.d.ts +5 -3
  543. package/dist/utils/messageSendService.d.ts.map +1 -1
  544. package/dist/utils/messageSendService.js +12 -5
  545. package/dist/utils/messageSendService.js.map +1 -1
  546. package/dist/utils/openCodeCompactPlugin.d.ts +39 -14
  547. package/dist/utils/openCodeCompactPlugin.d.ts.map +1 -1
  548. package/dist/utils/openCodeCompactPlugin.js +106 -38
  549. package/dist/utils/openCodeCompactPlugin.js.map +1 -1
  550. package/dist/utils/promptDelivery.d.ts +29 -12
  551. package/dist/utils/promptDelivery.d.ts.map +1 -1
  552. package/dist/utils/promptDelivery.js +13 -5
  553. package/dist/utils/promptDelivery.js.map +1 -1
  554. package/dist/utils/sentKindsSummary.d.ts +10 -0
  555. package/dist/utils/sentKindsSummary.d.ts.map +1 -0
  556. package/dist/utils/sentKindsSummary.js +18 -0
  557. package/dist/utils/sentKindsSummary.js.map +1 -0
  558. package/dist/utils/telegramError.d.ts +6 -0
  559. package/dist/utils/telegramError.d.ts.map +1 -1
  560. package/dist/utils/telegramError.js +12 -0
  561. package/dist/utils/telegramError.js.map +1 -1
  562. package/dist/utils/topicView.d.ts +1 -1
  563. package/dist/utils/topicView.js +1 -1
  564. package/dist/utils/transcribeAudio.d.ts +10 -0
  565. package/dist/utils/transcribeAudio.d.ts.map +1 -1
  566. package/dist/utils/transcribeAudio.js +22 -3
  567. package/dist/utils/transcribeAudio.js.map +1 -1
  568. package/dist/utils/transcriptErrorTime.d.ts +8 -0
  569. package/dist/utils/transcriptErrorTime.d.ts.map +1 -0
  570. package/dist/utils/transcriptErrorTime.js +56 -0
  571. package/dist/utils/transcriptErrorTime.js.map +1 -0
  572. package/dist/utils/wedgeRecovery.d.ts +2 -0
  573. package/dist/utils/wedgeRecovery.d.ts.map +1 -1
  574. package/dist/utils/wedgeRecovery.js +1 -1
  575. package/dist/utils/wedgeRecovery.js.map +1 -1
  576. package/package.json +11 -3
  577. package/remoteRun/runner.sh +1242 -0
  578. package/stt/gigaam_sidecar.py +555 -50
package/CHANGELOG.md CHANGED
@@ -2,6 +2,273 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 3.7.0 — 2026-11-01
6
+
7
+ **The answers of `send_messages_to_user` and `send_file_to_user` now say what was sent, per kind — «Delivered 3 messages: 1 text, 2 documents.», «Sent 3 files: 1 photo, 2 documents.» — so an agent can see when a file did not go out as the kind it meant.**
8
+ Before, they only counted («Delivered 3 messages to the topic», «Sent 3 file(s) to the topic»), so a batch of images that arrived as plain text or as documents read as a full success.
9
+ Now the answer names what landed — texts, photos, videos, animations, documents — taken from what Telegram was actually asked to render: a photo sent with `as_file`, one over the photo size limit, or one in an album that fell back to documents is counted as a document.
10
+
11
+ **An agent that misnames a field when it calls one of the bot's tools now gets an error that says which field and what to write — attachments no longer vanish unseen.**
12
+ Before, a key the tool does not know was dropped silently: an agent that sent three images to `send_messages_to_user` as `{text, filePath}` (the field is `path`) had them posted as three text-only messages, and the tool still answered «Delivered 3 messages».
13
+ Now every bot tool refuses a key it does not list, at the top of a call or inside an item, and answers with the key, the nearest allowed one («unknown key `filePath` — did you mean `path`?») and the allowed keys; nothing is sent. `send_file_to_user` called with `path` instead of `paths` is told the same.
14
+
15
+ **Agents can now send heavy commands — test suites, builds, emulator runs — to another machine with `charness remote-run`, and get the output, the exit code and the result files back as if the command had run here.**
16
+ Before, everything an agent ran landed on the one machine the bot lives on, so a long test suite or an emulator run could take most of its CPU and memory for an hour while other agents waited on it.
17
+ Now you list machines you reach by ssh in `~/.config/charness/runners.json` (set up by hand: an account of its own, `rsync`, Pueue — see `docs/remote-run.md`), and an agent runs `charness remote-run yarn test` (or `--bg` plus `wait` for a long run): the project is synced there (tracked and untracked files, never what `.gitignore` names, never secret-looking files unless `.remote-run` says so), the command runs in a copy, its output streams back, and an interrupt, a timeout or a lost connection stops the whole remote job.
18
+ `charness remote-run runners` shows each machine's CPU, memory, disk, load and what it can do (Android, iOS, Docker, Playwright); `ls`, `status`, `logs`, `wait`, `kill`, `fetch` and `exec` manage the jobs. Two runs of one project queue on the runner, each against the files as they were when it was started.
19
+ Agents (Telegram topics and Jira issues alike) are told about it only while at least one runner is listed; without one nothing changes.
20
+
21
+ **A message no longer gets lost when Telegram has closed the connection the bot was about to reuse — it is sent again, once, on a fresh connection.**
22
+ Before, the bot kept its connections to Telegram open and reused them; when Telegram had closed an idle one a moment earlier (most often while the bot was starved of CPU), the next send failed with «socket hang up» and was dropped — a notice or a reply simply never appeared in the topic.
23
+ Now a send that fails this way — at once, before Telegram has started to answer — is retried once on a new connection, the answer to a button tap and the edit of a picker included. It is not retried after a timeout, once Telegram has begun to answer, when the connection broke only after a while, or on a connection that was new anyway, and a file the agent sends is not retried this way (it keeps its own delivery rules). If Telegram did take the message and the connection broke before a single byte of its answer, the retry cannot tell that from a closed connection and could post the message twice; that is rare.
24
+ The bot also closes a connection that sat unused for 30 seconds itself, long before Telegram would, so an ordinary pause between two messages does not meet a closed one. When it retries, the bot log says «pooled connection was closed by the server».
25
+
26
+ **Stopping every agent from General is typed `/quitall` — the «only available in the General topic» refusal now says so, in all 12 languages.**
27
+ Before, that refusal (and the docs) told you to use `/quit-all`, but Telegram ends a command at the hyphen, so `/quit-all` reached the bot as plain `/quit` and stopped only the one topic's agent, not all of them.
28
+ The refusal and the docs now name `/quitall`, the spelling the command menu lists; the command itself is unchanged.
29
+
30
+ **A question the agent asks now stays in the topic however it ends: answered, it shows your answer in place of the buttons; left alone, a note says it was not answered.**
31
+ Before, answering replaced the whole question with a short «✅ header: answer», walking away from it (another message, `/esc`) replaced it with «❌ Question cancelled», and re-posting or re-asking a question deleted the first message — so what the agent had asked was gone from the topic.
32
+ Now the message is never deleted: it keeps the question and its options, with «✅ Answer: …», «❌ Not answered» or «↓ Asked again below» under them, also when the question is re-asked after the idle compaction, when you leave the folder, or its agent is gone.
33
+ A question that waits through a long stream of the agent's output is put at the bottom again each time: the first message stays as the record and the newest copy is the live one, the copies in between are removed — also across a bot restart.
34
+ A bot restart in the middle of an idle compaction asks the question again when its conversation can still be resumed, instead of leaving it «Not answered» though you never had the chance to answer.
35
+ The pin works as before: one notification when the question comes, removed when it ends. The details are in `docs/commands.md`, «The agent's questions».
36
+
37
+ **Typing or saying «claude» (or `клод`) to start the agent now opens the same backend `/claude` does — json-stream by default, or the one the topic picked — not the deprecated tmux one.**
38
+ Before, a start phrase — in a text message or a voice note — handed the bare name `claude` on, which is the tmux backend's own name, so the phrase quietly
39
+ started the frozen tmux backend while `/claude` and the ▶️ Claude button opened the topic's backend. All three now open the same backend;
40
+ `opencode` and `terminal` are unchanged, and a topic that picked the tmux backend with `/claude_mode` still gets it.
41
+
42
+ **Binding a topic to a folder now leaves ONE message in the topic — the full welcome with the folder's facts and the start buttons — whichever way it happens.**
43
+ Before, a bind also posted extra messages that stayed in the topic as plainer copies of the same news: picking a folder with `/bind` (typed, tapped
44
+ in the picker or «create new folder») added a short «📁 Bound to `x`. Run /claude or /opencode.» just before the welcome, a topic the bot bound by
45
+ itself because its name matches a folder got a separate 👋 «auto-bound» greeting, a folder other topics already use got a separate ⚠️ warning, and
46
+ «create new folder» given the name of an existing folder added a «Folder already exists» note.
47
+ Now only the welcome is posted: a row in it says the bot bound the topic because its name matches the folder, another says the folder was there
48
+ already, and another names the topics that already use the folder — also when the bot bound the topic by itself. A topic is named there by the name
49
+ the bot saw it made with (or an admin renamed it to), else by a link that opens it; the name a non-admin gave a topic is not kept on its binding, since
50
+ the agent's thread context would repeat it. Only topics of the SAME chat are named: topics of other chats the bot serves (another group, a private chat) are
51
+ only counted, «+2 more» (a topic of this chat that has no name and no link to show is counted too), so one chat never learns what another calls its topics. A folder that does not exist still just gets its reason. When a topic is bound again, or leaves its folder, the buttons of its previous welcome (▶️ Claude, ▶️ OpenCode, 📋 Resume) are removed: they act on the topic's CURRENT folder, whatever the old message says, so an old welcome can no longer start an agent from a folder the topic has left. `/topic`'s «create new folder» still tells the topic
52
+ you typed the name in that the folder existed.
53
+ The `/bind` picker is now one-shot: once a folder is bound through it (a tap or «create new folder»), or «Leave current dir» is used, the picker message
54
+ is deleted — its «not bound, pick from the list» text would no longer be true — so an old tap cannot rebind the topic, and a second tap landing while the
55
+ first is still binding (on a folder, «create new folder» or «Leave current dir») is told «This picker was already used.» instead of binding or unbinding
56
+ twice; a refused pick, paging and the create-folder prompt leave it in place, and a tap whose answer reaches Telegram too late still does what it asked. Pickers the bot closes after a bind are refused at once, even those it could not delete (the bot keeps that in memory: after a restart a picker that still has its buttons works again), and a typed folder name that arrives while a tap holds the picker is told so instead of being dropped.
57
+ A «create new folder» wait ends with the bind or the leave that follows it, so the next plain message is never taken for a folder name, and its «send the folder
58
+ name» prompt is deleted with the bind (a refused name keeps it). Every plain message in an unbound topic posts a new folder picker, so a bind or a leave — by a tap,
59
+ a typed `/bind <folder>` or the bot's own auto-bind — deletes ALL the pickers still open in that topic, not only the tapped one: no stale one is left to rebind it.
60
+ When the bot binds a non-admin's topic on an admin's first message there, a plain message is answered by the welcome alone, without the extra «bound, run /claude» hint, and a
61
+ start phrase like `claude` still starts the agent; the topic is then stored under the matched folder's own name, never under the member's spelling. The
62
+ removed texts are gone from all 12 languages, the new rows and the toast are in all 12.
63
+ A topic you create whose name matches no folder now remembers that name for 24 hours: the folder picker you bind it through keeps it (the «also used by» row of a
64
+ later topic on that folder names it), and if a folder with that name appears meanwhile, your next message in the topic binds it by itself.
65
+
66
+ **`/task_agents` in General sets how many task agents may work at once — a number from the picker or any number you type.**
67
+ It opens a one-shot picker (5 / 10 / 15 / 20 / 30 / No limit, the value in force marked ✓) whose tap turns it into its confirmation;
68
+ `/task_agents 12` sets any whole number from 1 to 100, and `0` or `off` means no limit (a number over 100, a decimal or a word is refused with the
69
+ range). The screen names where the value comes from — set in General, `settings.json`, or the built-in default — and, on an instance that serves
70
+ Jira, how many agents work now and how many wait. General's own value beats `settings.json`'s once it is set, and a higher number starts the issues waiting for a slot at once; in a topic the command only reports
71
+ the value and says it is changed in General. The texts are in all 12 languages. General's `/help` also names it, and escapes the underscores of
72
+ its command names, so a pair of them can no longer be read as italics.
73
+
74
+ **The agents that work on Jira issues now run under ONE cap for the whole bot — 5 at once by default — and an issue over it waits in a queue and starts by itself.**
75
+ Before, every issue handed to the AI account started its agent at once, with nothing limiting how many ran together. Now the number of
76
+ tracker task agents working at the same time is capped for all projects together: `"taskAgents": { "maxConcurrent": 5 }` in
77
+ `settings.json` (`0` = no limit, 100 the most; read without a restart; nothing set means 5, so an instance gets the cap with this update).
78
+ An agent takes a slot when its issue is handed over and gives it back when it hands the issue back (a question or the final answer), when its
79
+ request is cancelled, or when the wake-up engine gave up on it and handed the issue back; an issue with several hand-overs open still holds one
80
+ slot, and an @-mention (answer only) never takes one or waits. An issue over the cap gets ONE short comment — «⏳ The AI is working on 5 tasks at
81
+ once, its limit, so this issue is queued (2 issues are ahead of it). It starts by itself when a slot frees up» — and stays assigned to the AI. The
82
+ waiting issues are one first-in-first-out list for the whole bot, kept in `state.json` so a restart keeps the order; the first one starts the
83
+ moment a slot frees — an agent hands its issue back, a request is cancelled, the wake-up engine gives up on one, or the cap is raised with
84
+ `/task_agents` — because the Jira poll then runs at once instead of at its next interval (a raise made by editing `settings.json` is noticed when
85
+ the bot next reads the file, at the latest at the next poll). An issue moved away from the AI while it waits leaves the list; an issue whose
86
+ start fails (its text cannot be read, say) keeps its place but no longer holds up the ones behind it, and after three failed starts in a row it
87
+ moves to the end of the list. A lower cap never stops an agent that is already working. A mistyped `taskAgents` is logged once as
88
+ `[Settings] settings.json taskAgents.maxConcurrent: …` and the built-in 5 applies.
89
+
90
+ **The "↩️ Resumed — last 3 messages" preview no longer shows what Claude Code records for itself: a `/compact` you ran there shows as just `/compact`.**
91
+ Before, resuming a conversation whose last entries were a command run in Claude Code itself printed the raw `<local-command-caveat>`,
92
+ `<command-name>… <command-args>…` (with the whole, often very long, argument text) and `<local-command-stdout>` entries as if they were your
93
+ messages, and a skill loaded in the last turn flooded the topic with its whole text. Now a command shows as its name only (a `!` shell command as
94
+ `!ls`), and the entries Claude Code flags as its own are left out — the summary a compaction leaves, a loaded skill's text, the caveat before a
95
+ command, image notes, messages from another session — as is an entry that is only a command's output, a reminder or a task notification. The
96
+ entries left out do not count: the preview still shows the last three real messages. A message of yours is shown whole, also when it pastes or
97
+ mentions one of these tags; only a `<system-reminder>` block that a hook appended to it is cut. The same goes for the recap after a bot restart
98
+ and for the titles in the `/sessions` list. When a limit moves a topic to another agent, the summary of the conversation's earlier compaction
99
+ (Claude topics) is handed over as context, labelled as such, and never as something you said.
100
+
101
+ **The skills Charness gives its agents can now be switched off — `/bot_skills` in General for the whole instance, in a topic for that topic only.**
102
+ A deployment whose workspace instructions name skills of their own (a Jira-only instance, say) no longer has to live with the bot's
103
+ `charness-manager` and delegate skills beside them, nor with the hint in the bot MCP's instructions to load the manager. `/bot_skills` opens a
104
+ one-shot picker: in General On / Off for the instance, in a topic On / Off / «As in General» with the current choice marked; a tap turns the picker
105
+ into its confirmation (the texts are in all 12 languages). An instance without General sets the default with `"botSkills": "on" | "off"` in
106
+ `settings.json` (read without a restart; General's own choice beats it once made; nothing set means ON, exactly as before). With the switch off a
107
+ Claude conversation starts and resumes without the bot's skills folder, and the hint is gone from its instructions (the worker-watch recipe in
108
+ `schedule_create` stays: it is a tool fact, not a skill). A running agent keeps its skills until its next start (the idle stop and resume, a new
109
+ session or a model change). OpenCode has one server for every topic, so only the instance value counts there: the server is replaced at the
110
+ bot's next start, once nothing works in it, by one started without (or, when turned back on, with) the skills folder — a `settings.json` that says
111
+ `off` is followed already by the server the hot supervisor starts first — and a topic's own choice changes only its hint — its screen says the listed skills stay, that the hint changes when the OpenCode server next restarts and that the
112
+ OpenCode topics of one folder share it. General's screen names where the value comes from (set in General, `settings.json`, or the built-in
113
+ default). A mistyped `botSkills` is logged once as `[Settings] settings.json botSkills: …`
114
+ and ON applies.
115
+
116
+ **The tmux backend for Claude Code is now marked deprecated: it is frozen and no longer developed, and `/claude_mode` says so.**
117
+ Before, nothing told you that, so you could pick a backend that gets no new features. The `/claude_mode` picker now shows it as
118
+ «🖥 tmux (deprecated)» with a line pointing to the recommended json-stream backend, the same hint follows a switch to it, `/status`
119
+ flags a topic that runs on it, and the command's menu text says «tmux (deprecated)». Nothing else changes: it stays selectable, a topic
120
+ already on it keeps working exactly as before and nothing is migrated for you. The texts are in all 12 languages.
121
+
122
+ **The local speech recognition (GigaAM) now recognises a voice message to its last second also when it is an MP3, an M4A or two OGG files joined into one.**
123
+ Before, an MP3 without a length header (a cut-out stream, or a variable-bitrate file) was read for only its first seconds — 6.7 s of a 40 s
124
+ file — the second half of two OGG files joined into one was dropped, and an M4A (AAC) was refused, so the next engine in your list
125
+ answered it or nothing did. Telegram's usual OGG/Opus voice notes are read exactly as before. The three formats are now decoded with
126
+ `av` (ffmpeg's libraries) in the engine's private Python environment: after this update the local engine re-installs itself once (about
127
+ a minute and a ~35 MB download, ~100 MB more disk; the model is not downloaded again, progress shows in General), and a voice sent
128
+ meanwhile goes to the next engine in your list.
129
+
130
+ **Every compaction summary now ends with a numbered checklist of what the agent does next, and its first item is to load the skills it had loaded.**
131
+ After a compaction the continuing session often skipped reloading its skills and worked without them. The checklist is now asked for on every path:
132
+ the idle compaction, `/compact`, the compaction the agent arms itself (`compact_conversation`), and the one the agent CLI or OpenCode runs by
133
+ itself when the context overflows. Item 1 is «load these skills» with their exact names (no such item when none was loaded), then the next steps the
134
+ summary already records, in order — none invented. The list is the last thing in the summary; where the idle compaction asks for the closing
135
+ «where we stopped» section, it is that section's last part. An OpenCode server that was already running gets the new text too: the plugin file in
136
+ OpenCode's plugin folder now carries a hash of its text in its name (`charness-compaction-<hash>.js`), so at the bot's next start a project folder
137
+ whose instance loaded an older text is recreated (when nothing runs in it; a working one is retried at the next start) and the older copies of the
138
+ file are removed.
139
+
140
+ **A usage-limit resume that finds its session gone no longer says «resumed» right before «no session».** When the bot restarted while a
141
+ topic waited for a limit's reset and the conversation was ended in the same moment, the topic read the pinned «work resumed» notice and
142
+ then «no session». The «resumed» notice now goes out only after a session took the "continue" prompt.
143
+
144
+ **A hot-mode bot no longer keeps running the old build after a big update because its TypeScript watcher went blind.** After a pull of
145
+ dozens of commits followed by a dependency install, the watcher could miss the changed files (the operating system drops file-change
146
+ events when too many arrive while the compiler is busy): it then reported errors that did not exist, or a clean build that emitted
147
+ nothing, `touch tsconfig.json` did not help and only a full service restart did, while the bot kept serving the old code without a
148
+ word. The hot supervisor now compares the watcher with the sources every 30 s and, when a source stays a minute newer than the build,
149
+ restarts the watcher alone (when it reports errors, only after a fresh compile finds none) — the bot, its agents and the supervisor
150
+ stay up, and the update reaches the worker like any other.
151
+
152
+ **Switching to the next entry of the fallback list on a usage limit is now ON by default, also with a single signed-in account.** The
153
+ «🔁 Auto switch» setting of `/limits_autoswitch` used to start OFF, so a limit stranded the work on the limit notice until someone
154
+ tapped «Switch to …» even when another entry had room. Now a topic that hits a limit moves by itself to the first entry of the list
155
+ with room — another Claude account, or an OpenCode provider and model, which hands the conversation over to a different agent in
156
+ compacted form. With one account and no list there is nothing to move to, so the bot waits for the reset as before, and an account
157
+ or an entry added later is used from the first limit on. An instance where you turned it OFF (in General or for one topic) keeps
158
+ your choice; if you do not want conversations handed to OpenCode by themselves, turn it OFF or leave OpenCode out of the list.
159
+
160
+ **Agents now get Charness's own orchestration skills.** Every agent session the bot starts — Claude Code in a topic or a Jira
161
+ conversation (the stream and the tmux backend) and OpenCode — gets the bot's skills: `charness-manager` for driving work
162
+ through detached workers with the bot's own tools, and `charness-delegate-claude` / `charness-delegate-opencode` for
163
+ launching, watching and resuming those workers (Claude Code lists them as `charness:charness-manager`, …). The manager
164
+ watches every worker with a bot check that fires when the worker exits OR stops writing for 45 minutes — a check that only
165
+ asks whether the process is alive never fires on a hung worker. Its alert pins silently, since a worker that simply finished
166
+ fires it too, and cancelling a watchdog check (`schedule_cancel`) unpins the alerts it pinned. A user or project skill of the same kind stays as it is, a Claude
167
+ Code older than 2.0.25 (which has no `--plugin-dir`) starts without them, the operator's own sessions outside the bot do not
168
+ get these skills, and an `OPENCODE_CONFIG_DIR` the operator set is kept (its
169
+ OpenCode topics then go without them). An OpenCode server the bot runs that an earlier version started is replaced at the bot's
170
+ next start once nothing works in it; a server the bot does not own is left as it is.
171
+
172
+ **A `/claude` sent right after `/quit` no longer loses its new session at start.** The ended session killed its tmux session a
173
+ second time, by name and without waiting, after the stop had killed it already; on a busy host that second kill could run once
174
+ the new session had created its own tmux session of the same name, and the start then failed with "the CLI exited before its
175
+ initialize handshake". An explicit stop kills the tmux session once. And `/quit` now says «stopped» only when the session is
176
+ stopped: a `/claude` sent on that reply used to be told "already running", and then nothing ran.
177
+
178
+ **A prompt that waited for the agent's running turn is no longer lost when the process is stopped right after that turn.** A Jira
179
+ hand-over or a scheduled run that arrived while the agent was still working was written to the process the per-turn stop had
180
+ just ended and dropped; the agent got it only minutes later, as a whole re-post. The prompt now makes sure the conversation is
181
+ awake again before it is sent, so the agent reads it once, as it was built.
182
+
183
+ **A usage-limit switch no longer prompts the agent twice.** Moving a limited topic to another model or account re-spawns the
184
+ session for a few seconds; a reminder for the interrupted request could land in that gap on top of the "continue" prompt the
185
+ move sends, and the agent answered twice (one answer's streamed text was lost). The request is no longer reminded while the
186
+ move is under way.
187
+
188
+ **A new turn's text no longer lands inside the previous turn's message.** When the Telegram API was slow, the previous turn's
189
+ last text could finish sending after the next prompt had gone to the agent, and the next turn's first text was then appended
190
+ to that message by an edit instead of starting its own. The "new message" mark now belongs to the first text queued after it,
191
+ and text still waiting when your next prompt goes out is no longer pulled into the new reply's message.
192
+
193
+ **The text a turn streamed before it failed now arrives before the error notice, and a restart no longer repeats an error already handled.**
194
+ A turn that ended on an error (a usage limit, an API error, an interrupt) kept its last text in the answer batch while the notice
195
+ went out at once: the text showed up below the limit notice, the switch offer and the usage board, and a bot restart in that
196
+ moment replayed the turn together with its error — a second notice or error line for a limit that was already announced, or a lost
197
+ auto-retry. The turn's text is now sent first, and the bot saves where it stopped reading at the end of the turn, as it does for
198
+ a turn that succeeded.
199
+
200
+ **A message sent right after a bot restart no longer mixes with a turn that was running when the bot went down.** The restarted
201
+ bot reads what the agent wrote while it was down a moment after it starts; a prompt that reached the agent before that (the
202
+ bot's own resume after a usage limit, a scheduled run, your message) reset the reply the replayed text still belonged to, so the
203
+ old turn's text could end up inside the new reply's message, and an error of the old turn took the new turn's place — shown as
204
+ a plain "Claude error" line and not retried. A prompt now waits for that replay (at most 30 s) before it is sent; if the agent is gone
205
+ when the wait ends, the topic says so and the request the message opened is closed, instead of the bot later asking the agent about
206
+ an answer it never started.
207
+
208
+ **A usage limit that stopped the agent while the bot was down is now handled once after the restart.** The restarted bot found the
209
+ limit error twice — once when it checked the agent's log at start (it resumes the topic at once when the window is over), and
210
+ once more when it read what the agent wrote during the downtime. The second copy was handled as a fresh limit: the topic got a
211
+ "Usage limit reached" notice for a window that was already over (for a reset written as a clock time, a wait of up to a day),
212
+ a second "work resumed" message, and the agent a second "Continue" prompt and a second turn. The first one now owns the
213
+ episode and the replayed copy is left out.
214
+
215
+ **A bot restart in the middle of a per-turn topic's turn no longer wipes that turn's working files.** The cleanup at start took the
216
+ running agent of a per-turn topic for a leftover and deleted its output log and pipes while the agent was still working, so the bot
217
+ could neither read the rest of the turn nor write to the agent: the answer never reached the topic. The daily cleanup did the same to
218
+ a turn that happened to be running then. The cleanup now knows both Claude lifecycles.
219
+
220
+ **After a restart, a usage limit that ended a turn while the bot was down no longer keeps the account marked limited for a day.** When the
221
+ restarted bot read that limit error from what the agent wrote during the downtime, it worked out a reset named by its clock
222
+ ("resets 10:20am") from the moment it read the error, not from the moment the error happened: a window that had closed half an
223
+ hour before was taken as closing tomorrow, and the account stayed limited — shown so on `/limits`, passed over by the account
224
+ switch — for up to a day. The reset is now worked out from the time the agent's transcript recorded the error.
225
+
226
+ **A working agent now hears of another topic's todo change in the middle of its turn.** Claude gets the project
227
+ board's changes with the result of its next tool call (a `PostToolUse` hook in the settings file the bot starts every
228
+ Claude session with), OpenCode as a queued message it reads between steps; an idle or sleeping agent is never woken
229
+ for it.
230
+
231
+ **The agents of one repository now see each other's todo lists.** Topics on checkouts or worktrees of the same git
232
+ repository form a project, and every prompt an agent gets carries the project board — the whole of it on a fresh
233
+ context, later only what changed in the other topics — as does its own `todo_update`; another topic's change never
234
+ wakes an agent. `/todo` → Project ▸ joins another topic's project or keeps an own one, `/todo` in General lists every
235
+ project, and Jira conversations share a board with the topics on the repositories their `jira.json` project lists in
236
+ the new `repos` key.
237
+
238
+ **An agent that works for an hour without updating its todo list is reminded to.** The next prompt it gets carries
239
+ one line; an agent that keeps working on its own gets a short prompt of its own at the end of a turn — never into a
240
+ running turn, a sleeping session, an unanswered request, a usage limit or an account billed to API credits — and the
241
+ bot falls silent after two ignored reminders. `/todo` in General → Settings turns the lists off or sets the interval
242
+ (off, 30 min, 1 h, 2 h, 4 h); an instance without General sets `todo` in `settings.json`.
243
+
244
+ **Agents publish what they work on, and `/todo` shows it.** Every topic's agent now keeps a short published todo list
245
+ — in work, the queue in order, done — through a new bot tool, adding an item before it starts a task and closing it
246
+ when it is done; `/todo` in a topic shows the list. It belongs to the topic, so `/new`, `/quit`, a backend switch and
247
+ a restart keep it, and a final answer while the list still shows unfinished work reminds the agent to update it. Jira
248
+ conversations publish the same way.
249
+
250
+ **Voice notes with pauses no longer lose phrases.** The local recognition (GigaAM) now cuts every voice at its pauses and
251
+ recognises the parts separately, so a phrase said after a pause is no longer dropped or merged into the previous one
252
+ (for example, "…купи хлеб? … и ещё молоко" could come out as just "…купи хлеб"). Nothing is cut away: the parts cover the whole
253
+ voice. After this update the local engine re-installs itself once (about a minute, the model is not downloaded again, the
254
+ progress shows in General); a voice sent meanwhile goes to the next engine in your list, or, with no other engine, the bot
255
+ asks you to send it again when the engine is ready.
256
+
257
+ **Voice notes from different topics are transcribed in the order they were sent.** The local recognition used to let
258
+ a short voice jump ahead of a longer one sent before it from another topic; now each voice waits its turn, and the bot
259
+ waits for it as long as its turn takes instead of giving up after the time its own length needs. A voice the bot has
260
+ stopped waiting for is no longer recognised in vain.
261
+
262
+ **Agents now launch workers on the Claude account whose weekly limit resets soonest, keep a resumed worker on its own account, and move a worker stopped by a limit to another account at once.**
263
+ Before, a worker (or a topic whose account hit its limit, with no `/limits_autoswitch` list) went to the account with the most room left, so an account about to
264
+ expire its week unused sat idle while the one with a fresh week took the work. Now a new worker starts on the usable account that resets its weekly window
265
+ first (an account whose five-hour window is at 90 % or more waits; Fable's own window takes out only Fable), a resumed worker stays on the account it
266
+ ran on, and one that broke off on a usage limit is resumed on another account straight away instead of waiting. When no account is usable the answer says
267
+ which one frees up first and when, so the manager schedules a single resume for that moment; when no account can say when it frees up, the manager asks you
268
+ and tries again in about half an hour. An account switched off in `/limits_autoswitch` is never picked
269
+ for a new worker, and one billed to API credits never is either. `charness claude-profiles` takes `--current <name>` and `--stopped-by-limit` for the same,
270
+ and a topic stopped by a limit with no list of its own now moves to the account that resets soonest rather than the roomiest.
271
+
5
272
  ## 3.6.1 — 2026-10-26
6
273
 
7
274
  **An agent @-mentioned on a Jira issue that is already assigned to it no longer asks to be assigned.** When the issue
package/DEVELOPMENT.md CHANGED
@@ -13,7 +13,7 @@ The per-topic folder layout is in [SETUP.md](SETUP.md) under
13
13
  Routing key is `(chatId, threadId)` everywhere. Per-thread state lives in
14
14
  `${DATA_DIR}/state.json` (atomic writes with `fsync`, archived on
15
15
  corruption). Bot-owned tmux sessions are named per backend —
16
- `claude-<chatId>-<threadId>` (Claude tmux-scrape), `cjson-…` (the Claude
16
+ `claude-<chatId>-<threadId>` (Claude tmux-scrape, deprecated), `cjson-…` (the Claude
17
17
  json-stream host process), `term-…` (terminal) — see
18
18
  `src/utils/tmuxSessionName.ts`; opencode sessions are keyed by the same
19
19
  `<chatId>:<threadId>` string. Two topics on the same folder stay independent.
@@ -27,7 +27,7 @@ tracker or Teams surface means adding a directory under `src/connectors/`, not
27
27
  editing the core.
28
28
 
29
29
  ```
30
- Telegram <-> connectors/telegram/ <-> bot.ts <-> AgentAdapter <-> { Claude CLI (tmux scrape) |
30
+ Telegram <-> connectors/telegram/ <-> bot.ts <-> AgentAdapter <-> { Claude CLI (tmux scrape, deprecated) |
31
31
  inbound.ts (core) │ Claude CLI (stream-json) |
32
32
  outbound.ts + output/ │ │ OpenCode (HTTP+SSE) |
33
33
  sessionKeyCodec.ts │ │ Terminal ($SHELL in tmux) }
@@ -104,6 +104,17 @@ keep when touching the restart path:
104
104
  sends `SIGUSR2` — only when pid and start token match. The supervisor stops `tsc -w` and nodemon, leaves the OpenCode
105
105
  server and the speech sidecar alone and `execve`s `cli.js hot`. A supervisor that predates this has no record and is
106
106
  never signalled (an unhandled `SIGUSR2` kills a process).
107
+ - **The hot supervisor guards its watcher** (`cli/tscWatchGuard.ts`). `tsc -w` learns of a changed source only from file-system
108
+ events, and a burst — a pull of dozens of commits, then `yarn install` — overflows the inotify queue (`max_queued_events`,
109
+ 16384) while the compiler is busy: the dropped events leave the watcher with the OLD text of the files it missed (errors where an
110
+ old definition meets new callers, or a clean report that emitted nothing); `touch tsconfig.json` re-reads none of them, only a
111
+ new `tsc -w` does, and the worker keeps running the old build. Every 30 s the supervisor compares the idle watcher with the
112
+ tree: a compiled source (`selfUpdate/emittedSource.ts`) a minute newer than its `dist/` output is a missed change — with "0
113
+ errors" the WATCHER (not the supervisor, not the worker) is restarted at once, with errors a one-shot `tsc --noEmit` decides
114
+ (clean there = the watcher is wrong). At most 3 restarts an hour, then it only says so; and a set of sources a restarted watcher still
115
+ leaves newer than their output (a modification time in the future, a path `tsconfig.json` excludes that `emittedSource.ts` does not know —
116
+ `emittedSource.test.ts` keeps the two lists equal) is reported once and not restarted for again. The flow `selfUpdateHotE2e` freezes the
117
+ real `tsc -w`, overflows the queue and replaces a source: the change must still reach `dist/`.
107
118
  - **`update-pending.json` is written BEFORE the switch**; every boot counts itself in (`cli/bot.ts`, once the instance lock is held and before the bot
108
119
  module is imported), the boot after two unconfirmed ones rolls back, the running bot confirms 60 s after launch.
109
120
 
@@ -139,6 +150,18 @@ To run your checkout as the global `charness` command instead of the npm package
139
150
  without re-installing; `npm install -g .` installs a copy instead. Configuration and launch are as in
140
151
  [SETUP.md](SETUP.md).
141
152
 
153
+ `yarn test:unit` also runs the STT sidecar's Python tests (`sttSidecarPython.test.ts` → `stt/test_gigaam_sidecar.py`,
154
+ no model needed). They want **`uv`** (an ephemeral environment with numpy and the pinned soundfile and av; the first run
155
+ downloads them, so it needs the network once) or a **`python3` that has numpy, soundfile and av**. Without either, or when
156
+ `uv` cannot reach the package index, a local run skips that test and says why; CI (`CI=true`, uv installed by the
157
+ workflow) fails instead.
158
+
159
+ The `charness remote-run` flow (two files that run side by side, each with a runner of its own — `remoteRunE2e.test.ts`, `remoteRunLifecycleE2e.test.ts`; the shared helpers are `remoteRunE2e/remoteRunFlowHarness.ts`) drives the built CLI against a throwaway loopback `sshd` (no root), `rsync` and a
160
+ private **Pueue** in temp dirs. It wants `sshd` (`openssh-server`), `ssh`, `rsync`, `pueue` / `pueued` 4.x on `PATH` and `yarn build`;
161
+ a local run without them is skipped with the reason, CI (`CI=true`) installs them (the workflow pins Pueue by checksum) and fails
162
+ without. A flow that is killed or times out cannot leave daemons behind: `remoteRunE2e/remoteRunFlowSweep.ts` ends what names its
163
+ layout, from the teardown, from a detached reaper and at the next start.
164
+
142
165
  Node applies `--test-timeout` to a whole test FILE (a `describe`'s own `timeout` cannot extend it), so a file that
143
166
  hangs or leaves a process alive fails by name when its limit passes, instead of hanging the run. A long-running
144
167
  flow file must be named `*E2e.test.ts` to get the flows' limit; `live/*Live.test.ts` is run directly (CLAUDE.md).
@@ -148,10 +171,13 @@ not with the runner's bare timeout. Run one flow directly with `--test-timeout=<
148
171
 
149
172
  A flow does not wait out the production windows in real time: its env file sets `CHARNESS_TEST_TIMINGS`, a JSON object
150
173
  of named overrides (`src/testTimings.ts`: `telegramSendIntervalMs` — the global send pacer's 2 s, `jiraPollIntervalMs` —
151
- below the 10 s floor of `jira.json`, `requestSweepIntervalMs` and `requestFirstPostRetryDelayMs` — the wake-up engine's
152
- minutes, `limitProbeDelayMs` — the two-minute probe of an unconfirmed usage limit, `stateSaveDebounceMs` — `state.json`'s
174
+ below the 10 s floor of `jira.json`, `requestTurnPollMs` — the wake-up engine's 10 s poll of the turns it watches,
175
+ `requestSweepIntervalMs` and `requestFirstPostRetryDelayMs` — the wake-up engine's minutes, `limitProbeDelayMs` — the two-minute probe of an unconfirmed usage limit, `stateSaveDebounceMs` — `state.json`'s
153
176
  500 ms save debounce, `openCodeServerUpBudgetMs` — the OpenCode server's 60 s of retries, `backgroundHoldMaxMs` — the 6 h the
154
- agent's own pending work holds a json-stream process). It is the ONE test-only timing seam,
177
+ agent's own pending work holds a json-stream process, `todoReminderPollMs` and `todoReminderIntervalMs` — the todo
178
+ reminder's 10 s poll and the interval `settings.json` sets, `scheduleMinFireIntervalMs` — the 5 min minimum between cron fires, `bindPickerClaimLimit` — how many `/bind` picker claims are kept (a count: 200), `tscWatchCheckIntervalMs` and `tscWatchStaleGraceMs` — the
179
+ hot supervisor's 30 s check of its `tsc -w` and the minute a source may stay newer than its output; the supervisor reads these two, the bot the rest).
180
+ It is the ONE test-only timing seam,
155
181
  never a setting: unset, every window is the production one; a value may only shorten its window (each key is capped at its
156
182
  production value); set, the boot prints `[test-timings] … overrides active`, and
157
183
  an unknown key or a bad value stops the start naming it.
@@ -20,7 +20,7 @@ start the bot renames the config and data dirs itself, see [Automatic migration]
20
20
  | `~/.telegramCode` — the default `DATA_DIR` | `~/.charness` | used while `~/.charness` does not exist (or holds no `state.json` while the old dir does); an explicit `DATA_DIR` is never touched |
21
21
  | `TELEGRAMCODE_HOT_RELOAD`, `TELEGRAMCODE_OPENCODE_PROCESS_FILE` | `CHARNESS_HOT_RELOAD`, `CHARNESS_OPENCODE_PROCESS_FILE` | read when the new one is unset; `charness hot` sets both |
22
22
  | MCP header `x-telegramcode-mcp-client-id` | `x-charness-mcp-client-id` | the bot's MCP server accepts both |
23
- | OpenCode plugin `telegramcode-compaction.js` (id `telegramcode-compaction`) | `charness-compaction.js` (id `charness-compaction`) | the old file is removed when the new one is installed |
23
+ | OpenCode plugin `telegramcode-compaction.js` (id `telegramcode-compaction`) | `charness-compaction-<hash>.js` (id `charness-compaction`; the hash is of the plugin's text) | the old file is removed when the new one is installed |
24
24
  | Docker image `telegramcode`, service `telegramcode`, container `telegramcode-main` | `charness`, `charness`, `charness-main` | a container of the old image keeps running as it is |
25
25
  | `/opt/telegramcode`, `/home/telegramcode`, `/srv/telegramcode/…` (Docker mounts and host paths) | `/opt/charness`, `/home/charness`, `/srv/charness/…` | the new image's entrypoint accepts the old mount points |
26
26
  | `telegramcode-restart-bot` | `charness-restart-bot` | the old name is a link in the new image and says so |
@@ -130,4 +130,5 @@ you next rebuild the image:
130
130
  - `[deprecated] TELEGRAMCODE_HOT_RELOAD … the running charness hot supervisor still sets it`: restart the
131
131
  supervisor (above).
132
132
  - The OpenCode compaction plugin is reinstalled under its new name and the old file is deleted; a folder whose
133
- OpenCode instance already loaded the old plugin keeps it until OpenCode is restarted.
133
+ OpenCode instance already loaded the old plugin is recreated at the bot's next start when nothing runs in it
134
+ (a working one keeps the old plugin until a later start finds it idle).