@jungjaehoon/mama-os 0.53.1 → 0.57.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 (1717) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/README.md +62 -259
  3. package/db/migrations/001-connector-event-index.sql +251 -0
  4. package/dist/agent/claude-native-tool-policy.d.ts +17 -0
  5. package/dist/agent/claude-native-tool-policy.d.ts.map +1 -0
  6. package/dist/agent/claude-native-tool-policy.js +88 -0
  7. package/dist/agent/claude-native-tool-policy.js.map +1 -0
  8. package/dist/api/attachment-actions.d.ts +16 -0
  9. package/dist/api/attachment-actions.d.ts.map +1 -0
  10. package/dist/api/attachment-actions.js +278 -0
  11. package/dist/api/attachment-actions.js.map +1 -0
  12. package/dist/api/auth-middleware.d.ts +15 -55
  13. package/dist/api/auth-middleware.d.ts.map +1 -1
  14. package/dist/api/auth-middleware.js +56 -233
  15. package/dist/api/auth-middleware.js.map +1 -1
  16. package/dist/api/cf-access.d.ts +6 -0
  17. package/dist/api/cf-access.d.ts.map +1 -0
  18. package/dist/api/cf-access.js +121 -0
  19. package/dist/api/cf-access.js.map +1 -0
  20. package/dist/api/file-delivery.d.ts +29 -0
  21. package/dist/api/file-delivery.d.ts.map +1 -0
  22. package/dist/api/file-delivery.js +90 -0
  23. package/dist/api/file-delivery.js.map +1 -0
  24. package/dist/api/owner-timezone-actions.d.ts +10 -0
  25. package/dist/api/owner-timezone-actions.d.ts.map +1 -0
  26. package/dist/api/owner-timezone-actions.js +73 -0
  27. package/dist/api/owner-timezone-actions.js.map +1 -0
  28. package/dist/api/report-actions.d.ts +22 -0
  29. package/dist/api/report-actions.d.ts.map +1 -0
  30. package/dist/api/report-actions.js +137 -0
  31. package/dist/api/report-actions.js.map +1 -0
  32. package/dist/api/report-handler.d.ts +15 -11
  33. package/dist/api/report-handler.d.ts.map +1 -1
  34. package/dist/api/report-handler.js +48 -120
  35. package/dist/api/report-handler.js.map +1 -1
  36. package/dist/api/report-persistence.d.ts +3 -3
  37. package/dist/api/report-persistence.d.ts.map +1 -1
  38. package/dist/api/report-persistence.js +35 -10
  39. package/dist/api/report-persistence.js.map +1 -1
  40. package/dist/api/report-source-actions.d.ts +11 -0
  41. package/dist/api/report-source-actions.d.ts.map +1 -0
  42. package/dist/api/report-source-actions.js +309 -0
  43. package/dist/api/report-source-actions.js.map +1 -0
  44. package/dist/api/security-events.d.ts +23 -0
  45. package/dist/api/security-events.d.ts.map +1 -0
  46. package/dist/api/security-events.js +71 -0
  47. package/dist/api/security-events.js.map +1 -0
  48. package/dist/api/source-actions.d.ts +9 -0
  49. package/dist/api/source-actions.d.ts.map +1 -0
  50. package/dist/api/source-actions.js +274 -0
  51. package/dist/api/source-actions.js.map +1 -0
  52. package/dist/api/stored-source-reader.d.ts +21 -0
  53. package/dist/api/stored-source-reader.d.ts.map +1 -0
  54. package/dist/api/stored-source-reader.js +269 -0
  55. package/dist/api/stored-source-reader.js.map +1 -0
  56. package/dist/api/viewer-data.d.ts +143 -0
  57. package/dist/api/viewer-data.d.ts.map +1 -0
  58. package/dist/api/viewer-data.js +518 -0
  59. package/dist/api/viewer-data.js.map +1 -0
  60. package/dist/api/viewer-request-security.d.ts +12 -0
  61. package/dist/api/viewer-request-security.d.ts.map +1 -0
  62. package/dist/api/viewer-request-security.js +217 -0
  63. package/dist/api/viewer-request-security.js.map +1 -0
  64. package/dist/api/viewer-server.d.ts +55 -0
  65. package/dist/api/viewer-server.d.ts.map +1 -0
  66. package/dist/api/viewer-server.js +933 -0
  67. package/dist/api/viewer-server.js.map +1 -0
  68. package/dist/api/wiki-actions.d.ts +20 -0
  69. package/dist/api/wiki-actions.d.ts.map +1 -0
  70. package/dist/api/wiki-actions.js +296 -0
  71. package/dist/api/wiki-actions.js.map +1 -0
  72. package/dist/api/work-actions.d.ts +109 -0
  73. package/dist/api/work-actions.d.ts.map +1 -0
  74. package/dist/api/work-actions.js +987 -0
  75. package/dist/api/work-actions.js.map +1 -0
  76. package/dist/cli/commands/daemon.d.ts +90 -0
  77. package/dist/cli/commands/daemon.d.ts.map +1 -0
  78. package/dist/cli/commands/daemon.js +620 -0
  79. package/dist/cli/commands/daemon.js.map +1 -0
  80. package/dist/cli/commands/init.d.ts +7 -18
  81. package/dist/cli/commands/init.d.ts.map +1 -1
  82. package/dist/cli/commands/init.js +357 -273
  83. package/dist/cli/commands/init.js.map +1 -1
  84. package/dist/cli/commands/replay.d.ts +12 -0
  85. package/dist/cli/commands/replay.d.ts.map +1 -0
  86. package/dist/cli/commands/replay.js +145 -0
  87. package/dist/cli/commands/replay.js.map +1 -0
  88. package/dist/cli/commands/secret.d.ts +6 -0
  89. package/dist/cli/commands/secret.d.ts.map +1 -0
  90. package/dist/cli/commands/secret.js +24 -0
  91. package/dist/cli/commands/secret.js.map +1 -0
  92. package/dist/cli/index.d.ts +0 -5
  93. package/dist/cli/index.d.ts.map +1 -1
  94. package/dist/cli/index.js +52 -95
  95. package/dist/cli/index.js.map +1 -1
  96. package/dist/cli/launch-files.d.ts +10 -0
  97. package/dist/cli/launch-files.d.ts.map +1 -0
  98. package/dist/cli/launch-files.js +74 -0
  99. package/dist/cli/launch-files.js.map +1 -0
  100. package/dist/cli/prompt.d.ts +15 -0
  101. package/dist/cli/prompt.d.ts.map +1 -0
  102. package/dist/cli/prompt.js +64 -0
  103. package/dist/cli/prompt.js.map +1 -0
  104. package/dist/cli/runtime/action-mcp-config.d.ts +15 -0
  105. package/dist/cli/runtime/action-mcp-config.d.ts.map +1 -0
  106. package/dist/cli/runtime/action-mcp-config.js +56 -0
  107. package/dist/cli/runtime/action-mcp-config.js.map +1 -0
  108. package/dist/cli/runtime/claude-caller-config.d.ts +4 -0
  109. package/dist/cli/runtime/claude-caller-config.d.ts.map +1 -0
  110. package/dist/cli/runtime/claude-caller-config.js +46 -0
  111. package/dist/cli/runtime/claude-caller-config.js.map +1 -0
  112. package/dist/cli/secrets.d.ts +9 -0
  113. package/dist/cli/secrets.d.ts.map +1 -0
  114. package/dist/cli/secrets.js +94 -0
  115. package/dist/cli/secrets.js.map +1 -0
  116. package/dist/connectors/calendar/index.d.ts +11 -10
  117. package/dist/connectors/calendar/index.d.ts.map +1 -1
  118. package/dist/connectors/calendar/index.js +171 -97
  119. package/dist/connectors/calendar/index.js.map +1 -1
  120. package/dist/connectors/chatwork/index.d.ts +31 -5
  121. package/dist/connectors/chatwork/index.d.ts.map +1 -1
  122. package/dist/connectors/chatwork/index.js +184 -20
  123. package/dist/connectors/chatwork/index.js.map +1 -1
  124. package/dist/connectors/claude-code/index.d.ts +0 -2
  125. package/dist/connectors/claude-code/index.d.ts.map +1 -1
  126. package/dist/connectors/claude-code/index.js +94 -70
  127. package/dist/connectors/claude-code/index.js.map +1 -1
  128. package/dist/connectors/config-loader.d.ts +1 -6
  129. package/dist/connectors/config-loader.d.ts.map +1 -1
  130. package/dist/connectors/config-loader.js +154 -134
  131. package/dist/connectors/config-loader.js.map +1 -1
  132. package/dist/connectors/discord/index.d.ts +8 -1
  133. package/dist/connectors/discord/index.d.ts.map +1 -1
  134. package/dist/connectors/discord/index.js +110 -32
  135. package/dist/connectors/discord/index.js.map +1 -1
  136. package/dist/connectors/drive/index.d.ts +10 -5
  137. package/dist/connectors/drive/index.d.ts.map +1 -1
  138. package/dist/connectors/drive/index.js +145 -88
  139. package/dist/connectors/drive/index.js.map +1 -1
  140. package/dist/connectors/framework/attachment-io.d.ts +5 -0
  141. package/dist/connectors/framework/attachment-io.d.ts.map +1 -0
  142. package/dist/connectors/framework/attachment-io.js +72 -0
  143. package/dist/connectors/framework/attachment-io.js.map +1 -0
  144. package/dist/connectors/framework/attachments.d.ts +32 -0
  145. package/dist/connectors/framework/attachments.d.ts.map +1 -0
  146. package/dist/connectors/framework/attachments.js +14 -0
  147. package/dist/connectors/framework/attachments.js.map +1 -0
  148. package/dist/connectors/framework/connector-event-types.d.ts +136 -0
  149. package/dist/connectors/framework/connector-event-types.d.ts.map +1 -0
  150. package/dist/connectors/framework/connector-event-types.js +3 -0
  151. package/dist/connectors/framework/connector-event-types.js.map +1 -0
  152. package/dist/connectors/framework/connector-state.d.ts +3 -0
  153. package/dist/connectors/framework/connector-state.d.ts.map +1 -0
  154. package/dist/connectors/framework/connector-state.js +47 -0
  155. package/dist/connectors/framework/connector-state.js.map +1 -0
  156. package/dist/connectors/framework/event-index.d.ts +28 -0
  157. package/dist/connectors/framework/event-index.d.ts.map +1 -0
  158. package/dist/connectors/framework/event-index.js +354 -0
  159. package/dist/connectors/framework/event-index.js.map +1 -0
  160. package/dist/connectors/framework/gws-utils.d.ts +3 -8
  161. package/dist/connectors/framework/gws-utils.d.ts.map +1 -1
  162. package/dist/connectors/framework/gws-utils.js +23 -30
  163. package/dist/connectors/framework/gws-utils.js.map +1 -1
  164. package/dist/connectors/framework/index.d.ts +4 -2
  165. package/dist/connectors/framework/index.d.ts.map +1 -1
  166. package/dist/connectors/framework/index.js +8 -6
  167. package/dist/connectors/framework/index.js.map +1 -1
  168. package/dist/connectors/framework/polling-scheduler.d.ts +71 -52
  169. package/dist/connectors/framework/polling-scheduler.d.ts.map +1 -1
  170. package/dist/connectors/framework/polling-scheduler.js +227 -168
  171. package/dist/connectors/framework/polling-scheduler.js.map +1 -1
  172. package/dist/connectors/framework/raw-query.d.ts +44 -0
  173. package/dist/connectors/framework/raw-query.d.ts.map +1 -0
  174. package/dist/connectors/framework/raw-query.js +584 -0
  175. package/dist/connectors/framework/raw-query.js.map +1 -0
  176. package/dist/connectors/framework/stored-index-read.d.ts +16 -0
  177. package/dist/connectors/framework/stored-index-read.d.ts.map +1 -0
  178. package/dist/connectors/framework/stored-index-read.js +66 -0
  179. package/dist/connectors/framework/stored-index-read.js.map +1 -0
  180. package/dist/connectors/framework/types.d.ts +17 -61
  181. package/dist/connectors/framework/types.d.ts.map +1 -1
  182. package/dist/connectors/framework/types.js +0 -4
  183. package/dist/connectors/framework/types.js.map +1 -1
  184. package/dist/connectors/gmail/index.d.ts +3 -2
  185. package/dist/connectors/gmail/index.d.ts.map +1 -1
  186. package/dist/connectors/gmail/index.js +74 -27
  187. package/dist/connectors/gmail/index.js.map +1 -1
  188. package/dist/connectors/ical/index.d.ts +29 -0
  189. package/dist/connectors/ical/index.d.ts.map +1 -0
  190. package/dist/connectors/ical/index.js +220 -0
  191. package/dist/connectors/ical/index.js.map +1 -0
  192. package/dist/connectors/ical/parser.d.ts +13 -0
  193. package/dist/connectors/ical/parser.d.ts.map +1 -0
  194. package/dist/connectors/ical/parser.js +117 -0
  195. package/dist/connectors/ical/parser.js.map +1 -0
  196. package/dist/connectors/imessage/index.d.ts +3 -1
  197. package/dist/connectors/imessage/index.d.ts.map +1 -1
  198. package/dist/connectors/imessage/index.js +31 -16
  199. package/dist/connectors/imessage/index.js.map +1 -1
  200. package/dist/connectors/index.d.ts +12 -5
  201. package/dist/connectors/index.d.ts.map +1 -1
  202. package/dist/connectors/index.js +67 -18
  203. package/dist/connectors/index.js.map +1 -1
  204. package/dist/connectors/kagemusha/index.d.ts +7 -19
  205. package/dist/connectors/kagemusha/index.d.ts.map +1 -1
  206. package/dist/connectors/kagemusha/index.js +123 -173
  207. package/dist/connectors/kagemusha/index.js.map +1 -1
  208. package/dist/connectors/notion/index.d.ts.map +1 -1
  209. package/dist/connectors/notion/index.js +79 -36
  210. package/dist/connectors/notion/index.js.map +1 -1
  211. package/dist/connectors/obsidian/index.d.ts +1 -1
  212. package/dist/connectors/obsidian/index.d.ts.map +1 -1
  213. package/dist/connectors/obsidian/index.js +59 -57
  214. package/dist/connectors/obsidian/index.js.map +1 -1
  215. package/dist/connectors/sheets/index.d.ts +8 -4
  216. package/dist/connectors/sheets/index.d.ts.map +1 -1
  217. package/dist/connectors/sheets/index.js +155 -143
  218. package/dist/connectors/sheets/index.js.map +1 -1
  219. package/dist/connectors/slack/index.d.ts +24 -5
  220. package/dist/connectors/slack/index.d.ts.map +1 -1
  221. package/dist/connectors/slack/index.js +177 -39
  222. package/dist/connectors/slack/index.js.map +1 -1
  223. package/dist/connectors/telegram/index.d.ts +9 -2
  224. package/dist/connectors/telegram/index.d.ts.map +1 -1
  225. package/dist/connectors/telegram/index.js +119 -70
  226. package/dist/connectors/telegram/index.js.map +1 -1
  227. package/dist/connectors/trello/index.d.ts +10 -3
  228. package/dist/connectors/trello/index.d.ts.map +1 -1
  229. package/dist/connectors/trello/index.js +88 -39
  230. package/dist/connectors/trello/index.js.map +1 -1
  231. package/dist/gateways/base-gateway.d.ts +9 -33
  232. package/dist/gateways/base-gateway.d.ts.map +1 -1
  233. package/dist/gateways/base-gateway.js +7 -28
  234. package/dist/gateways/base-gateway.js.map +1 -1
  235. package/dist/gateways/conversation-record.d.ts +52 -0
  236. package/dist/gateways/conversation-record.d.ts.map +1 -0
  237. package/dist/gateways/conversation-record.js +220 -0
  238. package/dist/gateways/conversation-record.js.map +1 -0
  239. package/dist/gateways/discord.d.ts +33 -135
  240. package/dist/gateways/discord.d.ts.map +1 -1
  241. package/dist/gateways/discord.js +258 -778
  242. package/dist/gateways/discord.js.map +1 -1
  243. package/dist/gateways/session-store.d.ts +28 -9
  244. package/dist/gateways/session-store.d.ts.map +1 -1
  245. package/dist/gateways/session-store.js +192 -60
  246. package/dist/gateways/session-store.js.map +1 -1
  247. package/dist/gateways/slack.d.ts +35 -105
  248. package/dist/gateways/slack.d.ts.map +1 -1
  249. package/dist/gateways/slack.js +282 -440
  250. package/dist/gateways/slack.js.map +1 -1
  251. package/dist/gateways/telegram-attachments.d.ts +32 -0
  252. package/dist/gateways/telegram-attachments.d.ts.map +1 -0
  253. package/dist/gateways/telegram-attachments.js +113 -0
  254. package/dist/gateways/telegram-attachments.js.map +1 -0
  255. package/dist/gateways/telegram-errors.d.ts +3 -0
  256. package/dist/gateways/telegram-errors.d.ts.map +1 -0
  257. package/dist/gateways/telegram-errors.js +10 -0
  258. package/dist/gateways/telegram-errors.js.map +1 -0
  259. package/dist/gateways/telegram-format.d.ts.map +1 -1
  260. package/dist/gateways/telegram-format.js +9 -1
  261. package/dist/gateways/telegram-format.js.map +1 -1
  262. package/dist/gateways/telegram-message-ledger.d.ts +31 -25
  263. package/dist/gateways/telegram-message-ledger.d.ts.map +1 -1
  264. package/dist/gateways/telegram-message-ledger.js +122 -146
  265. package/dist/gateways/telegram-message-ledger.js.map +1 -1
  266. package/dist/gateways/telegram-response-presenter.d.ts +3 -1
  267. package/dist/gateways/telegram-response-presenter.d.ts.map +1 -1
  268. package/dist/gateways/telegram-response-presenter.js +14 -0
  269. package/dist/gateways/telegram-response-presenter.js.map +1 -1
  270. package/dist/gateways/telegram-text-entities.d.ts +2 -3
  271. package/dist/gateways/telegram-text-entities.d.ts.map +1 -1
  272. package/dist/gateways/telegram-text-entities.js +4 -5
  273. package/dist/gateways/telegram-text-entities.js.map +1 -1
  274. package/dist/gateways/telegram.d.ts +39 -101
  275. package/dist/gateways/telegram.d.ts.map +1 -1
  276. package/dist/gateways/telegram.js +406 -919
  277. package/dist/gateways/telegram.js.map +1 -1
  278. package/dist/gateways/turn-contract.d.ts +27 -87
  279. package/dist/gateways/turn-contract.d.ts.map +1 -1
  280. package/dist/gateways/types.d.ts +14 -299
  281. package/dist/gateways/types.d.ts.map +1 -1
  282. package/dist/gateways/types.js +0 -3
  283. package/dist/gateways/types.js.map +1 -1
  284. package/dist/index.d.ts +1 -6
  285. package/dist/index.d.ts.map +1 -1
  286. package/dist/index.js +0 -23
  287. package/dist/index.js.map +1 -1
  288. package/dist/operator/board-read-views.d.ts +8 -10
  289. package/dist/operator/board-read-views.d.ts.map +1 -1
  290. package/dist/operator/board-read-views.js +4 -13
  291. package/dist/operator/board-read-views.js.map +1 -1
  292. package/dist/operator/board-slot-instructions.d.ts +10 -11
  293. package/dist/operator/board-slot-instructions.d.ts.map +1 -1
  294. package/dist/operator/board-slot-instructions.js +22 -21
  295. package/dist/operator/board-slot-instructions.js.map +1 -1
  296. package/dist/replay/import-manifest.d.ts +21 -0
  297. package/dist/replay/import-manifest.d.ts.map +1 -0
  298. package/dist/replay/import-manifest.js +157 -0
  299. package/dist/replay/import-manifest.js.map +1 -0
  300. package/dist/replay/jev-client.d.ts +35 -0
  301. package/dist/replay/jev-client.d.ts.map +1 -0
  302. package/dist/replay/jev-client.js +141 -0
  303. package/dist/replay/jev-client.js.map +1 -0
  304. package/dist/replay/kagemusha-import.d.ts +35 -0
  305. package/dist/replay/kagemusha-import.d.ts.map +1 -0
  306. package/dist/replay/kagemusha-import.js +543 -0
  307. package/dist/replay/kagemusha-import.js.map +1 -0
  308. package/dist/replay/replay-cursor.d.ts +31 -0
  309. package/dist/replay/replay-cursor.d.ts.map +1 -0
  310. package/dist/replay/replay-cursor.js +189 -0
  311. package/dist/replay/replay-cursor.js.map +1 -0
  312. package/dist/replay/replay-feeder.d.ts +55 -0
  313. package/dist/replay/replay-feeder.d.ts.map +1 -0
  314. package/dist/replay/replay-feeder.js +214 -0
  315. package/dist/replay/replay-feeder.js.map +1 -0
  316. package/dist/replay/replay-ledger.d.ts +32 -0
  317. package/dist/replay/replay-ledger.d.ts.map +1 -0
  318. package/dist/replay/replay-ledger.js +91 -0
  319. package/dist/replay/replay-ledger.js.map +1 -0
  320. package/dist/replay/replay-source-catalog.d.ts +66 -0
  321. package/dist/replay/replay-source-catalog.d.ts.map +1 -0
  322. package/dist/replay/replay-source-catalog.js +332 -0
  323. package/dist/replay/replay-source-catalog.js.map +1 -0
  324. package/dist/replay/trello-import.d.ts +33 -0
  325. package/dist/replay/trello-import.d.ts.map +1 -0
  326. package/dist/replay/trello-import.js +204 -0
  327. package/dist/replay/trello-import.js.map +1 -0
  328. package/dist/replay/window-queue.d.ts +116 -0
  329. package/dist/replay/window-queue.d.ts.map +1 -0
  330. package/dist/replay/window-queue.js +497 -0
  331. package/dist/replay/window-queue.js.map +1 -0
  332. package/dist/runtime/action-mcp-server.d.ts +30 -0
  333. package/dist/runtime/action-mcp-server.d.ts.map +1 -0
  334. package/dist/runtime/action-mcp-server.js +179 -0
  335. package/dist/runtime/action-mcp-server.js.map +1 -0
  336. package/dist/runtime/action-surface.d.ts +47 -0
  337. package/dist/runtime/action-surface.d.ts.map +1 -0
  338. package/dist/runtime/action-surface.js +182 -0
  339. package/dist/runtime/action-surface.js.map +1 -0
  340. package/dist/runtime/backend-security.d.ts +7 -0
  341. package/dist/runtime/backend-security.d.ts.map +1 -0
  342. package/dist/runtime/backend-security.js +28 -0
  343. package/dist/runtime/backend-security.js.map +1 -0
  344. package/dist/runtime/claude-caller-hook.d.ts +20 -0
  345. package/dist/runtime/claude-caller-hook.d.ts.map +1 -0
  346. package/dist/runtime/claude-caller-hook.js +41 -0
  347. package/dist/runtime/claude-caller-hook.js.map +1 -0
  348. package/dist/runtime/config.d.ts +84 -0
  349. package/dist/runtime/config.d.ts.map +1 -0
  350. package/dist/runtime/config.js +361 -0
  351. package/dist/runtime/config.js.map +1 -0
  352. package/dist/runtime/connectors.d.ts +41 -0
  353. package/dist/runtime/connectors.d.ts.map +1 -0
  354. package/dist/runtime/connectors.js +187 -0
  355. package/dist/runtime/connectors.js.map +1 -0
  356. package/dist/runtime/core-db.d.ts +8 -0
  357. package/dist/runtime/core-db.d.ts.map +1 -0
  358. package/dist/runtime/core-db.js +19 -0
  359. package/dist/runtime/core-db.js.map +1 -0
  360. package/dist/runtime/model-cache.d.ts +9 -0
  361. package/dist/runtime/model-cache.d.ts.map +1 -0
  362. package/dist/runtime/model-cache.js +22 -0
  363. package/dist/runtime/model-cache.js.map +1 -0
  364. package/dist/runtime/native-session.d.ts +80 -0
  365. package/dist/runtime/native-session.d.ts.map +1 -0
  366. package/dist/runtime/native-session.js +284 -0
  367. package/dist/runtime/native-session.js.map +1 -0
  368. package/dist/runtime/owner-policy.d.ts +10 -0
  369. package/dist/runtime/owner-policy.d.ts.map +1 -0
  370. package/dist/runtime/owner-policy.js +35 -0
  371. package/dist/runtime/owner-policy.js.map +1 -0
  372. package/dist/runtime/owner-runtime.d.ts +78 -0
  373. package/dist/runtime/owner-runtime.d.ts.map +1 -0
  374. package/dist/runtime/owner-runtime.js +255 -0
  375. package/dist/runtime/owner-runtime.js.map +1 -0
  376. package/dist/runtime/owner-system-prompt.d.ts +17 -0
  377. package/dist/runtime/owner-system-prompt.d.ts.map +1 -0
  378. package/dist/runtime/owner-system-prompt.js +122 -0
  379. package/dist/runtime/owner-system-prompt.js.map +1 -0
  380. package/dist/runtime/recent-owner-exchanges.d.ts +10 -0
  381. package/dist/runtime/recent-owner-exchanges.d.ts.map +1 -0
  382. package/dist/runtime/recent-owner-exchanges.js +53 -0
  383. package/dist/runtime/recent-owner-exchanges.js.map +1 -0
  384. package/dist/runtime/report-prompts.d.ts +14 -0
  385. package/dist/runtime/report-prompts.d.ts.map +1 -0
  386. package/dist/runtime/report-prompts.js +69 -0
  387. package/dist/runtime/report-prompts.js.map +1 -0
  388. package/dist/runtime/report-scheduler.d.ts +24 -0
  389. package/dist/runtime/report-scheduler.d.ts.map +1 -0
  390. package/dist/runtime/report-scheduler.js +97 -0
  391. package/dist/runtime/report-scheduler.js.map +1 -0
  392. package/dist/runtime/session-credential.d.ts +5 -0
  393. package/dist/runtime/session-credential.d.ts.map +1 -0
  394. package/dist/runtime/session-credential.js +19 -0
  395. package/dist/runtime/session-credential.js.map +1 -0
  396. package/dist/runtime/stimulus-delivery.d.ts +85 -0
  397. package/dist/runtime/stimulus-delivery.d.ts.map +1 -0
  398. package/dist/runtime/stimulus-delivery.js +590 -0
  399. package/dist/runtime/stimulus-delivery.js.map +1 -0
  400. package/dist/runtime/timezone.d.ts +13 -0
  401. package/dist/runtime/timezone.d.ts.map +1 -0
  402. package/dist/runtime/timezone.js +119 -0
  403. package/dist/runtime/timezone.js.map +1 -0
  404. package/dist/sqlite.d.ts +7 -32
  405. package/dist/sqlite.d.ts.map +1 -1
  406. package/dist/sqlite.js +10 -48
  407. package/dist/sqlite.js.map +1 -1
  408. package/dist/storage/migrations/raw-item-revisions.d.ts +6 -0
  409. package/dist/storage/migrations/raw-item-revisions.d.ts.map +1 -0
  410. package/dist/storage/migrations/raw-item-revisions.js +109 -0
  411. package/dist/storage/migrations/raw-item-revisions.js.map +1 -0
  412. package/dist/storage/migrations-source.d.ts +5 -0
  413. package/dist/storage/migrations-source.d.ts.map +1 -0
  414. package/dist/storage/migrations-source.js +24 -0
  415. package/dist/storage/migrations-source.js.map +1 -0
  416. package/dist/storage/source-archive.d.ts +123 -0
  417. package/dist/storage/source-archive.d.ts.map +1 -0
  418. package/dist/storage/source-archive.js +595 -0
  419. package/dist/storage/source-archive.js.map +1 -0
  420. package/dist/storage-sqlite.d.ts +59 -0
  421. package/dist/storage-sqlite.d.ts.map +1 -0
  422. package/dist/storage-sqlite.js +75 -0
  423. package/dist/storage-sqlite.js.map +1 -0
  424. package/dist/utils/untrusted-content.d.ts +5 -35
  425. package/dist/utils/untrusted-content.d.ts.map +1 -1
  426. package/dist/utils/untrusted-content.js +16 -75
  427. package/dist/utils/untrusted-content.js.map +1 -1
  428. package/dist/wiki/obsidian-writer.d.ts +4 -2
  429. package/dist/wiki/obsidian-writer.d.ts.map +1 -1
  430. package/dist/wiki/obsidian-writer.js +85 -4
  431. package/dist/wiki/obsidian-writer.js.map +1 -1
  432. package/dist/wiki/path-safety.d.ts +2 -0
  433. package/dist/wiki/path-safety.d.ts.map +1 -1
  434. package/dist/wiki/path-safety.js +11 -3
  435. package/dist/wiki/path-safety.js.map +1 -1
  436. package/dist/wiki/wiki-edits.d.ts +17 -0
  437. package/dist/wiki/wiki-edits.d.ts.map +1 -0
  438. package/dist/wiki/wiki-edits.js +75 -0
  439. package/dist/wiki/wiki-edits.js.map +1 -0
  440. package/dist/wiki/wiki-read.d.ts +20 -11
  441. package/dist/wiki/wiki-read.d.ts.map +1 -1
  442. package/dist/wiki/wiki-read.js +87 -89
  443. package/dist/wiki/wiki-read.js.map +1 -1
  444. package/dist/wiki-artifacts/types.d.ts +1 -1
  445. package/dist/wiki-artifacts/types.d.ts.map +1 -1
  446. package/dist/wiki-artifacts/wiki-publish-adapter.d.ts.map +1 -1
  447. package/dist/wiki-artifacts/wiki-publish-adapter.js +13 -9
  448. package/dist/wiki-artifacts/wiki-publish-adapter.js.map +1 -1
  449. package/package.json +11 -41
  450. package/public/viewer/js/modules/graph.js +111 -41
  451. package/public/viewer/js/modules/memory.js +4 -31
  452. package/public/viewer/js/modules/wiki.js +0 -37
  453. package/public/viewer/js/utils/api.js +4 -50
  454. package/public/viewer/log-viewer.html +46 -0
  455. package/public/viewer/operator/operator.css +1 -1
  456. package/public/viewer/operator/operator.js +10835 -8211
  457. package/public/viewer/src/modules/graph.ts +133 -41
  458. package/public/viewer/src/modules/memory.ts +4 -31
  459. package/public/viewer/src/modules/wiki.ts +0 -42
  460. package/public/viewer/src/types/global.d.ts +1 -1
  461. package/public/viewer/src/utils/api.ts +7 -83
  462. package/public/viewer/viewer.html +7 -96
  463. package/dist/agent/agent-loop.d.ts +0 -289
  464. package/dist/agent/agent-loop.d.ts.map +0 -1
  465. package/dist/agent/agent-loop.js +0 -2842
  466. package/dist/agent/agent-loop.js.map +0 -1
  467. package/dist/agent/attachment-text-extractor.d.ts +0 -2
  468. package/dist/agent/attachment-text-extractor.d.ts.map +0 -1
  469. package/dist/agent/attachment-text-extractor.js +0 -128
  470. package/dist/agent/attachment-text-extractor.js.map +0 -1
  471. package/dist/agent/backend-model-policy.d.ts +0 -58
  472. package/dist/agent/backend-model-policy.d.ts.map +0 -1
  473. package/dist/agent/backend-model-policy.js +0 -167
  474. package/dist/agent/backend-model-policy.js.map +0 -1
  475. package/dist/agent/backend-model-runner-factory.d.ts +0 -27
  476. package/dist/agent/backend-model-runner-factory.d.ts.map +0 -1
  477. package/dist/agent/backend-model-runner-factory.js +0 -88
  478. package/dist/agent/backend-model-runner-factory.js.map +0 -1
  479. package/dist/agent/claude-cli-wrapper.d.ts +0 -144
  480. package/dist/agent/claude-cli-wrapper.d.ts.map +0 -1
  481. package/dist/agent/claude-cli-wrapper.js +0 -382
  482. package/dist/agent/claude-cli-wrapper.js.map +0 -1
  483. package/dist/agent/cli-arg-redaction.d.ts +0 -2
  484. package/dist/agent/cli-arg-redaction.d.ts.map +0 -1
  485. package/dist/agent/cli-arg-redaction.js +0 -18
  486. package/dist/agent/cli-arg-redaction.js.map +0 -1
  487. package/dist/agent/cline-cli-adapter.d.ts +0 -126
  488. package/dist/agent/cline-cli-adapter.d.ts.map +0 -1
  489. package/dist/agent/cline-cli-adapter.js +0 -1042
  490. package/dist/agent/cline-cli-adapter.js.map +0 -1
  491. package/dist/agent/cline-native-tool-policy.d.ts +0 -9
  492. package/dist/agent/cline-native-tool-policy.d.ts.map +0 -1
  493. package/dist/agent/cline-native-tool-policy.js +0 -61
  494. package/dist/agent/cline-native-tool-policy.js.map +0 -1
  495. package/dist/agent/code-act/completed-terminal-result.d.ts +0 -5
  496. package/dist/agent/code-act/completed-terminal-result.d.ts.map +0 -1
  497. package/dist/agent/code-act/completed-terminal-result.js +0 -83
  498. package/dist/agent/code-act/completed-terminal-result.js.map +0 -1
  499. package/dist/agent/code-act/constants.d.ts +0 -11
  500. package/dist/agent/code-act/constants.d.ts.map +0 -1
  501. package/dist/agent/code-act/constants.js +0 -64
  502. package/dist/agent/code-act/constants.js.map +0 -1
  503. package/dist/agent/code-act/host-bridge.d.ts +0 -50
  504. package/dist/agent/code-act/host-bridge.d.ts.map +0 -1
  505. package/dist/agent/code-act/host-bridge.js +0 -1405
  506. package/dist/agent/code-act/host-bridge.js.map +0 -1
  507. package/dist/agent/code-act/index.d.ts +0 -10
  508. package/dist/agent/code-act/index.d.ts.map +0 -1
  509. package/dist/agent/code-act/index.js +0 -22
  510. package/dist/agent/code-act/index.js.map +0 -1
  511. package/dist/agent/code-act/run-context-registry.d.ts +0 -36
  512. package/dist/agent/code-act/run-context-registry.d.ts.map +0 -1
  513. package/dist/agent/code-act/run-context-registry.js +0 -143
  514. package/dist/agent/code-act/run-context-registry.js.map +0 -1
  515. package/dist/agent/code-act/sandbox.d.ts +0 -25
  516. package/dist/agent/code-act/sandbox.d.ts.map +0 -1
  517. package/dist/agent/code-act/sandbox.js +0 -494
  518. package/dist/agent/code-act/sandbox.js.map +0 -1
  519. package/dist/agent/code-act/tool-catalog.d.ts +0 -30
  520. package/dist/agent/code-act/tool-catalog.d.ts.map +0 -1
  521. package/dist/agent/code-act/tool-catalog.js +0 -185
  522. package/dist/agent/code-act/tool-catalog.js.map +0 -1
  523. package/dist/agent/code-act/tool-policy.d.ts +0 -51
  524. package/dist/agent/code-act/tool-policy.d.ts.map +0 -1
  525. package/dist/agent/code-act/tool-policy.js +0 -160
  526. package/dist/agent/code-act/tool-policy.js.map +0 -1
  527. package/dist/agent/code-act/type-definition-generator.d.ts +0 -19
  528. package/dist/agent/code-act/type-definition-generator.d.ts.map +0 -1
  529. package/dist/agent/code-act/type-definition-generator.js +0 -73
  530. package/dist/agent/code-act/type-definition-generator.js.map +0 -1
  531. package/dist/agent/code-act/types.d.ts +0 -57
  532. package/dist/agent/code-act/types.d.ts.map +0 -1
  533. package/dist/agent/code-act/types.js +0 -14
  534. package/dist/agent/code-act/types.js.map +0 -1
  535. package/dist/agent/codex-app-server-process.d.ts +0 -257
  536. package/dist/agent/codex-app-server-process.d.ts.map +0 -1
  537. package/dist/agent/codex-app-server-process.js +0 -2084
  538. package/dist/agent/codex-app-server-process.js.map +0 -1
  539. package/dist/agent/codex-auth.d.ts +0 -2
  540. package/dist/agent/codex-auth.d.ts.map +0 -1
  541. package/dist/agent/codex-auth.js +0 -17
  542. package/dist/agent/codex-auth.js.map +0 -1
  543. package/dist/agent/codex-auxiliary-tools.d.ts +0 -17
  544. package/dist/agent/codex-auxiliary-tools.d.ts.map +0 -1
  545. package/dist/agent/codex-auxiliary-tools.js +0 -267
  546. package/dist/agent/codex-auxiliary-tools.js.map +0 -1
  547. package/dist/agent/codex-home.d.ts +0 -13
  548. package/dist/agent/codex-home.d.ts.map +0 -1
  549. package/dist/agent/codex-home.js +0 -644
  550. package/dist/agent/codex-home.js.map +0 -1
  551. package/dist/agent/codex-thread-registry.d.ts +0 -63
  552. package/dist/agent/codex-thread-registry.d.ts.map +0 -1
  553. package/dist/agent/codex-thread-registry.js +0 -433
  554. package/dist/agent/codex-thread-registry.js.map +0 -1
  555. package/dist/agent/content-dedup.d.ts +0 -86
  556. package/dist/agent/content-dedup.d.ts.map +0 -1
  557. package/dist/agent/content-dedup.js +0 -114
  558. package/dist/agent/content-dedup.js.map +0 -1
  559. package/dist/agent/context-compile-contract.d.ts +0 -5
  560. package/dist/agent/context-compile-contract.d.ts.map +0 -1
  561. package/dist/agent/context-compile-contract.js +0 -8
  562. package/dist/agent/context-compile-contract.js.map +0 -1
  563. package/dist/agent/context-compile-service.d.ts +0 -60
  564. package/dist/agent/context-compile-service.d.ts.map +0 -1
  565. package/dist/agent/context-compile-service.js +0 -481
  566. package/dist/agent/context-compile-service.js.map +0 -1
  567. package/dist/agent/context-prompt-builder.d.ts +0 -24
  568. package/dist/agent/context-prompt-builder.d.ts.map +0 -1
  569. package/dist/agent/context-prompt-builder.js +0 -61
  570. package/dist/agent/context-prompt-builder.js.map +0 -1
  571. package/dist/agent/contract-extractor.d.ts +0 -124
  572. package/dist/agent/contract-extractor.d.ts.map +0 -1
  573. package/dist/agent/contract-extractor.js +0 -465
  574. package/dist/agent/contract-extractor.js.map +0 -1
  575. package/dist/agent/drive-tools.d.ts +0 -83
  576. package/dist/agent/drive-tools.d.ts.map +0 -1
  577. package/dist/agent/drive-tools.js +0 -338
  578. package/dist/agent/drive-tools.js.map +0 -1
  579. package/dist/agent/gateway-tool-catalog.d.ts +0 -14
  580. package/dist/agent/gateway-tool-catalog.d.ts.map +0 -1
  581. package/dist/agent/gateway-tool-catalog.js +0 -41
  582. package/dist/agent/gateway-tool-catalog.js.map +0 -1
  583. package/dist/agent/gateway-tool-executor.d.ts +0 -353
  584. package/dist/agent/gateway-tool-executor.d.ts.map +0 -1
  585. package/dist/agent/gateway-tool-executor.js +0 -5448
  586. package/dist/agent/gateway-tool-executor.js.map +0 -1
  587. package/dist/agent/gateway-tools.md +0 -166
  588. package/dist/agent/image-translation-tools.d.ts +0 -48
  589. package/dist/agent/image-translation-tools.d.ts.map +0 -1
  590. package/dist/agent/image-translation-tools.js +0 -274
  591. package/dist/agent/image-translation-tools.js.map +0 -1
  592. package/dist/agent/index.d.ts +0 -13
  593. package/dist/agent/index.d.ts.map +0 -1
  594. package/dist/agent/index.js +0 -18
  595. package/dist/agent/index.js.map +0 -1
  596. package/dist/agent/mama-tool-handlers.d.ts +0 -11
  597. package/dist/agent/mama-tool-handlers.d.ts.map +0 -1
  598. package/dist/agent/mama-tool-handlers.js +0 -220
  599. package/dist/agent/mama-tool-handlers.js.map +0 -1
  600. package/dist/agent/managed-agent-runtime-sync.d.ts +0 -36
  601. package/dist/agent/managed-agent-runtime-sync.d.ts.map +0 -1
  602. package/dist/agent/managed-agent-runtime-sync.js +0 -245
  603. package/dist/agent/managed-agent-runtime-sync.js.map +0 -1
  604. package/dist/agent/managed-agent-validation.d.ts +0 -4
  605. package/dist/agent/managed-agent-validation.d.ts.map +0 -1
  606. package/dist/agent/managed-agent-validation.js +0 -85
  607. package/dist/agent/managed-agent-validation.js.map +0 -1
  608. package/dist/agent/model-runner.d.ts +0 -180
  609. package/dist/agent/model-runner.d.ts.map +0 -1
  610. package/dist/agent/model-runner.js +0 -54
  611. package/dist/agent/model-runner.js.map +0 -1
  612. package/dist/agent/native-effect-observer.d.ts +0 -20
  613. package/dist/agent/native-effect-observer.d.ts.map +0 -1
  614. package/dist/agent/native-effect-observer.js +0 -86
  615. package/dist/agent/native-effect-observer.js.map +0 -1
  616. package/dist/agent/obsidian-cli-args.d.ts +0 -14
  617. package/dist/agent/obsidian-cli-args.d.ts.map +0 -1
  618. package/dist/agent/obsidian-cli-args.js +0 -57
  619. package/dist/agent/obsidian-cli-args.js.map +0 -1
  620. package/dist/agent/os-agent-capabilities.md +0 -367
  621. package/dist/agent/persistent-cli-adapter.d.ts +0 -173
  622. package/dist/agent/persistent-cli-adapter.d.ts.map +0 -1
  623. package/dist/agent/persistent-cli-adapter.js +0 -506
  624. package/dist/agent/persistent-cli-adapter.js.map +0 -1
  625. package/dist/agent/persistent-cli-process.d.ts +0 -392
  626. package/dist/agent/persistent-cli-process.d.ts.map +0 -1
  627. package/dist/agent/persistent-cli-process.js +0 -1568
  628. package/dist/agent/persistent-cli-process.js.map +0 -1
  629. package/dist/agent/post-tool-handler.d.ts +0 -27
  630. package/dist/agent/post-tool-handler.d.ts.map +0 -1
  631. package/dist/agent/post-tool-handler.js +0 -194
  632. package/dist/agent/post-tool-handler.js.map +0 -1
  633. package/dist/agent/pre-compact-handler.d.ts +0 -36
  634. package/dist/agent/pre-compact-handler.d.ts.map +0 -1
  635. package/dist/agent/pre-compact-handler.js +0 -162
  636. package/dist/agent/pre-compact-handler.js.map +0 -1
  637. package/dist/agent/prompt-enhancer.d.ts +0 -33
  638. package/dist/agent/prompt-enhancer.d.ts.map +0 -1
  639. package/dist/agent/prompt-enhancer.js +0 -811
  640. package/dist/agent/prompt-enhancer.js.map +0 -1
  641. package/dist/agent/prompt-size-monitor.d.ts +0 -104
  642. package/dist/agent/prompt-size-monitor.d.ts.map +0 -1
  643. package/dist/agent/prompt-size-monitor.js +0 -192
  644. package/dist/agent/prompt-size-monitor.js.map +0 -1
  645. package/dist/agent/role-manager.d.ts +0 -122
  646. package/dist/agent/role-manager.d.ts.map +0 -1
  647. package/dist/agent/role-manager.js +0 -300
  648. package/dist/agent/role-manager.js.map +0 -1
  649. package/dist/agent/session-pool.d.ts +0 -176
  650. package/dist/agent/session-pool.d.ts.map +0 -1
  651. package/dist/agent/session-pool.js +0 -368
  652. package/dist/agent/session-pool.js.map +0 -1
  653. package/dist/agent/skill-loader.d.ts +0 -87
  654. package/dist/agent/skill-loader.d.ts.map +0 -1
  655. package/dist/agent/skill-loader.js +0 -461
  656. package/dist/agent/skill-loader.js.map +0 -1
  657. package/dist/agent/stop-continuation-handler.d.ts +0 -106
  658. package/dist/agent/stop-continuation-handler.d.ts.map +0 -1
  659. package/dist/agent/stop-continuation-handler.js +0 -230
  660. package/dist/agent/stop-continuation-handler.js.map +0 -1
  661. package/dist/agent/subagent-run-reconcile.d.ts +0 -23
  662. package/dist/agent/subagent-run-reconcile.d.ts.map +0 -1
  663. package/dist/agent/subagent-run-reconcile.js +0 -56
  664. package/dist/agent/subagent-run-reconcile.js.map +0 -1
  665. package/dist/agent/temporal-code-act-breaker.d.ts +0 -26
  666. package/dist/agent/temporal-code-act-breaker.d.ts.map +0 -1
  667. package/dist/agent/temporal-code-act-breaker.js +0 -94
  668. package/dist/agent/temporal-code-act-breaker.js.map +0 -1
  669. package/dist/agent/token-estimator.d.ts +0 -25
  670. package/dist/agent/token-estimator.d.ts.map +0 -1
  671. package/dist/agent/token-estimator.js +0 -75
  672. package/dist/agent/token-estimator.js.map +0 -1
  673. package/dist/agent/tool-registry.d.ts +0 -81
  674. package/dist/agent/tool-registry.d.ts.map +0 -1
  675. package/dist/agent/tool-registry.js +0 -876
  676. package/dist/agent/tool-registry.js.map +0 -1
  677. package/dist/agent/types.d.ts +0 -1261
  678. package/dist/agent/types.d.ts.map +0 -1
  679. package/dist/agent/types.js +0 -60
  680. package/dist/agent/types.js.map +0 -1
  681. package/dist/agent/yaml-frontmatter.d.ts +0 -75
  682. package/dist/agent/yaml-frontmatter.d.ts.map +0 -1
  683. package/dist/agent/yaml-frontmatter.js +0 -166
  684. package/dist/agent/yaml-frontmatter.js.map +0 -1
  685. package/dist/api/agent-context-handler.d.ts +0 -10
  686. package/dist/api/agent-context-handler.d.ts.map +0 -1
  687. package/dist/api/agent-context-handler.js +0 -216
  688. package/dist/api/agent-context-handler.js.map +0 -1
  689. package/dist/api/agent-graph-handler.d.ts +0 -18
  690. package/dist/api/agent-graph-handler.d.ts.map +0 -1
  691. package/dist/api/agent-graph-handler.js +0 -569
  692. package/dist/api/agent-graph-handler.js.map +0 -1
  693. package/dist/api/agent-handler.d.ts +0 -36
  694. package/dist/api/agent-handler.d.ts.map +0 -1
  695. package/dist/api/agent-handler.js +0 -223
  696. package/dist/api/agent-handler.js.map +0 -1
  697. package/dist/api/agent-raw-handler.d.ts +0 -70
  698. package/dist/api/agent-raw-handler.d.ts.map +0 -1
  699. package/dist/api/agent-raw-handler.js +0 -262
  700. package/dist/api/agent-raw-handler.js.map +0 -1
  701. package/dist/api/agent-situation-handler.d.ts +0 -14
  702. package/dist/api/agent-situation-handler.d.ts.map +0 -1
  703. package/dist/api/agent-situation-handler.js +0 -383
  704. package/dist/api/agent-situation-handler.js.map +0 -1
  705. package/dist/api/connector-feed-handler.d.ts +0 -42
  706. package/dist/api/connector-feed-handler.d.ts.map +0 -1
  707. package/dist/api/connector-feed-handler.js +0 -180
  708. package/dist/api/connector-feed-handler.js.map +0 -1
  709. package/dist/api/cron-handler.d.ts +0 -44
  710. package/dist/api/cron-handler.d.ts.map +0 -1
  711. package/dist/api/cron-handler.js +0 -261
  712. package/dist/api/cron-handler.js.map +0 -1
  713. package/dist/api/entity-audit-handler.d.ts +0 -12
  714. package/dist/api/entity-audit-handler.d.ts.map +0 -1
  715. package/dist/api/entity-audit-handler.js +0 -119
  716. package/dist/api/entity-audit-handler.js.map +0 -1
  717. package/dist/api/entity-audit-queue.d.ts +0 -74
  718. package/dist/api/entity-audit-queue.d.ts.map +0 -1
  719. package/dist/api/entity-audit-queue.js +0 -123
  720. package/dist/api/entity-audit-queue.js.map +0 -1
  721. package/dist/api/entity-audit-runner.d.ts +0 -9
  722. package/dist/api/entity-audit-runner.d.ts.map +0 -1
  723. package/dist/api/entity-audit-runner.js +0 -240
  724. package/dist/api/entity-audit-runner.js.map +0 -1
  725. package/dist/api/entity-review-handler.d.ts +0 -18
  726. package/dist/api/entity-review-handler.d.ts.map +0 -1
  727. package/dist/api/entity-review-handler.js +0 -521
  728. package/dist/api/entity-review-handler.js.map +0 -1
  729. package/dist/api/error-handler.d.ts +0 -22
  730. package/dist/api/error-handler.d.ts.map +0 -1
  731. package/dist/api/error-handler.js +0 -104
  732. package/dist/api/error-handler.js.map +0 -1
  733. package/dist/api/graph-api-types.d.ts +0 -105
  734. package/dist/api/graph-api-types.d.ts.map +0 -1
  735. package/dist/api/graph-api-types.js +0 -6
  736. package/dist/api/graph-api-types.js.map +0 -1
  737. package/dist/api/graph-api.d.ts +0 -42
  738. package/dist/api/graph-api.d.ts.map +0 -1
  739. package/dist/api/graph-api.js +0 -3460
  740. package/dist/api/graph-api.js.map +0 -1
  741. package/dist/api/heartbeat-handler.d.ts +0 -49
  742. package/dist/api/heartbeat-handler.d.ts.map +0 -1
  743. package/dist/api/heartbeat-handler.js +0 -106
  744. package/dist/api/heartbeat-handler.js.map +0 -1
  745. package/dist/api/index.d.ts +0 -145
  746. package/dist/api/index.d.ts.map +0 -1
  747. package/dist/api/index.js +0 -448
  748. package/dist/api/index.js.map +0 -1
  749. package/dist/api/intelligence-handler.d.ts +0 -116
  750. package/dist/api/intelligence-handler.d.ts.map +0 -1
  751. package/dist/api/intelligence-handler.js +0 -280
  752. package/dist/api/intelligence-handler.js.map +0 -1
  753. package/dist/api/memory-provenance-handler.d.ts +0 -3
  754. package/dist/api/memory-provenance-handler.d.ts.map +0 -1
  755. package/dist/api/memory-provenance-handler.js +0 -120
  756. package/dist/api/memory-provenance-handler.js.map +0 -1
  757. package/dist/api/operator-handler.d.ts +0 -19
  758. package/dist/api/operator-handler.d.ts.map +0 -1
  759. package/dist/api/operator-handler.js +0 -106
  760. package/dist/api/operator-handler.js.map +0 -1
  761. package/dist/api/operator-summary.d.ts +0 -3
  762. package/dist/api/operator-summary.d.ts.map +0 -1
  763. package/dist/api/operator-summary.js +0 -72
  764. package/dist/api/operator-summary.js.map +0 -1
  765. package/dist/api/operator-tasks-handler.d.ts +0 -7
  766. package/dist/api/operator-tasks-handler.d.ts.map +0 -1
  767. package/dist/api/operator-tasks-handler.js +0 -192
  768. package/dist/api/operator-tasks-handler.js.map +0 -1
  769. package/dist/api/runtime-status-handler.d.ts +0 -42
  770. package/dist/api/runtime-status-handler.d.ts.map +0 -1
  771. package/dist/api/runtime-status-handler.js +0 -56
  772. package/dist/api/runtime-status-handler.js.map +0 -1
  773. package/dist/api/skills-handler.d.ts +0 -12
  774. package/dist/api/skills-handler.d.ts.map +0 -1
  775. package/dist/api/skills-handler.js +0 -156
  776. package/dist/api/skills-handler.js.map +0 -1
  777. package/dist/api/token-handler.d.ts +0 -33
  778. package/dist/api/token-handler.d.ts.map +0 -1
  779. package/dist/api/token-handler.js +0 -118
  780. package/dist/api/token-handler.js.map +0 -1
  781. package/dist/api/types.d.ts +0 -155
  782. package/dist/api/types.d.ts.map +0 -1
  783. package/dist/api/types.js +0 -49
  784. package/dist/api/types.js.map +0 -1
  785. package/dist/api/ui-command-handler.d.ts +0 -48
  786. package/dist/api/ui-command-handler.d.ts.map +0 -1
  787. package/dist/api/ui-command-handler.js +0 -160
  788. package/dist/api/ui-command-handler.js.map +0 -1
  789. package/dist/api/upload-handler.d.ts +0 -12
  790. package/dist/api/upload-handler.d.ts.map +0 -1
  791. package/dist/api/upload-handler.js +0 -321
  792. package/dist/api/upload-handler.js.map +0 -1
  793. package/dist/api/wiki-handler.d.ts +0 -19
  794. package/dist/api/wiki-handler.d.ts.map +0 -1
  795. package/dist/api/wiki-handler.js +0 -136
  796. package/dist/api/wiki-handler.js.map +0 -1
  797. package/dist/api/worker-envelope.d.ts +0 -26
  798. package/dist/api/worker-envelope.d.ts.map +0 -1
  799. package/dist/api/worker-envelope.js +0 -176
  800. package/dist/api/worker-envelope.js.map +0 -1
  801. package/dist/auth/claude-client.d.ts +0 -12
  802. package/dist/auth/claude-client.d.ts.map +0 -1
  803. package/dist/auth/claude-client.js +0 -36
  804. package/dist/auth/claude-client.js.map +0 -1
  805. package/dist/auth/claude-code-auth.d.ts +0 -12
  806. package/dist/auth/claude-code-auth.d.ts.map +0 -1
  807. package/dist/auth/claude-code-auth.js +0 -85
  808. package/dist/auth/claude-code-auth.js.map +0 -1
  809. package/dist/auth/index.d.ts +0 -9
  810. package/dist/auth/index.d.ts.map +0 -1
  811. package/dist/auth/index.js +0 -13
  812. package/dist/auth/index.js.map +0 -1
  813. package/dist/auth/oauth-manager.d.ts +0 -59
  814. package/dist/auth/oauth-manager.d.ts.map +0 -1
  815. package/dist/auth/oauth-manager.js +0 -252
  816. package/dist/auth/oauth-manager.js.map +0 -1
  817. package/dist/auth/types.d.ts +0 -92
  818. package/dist/auth/types.d.ts.map +0 -1
  819. package/dist/auth/types.js +0 -23
  820. package/dist/auth/types.js.map +0 -1
  821. package/dist/cli/commands/connector.d.ts +0 -14
  822. package/dist/cli/commands/connector.d.ts.map +0 -1
  823. package/dist/cli/commands/connector.js +0 -174
  824. package/dist/cli/commands/connector.js.map +0 -1
  825. package/dist/cli/commands/gateway.d.ts +0 -18
  826. package/dist/cli/commands/gateway.d.ts.map +0 -1
  827. package/dist/cli/commands/gateway.js +0 -144
  828. package/dist/cli/commands/gateway.js.map +0 -1
  829. package/dist/cli/commands/report.d.ts +0 -14
  830. package/dist/cli/commands/report.d.ts.map +0 -1
  831. package/dist/cli/commands/report.js +0 -102
  832. package/dist/cli/commands/report.js.map +0 -1
  833. package/dist/cli/commands/run.d.ts +0 -19
  834. package/dist/cli/commands/run.d.ts.map +0 -1
  835. package/dist/cli/commands/run.js +0 -123
  836. package/dist/cli/commands/run.js.map +0 -1
  837. package/dist/cli/commands/setup.d.ts +0 -3
  838. package/dist/cli/commands/setup.d.ts.map +0 -1
  839. package/dist/cli/commands/setup.js +0 -9
  840. package/dist/cli/commands/setup.js.map +0 -1
  841. package/dist/cli/commands/start.d.ts +0 -263
  842. package/dist/cli/commands/start.d.ts.map +0 -1
  843. package/dist/cli/commands/start.js +0 -2230
  844. package/dist/cli/commands/start.js.map +0 -1
  845. package/dist/cli/commands/status.d.ts +0 -18
  846. package/dist/cli/commands/status.d.ts.map +0 -1
  847. package/dist/cli/commands/status.js +0 -326
  848. package/dist/cli/commands/status.js.map +0 -1
  849. package/dist/cli/commands/stop.d.ts +0 -28
  850. package/dist/cli/commands/stop.d.ts.map +0 -1
  851. package/dist/cli/commands/stop.js +0 -597
  852. package/dist/cli/commands/stop.js.map +0 -1
  853. package/dist/cli/config/config-manager.d.ts +0 -84
  854. package/dist/cli/config/config-manager.d.ts.map +0 -1
  855. package/dist/cli/config/config-manager.js +0 -886
  856. package/dist/cli/config/config-manager.js.map +0 -1
  857. package/dist/cli/config/types.d.ts +0 -633
  858. package/dist/cli/config/types.d.ts.map +0 -1
  859. package/dist/cli/config/types.js +0 -247
  860. package/dist/cli/config/types.js.map +0 -1
  861. package/dist/cli/runtime/agent-loop-init.d.ts +0 -53
  862. package/dist/cli/runtime/agent-loop-init.d.ts.map +0 -1
  863. package/dist/cli/runtime/agent-loop-init.js +0 -368
  864. package/dist/cli/runtime/agent-loop-init.js.map +0 -1
  865. package/dist/cli/runtime/api-routes-init.d.ts +0 -84
  866. package/dist/cli/runtime/api-routes-init.d.ts.map +0 -1
  867. package/dist/cli/runtime/api-routes-init.js +0 -1542
  868. package/dist/cli/runtime/api-routes-init.js.map +0 -1
  869. package/dist/cli/runtime/api-server-init.d.ts +0 -59
  870. package/dist/cli/runtime/api-server-init.d.ts.map +0 -1
  871. package/dist/cli/runtime/api-server-init.js +0 -159
  872. package/dist/cli/runtime/api-server-init.js.map +0 -1
  873. package/dist/cli/runtime/code-act-executor.d.ts +0 -14
  874. package/dist/cli/runtime/code-act-executor.d.ts.map +0 -1
  875. package/dist/cli/runtime/code-act-executor.js +0 -108
  876. package/dist/cli/runtime/code-act-executor.js.map +0 -1
  877. package/dist/cli/runtime/connector-bootstrap.d.ts +0 -8
  878. package/dist/cli/runtime/connector-bootstrap.d.ts.map +0 -1
  879. package/dist/cli/runtime/connector-bootstrap.js +0 -14
  880. package/dist/cli/runtime/connector-bootstrap.js.map +0 -1
  881. package/dist/cli/runtime/connector-init.d.ts +0 -64
  882. package/dist/cli/runtime/connector-init.d.ts.map +0 -1
  883. package/dist/cli/runtime/connector-init.js +0 -237
  884. package/dist/cli/runtime/connector-init.js.map +0 -1
  885. package/dist/cli/runtime/daemon.d.ts +0 -38
  886. package/dist/cli/runtime/daemon.d.ts.map +0 -1
  887. package/dist/cli/runtime/daemon.js +0 -263
  888. package/dist/cli/runtime/daemon.js.map +0 -1
  889. package/dist/cli/runtime/envelope-bootstrap.d.ts +0 -17
  890. package/dist/cli/runtime/envelope-bootstrap.d.ts.map +0 -1
  891. package/dist/cli/runtime/envelope-bootstrap.js +0 -56
  892. package/dist/cli/runtime/envelope-bootstrap.js.map +0 -1
  893. package/dist/cli/runtime/gateway-init.d.ts +0 -55
  894. package/dist/cli/runtime/gateway-init.d.ts.map +0 -1
  895. package/dist/cli/runtime/gateway-init.js +0 -196
  896. package/dist/cli/runtime/gateway-init.js.map +0 -1
  897. package/dist/cli/runtime/gateway-wiring.d.ts +0 -51
  898. package/dist/cli/runtime/gateway-wiring.d.ts.map +0 -1
  899. package/dist/cli/runtime/gateway-wiring.js +0 -215
  900. package/dist/cli/runtime/gateway-wiring.js.map +0 -1
  901. package/dist/cli/runtime/mama-core-init.d.ts +0 -42
  902. package/dist/cli/runtime/mama-core-init.d.ts.map +0 -1
  903. package/dist/cli/runtime/mama-core-init.js +0 -211
  904. package/dist/cli/runtime/mama-core-init.js.map +0 -1
  905. package/dist/cli/runtime/message-router-config.d.ts +0 -4
  906. package/dist/cli/runtime/message-router-config.d.ts.map +0 -1
  907. package/dist/cli/runtime/message-router-config.js +0 -11
  908. package/dist/cli/runtime/message-router-config.js.map +0 -1
  909. package/dist/cli/runtime/metrics-init.d.ts +0 -28
  910. package/dist/cli/runtime/metrics-init.d.ts.map +0 -1
  911. package/dist/cli/runtime/metrics-init.js +0 -131
  912. package/dist/cli/runtime/metrics-init.js.map +0 -1
  913. package/dist/cli/runtime/owner-backfill.d.ts +0 -24
  914. package/dist/cli/runtime/owner-backfill.d.ts.map +0 -1
  915. package/dist/cli/runtime/owner-backfill.js +0 -24
  916. package/dist/cli/runtime/owner-backfill.js.map +0 -1
  917. package/dist/cli/runtime/scheduler-init.d.ts +0 -60
  918. package/dist/cli/runtime/scheduler-init.d.ts.map +0 -1
  919. package/dist/cli/runtime/scheduler-init.js +0 -173
  920. package/dist/cli/runtime/scheduler-init.js.map +0 -1
  921. package/dist/cli/runtime/server-start.d.ts +0 -23
  922. package/dist/cli/runtime/server-start.d.ts.map +0 -1
  923. package/dist/cli/runtime/server-start.js +0 -174
  924. package/dist/cli/runtime/server-start.js.map +0 -1
  925. package/dist/cli/runtime/shutdown.d.ts +0 -46
  926. package/dist/cli/runtime/shutdown.d.ts.map +0 -1
  927. package/dist/cli/runtime/shutdown.js +0 -240
  928. package/dist/cli/runtime/shutdown.js.map +0 -1
  929. package/dist/cli/runtime/temporal-init.d.ts +0 -26
  930. package/dist/cli/runtime/temporal-init.d.ts.map +0 -1
  931. package/dist/cli/runtime/temporal-init.js +0 -57
  932. package/dist/cli/runtime/temporal-init.js.map +0 -1
  933. package/dist/cli/runtime/types.d.ts +0 -127
  934. package/dist/cli/runtime/types.d.ts.map +0 -1
  935. package/dist/cli/runtime/types.js +0 -12
  936. package/dist/cli/runtime/types.js.map +0 -1
  937. package/dist/cli/runtime/utilities.d.ts +0 -72
  938. package/dist/cli/runtime/utilities.d.ts.map +0 -1
  939. package/dist/cli/runtime/utilities.js +0 -472
  940. package/dist/cli/runtime/utilities.js.map +0 -1
  941. package/dist/cli/shutdown-utils.d.ts +0 -6
  942. package/dist/cli/shutdown-utils.d.ts.map +0 -1
  943. package/dist/cli/shutdown-utils.js +0 -11
  944. package/dist/cli/shutdown-utils.js.map +0 -1
  945. package/dist/cli/utils/pid-manager.d.ts +0 -56
  946. package/dist/cli/utils/pid-manager.d.ts.map +0 -1
  947. package/dist/cli/utils/pid-manager.js +0 -141
  948. package/dist/cli/utils/pid-manager.js.map +0 -1
  949. package/dist/concurrency/index.d.ts +0 -13
  950. package/dist/concurrency/index.d.ts.map +0 -1
  951. package/dist/concurrency/index.js +0 -22
  952. package/dist/concurrency/index.js.map +0 -1
  953. package/dist/concurrency/lane-manager.d.ts +0 -113
  954. package/dist/concurrency/lane-manager.d.ts.map +0 -1
  955. package/dist/concurrency/lane-manager.js +0 -248
  956. package/dist/concurrency/lane-manager.js.map +0 -1
  957. package/dist/concurrency/session-key.d.ts +0 -41
  958. package/dist/concurrency/session-key.d.ts.map +0 -1
  959. package/dist/concurrency/session-key.js +0 -61
  960. package/dist/concurrency/session-key.js.map +0 -1
  961. package/dist/concurrency/types.d.ts +0 -73
  962. package/dist/concurrency/types.d.ts.map +0 -1
  963. package/dist/concurrency/types.js +0 -16
  964. package/dist/concurrency/types.js.map +0 -1
  965. package/dist/connectors/framework/raw-store.d.ts +0 -63
  966. package/dist/connectors/framework/raw-store.d.ts.map +0 -1
  967. package/dist/connectors/framework/raw-store.js +0 -356
  968. package/dist/connectors/framework/raw-store.js.map +0 -1
  969. package/dist/connectors/kagemusha/query-tools.d.ts +0 -146
  970. package/dist/connectors/kagemusha/query-tools.d.ts.map +0 -1
  971. package/dist/connectors/kagemusha/query-tools.js +0 -467
  972. package/dist/connectors/kagemusha/query-tools.js.map +0 -1
  973. package/dist/connectors/private-connector-policy.d.ts +0 -174
  974. package/dist/connectors/private-connector-policy.d.ts.map +0 -1
  975. package/dist/connectors/private-connector-policy.js +0 -299
  976. package/dist/connectors/private-connector-policy.js.map +0 -1
  977. package/dist/connectors/private-prompt-overlay.d.ts +0 -17
  978. package/dist/connectors/private-prompt-overlay.d.ts.map +0 -1
  979. package/dist/connectors/private-prompt-overlay.js +0 -156
  980. package/dist/connectors/private-prompt-overlay.js.map +0 -1
  981. package/dist/connectors/trello/query-tools.d.ts +0 -243
  982. package/dist/connectors/trello/query-tools.d.ts.map +0 -1
  983. package/dist/connectors/trello/query-tools.js +0 -661
  984. package/dist/connectors/trello/query-tools.js.map +0 -1
  985. package/dist/db/agent-store.d.ts +0 -145
  986. package/dist/db/agent-store.d.ts.map +0 -1
  987. package/dist/db/agent-store.js +0 -279
  988. package/dist/db/agent-store.js.map +0 -1
  989. package/dist/db/migrations/agent-activity-envelope-hash.d.ts +0 -3
  990. package/dist/db/migrations/agent-activity-envelope-hash.d.ts.map +0 -1
  991. package/dist/db/migrations/agent-activity-envelope-hash.js +0 -29
  992. package/dist/db/migrations/agent-activity-envelope-hash.js.map +0 -1
  993. package/dist/db/migrations/agent-activity-gateway-call-id.d.ts +0 -3
  994. package/dist/db/migrations/agent-activity-gateway-call-id.d.ts.map +0 -1
  995. package/dist/db/migrations/agent-activity-gateway-call-id.js +0 -17
  996. package/dist/db/migrations/agent-activity-gateway-call-id.js.map +0 -1
  997. package/dist/db/migrations/agent-activity-tool-name.d.ts +0 -8
  998. package/dist/db/migrations/agent-activity-tool-name.d.ts.map +0 -1
  999. package/dist/db/migrations/agent-activity-tool-name.js +0 -24
  1000. package/dist/db/migrations/agent-activity-tool-name.js.map +0 -1
  1001. package/dist/db/migrations/agent-activity-validation-columns.d.ts +0 -3
  1002. package/dist/db/migrations/agent-activity-validation-columns.d.ts.map +0 -1
  1003. package/dist/db/migrations/agent-activity-validation-columns.js +0 -22
  1004. package/dist/db/migrations/agent-activity-validation-columns.js.map +0 -1
  1005. package/dist/db/migrations/agent-metrics-response-avg.d.ts +0 -3
  1006. package/dist/db/migrations/agent-metrics-response-avg.d.ts.map +0 -1
  1007. package/dist/db/migrations/agent-metrics-response-avg.js +0 -19
  1008. package/dist/db/migrations/agent-metrics-response-avg.js.map +0 -1
  1009. package/dist/db/migrations/agent-store-tables.d.ts +0 -3
  1010. package/dist/db/migrations/agent-store-tables.d.ts.map +0 -1
  1011. package/dist/db/migrations/agent-store-tables.js +0 -64
  1012. package/dist/db/migrations/agent-store-tables.js.map +0 -1
  1013. package/dist/db/migrations/envelope-tables.d.ts +0 -3
  1014. package/dist/db/migrations/envelope-tables.d.ts.map +0 -1
  1015. package/dist/db/migrations/envelope-tables.js +0 -38
  1016. package/dist/db/migrations/envelope-tables.js.map +0 -1
  1017. package/dist/db/migrations/operator-owner-action-candidates.d.ts +0 -19
  1018. package/dist/db/migrations/operator-owner-action-candidates.d.ts.map +0 -1
  1019. package/dist/db/migrations/operator-owner-action-candidates.js +0 -254
  1020. package/dist/db/migrations/operator-owner-action-candidates.js.map +0 -1
  1021. package/dist/db/migrations/operator-procedures.d.ts +0 -4
  1022. package/dist/db/migrations/operator-procedures.d.ts.map +0 -1
  1023. package/dist/db/migrations/operator-procedures.js +0 -63
  1024. package/dist/db/migrations/operator-procedures.js.map +0 -1
  1025. package/dist/db/migrations/operator-task-classification.d.ts +0 -15
  1026. package/dist/db/migrations/operator-task-classification.d.ts.map +0 -1
  1027. package/dist/db/migrations/operator-task-classification.js +0 -25
  1028. package/dist/db/migrations/operator-task-classification.js.map +0 -1
  1029. package/dist/db/migrations/operator-task-external-lifecycle.d.ts +0 -17
  1030. package/dist/db/migrations/operator-task-external-lifecycle.d.ts.map +0 -1
  1031. package/dist/db/migrations/operator-task-external-lifecycle.js +0 -199
  1032. package/dist/db/migrations/operator-task-external-lifecycle.js.map +0 -1
  1033. package/dist/db/migrations/operator-task-review-lifecycle.d.ts +0 -4
  1034. package/dist/db/migrations/operator-task-review-lifecycle.d.ts.map +0 -1
  1035. package/dist/db/migrations/operator-task-review-lifecycle.js +0 -17
  1036. package/dist/db/migrations/operator-task-review-lifecycle.js.map +0 -1
  1037. package/dist/db/migrations/operator-task-temporal.d.ts +0 -8
  1038. package/dist/db/migrations/operator-task-temporal.d.ts.map +0 -1
  1039. package/dist/db/migrations/operator-task-temporal.js +0 -214
  1040. package/dist/db/migrations/operator-task-temporal.js.map +0 -1
  1041. package/dist/db/migrations/owner-action-effects.d.ts +0 -18
  1042. package/dist/db/migrations/owner-action-effects.d.ts.map +0 -1
  1043. package/dist/db/migrations/owner-action-effects.js +0 -111
  1044. package/dist/db/migrations/owner-action-effects.js.map +0 -1
  1045. package/dist/db/migrations/raw-item-revisions.d.ts +0 -4
  1046. package/dist/db/migrations/raw-item-revisions.d.ts.map +0 -1
  1047. package/dist/db/migrations/raw-item-revisions.js +0 -29
  1048. package/dist/db/migrations/raw-item-revisions.js.map +0 -1
  1049. package/dist/db/migrations/token-usage-agent-version.d.ts +0 -3
  1050. package/dist/db/migrations/token-usage-agent-version.d.ts.map +0 -1
  1051. package/dist/db/migrations/token-usage-agent-version.js +0 -16
  1052. package/dist/db/migrations/token-usage-agent-version.js.map +0 -1
  1053. package/dist/db/migrations/validation-session-tables.d.ts +0 -3
  1054. package/dist/db/migrations/validation-session-tables.d.ts.map +0 -1
  1055. package/dist/db/migrations/validation-session-tables.js +0 -59
  1056. package/dist/db/migrations/validation-session-tables.js.map +0 -1
  1057. package/dist/envelope/authority.d.ts +0 -15
  1058. package/dist/envelope/authority.d.ts.map +0 -1
  1059. package/dist/envelope/authority.js +0 -95
  1060. package/dist/envelope/authority.js.map +0 -1
  1061. package/dist/envelope/canonical.d.ts +0 -14
  1062. package/dist/envelope/canonical.d.ts.map +0 -1
  1063. package/dist/envelope/canonical.js +0 -68
  1064. package/dist/envelope/canonical.js.map +0 -1
  1065. package/dist/envelope/enforcer.d.ts +0 -30
  1066. package/dist/envelope/enforcer.d.ts.map +0 -1
  1067. package/dist/envelope/enforcer.js +0 -286
  1068. package/dist/envelope/enforcer.js.map +0 -1
  1069. package/dist/envelope/expiry.d.ts +0 -2
  1070. package/dist/envelope/expiry.d.ts.map +0 -1
  1071. package/dist/envelope/expiry.js +0 -15
  1072. package/dist/envelope/expiry.js.map +0 -1
  1073. package/dist/envelope/index.d.ts +0 -9
  1074. package/dist/envelope/index.d.ts.map +0 -1
  1075. package/dist/envelope/index.js +0 -25
  1076. package/dist/envelope/index.js.map +0 -1
  1077. package/dist/envelope/key-provider.d.ts +0 -7
  1078. package/dist/envelope/key-provider.d.ts.map +0 -1
  1079. package/dist/envelope/key-provider.js +0 -137
  1080. package/dist/envelope/key-provider.js.map +0 -1
  1081. package/dist/envelope/reactive-config.d.ts +0 -24
  1082. package/dist/envelope/reactive-config.d.ts.map +0 -1
  1083. package/dist/envelope/reactive-config.js +0 -198
  1084. package/dist/envelope/reactive-config.js.map +0 -1
  1085. package/dist/envelope/run-guard.d.ts +0 -10
  1086. package/dist/envelope/run-guard.d.ts.map +0 -1
  1087. package/dist/envelope/run-guard.js +0 -19
  1088. package/dist/envelope/run-guard.js.map +0 -1
  1089. package/dist/envelope/signature.d.ts +0 -15
  1090. package/dist/envelope/signature.d.ts.map +0 -1
  1091. package/dist/envelope/signature.js +0 -75
  1092. package/dist/envelope/signature.js.map +0 -1
  1093. package/dist/envelope/store.d.ts +0 -16
  1094. package/dist/envelope/store.d.ts.map +0 -1
  1095. package/dist/envelope/store.js +0 -118
  1096. package/dist/envelope/store.js.map +0 -1
  1097. package/dist/envelope/tool-connector-scope.d.ts +0 -35
  1098. package/dist/envelope/tool-connector-scope.d.ts.map +0 -1
  1099. package/dist/envelope/tool-connector-scope.js +0 -61
  1100. package/dist/envelope/tool-connector-scope.js.map +0 -1
  1101. package/dist/envelope/types.d.ts +0 -60
  1102. package/dist/envelope/types.d.ts.map +0 -1
  1103. package/dist/envelope/types.js +0 -9
  1104. package/dist/envelope/types.js.map +0 -1
  1105. package/dist/evidence/effects.d.ts +0 -125
  1106. package/dist/evidence/effects.d.ts.map +0 -1
  1107. package/dist/evidence/effects.js +0 -409
  1108. package/dist/evidence/effects.js.map +0 -1
  1109. package/dist/evidence/read.d.ts +0 -130
  1110. package/dist/evidence/read.d.ts.map +0 -1
  1111. package/dist/evidence/read.js +0 -167
  1112. package/dist/evidence/read.js.map +0 -1
  1113. package/dist/gateways/attachment-utils.d.ts +0 -28
  1114. package/dist/gateways/attachment-utils.d.ts.map +0 -1
  1115. package/dist/gateways/attachment-utils.js +0 -489
  1116. package/dist/gateways/attachment-utils.js.map +0 -1
  1117. package/dist/gateways/channel-history.d.ts +0 -148
  1118. package/dist/gateways/channel-history.d.ts.map +0 -1
  1119. package/dist/gateways/channel-history.js +0 -385
  1120. package/dist/gateways/channel-history.js.map +0 -1
  1121. package/dist/gateways/context-injector.d.ts +0 -255
  1122. package/dist/gateways/context-injector.d.ts.map +0 -1
  1123. package/dist/gateways/context-injector.js +0 -285
  1124. package/dist/gateways/context-injector.js.map +0 -1
  1125. package/dist/gateways/image-analyzer.d.ts +0 -28
  1126. package/dist/gateways/image-analyzer.d.ts.map +0 -1
  1127. package/dist/gateways/image-analyzer.js +0 -154
  1128. package/dist/gateways/image-analyzer.js.map +0 -1
  1129. package/dist/gateways/index.d.ts +0 -35
  1130. package/dist/gateways/index.d.ts.map +0 -1
  1131. package/dist/gateways/index.js +0 -55
  1132. package/dist/gateways/index.js.map +0 -1
  1133. package/dist/gateways/member-candidate-store.d.ts +0 -26
  1134. package/dist/gateways/member-candidate-store.d.ts.map +0 -1
  1135. package/dist/gateways/member-candidate-store.js +0 -90
  1136. package/dist/gateways/member-candidate-store.js.map +0 -1
  1137. package/dist/gateways/member-effective-scope.d.ts +0 -25
  1138. package/dist/gateways/member-effective-scope.d.ts.map +0 -1
  1139. package/dist/gateways/member-effective-scope.js +0 -323
  1140. package/dist/gateways/member-effective-scope.js.map +0 -1
  1141. package/dist/gateways/message-router.d.ts +0 -239
  1142. package/dist/gateways/message-router.d.ts.map +0 -1
  1143. package/dist/gateways/message-router.js +0 -1714
  1144. package/dist/gateways/message-router.js.map +0 -1
  1145. package/dist/gateways/plugin-loader.d.ts +0 -80
  1146. package/dist/gateways/plugin-loader.d.ts.map +0 -1
  1147. package/dist/gateways/plugin-loader.js +0 -299
  1148. package/dist/gateways/plugin-loader.js.map +0 -1
  1149. package/dist/gateways/principal.d.ts +0 -37
  1150. package/dist/gateways/principal.d.ts.map +0 -1
  1151. package/dist/gateways/principal.js +0 -95
  1152. package/dist/gateways/principal.js.map +0 -1
  1153. package/dist/gateways/report-projection-v1.d.ts +0 -41
  1154. package/dist/gateways/report-projection-v1.d.ts.map +0 -1
  1155. package/dist/gateways/report-projection-v1.js +0 -160
  1156. package/dist/gateways/report-projection-v1.js.map +0 -1
  1157. package/dist/gateways/telegram-media.d.ts +0 -41
  1158. package/dist/gateways/telegram-media.d.ts.map +0 -1
  1159. package/dist/gateways/telegram-media.js +0 -242
  1160. package/dist/gateways/telegram-media.js.map +0 -1
  1161. package/dist/gateways/telegram-report-context-store.d.ts +0 -131
  1162. package/dist/gateways/telegram-report-context-store.d.ts.map +0 -1
  1163. package/dist/gateways/telegram-report-context-store.js +0 -388
  1164. package/dist/gateways/telegram-report-context-store.js.map +0 -1
  1165. package/dist/gateways/tool-status-tracker.d.ts +0 -87
  1166. package/dist/gateways/tool-status-tracker.d.ts.map +0 -1
  1167. package/dist/gateways/tool-status-tracker.js +0 -284
  1168. package/dist/gateways/tool-status-tracker.js.map +0 -1
  1169. package/dist/mcp/code-act-api-client.d.ts +0 -32
  1170. package/dist/mcp/code-act-api-client.d.ts.map +0 -1
  1171. package/dist/mcp/code-act-api-client.js +0 -80
  1172. package/dist/mcp/code-act-api-client.js.map +0 -1
  1173. package/dist/mcp/code-act-mcp-config.d.ts +0 -49
  1174. package/dist/mcp/code-act-mcp-config.d.ts.map +0 -1
  1175. package/dist/mcp/code-act-mcp-config.js +0 -124
  1176. package/dist/mcp/code-act-mcp-config.js.map +0 -1
  1177. package/dist/mcp/code-act-server.d.ts +0 -14
  1178. package/dist/mcp/code-act-server.d.ts.map +0 -1
  1179. package/dist/mcp/code-act-server.js +0 -204
  1180. package/dist/mcp/code-act-server.js.map +0 -1
  1181. package/dist/mcp/code-act-terminal-transport.d.ts +0 -64
  1182. package/dist/mcp/code-act-terminal-transport.d.ts.map +0 -1
  1183. package/dist/mcp/code-act-terminal-transport.js +0 -176
  1184. package/dist/mcp/code-act-terminal-transport.js.map +0 -1
  1185. package/dist/memory/agent-notice-queue.d.ts +0 -24
  1186. package/dist/memory/agent-notice-queue.d.ts.map +0 -1
  1187. package/dist/memory/agent-notice-queue.js +0 -40
  1188. package/dist/memory/agent-notice-queue.js.map +0 -1
  1189. package/dist/memory/audit-task-queue.d.ts +0 -28
  1190. package/dist/memory/audit-task-queue.d.ts.map +0 -1
  1191. package/dist/memory/audit-task-queue.js +0 -29
  1192. package/dist/memory/audit-task-queue.js.map +0 -1
  1193. package/dist/memory/bootstrap-context.d.ts +0 -12
  1194. package/dist/memory/bootstrap-context.d.ts.map +0 -1
  1195. package/dist/memory/bootstrap-context.js +0 -68
  1196. package/dist/memory/bootstrap-context.js.map +0 -1
  1197. package/dist/memory/history-extractor.d.ts +0 -69
  1198. package/dist/memory/history-extractor.d.ts.map +0 -1
  1199. package/dist/memory/history-extractor.js +0 -210
  1200. package/dist/memory/history-extractor.js.map +0 -1
  1201. package/dist/memory/memory-agent-ack.d.ts +0 -4
  1202. package/dist/memory/memory-agent-ack.d.ts.map +0 -1
  1203. package/dist/memory/memory-agent-ack.js +0 -54
  1204. package/dist/memory/memory-agent-ack.js.map +0 -1
  1205. package/dist/memory/memory-agent-dashboard.d.ts +0 -35
  1206. package/dist/memory/memory-agent-dashboard.d.ts.map +0 -1
  1207. package/dist/memory/memory-agent-dashboard.js +0 -116
  1208. package/dist/memory/memory-agent-dashboard.js.map +0 -1
  1209. package/dist/memory/memory-logger.d.ts +0 -47
  1210. package/dist/memory/memory-logger.d.ts.map +0 -1
  1211. package/dist/memory/memory-logger.js +0 -126
  1212. package/dist/memory/memory-logger.js.map +0 -1
  1213. package/dist/memory/provenance-live.d.ts +0 -111
  1214. package/dist/memory/provenance-live.d.ts.map +0 -1
  1215. package/dist/memory/provenance-live.js +0 -381
  1216. package/dist/memory/provenance-live.js.map +0 -1
  1217. package/dist/memory/provenance-resolver.d.ts +0 -184
  1218. package/dist/memory/provenance-resolver.d.ts.map +0 -1
  1219. package/dist/memory/provenance-resolver.js +0 -152
  1220. package/dist/memory/provenance-resolver.js.map +0 -1
  1221. package/dist/memory/raw-backed-memory-ingest.d.ts +0 -26
  1222. package/dist/memory/raw-backed-memory-ingest.d.ts.map +0 -1
  1223. package/dist/memory/raw-backed-memory-ingest.js +0 -214
  1224. package/dist/memory/raw-backed-memory-ingest.js.map +0 -1
  1225. package/dist/memory/recall-bundle-formatter.d.ts +0 -26
  1226. package/dist/memory/recall-bundle-formatter.d.ts.map +0 -1
  1227. package/dist/memory/recall-bundle-formatter.js +0 -53
  1228. package/dist/memory/recall-bundle-formatter.js.map +0 -1
  1229. package/dist/memory/save-candidate-extractor.d.ts +0 -16
  1230. package/dist/memory/save-candidate-extractor.d.ts.map +0 -1
  1231. package/dist/memory/save-candidate-extractor.js +0 -127
  1232. package/dist/memory/save-candidate-extractor.js.map +0 -1
  1233. package/dist/memory/save-candidate-types.d.ts +0 -16
  1234. package/dist/memory/save-candidate-types.d.ts.map +0 -1
  1235. package/dist/memory/save-candidate-types.js +0 -3
  1236. package/dist/memory/save-candidate-types.js.map +0 -1
  1237. package/dist/memory/scope-context.d.ts +0 -12
  1238. package/dist/memory/scope-context.d.ts.map +0 -1
  1239. package/dist/memory/scope-context.js +0 -18
  1240. package/dist/memory/scope-context.js.map +0 -1
  1241. package/dist/memory/secret-filter.d.ts +0 -23
  1242. package/dist/memory/secret-filter.d.ts.map +0 -1
  1243. package/dist/memory/secret-filter.js +0 -90
  1244. package/dist/memory/secret-filter.js.map +0 -1
  1245. package/dist/multi-agent/agent-event-bus.d.ts +0 -50
  1246. package/dist/multi-agent/agent-event-bus.d.ts.map +0 -1
  1247. package/dist/multi-agent/agent-event-bus.js +0 -101
  1248. package/dist/multi-agent/agent-event-bus.js.map +0 -1
  1249. package/dist/multi-agent/agent-process-manager.d.ts +0 -205
  1250. package/dist/multi-agent/agent-process-manager.d.ts.map +0 -1
  1251. package/dist/multi-agent/agent-process-manager.js +0 -1191
  1252. package/dist/multi-agent/agent-process-manager.js.map +0 -1
  1253. package/dist/multi-agent/bmad-templates.d.ts +0 -49
  1254. package/dist/multi-agent/bmad-templates.d.ts.map +0 -1
  1255. package/dist/multi-agent/bmad-templates.js +0 -121
  1256. package/dist/multi-agent/bmad-templates.js.map +0 -1
  1257. package/dist/multi-agent/runtime-process.d.ts +0 -74
  1258. package/dist/multi-agent/runtime-process.d.ts.map +0 -1
  1259. package/dist/multi-agent/runtime-process.js +0 -160
  1260. package/dist/multi-agent/runtime-process.js.map +0 -1
  1261. package/dist/multi-agent/tool-permission-manager.d.ts +0 -70
  1262. package/dist/multi-agent/tool-permission-manager.d.ts.map +0 -1
  1263. package/dist/multi-agent/tool-permission-manager.js +0 -195
  1264. package/dist/multi-agent/tool-permission-manager.js.map +0 -1
  1265. package/dist/multi-agent/types.d.ts +0 -438
  1266. package/dist/multi-agent/types.d.ts.map +0 -1
  1267. package/dist/multi-agent/types.js +0 -27
  1268. package/dist/multi-agent/types.js.map +0 -1
  1269. package/dist/multi-agent/wiki-agent-persona.d.ts +0 -16
  1270. package/dist/multi-agent/wiki-agent-persona.d.ts.map +0 -1
  1271. package/dist/multi-agent/wiki-agent-persona.js +0 -23
  1272. package/dist/multi-agent/wiki-agent-persona.js.map +0 -1
  1273. package/dist/multi-agent/workflow-types.d.ts +0 -186
  1274. package/dist/multi-agent/workflow-types.d.ts.map +0 -1
  1275. package/dist/multi-agent/workflow-types.js +0 -9
  1276. package/dist/multi-agent/workflow-types.js.map +0 -1
  1277. package/dist/observability/code-audit.d.ts +0 -87
  1278. package/dist/observability/code-audit.d.ts.map +0 -1
  1279. package/dist/observability/code-audit.js +0 -414
  1280. package/dist/observability/code-audit.js.map +0 -1
  1281. package/dist/observability/health-check.d.ts +0 -102
  1282. package/dist/observability/health-check.d.ts.map +0 -1
  1283. package/dist/observability/health-check.js +0 -422
  1284. package/dist/observability/health-check.js.map +0 -1
  1285. package/dist/observability/health-score.d.ts +0 -29
  1286. package/dist/observability/health-score.d.ts.map +0 -1
  1287. package/dist/observability/health-score.js +0 -83
  1288. package/dist/observability/health-score.js.map +0 -1
  1289. package/dist/observability/metrics-cleanup.d.ts +0 -24
  1290. package/dist/observability/metrics-cleanup.d.ts.map +0 -1
  1291. package/dist/observability/metrics-cleanup.js +0 -51
  1292. package/dist/observability/metrics-cleanup.js.map +0 -1
  1293. package/dist/observability/metrics-store.d.ts +0 -52
  1294. package/dist/observability/metrics-store.d.ts.map +0 -1
  1295. package/dist/observability/metrics-store.js +0 -186
  1296. package/dist/observability/metrics-store.js.map +0 -1
  1297. package/dist/observability/operational-issues.d.ts +0 -55
  1298. package/dist/observability/operational-issues.d.ts.map +0 -1
  1299. package/dist/observability/operational-issues.js +0 -170
  1300. package/dist/observability/operational-issues.js.map +0 -1
  1301. package/dist/onboarding/agent-contract.d.ts +0 -42
  1302. package/dist/onboarding/agent-contract.d.ts.map +0 -1
  1303. package/dist/onboarding/agent-contract.js +0 -129
  1304. package/dist/onboarding/agent-contract.js.map +0 -1
  1305. package/dist/onboarding/assess-live.d.ts +0 -22
  1306. package/dist/onboarding/assess-live.d.ts.map +0 -1
  1307. package/dist/onboarding/assess-live.js +0 -200
  1308. package/dist/onboarding/assess-live.js.map +0 -1
  1309. package/dist/onboarding/bootstrap-template.d.ts +0 -5
  1310. package/dist/onboarding/bootstrap-template.d.ts.map +0 -1
  1311. package/dist/onboarding/bootstrap-template.js +0 -34
  1312. package/dist/onboarding/bootstrap-template.js.map +0 -1
  1313. package/dist/operator/action-verifier.d.ts +0 -75
  1314. package/dist/operator/action-verifier.d.ts.map +0 -1
  1315. package/dist/operator/action-verifier.js +0 -149
  1316. package/dist/operator/action-verifier.js.map +0 -1
  1317. package/dist/operator/board-delta-gate.d.ts +0 -131
  1318. package/dist/operator/board-delta-gate.d.ts.map +0 -1
  1319. package/dist/operator/board-delta-gate.js +0 -181
  1320. package/dist/operator/board-delta-gate.js.map +0 -1
  1321. package/dist/operator/board-pipeline-render.d.ts +0 -16
  1322. package/dist/operator/board-pipeline-render.d.ts.map +0 -1
  1323. package/dist/operator/board-pipeline-render.js +0 -69
  1324. package/dist/operator/board-pipeline-render.js.map +0 -1
  1325. package/dist/operator/board-reconcile.d.ts +0 -61
  1326. package/dist/operator/board-reconcile.d.ts.map +0 -1
  1327. package/dist/operator/board-reconcile.js +0 -157
  1328. package/dist/operator/board-reconcile.js.map +0 -1
  1329. package/dist/operator/board-refresh-gate.d.ts +0 -39
  1330. package/dist/operator/board-refresh-gate.d.ts.map +0 -1
  1331. package/dist/operator/board-refresh-gate.js +0 -83
  1332. package/dist/operator/board-refresh-gate.js.map +0 -1
  1333. package/dist/operator/changes-projection.d.ts +0 -72
  1334. package/dist/operator/changes-projection.d.ts.map +0 -1
  1335. package/dist/operator/changes-projection.js +0 -110
  1336. package/dist/operator/changes-projection.js.map +0 -1
  1337. package/dist/operator/connector-delta-repo.d.ts +0 -33
  1338. package/dist/operator/connector-delta-repo.d.ts.map +0 -1
  1339. package/dist/operator/connector-delta-repo.js +0 -0
  1340. package/dist/operator/connector-delta-repo.js.map +0 -1
  1341. package/dist/operator/console-brief.d.ts +0 -40
  1342. package/dist/operator/console-brief.d.ts.map +0 -1
  1343. package/dist/operator/console-brief.js +0 -246
  1344. package/dist/operator/console-brief.js.map +0 -1
  1345. package/dist/operator/experience-evidence.d.ts +0 -18
  1346. package/dist/operator/experience-evidence.d.ts.map +0 -1
  1347. package/dist/operator/experience-evidence.js +0 -82
  1348. package/dist/operator/experience-evidence.js.map +0 -1
  1349. package/dist/operator/experience-hints.d.ts +0 -44
  1350. package/dist/operator/experience-hints.d.ts.map +0 -1
  1351. package/dist/operator/experience-hints.js +0 -98
  1352. package/dist/operator/experience-hints.js.map +0 -1
  1353. package/dist/operator/external-correlation.d.ts +0 -94
  1354. package/dist/operator/external-correlation.d.ts.map +0 -1
  1355. package/dist/operator/external-correlation.js +0 -177
  1356. package/dist/operator/external-correlation.js.map +0 -1
  1357. package/dist/operator/external-lifecycle-candidates.d.ts +0 -70
  1358. package/dist/operator/external-lifecycle-candidates.d.ts.map +0 -1
  1359. package/dist/operator/external-lifecycle-candidates.js +0 -579
  1360. package/dist/operator/external-lifecycle-candidates.js.map +0 -1
  1361. package/dist/operator/external-lifecycle-discovery.d.ts +0 -61
  1362. package/dist/operator/external-lifecycle-discovery.d.ts.map +0 -1
  1363. package/dist/operator/external-lifecycle-discovery.js +0 -103
  1364. package/dist/operator/external-lifecycle-discovery.js.map +0 -1
  1365. package/dist/operator/external-lifecycle.d.ts +0 -105
  1366. package/dist/operator/external-lifecycle.d.ts.map +0 -1
  1367. package/dist/operator/external-lifecycle.js +0 -27
  1368. package/dist/operator/external-lifecycle.js.map +0 -1
  1369. package/dist/operator/file-coordination.d.ts +0 -7
  1370. package/dist/operator/file-coordination.d.ts.map +0 -1
  1371. package/dist/operator/file-coordination.js +0 -84
  1372. package/dist/operator/file-coordination.js.map +0 -1
  1373. package/dist/operator/file-export.d.ts +0 -22
  1374. package/dist/operator/file-export.d.ts.map +0 -1
  1375. package/dist/operator/file-export.js +0 -115
  1376. package/dist/operator/file-export.js.map +0 -1
  1377. package/dist/operator/leg-cadence.d.ts +0 -72
  1378. package/dist/operator/leg-cadence.d.ts.map +0 -1
  1379. package/dist/operator/leg-cadence.js +0 -122
  1380. package/dist/operator/leg-cadence.js.map +0 -1
  1381. package/dist/operator/mama-memory-port.d.ts +0 -13
  1382. package/dist/operator/mama-memory-port.d.ts.map +0 -1
  1383. package/dist/operator/mama-memory-port.js +0 -33
  1384. package/dist/operator/mama-memory-port.js.map +0 -1
  1385. package/dist/operator/operator-interfaces.d.ts +0 -136
  1386. package/dist/operator/operator-interfaces.d.ts.map +0 -1
  1387. package/dist/operator/operator-interfaces.js +0 -15
  1388. package/dist/operator/operator-interfaces.js.map +0 -1
  1389. package/dist/operator/operator-trigger-loop.d.ts +0 -203
  1390. package/dist/operator/operator-trigger-loop.d.ts.map +0 -1
  1391. package/dist/operator/operator-trigger-loop.js +0 -827
  1392. package/dist/operator/operator-trigger-loop.js.map +0 -1
  1393. package/dist/operator/owner-action-effects.d.ts +0 -112
  1394. package/dist/operator/owner-action-effects.d.ts.map +0 -1
  1395. package/dist/operator/owner-action-effects.js +0 -375
  1396. package/dist/operator/owner-action-effects.js.map +0 -1
  1397. package/dist/operator/owner-event-effects.d.ts +0 -65
  1398. package/dist/operator/owner-event-effects.d.ts.map +0 -1
  1399. package/dist/operator/owner-event-effects.js +0 -249
  1400. package/dist/operator/owner-event-effects.js.map +0 -1
  1401. package/dist/operator/owner-event-inbox.d.ts +0 -124
  1402. package/dist/operator/owner-event-inbox.d.ts.map +0 -1
  1403. package/dist/operator/owner-event-inbox.js +0 -440
  1404. package/dist/operator/owner-event-inbox.js.map +0 -1
  1405. package/dist/operator/owner-event-loop.d.ts +0 -99
  1406. package/dist/operator/owner-event-loop.d.ts.map +0 -1
  1407. package/dist/operator/owner-event-loop.js +0 -253
  1408. package/dist/operator/owner-event-loop.js.map +0 -1
  1409. package/dist/operator/owner-event-outcome.d.ts +0 -36
  1410. package/dist/operator/owner-event-outcome.d.ts.map +0 -1
  1411. package/dist/operator/owner-event-outcome.js +0 -174
  1412. package/dist/operator/owner-event-outcome.js.map +0 -1
  1413. package/dist/operator/owner-event-policy.d.ts +0 -40
  1414. package/dist/operator/owner-event-policy.d.ts.map +0 -1
  1415. package/dist/operator/owner-event-policy.js +0 -75
  1416. package/dist/operator/owner-event-policy.js.map +0 -1
  1417. package/dist/operator/owner-event-prompt.d.ts +0 -21
  1418. package/dist/operator/owner-event-prompt.d.ts.map +0 -1
  1419. package/dist/operator/owner-event-prompt.js +0 -69
  1420. package/dist/operator/owner-event-prompt.js.map +0 -1
  1421. package/dist/operator/owner-runtime-journal.d.ts +0 -21
  1422. package/dist/operator/owner-runtime-journal.d.ts.map +0 -1
  1423. package/dist/operator/owner-runtime-journal.js +0 -135
  1424. package/dist/operator/owner-runtime-journal.js.map +0 -1
  1425. package/dist/operator/owner-runtime.d.ts +0 -48
  1426. package/dist/operator/owner-runtime.d.ts.map +0 -1
  1427. package/dist/operator/owner-runtime.js +0 -99
  1428. package/dist/operator/owner-runtime.js.map +0 -1
  1429. package/dist/operator/pending-report-store.d.ts +0 -99
  1430. package/dist/operator/pending-report-store.d.ts.map +0 -1
  1431. package/dist/operator/pending-report-store.js +0 -554
  1432. package/dist/operator/pending-report-store.js.map +0 -1
  1433. package/dist/operator/procedure-activation.d.ts +0 -7
  1434. package/dist/operator/procedure-activation.d.ts.map +0 -1
  1435. package/dist/operator/procedure-activation.js +0 -132
  1436. package/dist/operator/procedure-activation.js.map +0 -1
  1437. package/dist/operator/procedure-projection.d.ts +0 -25
  1438. package/dist/operator/procedure-projection.d.ts.map +0 -1
  1439. package/dist/operator/procedure-projection.js +0 -80
  1440. package/dist/operator/procedure-projection.js.map +0 -1
  1441. package/dist/operator/procedure-runtime.d.ts +0 -45
  1442. package/dist/operator/procedure-runtime.d.ts.map +0 -1
  1443. package/dist/operator/procedure-runtime.js +0 -496
  1444. package/dist/operator/procedure-runtime.js.map +0 -1
  1445. package/dist/operator/procedure-store.d.ts +0 -97
  1446. package/dist/operator/procedure-store.d.ts.map +0 -1
  1447. package/dist/operator/procedure-store.js +0 -368
  1448. package/dist/operator/procedure-store.js.map +0 -1
  1449. package/dist/operator/provenance-lookup.d.ts +0 -18
  1450. package/dist/operator/provenance-lookup.d.ts.map +0 -1
  1451. package/dist/operator/provenance-lookup.js +0 -54
  1452. package/dist/operator/provenance-lookup.js.map +0 -1
  1453. package/dist/operator/repair-request.d.ts +0 -29
  1454. package/dist/operator/repair-request.d.ts.map +0 -1
  1455. package/dist/operator/repair-request.js +0 -115
  1456. package/dist/operator/repair-request.js.map +0 -1
  1457. package/dist/operator/report-carry-delivery.d.ts +0 -35
  1458. package/dist/operator/report-carry-delivery.d.ts.map +0 -1
  1459. package/dist/operator/report-carry-delivery.js +0 -55
  1460. package/dist/operator/report-carry-delivery.js.map +0 -1
  1461. package/dist/operator/report-carry.d.ts +0 -66
  1462. package/dist/operator/report-carry.d.ts.map +0 -1
  1463. package/dist/operator/report-carry.js +0 -352
  1464. package/dist/operator/report-carry.js.map +0 -1
  1465. package/dist/operator/report-delivery-coordinator.d.ts +0 -84
  1466. package/dist/operator/report-delivery-coordinator.d.ts.map +0 -1
  1467. package/dist/operator/report-delivery-coordinator.js +0 -146
  1468. package/dist/operator/report-delivery-coordinator.js.map +0 -1
  1469. package/dist/operator/report-run.d.ts +0 -52
  1470. package/dist/operator/report-run.d.ts.map +0 -1
  1471. package/dist/operator/report-run.js +0 -32
  1472. package/dist/operator/report-run.js.map +0 -1
  1473. package/dist/operator/report-scheduler.d.ts +0 -66
  1474. package/dist/operator/report-scheduler.d.ts.map +0 -1
  1475. package/dist/operator/report-scheduler.js +0 -135
  1476. package/dist/operator/report-scheduler.js.map +0 -1
  1477. package/dist/operator/runtime-config.d.ts +0 -10
  1478. package/dist/operator/runtime-config.d.ts.map +0 -1
  1479. package/dist/operator/runtime-config.js +0 -21
  1480. package/dist/operator/runtime-config.js.map +0 -1
  1481. package/dist/operator/situation-report.d.ts +0 -197
  1482. package/dist/operator/situation-report.d.ts.map +0 -1
  1483. package/dist/operator/situation-report.js +0 -462
  1484. package/dist/operator/situation-report.js.map +0 -1
  1485. package/dist/operator/subagent-stimulus.d.ts +0 -34
  1486. package/dist/operator/subagent-stimulus.d.ts.map +0 -1
  1487. package/dist/operator/subagent-stimulus.js +0 -145
  1488. package/dist/operator/subagent-stimulus.js.map +0 -1
  1489. package/dist/operator/task-ledger.d.ts +0 -879
  1490. package/dist/operator/task-ledger.d.ts.map +0 -1
  1491. package/dist/operator/task-ledger.js +0 -3601
  1492. package/dist/operator/task-ledger.js.map +0 -1
  1493. package/dist/operator/task-list-views.d.ts +0 -91
  1494. package/dist/operator/task-list-views.d.ts.map +0 -1
  1495. package/dist/operator/task-list-views.js +0 -532
  1496. package/dist/operator/task-list-views.js.map +0 -1
  1497. package/dist/operator/task-temporal.d.ts +0 -24
  1498. package/dist/operator/task-temporal.d.ts.map +0 -1
  1499. package/dist/operator/task-temporal.js +0 -123
  1500. package/dist/operator/task-temporal.js.map +0 -1
  1501. package/dist/operator/temporal-effect.d.ts +0 -65
  1502. package/dist/operator/temporal-effect.d.ts.map +0 -1
  1503. package/dist/operator/temporal-effect.js +0 -71
  1504. package/dist/operator/temporal-effect.js.map +0 -1
  1505. package/dist/operator/temporal-reconcile.d.ts +0 -49
  1506. package/dist/operator/temporal-reconcile.d.ts.map +0 -1
  1507. package/dist/operator/temporal-reconcile.js +0 -231
  1508. package/dist/operator/temporal-reconcile.js.map +0 -1
  1509. package/dist/operator/temporal-runtime.d.ts +0 -51
  1510. package/dist/operator/temporal-runtime.d.ts.map +0 -1
  1511. package/dist/operator/temporal-runtime.js +0 -104
  1512. package/dist/operator/temporal-runtime.js.map +0 -1
  1513. package/dist/operator/temporal-worker.d.ts +0 -18
  1514. package/dist/operator/temporal-worker.d.ts.map +0 -1
  1515. package/dist/operator/temporal-worker.js +0 -82
  1516. package/dist/operator/temporal-worker.js.map +0 -1
  1517. package/dist/operator/thread-brief-memory.d.ts +0 -29
  1518. package/dist/operator/thread-brief-memory.d.ts.map +0 -1
  1519. package/dist/operator/thread-brief-memory.js +0 -61
  1520. package/dist/operator/thread-brief-memory.js.map +0 -1
  1521. package/dist/operator/trigger-author.d.ts +0 -63
  1522. package/dist/operator/trigger-author.d.ts.map +0 -1
  1523. package/dist/operator/trigger-author.js +0 -384
  1524. package/dist/operator/trigger-author.js.map +0 -1
  1525. package/dist/operator/trigger-evolve.d.ts +0 -31
  1526. package/dist/operator/trigger-evolve.d.ts.map +0 -1
  1527. package/dist/operator/trigger-evolve.js +0 -51
  1528. package/dist/operator/trigger-evolve.js.map +0 -1
  1529. package/dist/operator/trigger-fire.d.ts +0 -29
  1530. package/dist/operator/trigger-fire.d.ts.map +0 -1
  1531. package/dist/operator/trigger-fire.js +0 -41
  1532. package/dist/operator/trigger-fire.js.map +0 -1
  1533. package/dist/operator/trigger-matcher.d.ts +0 -19
  1534. package/dist/operator/trigger-matcher.d.ts.map +0 -1
  1535. package/dist/operator/trigger-matcher.js +0 -65
  1536. package/dist/operator/trigger-matcher.js.map +0 -1
  1537. package/dist/operator/trigger-registry.d.ts +0 -58
  1538. package/dist/operator/trigger-registry.d.ts.map +0 -1
  1539. package/dist/operator/trigger-registry.js +0 -349
  1540. package/dist/operator/trigger-registry.js.map +0 -1
  1541. package/dist/operator/trigger-review.d.ts +0 -23
  1542. package/dist/operator/trigger-review.d.ts.map +0 -1
  1543. package/dist/operator/trigger-review.js +0 -193
  1544. package/dist/operator/trigger-review.js.map +0 -1
  1545. package/dist/operator/trigger-types.d.ts +0 -95
  1546. package/dist/operator/trigger-types.d.ts.map +0 -1
  1547. package/dist/operator/trigger-types.js +0 -14
  1548. package/dist/operator/trigger-types.js.map +0 -1
  1549. package/dist/operator/wiki-continuity.d.ts +0 -153
  1550. package/dist/operator/wiki-continuity.d.ts.map +0 -1
  1551. package/dist/operator/wiki-continuity.js +0 -221
  1552. package/dist/operator/wiki-continuity.js.map +0 -1
  1553. package/dist/operator/worker-run.d.ts +0 -109
  1554. package/dist/operator/worker-run.d.ts.map +0 -1
  1555. package/dist/operator/worker-run.js +0 -131
  1556. package/dist/operator/worker-run.js.map +0 -1
  1557. package/dist/operator/workorder-consumer.d.ts +0 -294
  1558. package/dist/operator/workorder-consumer.d.ts.map +0 -1
  1559. package/dist/operator/workorder-consumer.js +0 -1108
  1560. package/dist/operator/workorder-consumer.js.map +0 -1
  1561. package/dist/operator/workorder-hooks.d.ts +0 -162
  1562. package/dist/operator/workorder-hooks.d.ts.map +0 -1
  1563. package/dist/operator/workorder-hooks.js +0 -342
  1564. package/dist/operator/workorder-hooks.js.map +0 -1
  1565. package/dist/operator/workorder-publishers.d.ts +0 -117
  1566. package/dist/operator/workorder-publishers.d.ts.map +0 -1
  1567. package/dist/operator/workorder-publishers.js +0 -544
  1568. package/dist/operator/workorder-publishers.js.map +0 -1
  1569. package/dist/runners/cli-runner.d.ts +0 -59
  1570. package/dist/runners/cli-runner.d.ts.map +0 -1
  1571. package/dist/runners/cli-runner.js +0 -191
  1572. package/dist/runners/cli-runner.js.map +0 -1
  1573. package/dist/runners/index.d.ts +0 -11
  1574. package/dist/runners/index.d.ts.map +0 -1
  1575. package/dist/runners/index.js +0 -15
  1576. package/dist/runners/index.js.map +0 -1
  1577. package/dist/runners/types.d.ts +0 -81
  1578. package/dist/runners/types.d.ts.map +0 -1
  1579. package/dist/runners/types.js +0 -31
  1580. package/dist/runners/types.js.map +0 -1
  1581. package/dist/scheduler/cron-result-router.d.ts +0 -24
  1582. package/dist/scheduler/cron-result-router.d.ts.map +0 -1
  1583. package/dist/scheduler/cron-result-router.js +0 -63
  1584. package/dist/scheduler/cron-result-router.js.map +0 -1
  1585. package/dist/scheduler/cron-scheduler.d.ts +0 -115
  1586. package/dist/scheduler/cron-scheduler.d.ts.map +0 -1
  1587. package/dist/scheduler/cron-scheduler.js +0 -336
  1588. package/dist/scheduler/cron-scheduler.js.map +0 -1
  1589. package/dist/scheduler/cron-worker.d.ts +0 -39
  1590. package/dist/scheduler/cron-worker.d.ts.map +0 -1
  1591. package/dist/scheduler/cron-worker.js +0 -94
  1592. package/dist/scheduler/cron-worker.js.map +0 -1
  1593. package/dist/scheduler/heartbeat.d.ts +0 -64
  1594. package/dist/scheduler/heartbeat.d.ts.map +0 -1
  1595. package/dist/scheduler/heartbeat.js +0 -197
  1596. package/dist/scheduler/heartbeat.js.map +0 -1
  1597. package/dist/scheduler/index.d.ts +0 -26
  1598. package/dist/scheduler/index.d.ts.map +0 -1
  1599. package/dist/scheduler/index.js +0 -37
  1600. package/dist/scheduler/index.js.map +0 -1
  1601. package/dist/scheduler/job-lock.d.ts +0 -85
  1602. package/dist/scheduler/job-lock.d.ts.map +0 -1
  1603. package/dist/scheduler/job-lock.js +0 -137
  1604. package/dist/scheduler/job-lock.js.map +0 -1
  1605. package/dist/scheduler/recovery.d.ts +0 -78
  1606. package/dist/scheduler/recovery.d.ts.map +0 -1
  1607. package/dist/scheduler/recovery.js +0 -124
  1608. package/dist/scheduler/recovery.js.map +0 -1
  1609. package/dist/scheduler/schedule-store.d.ts +0 -112
  1610. package/dist/scheduler/schedule-store.d.ts.map +0 -1
  1611. package/dist/scheduler/schedule-store.js +0 -259
  1612. package/dist/scheduler/schedule-store.js.map +0 -1
  1613. package/dist/scheduler/token-keep-alive.d.ts +0 -49
  1614. package/dist/scheduler/token-keep-alive.d.ts.map +0 -1
  1615. package/dist/scheduler/token-keep-alive.js +0 -102
  1616. package/dist/scheduler/token-keep-alive.js.map +0 -1
  1617. package/dist/scheduler/types.d.ts +0 -98
  1618. package/dist/scheduler/types.d.ts.map +0 -1
  1619. package/dist/scheduler/types.js +0 -21
  1620. package/dist/scheduler/types.js.map +0 -1
  1621. package/dist/security/security-monitor.d.ts +0 -56
  1622. package/dist/security/security-monitor.d.ts.map +0 -1
  1623. package/dist/security/security-monitor.js +0 -779
  1624. package/dist/security/security-monitor.js.map +0 -1
  1625. package/dist/security/trusted-proxy.d.ts +0 -9
  1626. package/dist/security/trusted-proxy.d.ts.map +0 -1
  1627. package/dist/security/trusted-proxy.js +0 -36
  1628. package/dist/security/trusted-proxy.js.map +0 -1
  1629. package/dist/skills/index.d.ts +0 -10
  1630. package/dist/skills/index.d.ts.map +0 -1
  1631. package/dist/skills/index.js +0 -26
  1632. package/dist/skills/index.js.map +0 -1
  1633. package/dist/skills/skill-executor.d.ts +0 -48
  1634. package/dist/skills/skill-executor.d.ts.map +0 -1
  1635. package/dist/skills/skill-executor.js +0 -483
  1636. package/dist/skills/skill-executor.js.map +0 -1
  1637. package/dist/skills/skill-loader.d.ts +0 -40
  1638. package/dist/skills/skill-loader.d.ts.map +0 -1
  1639. package/dist/skills/skill-loader.js +0 -233
  1640. package/dist/skills/skill-loader.js.map +0 -1
  1641. package/dist/skills/skill-matcher.d.ts +0 -33
  1642. package/dist/skills/skill-matcher.d.ts.map +0 -1
  1643. package/dist/skills/skill-matcher.js +0 -190
  1644. package/dist/skills/skill-matcher.js.map +0 -1
  1645. package/dist/skills/skill-registry.d.ts +0 -117
  1646. package/dist/skills/skill-registry.d.ts.map +0 -1
  1647. package/dist/skills/skill-registry.js +0 -627
  1648. package/dist/skills/skill-registry.js.map +0 -1
  1649. package/dist/skills/types.d.ts +0 -131
  1650. package/dist/skills/types.d.ts.map +0 -1
  1651. package/dist/skills/types.js +0 -12
  1652. package/dist/skills/types.js.map +0 -1
  1653. package/dist/utils/log-sanitizer.d.ts +0 -79
  1654. package/dist/utils/log-sanitizer.d.ts.map +0 -1
  1655. package/dist/utils/log-sanitizer.js +0 -215
  1656. package/dist/utils/log-sanitizer.js.map +0 -1
  1657. package/dist/validation/session-service.d.ts +0 -72
  1658. package/dist/validation/session-service.d.ts.map +0 -1
  1659. package/dist/validation/session-service.js +0 -298
  1660. package/dist/validation/session-service.js.map +0 -1
  1661. package/dist/validation/store.d.ts +0 -25
  1662. package/dist/validation/store.d.ts.map +0 -1
  1663. package/dist/validation/store.js +0 -200
  1664. package/dist/validation/store.js.map +0 -1
  1665. package/dist/validation/types.d.ts +0 -119
  1666. package/dist/validation/types.d.ts.map +0 -1
  1667. package/dist/validation/types.js +0 -57
  1668. package/dist/validation/types.js.map +0 -1
  1669. package/dist/wiki/wiki-turn-contract.d.ts +0 -19
  1670. package/dist/wiki/wiki-turn-contract.d.ts.map +0 -1
  1671. package/dist/wiki/wiki-turn-contract.js +0 -60
  1672. package/dist/wiki/wiki-turn-contract.js.map +0 -1
  1673. package/public/viewer/js/utils/ui-commands.js +0 -88
  1674. package/public/viewer/src/utils/ui-commands.ts +0 -114
  1675. package/scripts/attachment/extract-office-text.js +0 -179
  1676. package/scripts/attachment/extract-pdf-text.swift +0 -36
  1677. package/scripts/backfill-channel-keys.ts +0 -509
  1678. package/scripts/crack-failure-digests.ts +0 -55
  1679. package/scripts/generate-gateway-tools.ts +0 -131
  1680. package/scripts/image/fb-overlay.py +0 -128
  1681. package/scripts/image/ocr-image.py +0 -38
  1682. package/scripts/postinstall.js +0 -161
  1683. package/scripts/setup-ocr.js +0 -120
  1684. package/templates/AGENTS.claude.md +0 -23
  1685. package/templates/AGENTS.codex.md +0 -11
  1686. package/templates/bmad/LICENSE +0 -28
  1687. package/templates/bmad/architecture.md +0 -343
  1688. package/templates/bmad/bmm-workflow-status.template.yaml +0 -66
  1689. package/templates/bmad/prd.md +0 -198
  1690. package/templates/bmad/product-brief.md +0 -149
  1691. package/templates/bmad/sprint-status.template.yaml +0 -35
  1692. package/templates/bmad/tech-spec.md +0 -151
  1693. package/templates/entity-audit-fixtures/cross-language-aliases.json +0 -28
  1694. package/templates/entity-audit-fixtures/gold-canonical-identities.json +0 -46
  1695. package/templates/skills/danggeun-monitor.md +0 -88
  1696. package/templates/skills/document-analyze.md +0 -63
  1697. package/templates/skills/frontend-design.md +0 -71
  1698. package/templates/skills/image-translate.md +0 -62
  1699. package/templates/skills/multi-agent-collab.md +0 -145
  1700. package/templates/skills/scheduling.md +0 -107
  1701. package/templates/workspace/skill-forge/DESIGN.md +0 -115
  1702. package/templates/workspace/skill-forge/agents/architect.ts +0 -295
  1703. package/templates/workspace/skill-forge/agents/developer.ts +0 -364
  1704. package/templates/workspace/skill-forge/agents/qa.ts +0 -313
  1705. package/templates/workspace/skill-forge/claude-api.ts +0 -353
  1706. package/templates/workspace/skill-forge/discord-ui.ts +0 -580
  1707. package/templates/workspace/skill-forge/error-handler.ts +0 -354
  1708. package/templates/workspace/skill-forge/mama-integration.ts +0 -357
  1709. package/templates/workspace/skill-forge/orchestrator.ts +0 -495
  1710. package/templates/workspace/skill-forge/output/generated-skills/skills/hello-world/README.md +0 -24
  1711. package/templates/workspace/skill-forge/output/generated-skills/skills/hello-world/index.ts +0 -79
  1712. package/templates/workspace/skill-forge/output/generated-skills/skills/hello-world/types.ts +0 -17
  1713. package/templates/workspace/skill-forge/package.json +0 -21
  1714. package/templates/workspace/skill-forge/state/session.json +0 -132
  1715. package/templates/workspace/skill-forge/test-e2e.ts +0 -139
  1716. package/templates/workspace/skill-forge/tsconfig.json +0 -20
  1717. package/templates/workspace/skill-forge/types.ts +0 -159
@@ -1,3601 +0,0 @@
1
- "use strict";
2
- /**
3
- * TaskLedger - the operator-owned native work-item ledger (M8 Task 0.1).
4
- *
5
- * Extends the shape of Kagemusha's proven task store with assignment,
6
- * idempotency, temporal scheduling, durable generation, effect receipt, and
7
- * workorder state. Implements the pre-existing `TaskSource` interface
8
- * (operator-interfaces.ts) so the board projects one task model, not two.
9
- *
10
- * Owner conversations create rows through task_create. Reconcile runs update or
11
- * reclassify existing rows through the task_update/task_reclassify gateway
12
- * tools; the pipeline board slot is a projection of `list({order:
13
- * 'deadline_priority'})`. The agent proposes task changes, while this ledger
14
- * enforces revisions, temporal ownership, idempotency, and atomic receipts.
15
- *
16
- * Schema-extension note: CREATE TABLE IF NOT EXISTS is a no-op on existing
17
- * tables. Any post-ship column addition needs an explicit ALTER TABLE guarded
18
- * by a PRAGMA table_info check, added to runMigration().
19
- *
20
- * The db handle is SHARED with TriggerRegistry and owned by the caller
21
- * (start.ts opens and closes it once) - deliberately no close() here.
22
- */
23
- Object.defineProperty(exports, "__esModule", { value: true });
24
- exports.TaskLedger = exports.TASK_COMPLETION_CRITERIA_MAX_LENGTH = exports.TASK_RECLASSIFY_REASON_MAX_LENGTH = exports.TASK_RECLASSIFY_DISPOSITIONS = exports.TASK_RESOLUTION_KINDS = exports.WORKORDER_CHANNEL_PREFIX = exports.TEMPORAL_WORKORDER_MAX_ATTEMPTS = exports.WORKORDER_DELEGATED_AT_KEY = exports.WORKORDER_KINDS = exports.TASK_KINDS = exports.TASK_PRIORITIES = exports.TASK_STATUSES = void 0;
25
- exports.publisherPayloadOfStoredWorkOrder = publisherPayloadOfStoredWorkOrder;
26
- const node_crypto_1 = require("node:crypto");
27
- const operator_task_temporal_js_1 = require("../db/migrations/operator-task-temporal.js");
28
- const operator_task_external_lifecycle_js_1 = require("../db/migrations/operator-task-external-lifecycle.js");
29
- const operator_task_review_lifecycle_js_1 = require("../db/migrations/operator-task-review-lifecycle.js");
30
- const operator_task_classification_js_1 = require("../db/migrations/operator-task-classification.js");
31
- const operator_owner_action_candidates_js_1 = require("../db/migrations/operator-owner-action-candidates.js");
32
- const effects_js_1 = require("../evidence/effects.js");
33
- const temporal_effect_js_1 = require("./temporal-effect.js");
34
- const task_temporal_js_1 = require("./task-temporal.js");
35
- const external_lifecycle_candidates_js_1 = require("./external-lifecycle-candidates.js");
36
- const workorder_publishers_js_1 = require("./workorder-publishers.js");
37
- /** listPage() only: a page size large enough to be the whole board, so the limit+1
38
- * next-page probe stays intact when the caller passes no limit. list() has no LIMIT. */
39
- const WHOLE_BOARD_LIMIT = 100_000;
40
- exports.TASK_STATUSES = [
41
- 'pending',
42
- 'in_progress',
43
- 'review',
44
- 'blocked',
45
- 'done',
46
- 'cancelled',
47
- // System-only terminal for workorder rows. Owner rows can never reach it:
48
- // external create/update guards reject it, so it stays out of owner surfaces.
49
- 'failed',
50
- ];
51
- exports.TASK_PRIORITIES = ['high', 'normal', 'low'];
52
- function scheduledPromotionReservationKeys(idempotencyKey) {
53
- const legacy = /^promotion:(\d+)$/.exec(idempotencyKey);
54
- if (legacy) {
55
- return [idempotencyKey, `promotion:v2:${workorder_publishers_js_1.DEFAULT_PROMOTION_INTERVAL_MS}:${legacy[1]}`];
56
- }
57
- const versioned = /^promotion:v2:(\d+):(\d+)$/.exec(idempotencyKey);
58
- if (!versioned)
59
- return null;
60
- const [, intervalMs, slot] = versioned;
61
- return Number(intervalMs) === workorder_publishers_js_1.DEFAULT_PROMOTION_INTERVAL_MS
62
- ? [idempotencyKey, `promotion:${slot}`]
63
- : [idempotencyKey];
64
- }
65
- exports.TASK_KINDS = ['owner', 'system'];
66
- exports.WORKORDER_KINDS = [
67
- 'board',
68
- 'wiki',
69
- 'memory-curation',
70
- 'temporal',
71
- 'self-check',
72
- ];
73
- /**
74
- * Ledger-managed payload key holding the delegation timestamp. Like `attempts`, it is never
75
- * valid publisher input (validateWorkOrderPayload rejects unknown fields at enqueue) and it
76
- * is stripped from a requeued replacement, which has delegated nothing.
77
- */
78
- exports.WORKORDER_DELEGATED_AT_KEY = 'delegated_at';
79
- /**
80
- * Publisher-shaped view of a STORED workorder payload.
81
- *
82
- * Stored rows carry ledger-managed keys (`attempts`, `delegated_at`) that the enqueue
83
- * validator rejects by design. Revalidating a stored row must therefore check only what a
84
- * publisher could have supplied; validating the raw stored payload turned a
85
- * delegated-and-verified board attempt into a permanently "unresolved" receipt state
86
- * (live, 2026-09-09, workorder #4765). Enqueue input is still rejected loudly.
87
- */
88
- function publisherPayloadOfStoredWorkOrder(payload) {
89
- const { attempts: _attempts, [exports.WORKORDER_DELEGATED_AT_KEY]: _delegatedAt, ...publisherInput } = payload;
90
- return publisherInput;
91
- }
92
- exports.TEMPORAL_WORKORDER_MAX_ATTEMPTS = 3;
93
- /** source_channel namespace for workorder rows: 'workorder:<workKind>'. */
94
- exports.WORKORDER_CHANNEL_PREFIX = 'workorder:';
95
- /** SQL variable chunk for cause lookups (SQLite default limit is 999). */
96
- const EFFECT_CAUSE_CHUNK = 500;
97
- const KNOWN_WORKORDER_CHANNELS = exports.WORKORDER_KINDS.map((workKind) => `${exports.WORKORDER_CHANNEL_PREFIX}${workKind}`);
98
- const KNOWN_WORKORDER_CHANNELS_SQL = KNOWN_WORKORDER_CHANNELS.map(() => '?').join(',');
99
- /**
100
- * Why a row reached its terminal state. Without this the agent cannot tell
101
- * completed work from an item that was never a task, which is how connector
102
- * observations, principles and open questions accumulated as owner rows.
103
- */
104
- exports.TASK_RESOLUTION_KINDS = [
105
- 'completed_evidence',
106
- 'completed_no_issue',
107
- 'non_task_record',
108
- 'non_task_memory',
109
- ];
110
- /** The recorrection an agent may apply to an existing owner row. */
111
- exports.TASK_RECLASSIFY_DISPOSITIONS = [
112
- 'completed_evidence',
113
- 'completed_no_issue',
114
- 'non_task_record',
115
- 'non_task_memory',
116
- 'reopen',
117
- ];
118
- /** Upper bound on the preserved reason, matching latest_event's practical size. */
119
- exports.TASK_RECLASSIFY_REASON_MAX_LENGTH = 2000;
120
- exports.TASK_COMPLETION_CRITERIA_MAX_LENGTH = 500;
121
- const PRIORITY_RANK = { high: 0, normal: 1, low: 2 };
122
- function encodeListCursor(payload) {
123
- return Buffer.from(JSON.stringify(payload), 'utf8').toString('base64url');
124
- }
125
- /** Loud on anything malformed or from a different ordering: a cursor silently
126
- * reinterpreted under another order would skip or repeat rows, which is exactly
127
- * the incompleteness this page contract exists to rule out. */
128
- function decodeListCursor(cursor, order) {
129
- let parsed;
130
- try {
131
- parsed = JSON.parse(Buffer.from(cursor, 'base64url').toString('utf8'));
132
- }
133
- catch {
134
- throw new Error('[task-ledger] malformed list cursor');
135
- }
136
- const payload = parsed;
137
- if (!payload || payload.order !== order || !Array.isArray(payload.k)) {
138
- throw new Error(`[task-ledger] list cursor does not belong to order '${order}'`);
139
- }
140
- const expected = order === 'deadline_priority' ? 4 : 2;
141
- if (payload.k.length !== expected || payload.k.some((value) => value === null)) {
142
- throw new Error('[task-ledger] malformed list cursor');
143
- }
144
- return payload;
145
- }
146
- const ISO_DATE_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
147
- function isoToEpochMs(iso) {
148
- if (!iso)
149
- return null;
150
- const ms = Date.parse(`${iso}T00:00:00Z`);
151
- return Number.isNaN(ms) ? null : ms;
152
- }
153
- const OWNER_ACTION_IDENTITY_MAX_LENGTH = 512;
154
- function requireOwnerActionIdentity(value, field) {
155
- if (typeof value !== 'string') {
156
- throw new Error(`owner action ${field} must be a non-blank string`);
157
- }
158
- if (value.trim().length === 0 || value.trim() !== value) {
159
- throw new Error(`owner action ${field} must be a non-blank string without surrounding space`);
160
- }
161
- if (value.length > OWNER_ACTION_IDENTITY_MAX_LENGTH) {
162
- throw new Error(`owner action ${field} must be at most ${OWNER_ACTION_IDENTITY_MAX_LENGTH} characters`);
163
- }
164
- return value;
165
- }
166
- /**
167
- * Same identity rules as OwnerActionEffectLedger: every field is a trusted
168
- * host identity, never model text. Checked before any storage is touched.
169
- */
170
- function requireOwnerActionContext(context) {
171
- if (context === null || typeof context !== 'object') {
172
- throw new Error('owner action context is required');
173
- }
174
- const workOrderAttemptId = context.workOrderAttemptId;
175
- if (workOrderAttemptId !== undefined &&
176
- (!Number.isSafeInteger(workOrderAttemptId) || workOrderAttemptId <= 0)) {
177
- throw new Error('owner action workOrderAttemptId must be a positive integer when present');
178
- }
179
- return {
180
- ownerScope: requireOwnerActionIdentity(context.ownerScope, 'ownerScope'),
181
- occurrenceKey: requireOwnerActionIdentity(context.occurrenceKey, 'occurrenceKey'),
182
- modelRunId: requireOwnerActionIdentity(context.modelRunId, 'modelRunId'),
183
- envelopeHash: requireOwnerActionIdentity(context.envelopeHash, 'envelopeHash'),
184
- workOrderAttemptId: workOrderAttemptId ?? null,
185
- };
186
- }
187
- function assertEnum(value, allowed, field) {
188
- if (!allowed.includes(value)) {
189
- throw new Error(`${field} must be one of ${allowed.join('|')}, got: ${value}`);
190
- }
191
- }
192
- function assertIsoDate(value, field) {
193
- const match = ISO_DATE_PATTERN.exec(value);
194
- if (!match) {
195
- throw new Error(`${field} must be an ISO date (YYYY-MM-DD), got: ${value}`);
196
- }
197
- const [year, month, day] = value.split('-').map(Number);
198
- const date = new Date(Date.UTC(year, month - 1, day));
199
- const isRoundTrip = date.getUTCFullYear() === year && date.getUTCMonth() === month - 1 && date.getUTCDate() === day;
200
- if (!isRoundTrip) {
201
- throw new Error(`${field} must be an ISO date (YYYY-MM-DD), got: ${value}`);
202
- }
203
- }
204
- function normalizeCompletionCriteria(value, operation) {
205
- if (value === undefined || value === null)
206
- return null;
207
- if (typeof value !== 'string' || value.trim().length === 0) {
208
- throw new Error(`${operation}: completion_criteria must be a non-empty string`);
209
- }
210
- const normalized = value.trim();
211
- if (normalized.length > exports.TASK_COMPLETION_CRITERIA_MAX_LENGTH) {
212
- throw new Error(`${operation}: completion_criteria must be at most ${exports.TASK_COMPLETION_CRITERIA_MAX_LENGTH} characters`);
213
- }
214
- return normalized;
215
- }
216
- function rowToRecord(row, now, timeZone) {
217
- return {
218
- id: row.id,
219
- title: row.title,
220
- status: row.status,
221
- priority: row.priority,
222
- kind: (row.kind ?? 'owner'),
223
- deadline: isoToEpochMs(row.deadline),
224
- deadlineIso: row.deadline,
225
- assignee: row.assignee,
226
- sourceChannel: row.source_channel,
227
- sourceEventId: row.source_event_id,
228
- latestEvent: row.latest_event,
229
- autoCreated: row.auto_created === 1,
230
- confirmed: row.confirmed === 1,
231
- dueAt: row.due_at,
232
- deadlineOffsetMinutes: row.deadline_offset_minutes,
233
- revision: row.revision,
234
- temporalEpoch: row.temporal_epoch,
235
- temporalReconciledOccurrenceKey: row.temporal_reconciled_occurrence_key,
236
- lastTemporalCheckedAt: row.last_temporal_checked_at,
237
- nextTemporalCheckAt: row.next_temporal_check_at,
238
- lastTemporalAttemptId: row.last_temporal_attempt_id,
239
- temporalState: (0, task_temporal_js_1.deriveTemporalState)({
240
- status: row.status,
241
- dueAt: row.due_at,
242
- deadlineIso: row.deadline,
243
- deadlineOffsetMinutes: row.deadline_offset_minutes,
244
- }, now, timeZone),
245
- reviewStartedAt: row.review_started_at,
246
- reviewAnchorEventId: row.review_anchor_event_id,
247
- reviewAnchorSourceChannel: row.review_anchor_source_channel ?? null,
248
- completionCriteria: row.completion_criteria ?? null,
249
- resolutionKind: (row.resolution_kind ?? null),
250
- createdAt: row.created_at,
251
- updatedAt: row.updated_at,
252
- };
253
- }
254
- class TaskLedger {
255
- db;
256
- now;
257
- timeZone;
258
- onOwnerTaskChangeCommitted;
259
- pendingOwnerTaskGeneration = null;
260
- ownerTaskNotificationScheduled = false;
261
- constructor(db, options = {}) {
262
- this.db = db;
263
- this.now = options.now ?? Date.now;
264
- this.timeZone = options.timeZone ?? Intl.DateTimeFormat().resolvedOptions().timeZone;
265
- this.onOwnerTaskChangeCommitted = options.onOwnerTaskChangeCommitted;
266
- // Validate the injected or boot-resolved zone once, before reads depend on it.
267
- new Intl.DateTimeFormat('en-US', { timeZone: this.timeZone }).format(0);
268
- this.runMigration();
269
- }
270
- toRecord(row) {
271
- return rowToRecord(row, this.now(), this.timeZone);
272
- }
273
- toRecordAt(row, observedAt) {
274
- return rowToRecord(row, observedAt, this.timeZone);
275
- }
276
- temporalStateAt(task, observedAt) {
277
- return (0, task_temporal_js_1.deriveTemporalState)(task, observedAt, this.timeZone);
278
- }
279
- runMigration() {
280
- // Both construction sites (start.ts boot + operator-handler lazy) run this;
281
- // busy_timeout here covers BOTH connections against the rebuild race.
282
- this.db.pragma('busy_timeout = 5000');
283
- this.db.pragma('foreign_keys = ON');
284
- this.db.exec(`
285
- CREATE TABLE IF NOT EXISTS operator_tasks (${TaskLedger.TABLE_COLUMNS_SQL});
286
- ${TaskLedger.INDEXES_SQL}
287
-
288
- CREATE TABLE IF NOT EXISTS operator_no_update_notes (
289
- id INTEGER PRIMARY KEY AUTOINCREMENT,
290
- scope TEXT NOT NULL,
291
- reason TEXT NOT NULL,
292
- created_at INTEGER NOT NULL
293
- );
294
- CREATE INDEX IF NOT EXISTS idx_operator_no_update_scope
295
- ON operator_no_update_notes(scope, id);
296
- `);
297
- // Same database as the tasks, so a change and its cause commit or roll back together.
298
- // A ledger that can disagree with the rows it describes is worse than no ledger.
299
- (0, effects_js_1.ensureEffectLedger)(this.db);
300
- this.upgradeSchema();
301
- const foreignKeyViolations = this.db.pragma('foreign_key_check');
302
- if (foreignKeyViolations.length > 0) {
303
- throw new Error(`operator task migration found ${foreignKeyViolations.length} foreign key violation(s)`);
304
- }
305
- }
306
- /** Full current column set - single source for CREATE and the rebuild copy. */
307
- static TABLE_COLUMNS_SQL = `
308
- id INTEGER PRIMARY KEY AUTOINCREMENT,
309
- title TEXT NOT NULL,
310
- status TEXT NOT NULL DEFAULT 'pending'
311
- CHECK (status IN ('pending','in_progress','review','blocked','done','cancelled','failed')),
312
- priority TEXT NOT NULL DEFAULT 'normal' CHECK (priority IN ('high','normal','low')),
313
- kind TEXT NOT NULL DEFAULT 'owner' CHECK (kind IN ('owner','system')),
314
- payload TEXT,
315
- assignee TEXT,
316
- deadline TEXT,
317
- source_channel TEXT,
318
- source_event_id TEXT,
319
- latest_event TEXT,
320
- auto_created INTEGER NOT NULL DEFAULT 1,
321
- confirmed INTEGER NOT NULL DEFAULT 0,
322
- due_at INTEGER,
323
- deadline_offset_minutes INTEGER
324
- CHECK (deadline_offset_minutes BETWEEN -840 AND 840),
325
- revision INTEGER NOT NULL DEFAULT 0 CHECK (revision >= 0),
326
- temporal_epoch INTEGER NOT NULL DEFAULT 0 CHECK (temporal_epoch >= 0),
327
- temporal_reconciled_occurrence_key TEXT,
328
- last_temporal_checked_at INTEGER,
329
- next_temporal_check_at INTEGER,
330
- last_temporal_attempt_id INTEGER,
331
- review_started_at INTEGER,
332
- review_anchor_event_id TEXT,
333
- review_anchor_source_channel TEXT,
334
- completion_criteria TEXT,
335
- resolution_kind TEXT,
336
- created_at INTEGER NOT NULL,
337
- updated_at INTEGER NOT NULL`;
338
- // Unique-index predicate excludes terminal rows so a terminal keyed workorder
339
- // frees its idempotency slot for a fresh insert (plan M1); owner upsert is a
340
- // SELECT probe, unaffected.
341
- static INDEXES_SQL = `
342
- CREATE UNIQUE INDEX IF NOT EXISTS idx_operator_tasks_source
343
- ON operator_tasks(source_channel, source_event_id)
344
- WHERE source_event_id IS NOT NULL
345
- AND status NOT IN ('done','failed','cancelled');
346
- CREATE INDEX IF NOT EXISTS idx_operator_tasks_status ON operator_tasks(status);
347
- CREATE INDEX IF NOT EXISTS idx_operator_tasks_deadline ON operator_tasks(deadline);`;
348
- /**
349
- * Stage-2 in-place upgrade for pre-existing tables. Guards are re-checked
350
- * INSIDE `BEGIN IMMEDIATE`: two connections construct TaskLedger (boot +
351
- * lazy API handler) and both run this - the loser must see the winner's
352
- * finished work, not rebuild an already-migrated table.
353
- */
354
- upgradeSchema() {
355
- this.db.exec('BEGIN IMMEDIATE');
356
- try {
357
- const cols = this.db.prepare(`PRAGMA table_info(operator_tasks)`).all();
358
- if (!cols.some((c) => c.name === 'kind')) {
359
- this.db.exec(`ALTER TABLE operator_tasks ADD COLUMN kind TEXT NOT NULL DEFAULT 'owner'
360
- CHECK (kind IN ('owner','system'))`);
361
- }
362
- if (!cols.some((c) => c.name === 'payload')) {
363
- this.db.exec(`ALTER TABLE operator_tasks ADD COLUMN payload TEXT`);
364
- }
365
- // 'failed' lives in an inline CHECK -> table rebuild (copy-swap) required.
366
- const tableSql = this.db
367
- .prepare(`SELECT sql FROM sqlite_master WHERE type='table' AND name='operator_tasks'`)
368
- .get().sql;
369
- if (!tableSql.includes(`'failed'`)) {
370
- const seqRow = this.db
371
- .prepare(`SELECT seq FROM sqlite_sequence WHERE name='operator_tasks'`)
372
- .get();
373
- this.db.exec(`
374
- CREATE TABLE operator_tasks_new (${TaskLedger.TABLE_COLUMNS_SQL});
375
- INSERT INTO operator_tasks_new
376
- (id, title, status, priority, kind, payload, assignee, deadline, source_channel,
377
- source_event_id, latest_event, auto_created, confirmed, created_at, updated_at)
378
- SELECT id, title, status, priority, kind, payload, assignee, deadline,
379
- source_channel, source_event_id, latest_event, auto_created, confirmed,
380
- created_at, updated_at
381
- FROM operator_tasks;
382
- DROP TABLE operator_tasks;
383
- ALTER TABLE operator_tasks_new RENAME TO operator_tasks;
384
- `);
385
- if (seqRow) {
386
- // sqlite_sequence has NO unique key on name - INSERT OR REPLACE
387
- // would APPEND a duplicate row (review m2). UPDATE first; insert
388
- // only when the rename left no row behind.
389
- const updated = this.db
390
- .prepare(`UPDATE sqlite_sequence SET seq = ? WHERE name = 'operator_tasks'`)
391
- .run(seqRow.seq);
392
- if (updated.changes === 0) {
393
- this.db
394
- .prepare(`INSERT INTO sqlite_sequence (name, seq) VALUES ('operator_tasks', ?)`)
395
- .run(seqRow.seq);
396
- }
397
- }
398
- }
399
- (0, operator_task_temporal_js_1.applyOperatorTaskTemporalMigration)(this.db);
400
- (0, operator_task_external_lifecycle_js_1.applyOperatorTaskExternalLifecycleMigration)(this.db);
401
- (0, operator_owner_action_candidates_js_1.applyOperatorOwnerActionCandidatesMigration)(this.db);
402
- (0, operator_task_review_lifecycle_js_1.applyOperatorTaskReviewLifecycleMigration)(this.db);
403
- (0, operator_task_classification_js_1.applyOperatorTaskClassificationMigration)(this.db);
404
- // Old-predicate unique index (no terminal exclusion) -> swap in place.
405
- const idxRow = this.db
406
- .prepare(`SELECT sql FROM sqlite_master WHERE type='index' AND name='idx_operator_tasks_source'`)
407
- .get();
408
- if (!idxRow || !idxRow.sql.includes('status NOT IN')) {
409
- this.db.exec(`DROP INDEX IF EXISTS idx_operator_tasks_source;`);
410
- }
411
- this.db.exec(TaskLedger.INDEXES_SQL);
412
- this.db.exec('COMMIT');
413
- }
414
- catch (error) {
415
- this.db.exec('ROLLBACK');
416
- throw error;
417
- }
418
- }
419
- /** TaskSource conformance: open items in canonical board order. */
420
- getTasks() {
421
- return this.list({ order: 'deadline_priority' });
422
- }
423
- countOpenUnconfirmed() {
424
- const row = this.db
425
- .prepare(`SELECT COUNT(*) AS count
426
- FROM operator_tasks
427
- WHERE kind = 'owner'
428
- AND auto_created = 1
429
- AND confirmed = 0
430
- AND status NOT IN ('done', 'cancelled')`)
431
- .get();
432
- return row.count;
433
- }
434
- list(filter = {}) {
435
- const observedAt = this.temporalAsOf(filter.temporalAsOfMs);
436
- const { where, params } = this.buildListPredicate({
437
- ...filter,
438
- temporalAsOfMs: observedAt,
439
- });
440
- const rawLimit = Number(filter.limit);
441
- // No LIMIT at all unless the caller asks for one: the whole board is the read, and the
442
- // 50/200 bound is what made the board turn judge 216 tasks from 50 (owner, 2026-09-04).
443
- const limit = Number.isFinite(rawLimit) ? Math.max(1, Math.floor(rawLimit)) : null;
444
- const rows = this.db
445
- .prepare(`SELECT * FROM operator_tasks
446
- ${where.length > 0 ? `WHERE ${where.join(' AND ')}` : ''}
447
- ORDER BY ${TaskLedger.orderSql(filter.order)}
448
- ${limit === null ? '' : 'LIMIT ?'}`)
449
- .all(...params, ...(limit === null ? [] : [limit]));
450
- return rows.map((row) => this.toRecordAt(row, observedAt));
451
- }
452
- temporalAsOf(value) {
453
- const observedAt = value ?? this.now();
454
- if (!Number.isSafeInteger(observedAt)) {
455
- throw new Error('task list temporal as-of must be a finite integer epoch millisecond');
456
- }
457
- return observedAt;
458
- }
459
- /** Shared filter predicate. Owner surface only - system workorder rows never appear in
460
- * board/REST/gateway listings (Stage-2 kind filter; workorders have dedicated readers). */
461
- buildListPredicate(filter) {
462
- const where = [`kind = 'owner'`];
463
- const params = [];
464
- if (filter.status) {
465
- where.push('status = ?');
466
- params.push(filter.status);
467
- }
468
- else if (filter.includeTerminal === false) {
469
- where.push("status NOT IN ('done', 'cancelled')");
470
- }
471
- if (filter.channel) {
472
- where.push('source_channel = ?');
473
- params.push(filter.channel);
474
- }
475
- if (filter.search) {
476
- where.push('(title LIKE ? OR latest_event LIKE ? OR assignee LIKE ?)');
477
- const like = `%${filter.search}%`;
478
- params.push(like, like, like);
479
- }
480
- if (filter.assignee !== undefined) {
481
- where.push('assignee = ?');
482
- params.push(filter.assignee);
483
- }
484
- if (filter.priority !== undefined) {
485
- where.push('priority = ?');
486
- params.push(filter.priority);
487
- }
488
- if (filter.dueBeforeMs !== undefined) {
489
- where.push('due_at IS NOT NULL AND due_at < ?');
490
- params.push(filter.dueBeforeMs);
491
- }
492
- if (filter.dueAfterMs !== undefined) {
493
- where.push('due_at IS NOT NULL AND due_at >= ?');
494
- params.push(filter.dueAfterMs);
495
- }
496
- if (filter.updatedSinceMs !== undefined) {
497
- where.push('updated_at >= ?');
498
- params.push(filter.updatedSinceMs);
499
- }
500
- if (filter.updatedBeforeMs !== undefined) {
501
- where.push('updated_at < ?');
502
- params.push(filter.updatedBeforeMs);
503
- }
504
- if (filter.qualification === 'qualified') {
505
- where.push('completion_criteria IS NOT NULL');
506
- }
507
- else if (filter.qualification === 'legacy_unqualified') {
508
- where.push('completion_criteria IS NULL');
509
- }
510
- if (filter.dueBucket !== undefined) {
511
- const observedAt = this.temporalAsOf(filter.temporalAsOfMs);
512
- const rows = this.db
513
- .prepare(`SELECT id, status, due_at, deadline, deadline_offset_minutes
514
- FROM operator_tasks WHERE ${where.join(' AND ')}`)
515
- .all(...params);
516
- const ids = rows
517
- .filter((row) => {
518
- const state = (0, task_temporal_js_1.deriveTemporalState)({
519
- status: row.status,
520
- dueAt: row.due_at,
521
- deadlineIso: row.deadline,
522
- deadlineOffsetMinutes: row.deadline_offset_minutes,
523
- }, observedAt, this.timeZone);
524
- return (0, task_temporal_js_1.dueBucketForTemporalState)(state) === filter.dueBucket;
525
- })
526
- .map((row) => row.id);
527
- // One JSON parameter avoids SQLite's variable limit even on a large board.
528
- where.push('id IN (SELECT CAST(value AS INTEGER) FROM json_each(?))');
529
- params.push(JSON.stringify(ids));
530
- }
531
- return { where, params };
532
- }
533
- /** ORDER BY for both list() and listPage(); the trailing id makes it a TOTAL order,
534
- * which is what lets a keyset cursor resume without skipping or repeating a row.
535
- * LIMIT applies AFTER ordering, so a bounded read still returns the true top-N. */
536
- static orderSql(order) {
537
- return order === 'updated'
538
- ? 'updated_at DESC, id DESC'
539
- : // deadline asc NULLS LAST, then priority high>normal>low, then id.
540
- `CASE WHEN deadline IS NULL THEN 1 ELSE 0 END ASC, COALESCE(deadline, '') ASC,
541
- CASE priority WHEN 'high' THEN 0 WHEN 'normal' THEN 1 ELSE 2 END ASC, id ASC`;
542
- }
543
- static cursorFor(record, order) {
544
- if (order === 'updated') {
545
- return { order, k: [record.updatedAt, record.id] };
546
- }
547
- return {
548
- order,
549
- k: [
550
- record.deadlineIso === null ? 1 : 0,
551
- record.deadlineIso ?? '',
552
- PRIORITY_RANK[record.priority] ?? 2,
553
- record.id,
554
- ],
555
- };
556
- }
557
- /**
558
- * One page of the same ordered set, with the totals that make completeness provable.
559
- *
560
- * Keyset, not OFFSET: an offset page silently skips or repeats rows when the set
561
- * changes between pages, which would leave a "whole situation" claim resting on a
562
- * read that quietly lost items.
563
- */
564
- listPage(filter = {}) {
565
- const observedAt = this.temporalAsOf(filter.temporalAsOfMs);
566
- const order = filter.order === 'updated' ? 'updated' : 'deadline_priority';
567
- const { where, params } = this.buildListPredicate({
568
- ...filter,
569
- temporalAsOfMs: observedAt,
570
- });
571
- const rawLimit = Number(filter.limit);
572
- // No cap and a whole-board default: Kagemusha's task_list is selectAll, and the 50/200
573
- // bound is what made the board turn judge 216 tasks from 50 (owner, 2026-09-04). The
574
- // large default keeps the limit+1 next-page probe below intact.
575
- const limit = Number.isFinite(rawLimit) ? Math.max(1, Math.floor(rawLimit)) : WHOLE_BOARD_LIMIT;
576
- const totalRow = this.db
577
- .prepare(`SELECT COUNT(*) AS total FROM operator_tasks WHERE ${where.join(' AND ')}`)
578
- .get(...params);
579
- const pageWhere = [...where];
580
- const pageParams = [...params];
581
- if (filter.cursor) {
582
- const { k } = decodeListCursor(filter.cursor, order);
583
- if (order === 'updated') {
584
- pageWhere.push('(updated_at, id) < (?, ?)');
585
- }
586
- else {
587
- pageWhere.push(`(CASE WHEN deadline IS NULL THEN 1 ELSE 0 END, COALESCE(deadline, ''),
588
- CASE priority WHEN 'high' THEN 0 WHEN 'normal' THEN 1 ELSE 2 END, id) > (?, ?, ?, ?)`);
589
- }
590
- pageParams.push(...k);
591
- }
592
- // limit + 1 probes for a next page instead of guessing from a full page, so the
593
- // final page never hands out a cursor that resolves to nothing.
594
- const rows = this.db
595
- .prepare(`SELECT * FROM operator_tasks
596
- WHERE ${pageWhere.join(' AND ')}
597
- ORDER BY ${TaskLedger.orderSql(filter.order)}
598
- LIMIT ?`)
599
- .all(...pageParams, limit + 1);
600
- const hasMore = rows.length > limit;
601
- const tasks = rows.slice(0, limit).map((row) => this.toRecordAt(row, observedAt));
602
- const last = tasks[tasks.length - 1];
603
- return {
604
- tasks,
605
- total: totalRow.total,
606
- returned: tasks.length,
607
- nextCursor: hasMore && last ? encodeListCursor(TaskLedger.cursorFor(last, order)) : null,
608
- };
609
- }
610
- /**
611
- * One `listPage`, with the read generation and observation instant captured
612
- * in the SAME synchronous call so total/rows/version cannot straddle a write
613
- * from this process. The progressive `items` view pins its cursor to this
614
- * readVersion and restarts if a later page observes a different one.
615
- */
616
- itemsPage(filter = {}) {
617
- // One DEFERRED read transaction: the generation, the total and the rows all
618
- // read the SAME SQLite snapshot, so another connection committing between the
619
- // statements cannot make the returned readVersion disagree with the page it
620
- // describes. Synchronous JS alone is not a cross-connection snapshot.
621
- return this.readSnapshot(() => {
622
- const observedAt = this.temporalAsOf(filter.temporalAsOfMs);
623
- const readVersion = this.readGeneration();
624
- const page = this.listPage({ ...filter, temporalAsOfMs: observedAt });
625
- return { ...page, readVersion, observedAt };
626
- });
627
- }
628
- /** The ledger's clock (injected in tests); progressive views stamp observedAt with it. */
629
- nowMs() {
630
- return this.now();
631
- }
632
- /**
633
- * Run a read-only body inside a single DEFERRED transaction so every statement
634
- * shares one snapshot. better-sqlite3 nests via SAVEPOINT, so this is safe even
635
- * if a caller is already inside a transaction.
636
- */
637
- readSnapshot(body) {
638
- const runner = this.db.transaction(body);
639
- return runner();
640
- }
641
- /**
642
- * A conservative change signature for the whole owner board, derived from
643
- * existing columns - no snapshot table. COUNT catches inserts/deletes,
644
- * SUM(revision) catches every owner update (each bumps revision), MAX(id)
645
- * catches inserts, MAX(updated_at) is a coarse tie-breaker. It is NOT an
646
- * immutable snapshot id: it only lets a paged read reject its own cursor once
647
- * ANY owner row has changed, so a "whole board" claim never spans a write.
648
- * System workorder churn is deliberately excluded (kind='owner').
649
- */
650
- readGeneration() {
651
- const row = this.db
652
- .prepare(`SELECT COUNT(*) AS c, COALESCE(SUM(revision), 0) AS r,
653
- COALESCE(MAX(id), 0) AS m, COALESCE(MAX(updated_at), 0) AS u
654
- FROM operator_tasks WHERE kind = 'owner'`)
655
- .get();
656
- return (0, node_crypto_1.createHash)('sha256')
657
- .update(`${row.c}:${row.r}:${row.m}:${row.u}`)
658
- .digest('base64url')
659
- .slice(0, 22);
660
- }
661
- notifyOwnerTaskCommit(previousGeneration) {
662
- if (!this.onOwnerTaskChangeCommitted) {
663
- return;
664
- }
665
- const generation = this.readGeneration();
666
- if (generation === previousGeneration) {
667
- return;
668
- }
669
- this.pendingOwnerTaskGeneration = generation;
670
- if (this.ownerTaskNotificationScheduled) {
671
- return;
672
- }
673
- this.ownerTaskNotificationScheduled = true;
674
- queueMicrotask(() => this.flushOwnerTaskNotification());
675
- }
676
- flushOwnerTaskNotification() {
677
- this.ownerTaskNotificationScheduled = false;
678
- const expected = this.pendingOwnerTaskGeneration;
679
- this.pendingOwnerTaskGeneration = null;
680
- if (!expected || !this.onOwnerTaskChangeCommitted) {
681
- return;
682
- }
683
- const current = this.readGeneration();
684
- if (current !== expected) {
685
- this.pendingOwnerTaskGeneration = current;
686
- this.ownerTaskNotificationScheduled = true;
687
- queueMicrotask(() => this.flushOwnerTaskNotification());
688
- return;
689
- }
690
- this.onOwnerTaskChangeCommitted(current);
691
- }
692
- /**
693
- * Aggregate counts over the same owner predicate `listPage` filters by. Facets
694
- * come from SQL GROUP BY (each partitions total); due buckets are computed in
695
- * one JS pass over minimal rows using the SAME deriveTemporalState `items`
696
- * uses, so an overview bucket and an item's temporal_state never disagree.
697
- * readGeneration is captured in the same synchronous call as the counts.
698
- */
699
- overview(filter = {}) {
700
- return this.readSnapshot(() => this.overviewInSnapshot(filter));
701
- }
702
- overviewInSnapshot(filter) {
703
- // One captured time for every derived due bucket; one snapshot for every count.
704
- const now = this.temporalAsOf(filter.temporalAsOfMs);
705
- const readVersion = this.readGeneration();
706
- const { where, params } = this.buildListPredicate({ ...filter, temporalAsOfMs: now });
707
- const whereSql = where.join(' AND ');
708
- const groupBy = (column) => this.db
709
- .prepare(`SELECT ${column} AS key, COUNT(*) AS count FROM operator_tasks
710
- WHERE ${whereSql} GROUP BY ${column}`)
711
- .all(...params);
712
- const total = this.db
713
- .prepare(`SELECT COUNT(*) AS total FROM operator_tasks WHERE ${whereSql}`)
714
- .get(...params).total;
715
- const status = {};
716
- for (const row of groupBy('status'))
717
- status[String(row.key)] = row.count;
718
- const priority = {};
719
- for (const row of groupBy('priority'))
720
- priority[String(row.key)] = row.count;
721
- const channels = groupBy('source_channel').map((row) => ({
722
- channel: row.key,
723
- count: row.count,
724
- }));
725
- const assignees = groupBy('assignee').map((row) => ({ assignee: row.key, count: row.count }));
726
- const due = { missing: 0, overdue: 0, upcoming: 0, closed: 0 };
727
- const rows = this.db
728
- .prepare(`SELECT status, due_at, deadline, deadline_offset_minutes
729
- FROM operator_tasks WHERE ${whereSql}`)
730
- .all(...params);
731
- for (const row of rows) {
732
- const state = (0, task_temporal_js_1.deriveTemporalState)({
733
- status: row.status,
734
- dueAt: row.due_at,
735
- deadlineIso: row.deadline,
736
- deadlineOffsetMinutes: row.deadline_offset_minutes,
737
- }, now, this.timeZone);
738
- due[(0, task_temporal_js_1.dueBucketForTemporalState)(state)] += 1;
739
- }
740
- return { total, observedAt: now, readVersion, status, priority, channels, assignees, due };
741
- }
742
- /** Internal bounded page for temporal reconciliation; excludes rows that can never be candidates. */
743
- listTemporalScanPage(input) {
744
- const rawLimit = Number(input.limit);
745
- const rawAfterId = Number(input.afterId);
746
- const limit = Number.isFinite(rawLimit)
747
- ? Math.max(1, Math.min(200, Math.floor(rawLimit)))
748
- : 200;
749
- const afterId = Number.isFinite(rawAfterId) ? Math.max(0, Math.floor(rawAfterId)) : 0;
750
- const rows = this.db
751
- .prepare(`SELECT * FROM operator_tasks INDEXED BY idx_operator_tasks_temporal_scan_id
752
- WHERE kind = 'owner'
753
- AND status IN ('pending','in_progress','review','blocked')
754
- AND id > ?
755
- AND (due_at IS NOT NULL OR deadline IS NOT NULL OR next_temporal_check_at IS NOT NULL)
756
- ORDER BY id ASC
757
- LIMIT ?`)
758
- .all(afterId, limit);
759
- return rows.map((row) => this.toRecord(row));
760
- }
761
- /** Owner rows only - system workorder rows are invisible to external reads. */
762
- getById(id) {
763
- const record = this.getRowById(id);
764
- return record && record.kind === 'owner' ? record : null;
765
- }
766
- /** Internal fetch without the kind filter (guards and workorder paths). */
767
- getRowById(id) {
768
- const row = this.db.prepare(`SELECT * FROM operator_tasks WHERE id = ?`).get(id);
769
- return row ? this.toRecord(row) : null;
770
- }
771
- /** Returns one active, explicitly receipted external identity for an owner task. */
772
- getExternalBinding(taskId) {
773
- const row = this.db
774
- .prepare(`SELECT id, revision, task_id, connector, source_type, external_source_id,
775
- last_observation_seq, created_by_attempt_id, created_by_run_id,
776
- created_by_owner_scope, created_at
777
- FROM operator_external_task_bindings
778
- WHERE task_id = ? AND active = 1`)
779
- .get(taskId);
780
- return row ? this.externalBindingFromRow(row) : null;
781
- }
782
- /**
783
- * Host-only lookup material for immutable external-lifecycle candidates.
784
- * The caller supplies exact event/source ids obtained from the connector index;
785
- * no connector prose is read through this ledger surface.
786
- */
787
- getExternalLifecycleCandidateSupport(eventIds, externalSourceIds) {
788
- const uniqueEventIds = [...new Set(eventIds)];
789
- const uniqueSourceIds = [...new Set(externalSourceIds)];
790
- const directTaskIdsByEventId = new Map();
791
- const effectTaskIdsByEventId = new Map();
792
- const bindings = [];
793
- if (uniqueEventIds.length > 0) {
794
- const placeholders = uniqueEventIds.map(() => '?').join(',');
795
- const directRows = this.db
796
- .prepare(`SELECT source_event_id, id FROM operator_tasks
797
- WHERE kind = 'owner' AND source_event_id IN (${placeholders})`)
798
- .all(...uniqueEventIds);
799
- for (const row of directRows) {
800
- const ids = directTaskIdsByEventId.get(row.source_event_id) ?? [];
801
- directTaskIdsByEventId.set(row.source_event_id, [...ids, row.id]);
802
- }
803
- const effectRows = this.db
804
- .prepare(`SELECT DISTINCT json_each.value AS event_id, evidence_effects.target_id AS task_id
805
- FROM evidence_effects, json_each(evidence_effects.source_event_ids_json)
806
- WHERE evidence_effects.target_type = 'task'
807
- AND json_each.value IN (${placeholders})`)
808
- .all(...uniqueEventIds);
809
- for (const row of effectRows) {
810
- const taskId = Number(row.task_id);
811
- if (!Number.isSafeInteger(taskId) || taskId < 1)
812
- continue;
813
- const ids = effectTaskIdsByEventId.get(row.event_id) ?? [];
814
- effectTaskIdsByEventId.set(row.event_id, [...ids, taskId]);
815
- }
816
- }
817
- if (uniqueSourceIds.length > 0) {
818
- const placeholders = uniqueSourceIds.map(() => '?').join(',');
819
- const rows = this.db
820
- .prepare(`SELECT id, revision, task_id, connector, source_type, external_source_id,
821
- last_observation_seq
822
- FROM operator_external_task_bindings
823
- WHERE active = 1 AND connector = 'kagemusha' AND source_type = 'kanban_card'
824
- AND external_source_id IN (${placeholders})`)
825
- .all(...uniqueSourceIds);
826
- for (const row of rows) {
827
- bindings.push({
828
- bindingId: row.id,
829
- bindingRevision: row.revision,
830
- taskId: row.task_id,
831
- connector: row.connector,
832
- sourceType: row.source_type,
833
- externalSourceId: row.external_source_id,
834
- lastObservationSeq: row.last_observation_seq,
835
- });
836
- }
837
- }
838
- const taskIds = new Set();
839
- for (const ids of directTaskIdsByEventId.values())
840
- ids.forEach((id) => taskIds.add(id));
841
- for (const ids of effectTaskIdsByEventId.values())
842
- ids.forEach((id) => taskIds.add(id));
843
- for (const binding of bindings)
844
- taskIds.add(binding.taskId);
845
- const tasksById = new Map();
846
- if (taskIds.size > 0) {
847
- const ids = [...taskIds];
848
- const placeholders = ids.map(() => '?').join(',');
849
- const rows = this.db
850
- .prepare(`SELECT id, revision FROM operator_tasks WHERE kind = 'owner' AND id IN (${placeholders})`)
851
- .all(...ids);
852
- for (const row of rows)
853
- tasksById.set(row.id, { taskId: row.id, revision: row.revision });
854
- }
855
- return { taskHints: { directTaskIdsByEventId, effectTaskIdsByEventId }, tasksById, bindings };
856
- }
857
- getReceiptedExternalCandidateIds(candidateIds) {
858
- const ids = [...new Set(candidateIds)];
859
- if (ids.length === 0)
860
- return new Set();
861
- const placeholders = ids.map(() => '?').join(',');
862
- const rows = this.db
863
- .prepare(`SELECT candidate_id FROM operator_external_binding_receipts WHERE candidate_id IN (${placeholders})
864
- UNION
865
- SELECT candidate_id FROM operator_external_lifecycle_receipts WHERE candidate_id IN (${placeholders})`)
866
- .all(...ids, ...ids);
867
- return new Set(rows.map((row) => row.candidate_id));
868
- }
869
- /**
870
- * Recover a candidate only from the payload of the exact currently claimed
871
- * board attempt. Revalidate the serialized payload: database bytes are not
872
- * a capability merely because they originated in a previous host process.
873
- */
874
- loadBoardCandidate(attemptId, candidateId, kind) {
875
- const attempt = this.getWorkOrderById(attemptId);
876
- if (!attempt || attempt.workKind !== 'board' || attempt.status !== 'in_progress') {
877
- throw new Error(`external lifecycle candidate requires claimed board attempt ${attemptId}`);
878
- }
879
- const payload = publisherPayloadOfStoredWorkOrder(attempt.payload);
880
- (0, workorder_publishers_js_1.validateWorkOrderPayload)('board', payload);
881
- if (payload.mode !== 'reconcile' || !payload.candidates) {
882
- throw new Error(`external lifecycle candidate ${candidateId} is absent from attempt ${attemptId}`);
883
- }
884
- const candidatePayload = payload.candidates;
885
- const candidates = kind === 'binding'
886
- ? candidatePayload.bindingCandidates
887
- : candidatePayload.lifecycleCandidates;
888
- const candidate = candidates.find((value) => value.candidateId === candidateId);
889
- if (!candidate) {
890
- throw new Error(`external lifecycle ${kind} candidate ${candidateId} is absent from attempt ${attemptId}`);
891
- }
892
- return candidate;
893
- }
894
- /**
895
- * Read the complete, immutable candidate set for a board attempt against
896
- * its durable decision receipts. This deliberately works for stale claims
897
- * as well as live in-progress attempts: recovery must never infer effects
898
- * from a runner result when the database can answer exactly.
899
- */
900
- inspectBoardCandidateAttempt(attemptId) {
901
- const attempt = this.getWorkOrderById(attemptId);
902
- if (!attempt || attempt.workKind !== 'board') {
903
- throw new Error(`board candidate inspection requires board attempt ${attemptId}`);
904
- }
905
- const payload = publisherPayloadOfStoredWorkOrder(attempt.payload);
906
- (0, workorder_publishers_js_1.validateWorkOrderPayload)('board', payload);
907
- if (payload.mode !== 'reconcile' || !payload.candidates) {
908
- return { disposition: 'none' };
909
- }
910
- const candidates = payload.candidates;
911
- const all = [...candidates.bindingCandidates, ...candidates.lifecycleCandidates];
912
- if (all.length === 0) {
913
- return { disposition: 'none' };
914
- }
915
- // Receipts are global by candidate id, so a decision settled by an owner
916
- // run is seen here exactly like one settled by this attempt.
917
- return this.candidateReceiptDisposition(all);
918
- }
919
- /**
920
- * Resolve one candidate decision's authority (Task B2).
921
- *
922
- * A plain attempt id is the legacy Board wrapper. A discriminated source is
923
- * either that same Board path or a verified owner run whose host-attested
924
- * snapshot must match the caller's scope, run and envelope exactly. Both
925
- * return the SAME decision inputs; the receipt records which one settled it.
926
- */
927
- resolveExternalCandidateAuthority(source, kind, origin) {
928
- const resolved = typeof source === 'number' ? { kind: 'board', attemptId: source } : source;
929
- const label = kind === 'binding' ? 'external binding' : 'external lifecycle';
930
- if (resolved.kind === 'board') {
931
- const attemptId = resolved.attemptId;
932
- if (origin.workOrderAttemptId !== attemptId) {
933
- throw new Error(`${label} decision requires trusted attempt origin ${attemptId}`);
934
- }
935
- return {
936
- source: resolved,
937
- receiptOrigin: {
938
- attemptId,
939
- runId: origin.runId ?? null,
940
- ownerScope: null,
941
- envelopeHash: null,
942
- },
943
- load: (candidateId) => {
944
- const attempt = this.getWorkOrderById(attemptId);
945
- return {
946
- candidate: this.loadBoardCandidate(attemptId, candidateId, kind),
947
- snapshotAt: attempt?.createdAt ?? 0,
948
- };
949
- },
950
- };
951
- }
952
- const context = requireOwnerActionContext(resolved.context);
953
- if (origin.runId !== context.modelRunId) {
954
- throw new Error(`${label} decision requires trusted owner run origin ${context.modelRunId}`);
955
- }
956
- if ((origin.workOrderAttemptId ?? null) !== context.workOrderAttemptId) {
957
- throw new Error(`${label} decision attempt ${String(origin.workOrderAttemptId)} does not match the attesting owner run`);
958
- }
959
- if (context.workOrderAttemptId !== null) {
960
- this.assertWorkOrderAttemptActive(label, context.workOrderAttemptId);
961
- }
962
- return {
963
- source: resolved,
964
- receiptOrigin: {
965
- attemptId: context.workOrderAttemptId,
966
- runId: context.modelRunId,
967
- ownerScope: context.ownerScope,
968
- envelopeHash: context.envelopeHash,
969
- },
970
- load: (candidateId) => {
971
- const attested = this.loadOwnerAttestedCandidate(context, candidateId, kind);
972
- return { candidate: attested.candidate, snapshotAt: attested.attestedAt };
973
- },
974
- };
975
- }
976
- /** Same contract as loadBoardCandidate, for either authority source. */
977
- loadExternalCandidate(source, candidateId, kind) {
978
- const resolved = typeof source === 'number' ? { kind: 'board', attemptId: source } : source;
979
- return resolved.kind === 'board'
980
- ? this.loadBoardCandidate(resolved.attemptId, candidateId, kind)
981
- : this.loadOwnerActionCandidate(resolved.context, candidateId, kind);
982
- }
983
- /**
984
- * Persist host-built candidate snapshots under a verified owner run.
985
- *
986
- * Every snapshot is re-validated as host-built (exact shape, Kagemusha
987
- * mapping, fixed evidence summary, content-derived id) before it is stored;
988
- * model-authored bytes never enter this table. Rows are immutable. The same
989
- * run attesting the same candidate again with identical bytes is a no-op;
990
- * different bytes under the same id are a conflict, not a second row.
991
- */
992
- attestOwnerActionCandidates(context, candidates) {
993
- const verified = requireOwnerActionContext(context);
994
- const prepared = [
995
- ...candidates.bindingCandidates.map((candidate) => (0, external_lifecycle_candidates_js_1.parseHostBuiltExternalLifecycleCandidate)('binding', candidate)),
996
- ...candidates.lifecycleCandidates.map((candidate) => (0, external_lifecycle_candidates_js_1.parseHostBuiltExternalLifecycleCandidate)('lifecycle', candidate)),
997
- ].map((candidate) => {
998
- const json = (0, external_lifecycle_candidates_js_1.canonicalExternalLifecycleCandidateJson)(candidate);
999
- return { candidate, json, sha256: (0, node_crypto_1.createHash)('sha256').update(json).digest('hex') };
1000
- });
1001
- let attested = 0;
1002
- let alreadyAttested = 0;
1003
- this.db.exec('BEGIN IMMEDIATE');
1004
- try {
1005
- for (const entry of prepared) {
1006
- const existing = this.db
1007
- .prepare(`SELECT owner_scope, envelope_hash, occurrence_key, workorder_attempt_id,
1008
- candidate_kind, candidate_sha256
1009
- FROM ${operator_owner_action_candidates_js_1.OWNER_ACTION_CANDIDATES_TABLE}
1010
- WHERE model_run_id = ? AND candidate_id = ?`)
1011
- .get(verified.modelRunId, entry.candidate.candidateId);
1012
- if (existing) {
1013
- if (existing.owner_scope !== verified.ownerScope ||
1014
- existing.envelope_hash !== verified.envelopeHash ||
1015
- existing.occurrence_key !== verified.occurrenceKey ||
1016
- existing.workorder_attempt_id !== verified.workOrderAttemptId ||
1017
- existing.candidate_kind !== entry.candidate.kind ||
1018
- existing.candidate_sha256 !== entry.sha256) {
1019
- throw new Error(`owner action candidate ${entry.candidate.candidateId} attestation conflict: run ${verified.modelRunId} already holds a snapshot that differs`);
1020
- }
1021
- alreadyAttested += 1;
1022
- continue;
1023
- }
1024
- const task = this.getRowById(entry.candidate.taskId);
1025
- if (!task || task.kind !== 'owner') {
1026
- throw new Error(`owner action candidate ${entry.candidate.candidateId} references no owner task`);
1027
- }
1028
- this.db
1029
- .prepare(`INSERT INTO ${operator_owner_action_candidates_js_1.OWNER_ACTION_CANDIDATES_TABLE}
1030
- (model_run_id, candidate_id, owner_scope, envelope_hash, occurrence_key,
1031
- workorder_attempt_id, candidate_kind, task_id, event_id, candidate_json,
1032
- candidate_sha256, created_at)
1033
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
1034
- .run(verified.modelRunId, entry.candidate.candidateId, verified.ownerScope, verified.envelopeHash, verified.occurrenceKey, verified.workOrderAttemptId, entry.candidate.kind, entry.candidate.taskId, entry.candidate.eventId, entry.json, entry.sha256, this.now());
1035
- attested += 1;
1036
- }
1037
- this.db.exec('COMMIT');
1038
- }
1039
- catch (error) {
1040
- this.db.exec('ROLLBACK');
1041
- throw error;
1042
- }
1043
- return { attested, alreadyAttested };
1044
- }
1045
- /** Bounded, intent-free listing of what one owner run attested. */
1046
- listOwnerActionCandidates(context) {
1047
- const verified = requireOwnerActionContext(context);
1048
- return this.db
1049
- .prepare(`SELECT candidate_id, candidate_kind, task_id, event_id
1050
- FROM ${operator_owner_action_candidates_js_1.OWNER_ACTION_CANDIDATES_TABLE}
1051
- WHERE model_run_id = ? AND owner_scope = ? AND envelope_hash = ?
1052
- AND occurrence_key = ? AND workorder_attempt_id IS ?
1053
- ORDER BY created_at ASC, candidate_kind ASC, candidate_id ASC`)
1054
- .all(verified.modelRunId, verified.ownerScope, verified.envelopeHash, verified.occurrenceKey, verified.workOrderAttemptId).map((row) => ({
1055
- candidateId: row.candidate_id,
1056
- kind: row.candidate_kind,
1057
- taskId: row.task_id,
1058
- eventId: row.event_id,
1059
- }));
1060
- }
1061
- /**
1062
- * Receipt view of one owner run's attested candidates, in the same shape as
1063
- * inspectBoardCandidateAttempt so recovery can treat both sources alike.
1064
- */
1065
- inspectOwnerActionCandidateRun(context) {
1066
- const all = this.listOwnerActionCandidates(context);
1067
- if (all.length === 0) {
1068
- return { disposition: 'none' };
1069
- }
1070
- return this.candidateReceiptDisposition(all);
1071
- }
1072
- loadOwnerActionCandidate(context, candidateId, kind) {
1073
- return this.loadOwnerAttestedCandidate(requireOwnerActionContext(context), candidateId, kind)
1074
- .candidate;
1075
- }
1076
- /**
1077
- * Recover a candidate only from the attestation the exact owner run made.
1078
- * Stored bytes are revalidated: sha256 over the canonical JSON, exact shape,
1079
- * and the content-derived candidate id must all still agree.
1080
- */
1081
- loadOwnerAttestedCandidate(context, candidateId, kind) {
1082
- const row = this.db
1083
- .prepare(`SELECT owner_scope, envelope_hash, occurrence_key, workorder_attempt_id,
1084
- candidate_kind, task_id, event_id, candidate_json, candidate_sha256, created_at
1085
- FROM ${operator_owner_action_candidates_js_1.OWNER_ACTION_CANDIDATES_TABLE}
1086
- WHERE model_run_id = ? AND candidate_id = ?`)
1087
- .get(context.modelRunId, candidateId);
1088
- if (!row) {
1089
- throw new Error(`external lifecycle ${kind} candidate ${candidateId} is not attested for owner run ${context.modelRunId}`);
1090
- }
1091
- if (row.owner_scope !== context.ownerScope) {
1092
- throw new Error(`external lifecycle ${kind} candidate ${candidateId} was attested under a different owner scope`);
1093
- }
1094
- if (row.envelope_hash !== context.envelopeHash) {
1095
- throw new Error(`external lifecycle ${kind} candidate ${candidateId} was attested under a different envelope`);
1096
- }
1097
- if (row.occurrence_key !== context.occurrenceKey) {
1098
- throw new Error(`external lifecycle ${kind} candidate ${candidateId} was attested under a different occurrence`);
1099
- }
1100
- if (row.workorder_attempt_id !== context.workOrderAttemptId) {
1101
- throw new Error(`external lifecycle ${kind} candidate ${candidateId} was attested under a different workorder attempt`);
1102
- }
1103
- if (row.candidate_kind !== kind) {
1104
- throw new Error(`external lifecycle candidate ${candidateId} has the wrong kind (attested as ${row.candidate_kind})`);
1105
- }
1106
- const digest = (0, node_crypto_1.createHash)('sha256').update(row.candidate_json).digest('hex');
1107
- if (digest !== row.candidate_sha256) {
1108
- throw new Error(`external lifecycle ${kind} candidate ${candidateId} failed attestation integrity (sha256 mismatch)`);
1109
- }
1110
- let parsed;
1111
- try {
1112
- parsed = JSON.parse(row.candidate_json);
1113
- }
1114
- catch {
1115
- throw new Error(`external lifecycle ${kind} candidate ${candidateId} failed attestation integrity (unreadable)`);
1116
- }
1117
- const candidate = (0, external_lifecycle_candidates_js_1.parseHostBuiltExternalLifecycleCandidate)(kind, parsed);
1118
- if (candidate.candidateId !== candidateId ||
1119
- candidate.taskId !== row.task_id ||
1120
- candidate.eventId !== row.event_id ||
1121
- (0, external_lifecycle_candidates_js_1.canonicalExternalLifecycleCandidateJson)(candidate) !== row.candidate_json) {
1122
- throw new Error(`external lifecycle ${kind} candidate ${candidateId} failed attestation integrity (identity mismatch)`);
1123
- }
1124
- return { candidate, attestedAt: row.created_at };
1125
- }
1126
- candidateReceiptDisposition(all) {
1127
- const outcomes = [];
1128
- const missingCandidateIds = [];
1129
- for (const candidate of all) {
1130
- const receipt = this.getExternalCandidateReceipt(candidate.candidateId);
1131
- if (!receipt) {
1132
- missingCandidateIds.push(candidate.candidateId);
1133
- continue;
1134
- }
1135
- if (receipt.kind !== candidate.kind) {
1136
- throw new Error(`external lifecycle candidate ${candidate.candidateId} has a receipt of the wrong kind`);
1137
- }
1138
- outcomes.push(receipt.outcome);
1139
- }
1140
- if (missingCandidateIds.length === 0) {
1141
- return { disposition: 'complete', outcomes };
1142
- }
1143
- if (missingCandidateIds.length === all.length) {
1144
- return { disposition: 'zero' };
1145
- }
1146
- return { disposition: 'partial', missingCandidateIds };
1147
- }
1148
- applyExternalBindingDecision(source, input, origin) {
1149
- (0, external_lifecycle_candidates_js_1.validateExternalLifecycleDecision)('binding', input);
1150
- const authority = this.resolveExternalCandidateAuthority(source, 'binding', origin);
1151
- const receiptOrigin = authority.receiptOrigin;
1152
- let receipt = null;
1153
- this.db.exec('BEGIN IMMEDIATE');
1154
- try {
1155
- const { candidate } = authority.load(input.candidate_id);
1156
- if (candidate.kind !== 'binding') {
1157
- throw new Error(`external lifecycle candidate ${input.candidate_id} has the wrong kind`);
1158
- }
1159
- if (input.expected_revision !== candidate.taskRevision) {
1160
- throw new Error(`external binding candidate ${candidate.candidateId} revision does not match its host snapshot`);
1161
- }
1162
- if (origin.causeEventIds?.length !== 1 || origin.causeEventIds[0] !== candidate.eventId) {
1163
- throw new Error(`external binding candidate ${candidate.candidateId} requires its exact host origin event`);
1164
- }
1165
- const existing = this.getExternalCandidateReceipt(candidate.candidateId);
1166
- if (existing) {
1167
- if (existing.kind !== 'binding') {
1168
- throw new Error(`external lifecycle candidate ${candidate.candidateId} already has another receipt kind`);
1169
- }
1170
- this.assertBindingReplayMatches(existing, candidate, input);
1171
- receipt = existing;
1172
- }
1173
- else {
1174
- const task = this.getRowById(candidate.taskId);
1175
- if (!task || task.kind !== 'owner') {
1176
- throw new Error(`external binding candidate ${candidate.candidateId} references no owner task`);
1177
- }
1178
- const outcome = task.revision === candidate.taskRevision
1179
- ? input.decision === 'bind'
1180
- ? 'bound'
1181
- : 'declined'
1182
- : 'superseded';
1183
- let bindingId;
1184
- if (outcome === 'bound') {
1185
- const collision = this.db
1186
- .prepare(`SELECT id, task_id, external_source_id FROM operator_external_task_bindings
1187
- WHERE active = 1 AND (task_id = ? OR (connector = ? AND source_type = ? AND external_source_id = ?))`)
1188
- .get(candidate.taskId, candidate.connector, candidate.sourceType, candidate.externalSourceId);
1189
- if (collision) {
1190
- throw new Error(`external binding conflict for task ${candidate.taskId} or ${candidate.externalSourceId}`);
1191
- }
1192
- const now = this.now();
1193
- const inserted = this.db
1194
- .prepare(`INSERT INTO operator_external_task_bindings
1195
- (task_id, connector, source_type, external_source_id, last_observation_seq,
1196
- created_by_attempt_id, created_by_run_id, created_by_owner_scope,
1197
- created_by_envelope_hash, active, created_at, updated_at)
1198
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 1, ?, ?)`)
1199
- .run(candidate.taskId, candidate.connector, candidate.sourceType, candidate.externalSourceId, candidate.operatorObservationSeq, receiptOrigin.attemptId, receiptOrigin.runId, receiptOrigin.ownerScope, receiptOrigin.envelopeHash, now, now);
1200
- bindingId = Number(inserted.lastInsertRowid);
1201
- }
1202
- this.insertBindingReceipt(candidate, receiptOrigin, input, outcome, bindingId, origin);
1203
- receipt = {
1204
- kind: 'binding',
1205
- candidateId: candidate.candidateId,
1206
- workOrderAttemptId: receiptOrigin.attemptId,
1207
- originRunId: receiptOrigin.runId,
1208
- originOwnerScope: receiptOrigin.ownerScope,
1209
- taskId: candidate.taskId,
1210
- outcome,
1211
- reason: input.reason,
1212
- ...(bindingId === undefined ? {} : { bindingId }),
1213
- };
1214
- }
1215
- this.db.exec('COMMIT');
1216
- }
1217
- catch (error) {
1218
- this.db.exec('ROLLBACK');
1219
- throw error;
1220
- }
1221
- return receipt;
1222
- }
1223
- applyExternalLifecycleDecision(source, input, origin) {
1224
- (0, external_lifecycle_candidates_js_1.validateExternalLifecycleDecision)('lifecycle', input);
1225
- const authority = this.resolveExternalCandidateAuthority(source, 'lifecycle', origin);
1226
- const receiptOrigin = authority.receiptOrigin;
1227
- let receipt = null;
1228
- const previousGeneration = this.onOwnerTaskChangeCommitted ? this.readGeneration() : null;
1229
- this.db.exec('BEGIN IMMEDIATE');
1230
- try {
1231
- const { candidate, snapshotAt } = authority.load(input.candidate_id);
1232
- if (candidate.kind !== 'lifecycle') {
1233
- throw new Error(`external lifecycle candidate ${input.candidate_id} has the wrong kind`);
1234
- }
1235
- if (input.expected_revision !== candidate.taskRevision) {
1236
- throw new Error(`external lifecycle candidate ${candidate.candidateId} revision does not match its host snapshot`);
1237
- }
1238
- if (origin.causeEventIds?.length !== 1 || origin.causeEventIds[0] !== candidate.eventId) {
1239
- throw new Error(`external lifecycle candidate ${candidate.candidateId} requires its exact host origin event`);
1240
- }
1241
- const existing = this.getExternalCandidateReceipt(candidate.candidateId);
1242
- if (existing) {
1243
- if (existing.kind !== 'lifecycle') {
1244
- throw new Error(`external lifecycle candidate ${candidate.candidateId} already has another receipt kind`);
1245
- }
1246
- this.assertLifecycleReplayMatches(existing, candidate, input);
1247
- receipt = existing;
1248
- }
1249
- else {
1250
- const task = this.getRowById(candidate.taskId);
1251
- const binding = this.getExternalBinding(candidate.taskId);
1252
- if (!task || task.kind !== 'owner' || !binding) {
1253
- throw new Error(`external lifecycle candidate ${candidate.candidateId} has no active binding`);
1254
- }
1255
- // A binding that came into being after this candidate's snapshot cannot
1256
- // be the binding the snapshot described. Board attempts keep the exact
1257
- // legacy ordering rule; when either side lacks an attempt id (owner-run
1258
- // decisions), the ledger clock decides.
1259
- const bindingPostdatesSnapshot = authority.source.kind === 'board' && binding.createdByAttemptId !== null
1260
- ? binding.createdByAttemptId >= authority.source.attemptId
1261
- : binding.createdAt > snapshotAt;
1262
- const superseded = binding.id !== candidate.bindingId ||
1263
- binding.revision !== candidate.bindingRevision ||
1264
- binding.connector !== candidate.connector ||
1265
- binding.sourceType !== candidate.sourceType ||
1266
- binding.externalSourceId !== candidate.externalSourceId ||
1267
- bindingPostdatesSnapshot ||
1268
- task.revision !== candidate.taskRevision ||
1269
- candidate.operatorObservationSeq <= binding.lastObservationSeq;
1270
- const taskRevisionBefore = task.revision;
1271
- let taskRevisionAfter = task.revision;
1272
- let outcome;
1273
- if (superseded) {
1274
- outcome = 'superseded';
1275
- }
1276
- else if (input.decision === 'apply') {
1277
- const terminalEvidence = candidate.proposedStatus === 'done' || candidate.proposedStatus === 'cancelled';
1278
- const transitioned = this.transitionTaskInTransaction(candidate.taskId, {
1279
- status: candidate.proposedStatus,
1280
- latest_event: candidate.evidenceSummary,
1281
- // This candidate is a host-issued current authoritative lifecycle
1282
- // observation. Preserve its semantic completion, or clear an earlier
1283
- // terminal classification when later feedback reopens the same row.
1284
- resolution_kind: terminalEvidence ? 'completed_evidence' : null,
1285
- }, origin, true);
1286
- taskRevisionAfter = transitioned.revision;
1287
- outcome = 'applied';
1288
- }
1289
- else {
1290
- outcome = 'retained';
1291
- }
1292
- if (outcome !== 'superseded') {
1293
- const updated = this.db
1294
- .prepare(`UPDATE operator_external_task_bindings
1295
- SET last_observation_seq = ?, revision = revision + 1, updated_at = ?
1296
- WHERE id = ? AND revision = ? AND last_observation_seq < ?`)
1297
- .run(candidate.operatorObservationSeq, this.now(), candidate.bindingId, candidate.bindingRevision, candidate.operatorObservationSeq);
1298
- if (updated.changes !== 1) {
1299
- throw new Error(`external lifecycle candidate ${candidate.candidateId} binding watermark changed`);
1300
- }
1301
- }
1302
- this.insertLifecycleReceipt(candidate, receiptOrigin, input, outcome, taskRevisionBefore, taskRevisionAfter, origin);
1303
- receipt = {
1304
- kind: 'lifecycle',
1305
- candidateId: candidate.candidateId,
1306
- workOrderAttemptId: receiptOrigin.attemptId,
1307
- originRunId: receiptOrigin.runId,
1308
- originOwnerScope: receiptOrigin.ownerScope,
1309
- taskId: candidate.taskId,
1310
- outcome,
1311
- reason: input.reason,
1312
- taskRevisionBefore,
1313
- taskRevisionAfter,
1314
- };
1315
- }
1316
- this.db.exec('COMMIT');
1317
- }
1318
- catch (error) {
1319
- this.db.exec('ROLLBACK');
1320
- throw error;
1321
- }
1322
- this.notifyOwnerTaskCommit(previousGeneration);
1323
- return receipt;
1324
- }
1325
- getExternalCandidateReceipt(candidateId) {
1326
- const binding = this.db
1327
- .prepare(`SELECT candidate_id, workorder_attempt_id, origin_run_id, origin_owner_scope, task_id,
1328
- outcome, reason, binding_id
1329
- FROM operator_external_binding_receipts WHERE candidate_id = ?`)
1330
- .get(candidateId);
1331
- const lifecycle = this.db
1332
- .prepare(`SELECT candidate_id, workorder_attempt_id, origin_run_id, origin_owner_scope, task_id,
1333
- outcome, reason, task_revision_before, task_revision_after
1334
- FROM operator_external_lifecycle_receipts WHERE candidate_id = ?`)
1335
- .get(candidateId);
1336
- if (binding && lifecycle) {
1337
- throw new Error(`external lifecycle candidate ${candidateId} has duplicate global receipts`);
1338
- }
1339
- const receiptKind = binding ? 'binding' : lifecycle ? 'lifecycle' : null;
1340
- const identity = this.db
1341
- .prepare(`SELECT receipt_kind FROM operator_external_receipt_identities WHERE candidate_id = ?`)
1342
- .get(candidateId);
1343
- if (receiptKind === null) {
1344
- if (identity) {
1345
- throw new Error(`external lifecycle candidate ${candidateId} has an orphan receipt identity`);
1346
- }
1347
- return null;
1348
- }
1349
- if (!identity || identity.receipt_kind !== receiptKind) {
1350
- throw new Error(`external lifecycle candidate ${candidateId} has inconsistent global receipt identity`);
1351
- }
1352
- if (binding) {
1353
- return {
1354
- kind: 'binding',
1355
- candidateId: binding.candidate_id,
1356
- workOrderAttemptId: binding.workorder_attempt_id,
1357
- originRunId: binding.origin_run_id,
1358
- originOwnerScope: binding.origin_owner_scope,
1359
- taskId: binding.task_id,
1360
- outcome: binding.outcome,
1361
- reason: binding.reason,
1362
- ...(binding.binding_id === null ? {} : { bindingId: binding.binding_id }),
1363
- };
1364
- }
1365
- return lifecycle
1366
- ? {
1367
- kind: 'lifecycle',
1368
- candidateId: lifecycle.candidate_id,
1369
- workOrderAttemptId: lifecycle.workorder_attempt_id,
1370
- originRunId: lifecycle.origin_run_id,
1371
- originOwnerScope: lifecycle.origin_owner_scope,
1372
- taskId: lifecycle.task_id,
1373
- outcome: lifecycle.outcome,
1374
- reason: lifecycle.reason,
1375
- taskRevisionBefore: lifecycle.task_revision_before,
1376
- taskRevisionAfter: lifecycle.task_revision_after,
1377
- }
1378
- : null;
1379
- }
1380
- externalBindingFromRow(row) {
1381
- return {
1382
- id: row.id,
1383
- revision: row.revision,
1384
- taskId: row.task_id,
1385
- connector: row.connector,
1386
- sourceType: row.source_type,
1387
- externalSourceId: row.external_source_id,
1388
- lastObservationSeq: row.last_observation_seq,
1389
- createdByAttemptId: row.created_by_attempt_id,
1390
- createdByRunId: row.created_by_run_id,
1391
- createdByOwnerScope: row.created_by_owner_scope,
1392
- createdAt: row.created_at,
1393
- };
1394
- }
1395
- assertBindingReplayMatches(receipt, candidate, input) {
1396
- const stored = this.db
1397
- .prepare(`SELECT decision FROM operator_external_binding_receipts WHERE candidate_id = ?`)
1398
- .get(candidate.candidateId);
1399
- if (!stored ||
1400
- stored.decision !== input.decision ||
1401
- receipt.taskId !== candidate.taskId ||
1402
- receipt.reason !== input.reason) {
1403
- throw new Error(`external binding receipt ${candidate.candidateId} conflicts with replay decision`);
1404
- }
1405
- }
1406
- insertBindingReceipt(candidate, receiptOrigin, input, outcome, bindingId, origin) {
1407
- this.db
1408
- .prepare(`INSERT INTO operator_external_binding_receipts
1409
- (candidate_id, decision, workorder_attempt_id, task_id, event_id, connector, source_type,
1410
- external_source_id, channel_partition, content_sha256, source_timestamp_ms,
1411
- operator_ingest_seq, operator_observation_seq, task_revision, outcome, reason, binding_id,
1412
- origin_run_id, origin_cause_event_ids, origin_owner_scope, origin_envelope_hash,
1413
- created_at)
1414
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
1415
- .run(candidate.candidateId, input.decision, receiptOrigin.attemptId, candidate.taskId, candidate.eventId, candidate.connector, candidate.sourceType, candidate.externalSourceId, candidate.channelPartition, candidate.contentSha256, candidate.sourceTimestampMs, candidate.operatorIngestSeq, candidate.operatorObservationSeq, candidate.taskRevision, outcome, input.reason, bindingId ?? null, receiptOrigin.runId, JSON.stringify(origin.causeEventIds ?? []), receiptOrigin.ownerScope, receiptOrigin.envelopeHash, this.now());
1416
- }
1417
- assertLifecycleReplayMatches(receipt, candidate, input) {
1418
- const stored = this.db
1419
- .prepare(`SELECT decision FROM operator_external_lifecycle_receipts WHERE candidate_id = ?`)
1420
- .get(candidate.candidateId);
1421
- if (!stored ||
1422
- stored.decision !== input.decision ||
1423
- receipt.taskId !== candidate.taskId ||
1424
- receipt.reason !== input.reason) {
1425
- throw new Error(`external lifecycle receipt ${candidate.candidateId} conflicts with replay decision`);
1426
- }
1427
- }
1428
- insertLifecycleReceipt(candidate, receiptOrigin, input, outcome, taskRevisionBefore, taskRevisionAfter, origin) {
1429
- this.db
1430
- .prepare(`INSERT INTO operator_external_lifecycle_receipts
1431
- (candidate_id, decision, workorder_attempt_id, task_id, event_id, connector, source_type,
1432
- external_source_id, channel_partition, content_sha256, source_timestamp_ms,
1433
- operator_ingest_seq, operator_observation_seq, binding_id, binding_revision,
1434
- task_revision_before, task_revision_after, outcome, reason, origin_run_id,
1435
- origin_cause_event_ids, origin_owner_scope, origin_envelope_hash, created_at)
1436
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
1437
- .run(candidate.candidateId, input.decision, receiptOrigin.attemptId, candidate.taskId, candidate.eventId, candidate.connector, candidate.sourceType, candidate.externalSourceId, candidate.channelPartition, candidate.contentSha256, candidate.sourceTimestampMs, candidate.operatorIngestSeq, candidate.operatorObservationSeq, candidate.bindingId, candidate.bindingRevision, taskRevisionBefore, taskRevisionAfter, outcome, input.reason, receiptOrigin.runId, JSON.stringify(origin.causeEventIds ?? []), receiptOrigin.ownerScope, receiptOrigin.envelopeHash, this.now());
1438
- }
1439
- /**
1440
- * Create a task. Idempotent under at-least-once delivery: a duplicate
1441
- * (source_channel, source_event_id) UPSERTS - the existing row gets the new
1442
- * latest_event (and title stays) instead of a near-duplicate row appearing.
1443
- */
1444
- create(input, origin = {}) {
1445
- if (!input.title || input.title.trim() === '') {
1446
- throw new Error('task title must be a non-empty string');
1447
- }
1448
- if (input.status !== undefined)
1449
- assertEnum(input.status, exports.TASK_STATUSES, 'status');
1450
- if (input.status === 'failed') {
1451
- throw new Error(`task_create: 'failed' is a system-only status`);
1452
- }
1453
- if (input.status === 'review') {
1454
- // review carries a host-verified submission anchor (review_started_at,
1455
- // review_anchor_event_id) that only the task_update path can supply. A row
1456
- // created directly in review would sit in the unanchored state reserved for
1457
- // legacy rows and could never enter the Temporal review lifecycle.
1458
- throw new Error(`task_create: 'review' requires verified submission evidence; create the task, then task_update it to review`);
1459
- }
1460
- // Namespace reservation (review m3): the occurrence keys are deterministic
1461
- // (epoch slots, readable from OSS source) - an agent-created owner row on
1462
- // a 'workorder:' (channel,event) pair would collide with the system
1463
- // INSERT via the shared unique index and DoS that schedule slot.
1464
- if (input.source_channel?.startsWith(exports.WORKORDER_CHANNEL_PREFIX)) {
1465
- throw new Error(`task_create: source_channel namespace '${exports.WORKORDER_CHANNEL_PREFIX}*' is reserved for system workorders`);
1466
- }
1467
- if (input.priority !== undefined)
1468
- assertEnum(input.priority, exports.TASK_PRIORITIES, 'priority');
1469
- if (input.deadline !== undefined)
1470
- assertIsoDate(input.deadline, 'deadline');
1471
- const exactDue = input.due_at !== undefined ? (0, task_temporal_js_1.parseExactDueAt)(input.due_at) : null;
1472
- if (exactDue && input.deadline !== undefined && input.deadline !== exactDue.deadline) {
1473
- throw new Error('task_create: due_at and deadline conflict');
1474
- }
1475
- const normalizedDeadline = exactDue?.deadline ?? input.deadline ?? null;
1476
- const initialTemporalEpoch = normalizedDeadline !== null ? 1 : 0;
1477
- // Optional HERE on purpose: the PUBLIC task_create boundary requires it, while
1478
- // internal/system seeding and legacy callers stay backward compatible.
1479
- const normalizedCompletionCriteria = normalizeCompletionCriteria(input.completion_criteria, 'task_create');
1480
- const now = this.now();
1481
- if (input.source_channel && input.source_event_id) {
1482
- // kind='owner' probe: an agent-supplied (channel, event) pair can never
1483
- // reach a system workorder row (Stage-2 tamper guard).
1484
- const existing = this.db
1485
- .prepare(`SELECT * FROM operator_tasks
1486
- WHERE source_channel = ? AND source_event_id = ? AND kind = 'owner'`)
1487
- .get(input.source_channel, input.source_event_id);
1488
- if (existing) {
1489
- // Duplicate source delivery uses the same mutation boundary, including
1490
- // exact-time normalization and no-op detection. The original title stays
1491
- // stable across retries for backward compatibility.
1492
- return this.update(existing.id, {
1493
- ...(input.status !== undefined ? { status: input.status } : {}),
1494
- ...(input.priority !== undefined ? { priority: input.priority } : {}),
1495
- ...(input.assignee !== undefined ? { assignee: input.assignee } : {}),
1496
- ...(input.deadline !== undefined ? { deadline: input.deadline } : {}),
1497
- ...(input.due_at !== undefined ? { due_at: input.due_at } : {}),
1498
- ...(input.confirmed !== undefined ? { confirmed: input.confirmed } : {}),
1499
- ...(input.latest_event !== undefined ? { latest_event: input.latest_event } : {}),
1500
- ...(normalizedCompletionCriteria !== null
1501
- ? { completion_criteria: normalizedCompletionCriteria }
1502
- : {}),
1503
- ...(input.expected_revision !== undefined
1504
- ? { expected_revision: input.expected_revision }
1505
- : {}),
1506
- },
1507
- // A duplicate delivery of the same event. The HOST batch still wins
1508
- // (review: the agent-supplied source_event_id was overriding it here,
1509
- // letting a model forge an attributed cause on every judgment-borne
1510
- // create); the keyed event is only the fallback when the host
1511
- // carried nothing.
1512
- {
1513
- ...origin,
1514
- taskCreateUpsert: true,
1515
- causeEventIds: origin.causeEventIds?.length
1516
- ? origin.causeEventIds
1517
- : input.source_event_id
1518
- ? [input.source_event_id]
1519
- : origin.causeEventIds,
1520
- });
1521
- }
1522
- }
1523
- let createdId = 0;
1524
- const previousGeneration = this.onOwnerTaskChangeCommitted ? this.readGeneration() : null;
1525
- const write = this.db.transaction(() => {
1526
- const result = this.db
1527
- .prepare(`INSERT INTO operator_tasks
1528
- (title, status, priority, assignee, deadline, due_at, deadline_offset_minutes,
1529
- revision, temporal_epoch, source_channel, source_event_id, latest_event,
1530
- auto_created, confirmed, completion_criteria, created_at, updated_at)
1531
- VALUES (?, ?, ?, ?, ?, ?, ?, 1, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
1532
- .run(input.title.trim(), input.status ?? 'pending', input.priority ?? 'normal', input.assignee ?? null, normalizedDeadline, exactDue?.dueAt ?? null, exactDue?.offsetMinutes ?? null, initialTemporalEpoch, input.source_channel ?? null, input.source_event_id ?? null, input.latest_event ?? null, 1, input.confirmed ? 1 : 0, normalizedCompletionCriteria, now, now);
1533
- createdId = Number(result.lastInsertRowid);
1534
- this.recordTaskChange({
1535
- kind: 'task_create',
1536
- taskId: createdId,
1537
- // The HOST batch wins. `source_event_id` arrives on agent-authored task_create
1538
- // input, so letting it take precedence made the attribution the agent's to choose:
1539
- // any 1-200 character string passes the ledger's shape check, and the change was
1540
- // then stamped `attributed` on a cause nobody could resolve. The run id is already
1541
- // protected for exactly this reason; the cause was not. Found in review.
1542
- //
1543
- // The agent's field is still USED when the host handed the run no batch - a named
1544
- // source event is better evidence than none, and an unbounded run has nothing else.
1545
- // It is weaker evidence, not worthless.
1546
- //
1547
- // A plain spread would be wrong in the other direction: an absent caller field must
1548
- // not erase what the host knows.
1549
- origin: {
1550
- ...origin,
1551
- causeEventIds: origin.causeEventIds && origin.causeEventIds.length > 0
1552
- ? origin.causeEventIds
1553
- : input.source_event_id
1554
- ? [input.source_event_id]
1555
- : origin.causeEventIds,
1556
- },
1557
- channel: input.source_channel ?? null,
1558
- // Everything the INSERT wrote. A hash over two of fifteen columns cannot tell two
1559
- // materially different writes apart, which is most of what a receipt is for.
1560
- payload: {
1561
- title: input.title.trim(),
1562
- status: input.status ?? 'pending',
1563
- priority: input.priority ?? 'normal',
1564
- assignee: input.assignee ?? null,
1565
- deadline: normalizedDeadline,
1566
- due_at: exactDue?.dueAt ?? null,
1567
- deadline_offset_minutes: exactDue?.offsetMinutes ?? null,
1568
- temporal_epoch: initialTemporalEpoch,
1569
- source_channel: input.source_channel ?? null,
1570
- source_event_id: input.source_event_id ?? null,
1571
- latest_event: input.latest_event ?? null,
1572
- confirmed: input.confirmed ? 1 : 0,
1573
- completion_criteria: normalizedCompletionCriteria,
1574
- },
1575
- atMs: now,
1576
- });
1577
- }, 'immediate');
1578
- write();
1579
- this.notifyOwnerTaskCommit(previousGeneration);
1580
- const created = this.getById(createdId);
1581
- if (!created)
1582
- throw new Error('task_create: inserted row could not be read back');
1583
- return created;
1584
- }
1585
- /**
1586
- * Write the effect row for a task change.
1587
- *
1588
- * Called from inside the same transaction as the write it describes. The cause is the
1589
- * event the caller already recorded on the row - the tool has always accepted it, and
1590
- * 178 of the 179 owner tasks that carry one resolve to a real indexed event, so this is
1591
- * attribution that already exists rather than a new burden on the agent.
1592
- *
1593
- * When there is no cause the change is still recorded, marked unattributed. That is the
1594
- * honest reading of `task_update`, which has never had a cause field at all: the system
1595
- * has been changing owner work items without recording why, and the ledger's job is to
1596
- * show how often, not to pretend otherwise or to start refusing writes.
1597
- */
1598
- recordTaskChange(input) {
1599
- const common = {
1600
- runId: input.origin.runId ?? null,
1601
- channelId: input.channel,
1602
- kind: input.kind,
1603
- targetType: 'task',
1604
- targetId: String(input.taskId),
1605
- payload: input.payload,
1606
- atMs: input.atMs,
1607
- };
1608
- // A cause the ledger cannot use makes the change unattributed - it never makes the
1609
- // change fail. Some live rows carry 400-character legacy source identifiers, and an
1610
- // operator that cannot close a work item because its upstream id is malformed is a
1611
- // worse system than one that admits it does not know why the item changed.
1612
- const causes = (input.origin.causeEventIds ?? []).filter(effects_js_1.isUsableCause);
1613
- if (causes.length > 0) {
1614
- (0, effects_js_1.recordEffect)(this.db, { ...common, sourceEventIds: causes });
1615
- return;
1616
- }
1617
- (0, effects_js_1.recordUnattributedChange)(this.db, common, input.origin.causeKind ?? 'owner_message');
1618
- }
1619
- update(id, patch, origin = {}) {
1620
- this.validateTaskUpdatePatch(patch);
1621
- const previousGeneration = this.onOwnerTaskChangeCommitted ? this.readGeneration() : null;
1622
- const updated = this.db.transaction(() => this.transitionTaskInTransaction(id, patch, origin), 'immediate')();
1623
- this.notifyOwnerTaskCommit(previousGeneration);
1624
- return updated;
1625
- }
1626
- /**
1627
- * Recorrect an existing owner row with a NAMED disposition.
1628
- *
1629
- * Records and tasks are separate. Without a semantic terminal reason the agent
1630
- * could not distinguish completed work from an item that was never a task, so
1631
- * connector observations, principles, lessons and open questions accumulated as
1632
- * owner rows and could only be "closed" as if they had been done.
1633
- *
1634
- * Every path requires the exact current revision, a non-empty bounded reason
1635
- * preserved as `latest_event`, an OWNER row, and the same workorder-attempt
1636
- * currency and causal-provenance checks as task_update (TG-03/TG-04/TG-06) -
1637
- * a terminal attempt of any kind cannot mutate a row, and an owner-event
1638
- * decision cannot rest on a fabricated cause. Scheduler hint pages and the
1639
- * causal batch's channel select what the host READS; they do not narrow the
1640
- * authenticated owner's decisions. The whole transition, its
1641
- * `resolution_kind` and its effect receipt commit as ONE transaction.
1642
- */
1643
- reclassify(id, input, origin = {}) {
1644
- const disposition = input?.disposition;
1645
- if (!exports.TASK_RECLASSIFY_DISPOSITIONS.includes(disposition)) {
1646
- throw new Error(`task_reclassify: disposition must be one of ${exports.TASK_RECLASSIFY_DISPOSITIONS.join('|')}, got: ${String(disposition)}`);
1647
- }
1648
- const reason = typeof input.reason === 'string' ? input.reason.trim() : '';
1649
- if (reason.length === 0) {
1650
- throw new Error('task_reclassify: reason must be a non-empty string');
1651
- }
1652
- if (reason.length > exports.TASK_RECLASSIFY_REASON_MAX_LENGTH) {
1653
- throw new Error(`task_reclassify: reason must be at most ${exports.TASK_RECLASSIFY_REASON_MAX_LENGTH} characters`);
1654
- }
1655
- if (!Number.isSafeInteger(input.expected_revision) || input.expected_revision < 0) {
1656
- throw new Error('task_reclassify: expected_revision must be a non-negative integer');
1657
- }
1658
- const previousGeneration = this.onOwnerTaskChangeCommitted ? this.readGeneration() : null;
1659
- let record;
1660
- this.db.exec('BEGIN IMMEDIATE');
1661
- try {
1662
- const existing = this.db.prepare('SELECT * FROM operator_tasks WHERE id = ?').get(id);
1663
- if (!existing)
1664
- throw new Error(`task_reclassify: no task with id ${id}`);
1665
- if (existing.kind === 'system') {
1666
- throw new Error(`task_reclassify: task ${id} is a system workorder row (owner rows only)`);
1667
- }
1668
- if (input.expected_revision !== existing.revision) {
1669
- throw new Error(`task_reclassify: expected revision ${input.expected_revision}, current ${existing.revision}`);
1670
- }
1671
- this.assertTaskReclassificationAuthorized(origin);
1672
- const patch = this.buildReclassifyPatch(existing, disposition, reason);
1673
- // Same primitive as task_update: candidate guard, board-attempt liveness,
1674
- // revision-checked UPDATE, effect receipt, temporal generation supersession.
1675
- record = this.transitionTaskInTransaction(id, patch, origin);
1676
- this.db.exec('COMMIT');
1677
- }
1678
- catch (error) {
1679
- this.db.exec('ROLLBACK');
1680
- throw error;
1681
- }
1682
- this.notifyOwnerTaskCommit(previousGeneration);
1683
- return record;
1684
- }
1685
- assertTaskReclassificationAuthorized(origin) {
1686
- if (origin.workOrderAttemptId !== undefined) {
1687
- // A carried attempt must be CURRENT. Its kind is scheduling metadata: a
1688
- // wiki or temporal run that discovers a record-shaped owner row may
1689
- // reclassify it under the same CAS rules as a Board run. Its candidate
1690
- // page is a bounded-read hint, so a row outside the page is not refused.
1691
- this.assertWorkOrderAttemptActive('task_reclassify', origin.workOrderAttemptId);
1692
- }
1693
- if (origin.reclassificationCauseBound) {
1694
- const eventIds = (origin.causeEventIds ?? []).filter(effects_js_1.isUsableCause);
1695
- if (eventIds.length === 0) {
1696
- throw new Error('task_reclassify: owner-event reclassification requires causal events');
1697
- }
1698
- // Provenance: every cause must be an event a durable inbox batch actually
1699
- // carried. The batch's channel is not compared with the task's source -
1700
- // cross-source relevance is MAMA's judgment under the owner's grant.
1701
- const unknown = this.findCausalEventsWithoutInboxBatch(eventIds);
1702
- if (unknown.length > 0) {
1703
- throw new Error(`task_reclassify: causal event(s) ${unknown.join(', ')} were not carried by any owner-event inbox batch`);
1704
- }
1705
- }
1706
- }
1707
- /**
1708
- * A retained attempt context outlives its workorder: a late direct or nested
1709
- * tool call can still carry it after the row reached a terminal status. Any
1710
- * lifecycle judgment made under a carried attempt requires that attempt to be
1711
- * the claimed, in-progress one, whatever its work kind.
1712
- */
1713
- assertWorkOrderAttemptActive(tool, attemptId) {
1714
- const attempt = this.getWorkOrderById(attemptId);
1715
- if (!attempt) {
1716
- throw new Error(`${tool}: workorder ${String(attemptId)} is no longer active (missing)`);
1717
- }
1718
- if (attempt.status !== 'in_progress') {
1719
- throw new Error(`${tool}: ${attempt.workKind} workorder ${String(attemptId)} is no longer active (${attempt.status})`);
1720
- }
1721
- return attempt;
1722
- }
1723
- findCausalEventsWithoutInboxBatch(eventIds) {
1724
- const placeholders = eventIds.map(() => '?').join(',');
1725
- const known = new Set(this.db
1726
- .prepare(`SELECT DISTINCT event.value AS event_id
1727
- FROM owner_event_inbox AS inbox, json_each(inbox.event_ids_json) AS event
1728
- WHERE event.value IN (${placeholders})`)
1729
- .all(...eventIds).map((row) => row.event_id));
1730
- return eventIds.filter((eventId) => !known.has(eventId));
1731
- }
1732
- buildReclassifyPatch(existing, disposition, reason) {
1733
- const base = {
1734
- latest_event: reason,
1735
- expected_revision: existing.revision,
1736
- };
1737
- if (disposition === 'reopen') {
1738
- if (existing.status !== 'done' && existing.status !== 'cancelled') {
1739
- throw new Error(`task_reclassify: reopen requires a terminal owner row, task is '${existing.status}'`);
1740
- }
1741
- // A reopened row must not inherit a deadline that already passed: it would
1742
- // read as overdue the moment it reopens. A still-future deadline is kept.
1743
- const stale = this.isDeadlineInThePast(existing);
1744
- return {
1745
- ...base,
1746
- status: 'pending',
1747
- resolution_kind: null,
1748
- ...(stale ? { deadline: null, due_at: null } : {}),
1749
- };
1750
- }
1751
- if (existing.status === 'done' || existing.status === 'cancelled') {
1752
- throw new Error(`task_reclassify: ${disposition} requires an active owner row, task is '${existing.status}'`);
1753
- }
1754
- if (disposition === 'completed_evidence') {
1755
- return { ...base, status: 'done', resolution_kind: 'completed_evidence' };
1756
- }
1757
- if (disposition === 'completed_no_issue') {
1758
- // Owner policy: a PAST deadline plus a complete relevant-source check with no
1759
- // issue is enough. Without a passed deadline there is nothing to conclude from.
1760
- if (!this.isDeadlineInThePast(existing)) {
1761
- throw new Error('task_reclassify: completed_no_issue requires a deadline or due_at already in the past');
1762
- }
1763
- return { ...base, status: 'done', resolution_kind: 'completed_no_issue' };
1764
- }
1765
- // non_task_record / non_task_memory: this was never a task. Cancelled, not done,
1766
- // so accounting never reads it as finished work.
1767
- return {
1768
- ...base,
1769
- status: 'cancelled',
1770
- completion_criteria: null,
1771
- resolution_kind: disposition,
1772
- };
1773
- }
1774
- /** True when the row carries a deadline/due_at that has already passed. */
1775
- isDeadlineInThePast(existing) {
1776
- const state = (0, task_temporal_js_1.deriveTemporalState)({
1777
- // Terminal rows derive 'closed', which would hide a genuinely past deadline;
1778
- // ask the temporal question about the CLOCK fields only.
1779
- status: 'pending',
1780
- dueAt: existing.due_at,
1781
- deadlineIso: existing.deadline,
1782
- deadlineOffsetMinutes: existing.deadline_offset_minutes,
1783
- }, this.now(), this.timeZone);
1784
- return state === 'exact_overdue' || state === 'date_overdue';
1785
- }
1786
- /**
1787
- * The one mutation primitive for owner-task state. Callers own the outer
1788
- * transaction so lifecycle receipts, effects, generation ownership, and the
1789
- * row revision can commit or roll back as one unit.
1790
- */
1791
- transitionTaskInTransaction(id, patch, origin, skipCandidateGuard = false) {
1792
- this.validateTaskUpdatePatch(patch);
1793
- if (!skipCandidateGuard) {
1794
- this.assertCandidateTaskMutationAllowed(id, patch, origin);
1795
- }
1796
- const existing = this.db.prepare('SELECT * FROM operator_tasks WHERE id = ?').get(id);
1797
- if (!existing)
1798
- throw new Error(`task_update: no task with id ${id}`);
1799
- if (existing.kind === 'system') {
1800
- throw new Error(`task_update: task ${id} is a system workorder row (host-managed)`);
1801
- }
1802
- const hasLifecyclePatch = Object.prototype.hasOwnProperty.call(patch, 'status') ||
1803
- Object.prototype.hasOwnProperty.call(patch, 'due_at') ||
1804
- Object.prototype.hasOwnProperty.call(patch, 'latest_event') ||
1805
- Object.prototype.hasOwnProperty.call(patch, 'completion_criteria');
1806
- // Direct-ABI mutation under a carried attempt: the attempt must be current
1807
- // for EVERY patch shape (a stale attempt renaming a task is as stale as one
1808
- // closing it). Work kind is scheduling metadata, not owner authority.
1809
- // Internal receipted primitives (external lifecycle apply) do not set the
1810
- // direct-ABI guard and validate their own claimed attempt separately.
1811
- const isCarriedDirectMutation = origin.requiresExpectedRevision === true && origin.workOrderAttemptId !== undefined;
1812
- if (isCarriedDirectMutation) {
1813
- this.assertWorkOrderAttemptActive('task_update', origin.workOrderAttemptId);
1814
- }
1815
- // A lifecycle judgment additionally proves the revision actually read plus a reason.
1816
- const isWorkorderLifecycleJudgment = isCarriedDirectMutation && hasLifecyclePatch;
1817
- if (isWorkorderLifecycleJudgment) {
1818
- if (!Number.isSafeInteger(patch.expected_revision) || patch.expected_revision < 0) {
1819
- throw new Error('task_update: lifecycle workorder requires expected_revision');
1820
- }
1821
- if (patch.expected_revision !== existing.revision) {
1822
- throw new Error(`task_update: expected revision ${patch.expected_revision}, current ${existing.revision}`);
1823
- }
1824
- if (typeof patch.latest_event !== 'string' || patch.latest_event.trim().length === 0) {
1825
- throw new Error('task_update: lifecycle workorder requires a plain latest_event reason');
1826
- }
1827
- }
1828
- return this.transitionOwnerTaskRowInTransaction(id, existing, patch, origin);
1829
- }
1830
- validateTaskUpdatePatch(patch) {
1831
- if (patch.status === 'failed') {
1832
- throw new Error(`task_update: 'failed' is a system-only status`);
1833
- }
1834
- if (patch.status !== undefined)
1835
- assertEnum(patch.status, exports.TASK_STATUSES, 'status');
1836
- if (patch.priority !== undefined)
1837
- assertEnum(patch.priority, exports.TASK_PRIORITIES, 'priority');
1838
- if (patch.deadline !== undefined && patch.deadline !== null) {
1839
- assertIsoDate(patch.deadline, 'deadline');
1840
- }
1841
- if (patch.title !== undefined && patch.title.trim() === '') {
1842
- throw new Error('task title must be a non-empty string');
1843
- }
1844
- }
1845
- transitionOwnerTaskRowInTransaction(id, existing, patch, origin) {
1846
- const next = {
1847
- title: existing.title,
1848
- status: existing.status,
1849
- priority: existing.priority,
1850
- assignee: existing.assignee,
1851
- deadline: existing.deadline,
1852
- due_at: existing.due_at,
1853
- deadline_offset_minutes: existing.deadline_offset_minutes,
1854
- latest_event: existing.latest_event,
1855
- confirmed: existing.confirmed,
1856
- temporal_epoch: existing.temporal_epoch,
1857
- temporal_reconciled_occurrence_key: existing.temporal_reconciled_occurrence_key,
1858
- last_temporal_checked_at: existing.last_temporal_checked_at,
1859
- next_temporal_check_at: existing.next_temporal_check_at,
1860
- last_temporal_attempt_id: existing.last_temporal_attempt_id,
1861
- review_started_at: existing.review_started_at,
1862
- review_anchor_event_id: existing.review_anchor_event_id,
1863
- review_anchor_source_channel: existing.review_anchor_source_channel,
1864
- completion_criteria: existing.completion_criteria,
1865
- resolution_kind: existing.resolution_kind,
1866
- };
1867
- if (patch.title !== undefined)
1868
- next.title = patch.title.trim();
1869
- if (patch.status !== undefined)
1870
- next.status = patch.status;
1871
- if (patch.priority !== undefined)
1872
- next.priority = patch.priority;
1873
- if (patch.assignee !== undefined)
1874
- next.assignee = patch.assignee;
1875
- if (patch.latest_event !== undefined)
1876
- next.latest_event = patch.latest_event;
1877
- if (patch.confirmed !== undefined)
1878
- next.confirmed = patch.confirmed ? 1 : 0;
1879
- if (patch.completion_criteria !== undefined) {
1880
- next.completion_criteria = normalizeCompletionCriteria(patch.completion_criteria, 'task_update');
1881
- }
1882
- // Host-internal (reclassify only); the public task_update surface rejects it.
1883
- if (patch.resolution_kind !== undefined)
1884
- next.resolution_kind = patch.resolution_kind;
1885
- const leavingVerifiedReview = existing.status === 'review' &&
1886
- patch.status !== undefined &&
1887
- patch.status !== 'review' &&
1888
- existing.review_started_at !== null &&
1889
- typeof existing.review_anchor_event_id === 'string' &&
1890
- existing.review_anchor_event_id.trim().length > 0;
1891
- if (leavingVerifiedReview) {
1892
- next.review_started_at = null;
1893
- next.review_anchor_event_id = null;
1894
- next.review_anchor_source_channel = null;
1895
- next.due_at = null;
1896
- next.deadline = null;
1897
- next.deadline_offset_minutes = null;
1898
- }
1899
- const reviewAttempt = origin.requiresExpectedRevision
1900
- ? this.getWorkOrderById(origin.workOrderAttemptId ?? -1)
1901
- : null;
1902
- if (patch.status === 'review' &&
1903
- ((reviewAttempt?.workKind === 'board' && reviewAttempt.status === 'in_progress') ||
1904
- origin.verifiedReviewEvidence !== undefined)) {
1905
- if (Object.prototype.hasOwnProperty.call(patch, 'due_at') ||
1906
- Object.prototype.hasOwnProperty.call(patch, 'deadline')) {
1907
- throw new Error('task_update: review due_at and deadline are computed from verified evidence');
1908
- }
1909
- const evidence = origin.verifiedReviewEvidence;
1910
- if (!evidence) {
1911
- throw new Error('task_update: review requires host-verified submission evidence');
1912
- }
1913
- if (!evidence.sourceChannel.trim()) {
1914
- throw new Error('task_update: review evidence source is required');
1915
- }
1916
- if (!Number.isSafeInteger(evidence.sourceTimestampMs) || evidence.sourceTimestampMs < 0) {
1917
- throw new Error('task_update: review evidence timestamp is invalid');
1918
- }
1919
- next.review_started_at = evidence.sourceTimestampMs;
1920
- next.review_anchor_event_id = evidence.eventIndexId;
1921
- next.review_anchor_source_channel = evidence.sourceChannel;
1922
- next.due_at = evidence.sourceTimestampMs + 14 * 24 * 60 * 60 * 1000;
1923
- next.deadline = new Date(next.due_at).toISOString().slice(0, 10);
1924
- next.deadline_offset_minutes = 0;
1925
- }
1926
- const hasDueAt = Object.prototype.hasOwnProperty.call(patch, 'due_at');
1927
- const hasDeadline = Object.prototype.hasOwnProperty.call(patch, 'deadline');
1928
- if (hasDueAt && patch.due_at !== null && patch.due_at !== undefined) {
1929
- const exactDue = (0, task_temporal_js_1.parseExactDueAt)(patch.due_at);
1930
- if (hasDeadline && patch.deadline !== exactDue.deadline) {
1931
- throw new Error('task_update: due_at and deadline conflict');
1932
- }
1933
- next.due_at = exactDue.dueAt;
1934
- next.deadline = exactDue.deadline;
1935
- next.deadline_offset_minutes = exactDue.offsetMinutes;
1936
- }
1937
- else if (hasDeadline) {
1938
- next.deadline = patch.deadline ?? null;
1939
- next.due_at = null;
1940
- if (patch.deadline === null) {
1941
- next.deadline_offset_minutes = null;
1942
- }
1943
- }
1944
- else if (hasDueAt) {
1945
- next.due_at = null;
1946
- }
1947
- const temporalChanged = next.due_at !== existing.due_at || next.deadline !== existing.deadline;
1948
- const terminalToOpen = (existing.status === 'done' || existing.status === 'cancelled') &&
1949
- next.status !== 'done' &&
1950
- next.status !== 'cancelled';
1951
- if (terminalToOpen && existing.resolution_kind !== null && patch.resolution_kind !== null) {
1952
- throw new Error('task_update: a classified terminal row must reopen through task_reclassify');
1953
- }
1954
- if (patch.status !== undefined &&
1955
- next.status !== existing.status &&
1956
- patch.resolution_kind === undefined) {
1957
- // A generic status change has no semantic reclassification authority. Clear an
1958
- // old terminal meaning rather than rendering contradictory status/reason pairs.
1959
- next.resolution_kind = null;
1960
- }
1961
- const openToTerminal = existing.status !== 'done' &&
1962
- existing.status !== 'cancelled' &&
1963
- (next.status === 'done' || next.status === 'cancelled');
1964
- if (temporalChanged || terminalToOpen) {
1965
- next.temporal_epoch = existing.temporal_epoch + 1;
1966
- next.temporal_reconciled_occurrence_key = null;
1967
- next.last_temporal_checked_at = null;
1968
- next.next_temporal_check_at = null;
1969
- next.last_temporal_attempt_id = null;
1970
- }
1971
- const persistedColumns = [
1972
- 'title',
1973
- 'status',
1974
- 'priority',
1975
- 'assignee',
1976
- 'deadline',
1977
- 'due_at',
1978
- 'deadline_offset_minutes',
1979
- 'latest_event',
1980
- 'confirmed',
1981
- 'temporal_epoch',
1982
- 'temporal_reconciled_occurrence_key',
1983
- 'last_temporal_checked_at',
1984
- 'next_temporal_check_at',
1985
- 'last_temporal_attempt_id',
1986
- 'review_started_at',
1987
- 'review_anchor_event_id',
1988
- 'review_anchor_source_channel',
1989
- 'completion_criteria',
1990
- 'resolution_kind',
1991
- ];
1992
- const changedColumns = persistedColumns.filter((column) => next[column] !== existing[column]);
1993
- if (changedColumns.length === 0) {
1994
- return this.toRecord(existing);
1995
- }
1996
- else {
1997
- const nextRevision = existing.revision + 1;
1998
- const sets = changedColumns.map((column) => `${column} = ?`);
1999
- const values = changedColumns.map((column) => next[column]);
2000
- const updatedAt = this.now();
2001
- sets.push('revision = ?', 'updated_at = ?');
2002
- values.push(nextRevision, updatedAt);
2003
- const updated = this.db
2004
- .prepare(`UPDATE operator_tasks SET ${sets.join(', ')} WHERE id = ? AND revision = ?`)
2005
- .run(...values, id, existing.revision);
2006
- if (updated.changes !== 1) {
2007
- throw new Error(`task_update: task ${id} revision changed during transition`);
2008
- }
2009
- this.recordTaskChange({
2010
- kind: 'task_update',
2011
- taskId: id,
2012
- origin,
2013
- channel: existing.source_channel,
2014
- payload: {
2015
- revision: nextRevision,
2016
- changed: Object.fromEntries(changedColumns.map((column) => [column, next[column]])),
2017
- },
2018
- atMs: updatedAt,
2019
- });
2020
- if (temporalChanged || terminalToOpen) {
2021
- this.supersedeTemporalGenerationsInTransaction(id, Number(next.temporal_epoch));
2022
- }
2023
- else if (openToTerminal) {
2024
- this.supersedeAllActiveTemporalGenerationsInTransaction(id);
2025
- }
2026
- const transitioned = this.getRowById(id);
2027
- if (!transitioned)
2028
- throw new Error(`task_update: task ${id} disappeared during transition`);
2029
- return transitioned;
2030
- }
2031
- }
2032
- assertCandidateTaskMutationAllowed(taskId, patch, origin) {
2033
- if (origin.workOrderAttemptId === undefined ||
2034
- (!Object.prototype.hasOwnProperty.call(patch, 'status') &&
2035
- !Object.prototype.hasOwnProperty.call(patch, 'latest_event') &&
2036
- !Object.prototype.hasOwnProperty.call(patch, 'completion_criteria'))) {
2037
- return;
2038
- }
2039
- const attempt = this.getWorkOrderById(origin.workOrderAttemptId);
2040
- // Unlike a lifecycle decision, this is a standing mutation guard. A late
2041
- // direct or nested tool call can retain the host-issued attempt context
2042
- // after its board workorder has reached a terminal status, and its durable
2043
- // candidate payload must remain authoritative in that case. Decision
2044
- // application still calls loadBoardCandidate(), which requires a claimed
2045
- // in-progress attempt.
2046
- //
2047
- // The payload's reclassificationCandidates page is NOT consulted here: it is
2048
- // the scheduler's bounded-read hint, and qualifying a legacy row the owner
2049
- // discovered outside that page is an ordinary owner decision guarded by
2050
- // attempt currency, expected_revision and a plain reason (see
2051
- // transitionTaskInTransaction). Only host-attested external binding /
2052
- // lifecycle candidates keep their receipted-decision-only rule below.
2053
- if (!attempt || attempt.workKind !== 'board') {
2054
- return;
2055
- }
2056
- const payload = publisherPayloadOfStoredWorkOrder(attempt.payload);
2057
- (0, workorder_publishers_js_1.validateWorkOrderPayload)('board', payload);
2058
- if (payload.mode !== 'reconcile' || !payload.candidates) {
2059
- return;
2060
- }
2061
- const candidates = payload.candidates;
2062
- if ([...candidates.bindingCandidates, ...candidates.lifecycleCandidates].some((candidate) => candidate.taskId === taskId)) {
2063
- throw new Error(`task_update: candidate-bound lifecycle task ${taskId} may change status/latest_event only through its receipted decision`);
2064
- }
2065
- }
2066
- supersedeTemporalGenerationsInTransaction(taskId, currentEpoch, excludeGenerationKey, updatedAt = this.now()) {
2067
- const reason = 'task temporal occurrence superseded';
2068
- const exclusion = excludeGenerationKey ? ' AND generation_key != ?' : '';
2069
- const generationParams = excludeGenerationKey
2070
- ? [taskId, currentEpoch, excludeGenerationKey]
2071
- : [taskId, currentEpoch];
2072
- this.db
2073
- .prepare(`UPDATE operator_tasks SET status = 'cancelled', latest_event = ?, updated_at = ?
2074
- WHERE kind = 'system' AND status IN ('pending','in_progress') AND id IN (
2075
- SELECT last_workorder_id FROM operator_temporal_generations
2076
- WHERE task_id = ? AND disposition = 'active' AND temporal_epoch < ?${exclusion}
2077
- )`)
2078
- .run(reason, updatedAt, ...generationParams);
2079
- this.db
2080
- .prepare(`UPDATE operator_temporal_generations
2081
- SET disposition = 'superseded', reason = ?, updated_at = ?
2082
- WHERE task_id = ? AND disposition = 'active' AND temporal_epoch < ?${exclusion}`)
2083
- .run(reason, updatedAt, ...generationParams);
2084
- }
2085
- supersedeAllActiveTemporalGenerationsInTransaction(taskId, updatedAt = this.now()) {
2086
- const reason = 'owner task closed';
2087
- this.db
2088
- .prepare(`UPDATE operator_tasks SET status = 'cancelled', latest_event = ?, updated_at = ?
2089
- WHERE kind = 'system' AND status IN ('pending','in_progress') AND id IN (
2090
- SELECT last_workorder_id FROM operator_temporal_generations
2091
- WHERE task_id = ? AND disposition = 'active'
2092
- )`)
2093
- .run(reason, updatedAt, taskId);
2094
- this.db
2095
- .prepare(`UPDATE operator_temporal_generations
2096
- SET disposition = 'superseded', reason = ?, updated_at = ?
2097
- WHERE task_id = ? AND disposition = 'active'`)
2098
- .run(reason, updatedAt, taskId);
2099
- }
2100
- /**
2101
- * Stable hash over ordered OWNER rows - the Phase-2 verifier's ledger
2102
- * snapshot. kind filter keeps concurrent system enqueues from shaking the
2103
- * hash mid-bracket (evidence-only signal, but noise is noise).
2104
- */
2105
- payloadHash() {
2106
- const rows = this.db
2107
- .prepare(`SELECT id, title, status, priority, assignee, deadline, latest_event, confirmed,
2108
- updated_at
2109
- FROM operator_tasks WHERE kind = 'owner' ORDER BY id ASC`)
2110
- .all();
2111
- return (0, node_crypto_1.createHash)('sha256').update(JSON.stringify(rows)).digest('hex');
2112
- }
2113
- // ── Workorder API (Stage 2) ─────────────────────────────────────────────
2114
- // System rows only. These are the ONLY paths that create or transition
2115
- // kind='system' rows; external create/update guards reject everything else.
2116
- /**
2117
- * Enqueue a workorder. Idempotent per occurrence key: an open (pending or
2118
- * in_progress) keyed row dedups. Completed owner-event occurrences and
2119
- * scheduled promotion slots also dedup; other terminal rows free the key
2120
- * and a fresh row is inserted.
2121
- */
2122
- enqueueWorkOrder(order) {
2123
- if (order.workKind === 'temporal') {
2124
- throw new Error('enqueueWorkOrder: temporal work requires enqueueTemporalGeneration');
2125
- }
2126
- if (Object.prototype.hasOwnProperty.call(order.input, 'attempts')) {
2127
- throw new Error('enqueueWorkOrder: attempts is ledger-managed and cannot be supplied');
2128
- }
2129
- return this.insertWorkOrder(order, 1);
2130
- }
2131
- /** Read a durable workorder acceptance by its host-issued occurrence key. */
2132
- findWorkOrderByOccurrence(workKind, idempotencyKey) {
2133
- const row = this.db
2134
- .prepare(`SELECT * FROM operator_tasks
2135
- WHERE kind = 'system' AND source_channel = ? AND source_event_id = ?
2136
- ORDER BY id ASC LIMIT 1`)
2137
- .get(`${exports.WORKORDER_CHANNEL_PREFIX}${workKind}`, idempotencyKey);
2138
- return row ? this.rowToWorkOrder(row) : null;
2139
- }
2140
- /**
2141
- * The newest COMPLETED full-board-class run - the baseline the scheduled full-board producer
2142
- * gates against (board-delta-gate.ts). A `delta` run counts too: it publishes the same three
2143
- * judgment slots from the same accumulated state, so excluding it would leave the previous
2144
- * full run as the baseline forever and re-trigger a delta on every tick.
2145
- *
2146
- * Only `status='done'` full/delta rows count: an open or failed run has not
2147
- * discharged its interval. `watermark` is null when the run captured none
2148
- * (an owner-forced refresh), which makes the next scheduled tick enqueue
2149
- * rather than skip.
2150
- */
2151
- lastCompletedBoardFullRun() {
2152
- const row = this.db
2153
- .prepare(`SELECT json_extract(payload, '$.deltaWatermark') AS watermark, created_at, updated_at
2154
- FROM operator_tasks
2155
- WHERE kind = 'system' AND source_channel = ? AND status = 'done'
2156
- AND json_extract(payload, '$.mode') IN ('full', 'delta')
2157
- ORDER BY id DESC LIMIT 1`)
2158
- .get(`${exports.WORKORDER_CHANNEL_PREFIX}board`);
2159
- if (!row)
2160
- return null;
2161
- return {
2162
- watermark: typeof row.watermark === 'string' && row.watermark.length > 0 ? row.watermark : null,
2163
- createdAt: row.created_at,
2164
- completedAt: row.updated_at,
2165
- };
2166
- }
2167
- /**
2168
- * The newest COMPLETED wiki run - the baseline the wiki daily-continuity
2169
- * planner gates against (wiki-continuity.ts). Only `status='done'` rows count.
2170
- *
2171
- * `ownerDate`/`sourceWatermark` are read straight from the completed run's
2172
- * payload and are null for a LEGACY row (one enqueued before the continuity
2173
- * fields existed): the planner treats a null-field baseline as "no baseline"
2174
- * and re-runs from the owner day's start rather than fabricating a boundary.
2175
- */
2176
- lastCompletedWikiRun() {
2177
- const row = this.db
2178
- .prepare(`SELECT json_extract(payload, '$.ownerDate') AS owner_date,
2179
- json_extract(payload, '$.sourceWatermark') AS source_watermark,
2180
- json_extract(payload, '$.range.end_ms') AS covered_through_ms,
2181
- updated_at
2182
- FROM operator_tasks
2183
- WHERE kind = 'system' AND source_channel = ? AND status = 'done'
2184
- ORDER BY id DESC LIMIT 1`)
2185
- .get(`${exports.WORKORDER_CHANNEL_PREFIX}wiki`);
2186
- if (!row)
2187
- return null;
2188
- return {
2189
- ownerDate: typeof row.owner_date === 'string' && row.owner_date.length > 0 ? row.owner_date : null,
2190
- sourceWatermark: typeof row.source_watermark === 'string' && row.source_watermark.length > 0
2191
- ? row.source_watermark
2192
- : null,
2193
- // The prior run's range.end_ms - where the next same-day run resumes.
2194
- // Null for a legacy row with no range; never fabricated.
2195
- coveredThroughMs: typeof row.covered_through_ms === 'number' && Number.isFinite(row.covered_through_ms)
2196
- ? row.covered_through_ms
2197
- : null,
2198
- completedAt: row.updated_at,
2199
- };
2200
- }
2201
- /**
2202
- * Board-input term for the NATIVE owner task ledger - the pipeline slot's
2203
- * projection source. Reuses payloadHash(): it already digests exactly the
2204
- * owner-row fields the pipeline slot renders, so a status or assignee edit
2205
- * moves the term even within the same millisecond as the row's creation,
2206
- * which a MAX(updated_at) marker would miss. System workorder rows are
2207
- * excluded by that same query - they are pipeline plumbing, not board truth.
2208
- */
2209
- ownerTaskTerm() {
2210
- return `t:${this.payloadHash()}`;
2211
- }
2212
- insertWorkOrder(order, attempts) {
2213
- assertEnum(order.workKind, exports.WORKORDER_KINDS, 'workKind');
2214
- if (order.priority !== undefined) {
2215
- assertEnum(order.priority, exports.TASK_PRIORITIES, 'priority');
2216
- }
2217
- if (!order.idempotencyKey || order.idempotencyKey.trim() === '') {
2218
- throw new Error('enqueueWorkOrder: idempotencyKey must be non-empty');
2219
- }
2220
- const channel = `${exports.WORKORDER_CHANNEL_PREFIX}${order.workKind}`;
2221
- // Owner-event occurrences and scheduled six-hour promotion slots stay
2222
- // reserved after they COMPLETE. The former prevents post-enqueue/pre-ACK
2223
- // replay; the latter prevents daemon restarts from repeating an already
2224
- // discharged slot. Manual promotions use promotion:manual:<time> and do
2225
- // not enter this branch. 'failed' and 'cancelled' must NOT reserve either
2226
- // occurrence: those rows are dead and must remain retryable.
2227
- const durableOwnerEvent = order.idempotencyKey.startsWith('owner-event:');
2228
- const scheduledPromotionKeys = order.workKind === 'memory-curation'
2229
- ? scheduledPromotionReservationKeys(order.idempotencyKey)
2230
- : null;
2231
- const completedScheduledPromotion = scheduledPromotionKeys !== null;
2232
- const reservingStatuses = durableOwnerEvent || completedScheduledPromotion
2233
- ? "'pending','in_progress','done'"
2234
- : "'pending','in_progress'";
2235
- const reservationKeys = scheduledPromotionKeys ?? [order.idempotencyKey];
2236
- const reservationPlaceholders = reservationKeys.map(() => '?').join(',');
2237
- const open = this.db
2238
- .prepare(`SELECT * FROM operator_tasks
2239
- WHERE kind = 'system' AND source_channel = ?
2240
- AND source_event_id IN (${reservationPlaceholders})
2241
- AND status IN (${reservingStatuses})
2242
- ORDER BY id ASC LIMIT 1`)
2243
- .get(channel, ...reservationKeys);
2244
- if (open) {
2245
- return this.rowToWorkOrder(open);
2246
- }
2247
- if (!Number.isSafeInteger(attempts) || attempts < 1) {
2248
- throw new Error(`insertWorkOrder: attempts must be a positive integer, got: ${attempts}`);
2249
- }
2250
- const payload = JSON.stringify({ ...order.input, attempts });
2251
- const now = this.now();
2252
- const result = this.db
2253
- .prepare(`INSERT INTO operator_tasks
2254
- (title, status, priority, kind, payload, source_channel, source_event_id,
2255
- auto_created, confirmed, created_at, updated_at)
2256
- VALUES (?, 'pending', ?, 'system', ?, ?, ?, 1, 0, ?, ?)`)
2257
- .run(`workorder:${order.workKind}`, order.priority ?? 'normal', payload, channel, order.idempotencyKey, now, now);
2258
- return this.getWorkOrderById(Number(result.lastInsertRowid));
2259
- }
2260
- enqueueTemporalGeneration(input) {
2261
- this.validateTemporalGenerationInput(input);
2262
- const sourceChannelRef = this.temporalSourceIdentifierRef(input.sourceChannel);
2263
- const sourceEventIdRef = this.temporalSourceIdentifierRef(input.sourceEventId);
2264
- let result = null;
2265
- this.db.exec('BEGIN IMMEDIATE');
2266
- try {
2267
- const existing = this.getTemporalGeneration(input.generationKey);
2268
- if (existing) {
2269
- if (existing.taskId !== input.taskId ||
2270
- existing.temporalEpoch !== input.temporalEpoch ||
2271
- existing.occurrenceKey !== input.occurrenceKey ||
2272
- existing.checkAt !== input.checkAt) {
2273
- throw new Error(`temporal generation '${input.generationKey}' conflicts with its stored identity`);
2274
- }
2275
- if (existing.lastWorkOrderId === null) {
2276
- throw new Error(`temporal generation '${input.generationKey}' has no owning workorder attempt`);
2277
- }
2278
- const workOrder = this.getWorkOrderById(existing.lastWorkOrderId);
2279
- if (!workOrder) {
2280
- throw new Error(`temporal generation '${input.generationKey}' owns missing workorder ${existing.lastWorkOrderId}`);
2281
- }
2282
- this.assertTemporalPayloadMatches(workOrder, existing);
2283
- if (workOrder.payload.sourceChannel !== sourceChannelRef ||
2284
- workOrder.payload.sourceEventId !== sourceEventIdRef) {
2285
- throw new Error(`temporal generation '${input.generationKey}' conflicts with stored source identifiers`);
2286
- }
2287
- result = { generation: existing, workOrder, created: false };
2288
- }
2289
- else {
2290
- const task = this.getRowById(input.taskId);
2291
- if (!task || task.kind !== 'owner') {
2292
- throw new Error(`temporal generation: owner task ${input.taskId} does not exist`);
2293
- }
2294
- if (task.status === 'done' || task.status === 'cancelled') {
2295
- throw new Error(`temporal generation: task ${input.taskId} is closed`);
2296
- }
2297
- if (task.status === 'review' &&
2298
- (task.reviewStartedAt === null ||
2299
- !Number.isSafeInteger(task.reviewStartedAt) ||
2300
- typeof task.reviewAnchorEventId !== 'string' ||
2301
- task.reviewAnchorEventId.trim().length === 0)) {
2302
- throw new Error(`temporal generation: review task ${input.taskId} has no verified review anchor`);
2303
- }
2304
- const currentOccurrence = (0, task_temporal_js_1.occurrenceKeyForTask)(task);
2305
- if (task.temporalEpoch !== input.temporalEpoch ||
2306
- currentOccurrence !== input.occurrenceKey) {
2307
- throw new Error(`temporal generation: task occurrence no longer matches enqueue input`);
2308
- }
2309
- if (this.temporalSourceIdentifierRef(task.status === 'review'
2310
- ? (task.reviewAnchorSourceChannel ?? task.sourceChannel)
2311
- : task.sourceChannel) !== sourceChannelRef ||
2312
- this.temporalSourceIdentifierRef(task.status === 'review' && task.reviewAnchorEventId
2313
- ? task.reviewAnchorEventId
2314
- : task.sourceEventId) !== sourceEventIdRef) {
2315
- throw new Error(`temporal generation: source identifiers do not match owner task`);
2316
- }
2317
- const openCollision = this.db
2318
- .prepare(`SELECT id FROM operator_tasks
2319
- WHERE kind = 'system' AND source_channel = 'workorder:temporal'
2320
- AND source_event_id = ? AND status IN ('pending','in_progress')`)
2321
- .get(input.generationKey);
2322
- if (openCollision) {
2323
- throw new Error(`temporal generation '${input.generationKey}' has orphan open workorder ${openCollision.id}`);
2324
- }
2325
- const timestamp = this.now();
2326
- this.db
2327
- .prepare(`INSERT INTO operator_temporal_generations
2328
- (generation_key, task_id, temporal_epoch, occurrence_key, check_at,
2329
- disposition, created_at, updated_at)
2330
- VALUES (?, ?, ?, ?, ?, 'active', ?, ?)`)
2331
- .run(input.generationKey, input.taskId, input.temporalEpoch, input.occurrenceKey, input.checkAt, timestamp, timestamp);
2332
- const workOrder = this.insertWorkOrder({
2333
- workKind: 'temporal',
2334
- idempotencyKey: input.generationKey,
2335
- input: {
2336
- generationKey: input.generationKey,
2337
- taskId: input.taskId,
2338
- temporalEpoch: input.temporalEpoch,
2339
- occurrenceKey: input.occurrenceKey,
2340
- checkAt: input.checkAt,
2341
- sourceChannel: sourceChannelRef,
2342
- sourceEventId: sourceEventIdRef,
2343
- },
2344
- priority: input.priority ?? 'normal',
2345
- }, 1);
2346
- this.db
2347
- .prepare(`UPDATE operator_temporal_generations
2348
- SET last_workorder_id = ?, updated_at = ? WHERE generation_key = ?`)
2349
- .run(workOrder.id, timestamp, input.generationKey);
2350
- const generation = this.getTemporalGeneration(input.generationKey);
2351
- if (!generation) {
2352
- throw new Error(`temporal generation '${input.generationKey}' could not be read back`);
2353
- }
2354
- result = { generation, workOrder, created: true };
2355
- }
2356
- this.db.exec('COMMIT');
2357
- }
2358
- catch (error) {
2359
- this.db.exec('ROLLBACK');
2360
- throw error;
2361
- }
2362
- if (!result) {
2363
- throw new Error(`temporal generation '${input.generationKey}' produced no result`);
2364
- }
2365
- return result;
2366
- }
2367
- getTemporalGeneration(generationKey) {
2368
- const row = this.db
2369
- .prepare(`SELECT * FROM operator_temporal_generations WHERE generation_key = ?`)
2370
- .get(generationKey);
2371
- if (!row)
2372
- return null;
2373
- return {
2374
- generationKey: row.generation_key,
2375
- taskId: row.task_id,
2376
- temporalEpoch: row.temporal_epoch,
2377
- occurrenceKey: row.occurrence_key,
2378
- checkAt: row.check_at,
2379
- disposition: row.disposition,
2380
- lastWorkOrderId: row.last_workorder_id,
2381
- reason: row.reason,
2382
- createdAt: row.created_at,
2383
- updatedAt: row.updated_at,
2384
- };
2385
- }
2386
- loadTemporalWorkContext(attemptId) {
2387
- return this.loadTemporalWorkContextInternal(attemptId);
2388
- }
2389
- assertTemporalWorkContextActive(suppliedContext) {
2390
- const trustedContext = this.loadTemporalWorkContextInternal(suppliedContext.attemptId);
2391
- this.assertTemporalContextMatches(suppliedContext, trustedContext);
2392
- return trustedContext;
2393
- }
2394
- /**
2395
- * What this system changed, and what it changed it for.
2396
- *
2397
- * Reads live beside the writes because the effect ledger shares the tasks database on
2398
- * purpose. Exposed here rather than by handing out the connection: the ledger owns both
2399
- * halves, so a change and its account of itself cannot drift apart.
2400
- */
2401
- listChanges(query = {}) {
2402
- return (0, effects_js_1.listEffects)(this.db, query);
2403
- }
2404
- /** Owner rows created since `sinceMs` (the ledger stagnation probe's numerator). */
2405
- countOwnerTasksCreatedSince(sinceMs) {
2406
- const row = this.db
2407
- .prepare(`SELECT count(*) AS n FROM operator_tasks WHERE kind = 'owner' AND created_at >= ?`)
2408
- .get(sinceMs);
2409
- return Number(row?.n ?? 0);
2410
- }
2411
- /** Receipt for a run the host stopped on its token budget; target is the run id. */
2412
- recordBudgetStop(input) {
2413
- (0, effects_js_1.recordUnattributedChange)(this.db, {
2414
- runId: input.modelRunId,
2415
- channelId: null,
2416
- kind: 'run_budget_stop',
2417
- targetType: 'run',
2418
- targetId: input.modelRunId ?? `run:${this.now()}`,
2419
- payload: { budgetTokens: input.budgetTokens, runTokenBudget: input.runTokenBudget },
2420
- atMs: this.now(),
2421
- }, 'clock');
2422
- }
2423
- /** Receipt for a repair request filed by the self-check turn; target is the issue id. */
2424
- recordRepairRequest(input) {
2425
- const change = {
2426
- runId: input.runId,
2427
- channelId: null,
2428
- kind: 'repair_request',
2429
- targetType: 'issue',
2430
- targetId: input.issueId,
2431
- payload: { repairId: input.repairId },
2432
- atMs: this.now(),
2433
- };
2434
- const causes = (input.causeEventIds ?? []).filter(effects_js_1.isUsableCause);
2435
- if (causes.length > 0) {
2436
- (0, effects_js_1.recordEffect)(this.db, { ...change, sourceEventIds: causes });
2437
- }
2438
- else {
2439
- (0, effects_js_1.recordUnattributedChange)(this.db, change, 'clock');
2440
- }
2441
- }
2442
- /** Receipt for a deliverable file the owner can receive; target is the content hash. */
2443
- recordFileExport(input) {
2444
- const change = {
2445
- runId: input.runId,
2446
- channelId: input.channelId ?? null,
2447
- kind: 'file_export',
2448
- targetType: 'file',
2449
- targetId: input.sha256,
2450
- payload: input.payload,
2451
- atMs: this.now(),
2452
- };
2453
- const causes = (input.causeEventIds ?? []).filter(effects_js_1.isUsableCause);
2454
- if (causes.length > 0) {
2455
- (0, effects_js_1.recordEffect)(this.db, { ...change, sourceEventIds: causes });
2456
- }
2457
- else {
2458
- (0, effects_js_1.recordUnattributedChange)(this.db, change, 'owner_message');
2459
- }
2460
- }
2461
- /**
2462
- * Receipt for a memory write made inside a bounded run. Without it a crash between
2463
- * mama_save and the batch ACK re-runs the batch and saves the decision twice; with it
2464
- * the crash-recovery resolver (effectsCausedBy) sees the write and ACKs without a run.
2465
- * Unattributed when the run had no cause: the count of those stays visible.
2466
- */
2467
- recordMemoryWrite(input) {
2468
- const change = {
2469
- runId: input.runId,
2470
- channelId: input.channelId ?? null,
2471
- kind: 'memory_write',
2472
- targetType: 'memory',
2473
- targetId: input.memoryRef,
2474
- payload: input.payload,
2475
- atMs: this.now(),
2476
- };
2477
- const causes = (input.causeEventIds ?? []).filter(effects_js_1.isUsableCause);
2478
- if (causes.length > 0) {
2479
- (0, effects_js_1.recordEffect)(this.db, { ...change, sourceEventIds: causes });
2480
- }
2481
- else {
2482
- (0, effects_js_1.recordUnattributedChange)(this.db, change, 'owner_message');
2483
- }
2484
- }
2485
- /**
2486
- * Effect kinds this system recorded with ANY of the given events as cause.
2487
- * The owner-event crash-recovery receipt reads it: a ledger write that named
2488
- * the batch's events is a durable outcome even when the run died afterwards.
2489
- */
2490
- effectsCausedBy(eventIds, sinceMs = 0) {
2491
- const ids = [...new Set(eventIds.filter((id) => typeof id === 'string' && id.length > 0))];
2492
- if (ids.length === 0) {
2493
- return [];
2494
- }
2495
- const kinds = new Set();
2496
- // Chunked like the inbox's SEEN_CHUNK: a backfill batch must not hit SQLite's
2497
- // variable limit and abort the whole tick. Time-bounded to the batch: effects are
2498
- // never pruned, inbox dedupe is, so a re-delivered old event must not match its
2499
- // own year-old effect row and skip the model.
2500
- for (let offset = 0; offset < ids.length; offset += EFFECT_CAUSE_CHUNK) {
2501
- const chunk = ids.slice(offset, offset + EFFECT_CAUSE_CHUNK);
2502
- const rows = this.db
2503
- .prepare(`SELECT DISTINCT effect_kind FROM evidence_effects
2504
- WHERE cause_state = 'attributed'
2505
- AND created_at >= ?
2506
- AND EXISTS (
2507
- SELECT 1 FROM json_each(evidence_effects.source_event_ids_json)
2508
- WHERE json_each.value IN (${chunk.map(() => '?').join(', ')})
2509
- )`)
2510
- .all(sinceMs, ...chunk);
2511
- for (const row of rows)
2512
- kinds.add(row.effect_kind);
2513
- }
2514
- return [...kinds].sort();
2515
- }
2516
- /** Of what this system changed, how much rests on evidence. */
2517
- changeCoverage(sinceMs, targetType) {
2518
- return (0, effects_js_1.changeCoverage)(this.db, sinceMs, targetType);
2519
- }
2520
- getTemporalEffect(attemptId) {
2521
- const row = this.db
2522
- .prepare(`SELECT * FROM operator_temporal_effects WHERE workorder_attempt_id = ?`)
2523
- .get(attemptId);
2524
- if (!row)
2525
- return null;
2526
- const changedFields = JSON.parse(row.changed_fields);
2527
- if (!Array.isArray(changedFields) ||
2528
- !changedFields.every((field) => typeof field === 'string')) {
2529
- throw new Error(`temporal effect ${attemptId} has invalid changed_fields`);
2530
- }
2531
- if (!['resolved', 'final_no_update', 'deferred'].includes(row.outcome)) {
2532
- throw new Error(`temporal effect ${attemptId} has invalid outcome '${row.outcome}'`);
2533
- }
2534
- return {
2535
- workorderAttemptId: row.workorder_attempt_id,
2536
- taskId: row.task_id,
2537
- generationKey: row.generation_key,
2538
- occurrenceKey: row.occurrence_key,
2539
- outcome: row.outcome,
2540
- beforeRevision: row.before_revision,
2541
- afterRevision: row.after_revision,
2542
- changedFields,
2543
- reason: row.reason,
2544
- attestationVersion: row.attestation_version === 1 ? 1 : 0,
2545
- contextPacketId: row.context_packet_id ?? '',
2546
- contextPacketSha256: row.context_packet_sha256 ?? '',
2547
- packetCreatedAt: row.packet_created_at ?? null,
2548
- nextTemporalCheckAt: row.next_temporal_check_at,
2549
- createdAt: row.created_at,
2550
- };
2551
- }
2552
- /**
2553
- * Read and validate the durable state that decides a temporal attempt's
2554
- * terminal outcome. This intentionally does not require an active attempt:
2555
- * consumers must be able to arbitrate committed, superseded, and exhausted
2556
- * attempts after runner/auditor failures and daemon restarts.
2557
- */
2558
- inspectTemporalAttempt(attemptId) {
2559
- const workOrder = this.getWorkOrderById(attemptId);
2560
- if (!workOrder || workOrder.workKind !== 'temporal') {
2561
- throw new Error(`temporal attempt state: no temporal attempt ${attemptId}`);
2562
- }
2563
- const generationKey = this.requirePayloadString(workOrder.payload, 'generationKey', attemptId);
2564
- const generation = this.getTemporalGeneration(generationKey);
2565
- if (!generation) {
2566
- throw new Error(`temporal attempt state: generation '${generationKey}' is missing`);
2567
- }
2568
- this.assertTemporalPayloadMatches(workOrder, generation);
2569
- const receipt = this.getTemporalEffect(attemptId);
2570
- if (receipt) {
2571
- const receiptError = (0, temporal_effect_js_1.temporalReceiptInvariantError)(receipt, {
2572
- attemptId,
2573
- taskId: generation.taskId,
2574
- generationKey: generation.generationKey,
2575
- occurrenceKey: generation.occurrenceKey,
2576
- });
2577
- if (receiptError) {
2578
- throw new Error(`temporal attempt state: ${receiptError}`);
2579
- }
2580
- if (workOrder.status !== 'done' ||
2581
- generation.lastWorkOrderId !== attemptId ||
2582
- generation.disposition !== receipt.outcome) {
2583
- throw new Error(`temporal attempt state: receipt ${attemptId} is not atomically committed`);
2584
- }
2585
- const task = this.getById(generation.taskId);
2586
- if (!task || task.revision < receipt.afterRevision) {
2587
- throw new Error(`temporal attempt state: receipt ${attemptId} owner revision is invalid`);
2588
- }
2589
- if (receipt.outcome !== 'resolved') {
2590
- const scope = (0, temporal_effect_js_1.temporalNoUpdateScope)({
2591
- attemptId,
2592
- generationKey: generation.generationKey,
2593
- taskId: generation.taskId,
2594
- temporalEpoch: generation.temporalEpoch,
2595
- occurrenceKey: generation.occurrenceKey,
2596
- checkAt: generation.checkAt,
2597
- revision: receipt.beforeRevision,
2598
- sourceChannel: null,
2599
- sourceEventId: null,
2600
- });
2601
- const note = this.db
2602
- .prepare(`SELECT id FROM operator_no_update_notes
2603
- WHERE scope = ? AND reason = ? AND created_at = ? LIMIT 1`)
2604
- .get(scope, receipt.reason, receipt.createdAt);
2605
- if (!note) {
2606
- throw new Error(`temporal attempt state: exact-scope no-update note is missing`);
2607
- }
2608
- }
2609
- if (task.revision === receipt.afterRevision) {
2610
- if (task.lastTemporalAttemptId !== attemptId ||
2611
- task.lastTemporalCheckedAt !== receipt.createdAt) {
2612
- throw new Error(`temporal attempt state: owner attempt markers are invalid`);
2613
- }
2614
- if (receipt.outcome === 'resolved' || receipt.outcome === 'final_no_update') {
2615
- if (task.temporalReconciledOccurrenceKey !== generation.occurrenceKey ||
2616
- task.nextTemporalCheckAt !== null) {
2617
- throw new Error(`temporal attempt state: owner final markers are invalid`);
2618
- }
2619
- }
2620
- else if (task.nextTemporalCheckAt !== receipt.nextTemporalCheckAt) {
2621
- throw new Error(`temporal attempt state: owner deferred check is invalid`);
2622
- }
2623
- }
2624
- }
2625
- else if (workOrder.status === 'done') {
2626
- throw new Error(`temporal attempt state: done attempt ${attemptId} has no receipt`);
2627
- }
2628
- if (workOrder.status === 'in_progress') {
2629
- if (receipt ||
2630
- generation.disposition !== 'active' ||
2631
- generation.lastWorkOrderId !== attemptId) {
2632
- throw new Error(`temporal attempt state: active attempt ${attemptId} lost ownership`);
2633
- }
2634
- }
2635
- if (workOrder.status === 'cancelled' &&
2636
- generation.disposition !== 'superseded' &&
2637
- (generation.disposition !== 'active' || generation.lastWorkOrderId !== attemptId)) {
2638
- throw new Error(`temporal attempt state: cancelled attempt ${attemptId} has invalid ownership`);
2639
- }
2640
- if (workOrder.status === 'failed' &&
2641
- generation.disposition === 'active' &&
2642
- generation.lastWorkOrderId !== attemptId) {
2643
- const replacement = generation.lastWorkOrderId === null
2644
- ? null
2645
- : this.getWorkOrderById(generation.lastWorkOrderId);
2646
- if (!replacement ||
2647
- replacement.workKind !== 'temporal' ||
2648
- (replacement.status !== 'pending' && replacement.status !== 'in_progress')) {
2649
- throw new Error(`temporal attempt state: retry replacement is missing or terminal`);
2650
- }
2651
- this.assertTemporalPayloadMatches(replacement, generation);
2652
- }
2653
- if (generation.disposition === 'superseded' &&
2654
- workOrder.status !== 'cancelled' &&
2655
- workOrder.status !== 'failed') {
2656
- throw new Error(`temporal attempt state: superseded attempt ${attemptId} is still open`);
2657
- }
2658
- return { workOrder, generation, receipt };
2659
- }
2660
- applyTemporalEffect(suppliedContext, input, evidence, now = this.now()) {
2661
- if (!Number.isSafeInteger(now)) {
2662
- throw new Error('temporal effect time must be an epoch millisecond integer');
2663
- }
2664
- this.validateTemporalEffectInput(input, now);
2665
- if (!evidence ||
2666
- typeof evidence.contextPacketId !== 'string' ||
2667
- evidence.contextPacketId.trim().length < 1 ||
2668
- evidence.contextPacketId.length > 300 ||
2669
- !/^[a-f0-9]{64}$/.test(evidence.contextPacketSha256)) {
2670
- throw new Error('temporal effect requires a valid host evidence attestation');
2671
- }
2672
- let receipt = null;
2673
- const previousGeneration = this.onOwnerTaskChangeCommitted ? this.readGeneration() : null;
2674
- this.db.exec('BEGIN IMMEDIATE');
2675
- try {
2676
- const context = this.assertTemporalWorkContextActive(suppliedContext);
2677
- if (input.expected_revision !== context.revision) {
2678
- throw new Error(`temporal effect revision mismatch: expected ${input.expected_revision}, current ${context.revision}`);
2679
- }
2680
- const existing = this.db
2681
- .prepare(`SELECT * FROM operator_tasks WHERE id = ?`)
2682
- .get(context.taskId);
2683
- if (!existing || existing.kind !== 'owner' || existing.revision !== context.revision) {
2684
- throw new Error(`temporal effect owner task no longer matches trusted context`);
2685
- }
2686
- const next = {
2687
- status: existing.status,
2688
- deadline: existing.deadline,
2689
- due_at: existing.due_at,
2690
- deadline_offset_minutes: existing.deadline_offset_minutes,
2691
- temporal_epoch: existing.temporal_epoch,
2692
- temporal_reconciled_occurrence_key: existing.temporal_reconciled_occurrence_key,
2693
- last_temporal_checked_at: now,
2694
- next_temporal_check_at: null,
2695
- last_temporal_attempt_id: context.attemptId,
2696
- review_started_at: existing.review_started_at,
2697
- review_anchor_event_id: existing.review_anchor_event_id,
2698
- review_anchor_source_channel: existing.review_anchor_source_channel,
2699
- };
2700
- const auditParts = [`reason=${input.reason.trim()}`];
2701
- if (input.outcome === 'final_no_update') {
2702
- auditParts.push(`evidence=${input.evidence_summary.trim()}`);
2703
- }
2704
- const receiptReason = this.temporalAuditText(`effect-${input.outcome}`, auditParts);
2705
- let nextCheck = null;
2706
- let rescheduled = false;
2707
- if (input.outcome === 'resolved') {
2708
- if (input.status !== undefined)
2709
- next.status = input.status;
2710
- if (existing.status === 'review' && next.status !== 'review') {
2711
- // Leaving verified review through the Temporal path: the submission
2712
- // anchor and its derived 14-day due time do not survive the exit, exactly
2713
- // as the task_update path clears them. A later reopen re-verifies.
2714
- next.review_started_at = null;
2715
- next.review_anchor_event_id = null;
2716
- next.review_anchor_source_channel = null;
2717
- if (existing.review_started_at !== null &&
2718
- !Object.prototype.hasOwnProperty.call(input, 'due_at')) {
2719
- next.due_at = null;
2720
- next.deadline = null;
2721
- next.deadline_offset_minutes = null;
2722
- }
2723
- }
2724
- if (Object.prototype.hasOwnProperty.call(input, 'due_at')) {
2725
- if (input.due_at === null) {
2726
- next.due_at = null;
2727
- }
2728
- else if (input.due_at !== undefined) {
2729
- const exactDue = (0, task_temporal_js_1.parseExactDueAt)(input.due_at);
2730
- if (exactDue.dueAt !== existing.due_at) {
2731
- next.due_at = exactDue.dueAt;
2732
- next.deadline = exactDue.deadline;
2733
- next.deadline_offset_minutes = exactDue.offsetMinutes;
2734
- }
2735
- }
2736
- }
2737
- const resolvedEffectChanged = next.status !== existing.status || next.due_at !== existing.due_at;
2738
- if (!resolvedEffectChanged) {
2739
- throw new Error('temporal resolved outcome requires an actual status or due_at change');
2740
- }
2741
- rescheduled = next.due_at !== existing.due_at;
2742
- if (rescheduled)
2743
- next.temporal_epoch = existing.temporal_epoch + 1;
2744
- next.temporal_reconciled_occurrence_key = context.occurrenceKey;
2745
- }
2746
- else if (input.outcome === 'final_no_update') {
2747
- next.temporal_reconciled_occurrence_key = context.occurrenceKey;
2748
- }
2749
- else {
2750
- nextCheck = (0, task_temporal_js_1.parseExactDueAt)(input.next_temporal_check_at).dueAt;
2751
- next.next_temporal_check_at = nextCheck;
2752
- }
2753
- const persistedColumns = [
2754
- 'status',
2755
- 'deadline',
2756
- 'due_at',
2757
- 'deadline_offset_minutes',
2758
- 'temporal_epoch',
2759
- 'temporal_reconciled_occurrence_key',
2760
- 'last_temporal_checked_at',
2761
- 'next_temporal_check_at',
2762
- 'last_temporal_attempt_id',
2763
- 'review_started_at',
2764
- 'review_anchor_event_id',
2765
- 'review_anchor_source_channel',
2766
- ];
2767
- const changedFields = persistedColumns.filter((column) => next[column] !== existing[column]);
2768
- const afterRevision = existing.revision + 1;
2769
- const sets = changedFields.map((column) => `${column} = ?`);
2770
- const values = changedFields.map((column) => next[column]);
2771
- sets.push('revision = ?', 'updated_at = ?');
2772
- values.push(afterRevision, now);
2773
- const ownerUpdate = this.db
2774
- .prepare(`UPDATE operator_tasks SET ${sets.join(', ')} WHERE id = ? AND kind = 'owner' AND revision = ?`)
2775
- .run(...values, context.taskId, existing.revision);
2776
- if (ownerUpdate.changes !== 1) {
2777
- throw new Error(`temporal effect lost owner task revision for task ${context.taskId}`);
2778
- }
2779
- // The same ledger as every other owner-task change. This is the canonical case -
2780
- // a scheduled run closing a work item - and leaving it out would have meant the
2781
- // effect ledger could not see the one change type it was built to account for,
2782
- // with its receipt filed in a second table nobody joins against.
2783
- //
2784
- // Unattributed, and correctly so: a temporal check fires because a clock advanced,
2785
- // not because an event arrived. Its evidence is the context packet, which today
2786
- // carries recalled memories and zero connector events - measured, not assumed.
2787
- // Recording it as attributed would name a cause that does not exist.
2788
- this.recordTaskChange({
2789
- kind: 'task_update',
2790
- taskId: context.taskId,
2791
- origin: { runId: null, causeKind: 'clock' },
2792
- channel: existing.source_channel,
2793
- payload: {
2794
- revision: afterRevision,
2795
- outcome: input.outcome,
2796
- changed: Object.fromEntries(changedFields.map((column) => [column, next[column]])),
2797
- },
2798
- atMs: now,
2799
- });
2800
- if (rescheduled) {
2801
- this.supersedeTemporalGenerationsInTransaction(context.taskId, Number(next.temporal_epoch), context.generationKey, now);
2802
- }
2803
- const generationUpdate = this.db
2804
- .prepare(`UPDATE operator_temporal_generations
2805
- SET disposition = ?, reason = ?, updated_at = ?
2806
- WHERE generation_key = ? AND disposition = 'active' AND last_workorder_id = ?`)
2807
- .run(input.outcome, receiptReason, now, context.generationKey, context.attemptId);
2808
- if (generationUpdate.changes !== 1) {
2809
- throw new Error(`temporal effect lost generation ownership for attempt ${context.attemptId}`);
2810
- }
2811
- if (input.outcome === 'resolved' && (next.status === 'done' || next.status === 'cancelled')) {
2812
- this.supersedeAllActiveTemporalGenerationsInTransaction(context.taskId, now);
2813
- }
2814
- if (input.outcome !== 'resolved') {
2815
- this.insertNoUpdateNote((0, temporal_effect_js_1.temporalNoUpdateScope)(context), receiptReason, now);
2816
- }
2817
- this.db
2818
- .prepare(`INSERT INTO operator_temporal_effects
2819
- (workorder_attempt_id, task_id, generation_key, occurrence_key, outcome,
2820
- before_revision, after_revision, changed_fields, reason,
2821
- attestation_version, context_packet_id, context_packet_sha256,
2822
- packet_created_at, next_temporal_check_at, created_at)
2823
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 1, ?, ?, ?, ?, ?)`)
2824
- .run(context.attemptId, context.taskId, context.generationKey, context.occurrenceKey, input.outcome, existing.revision, afterRevision, JSON.stringify(changedFields), receiptReason, evidence.contextPacketId, evidence.contextPacketSha256, evidence.packetCreatedAt, nextCheck, now);
2825
- const workOrderUpdate = this.db
2826
- .prepare(`UPDATE operator_tasks SET status = 'done', latest_event = ?, updated_at = ?
2827
- WHERE id = ? AND kind = 'system' AND status = 'in_progress'
2828
- AND source_channel = 'workorder:temporal' AND source_event_id = ?`)
2829
- .run(receiptReason, now, context.attemptId, context.generationKey);
2830
- if (workOrderUpdate.changes !== 1) {
2831
- throw new Error(`temporal effect lost active workorder ${context.attemptId}`);
2832
- }
2833
- receipt = this.getTemporalEffect(context.attemptId);
2834
- if (!receipt)
2835
- throw new Error(`temporal effect receipt could not be read back`);
2836
- const receiptError = (0, temporal_effect_js_1.temporalReceiptInvariantError)(receipt, {
2837
- attemptId: context.attemptId,
2838
- taskId: context.taskId,
2839
- generationKey: context.generationKey,
2840
- occurrenceKey: context.occurrenceKey,
2841
- beforeRevision: context.revision,
2842
- });
2843
- if (receiptError) {
2844
- throw new Error(`temporal effect receipt invariant failed: ${receiptError}`);
2845
- }
2846
- this.db.exec('COMMIT');
2847
- }
2848
- catch (error) {
2849
- this.db.exec('ROLLBACK');
2850
- throw error;
2851
- }
2852
- this.notifyOwnerTaskCommit(previousGeneration);
2853
- if (!receipt)
2854
- throw new Error(`temporal effect produced no receipt`);
2855
- return receipt;
2856
- }
2857
- requeueTemporalWorkOrder(attemptId, reason) {
2858
- this.assertTemporalReason(reason);
2859
- const auditReason = this.temporalAuditText('worker-failure', [`failure=${reason}`]);
2860
- let replacement = null;
2861
- this.db.exec('BEGIN IMMEDIATE');
2862
- try {
2863
- const context = this.loadTemporalWorkContextInternal(attemptId);
2864
- const workOrder = this.getWorkOrderById(attemptId);
2865
- if (workOrder.payload.attempts >= exports.TEMPORAL_WORKORDER_MAX_ATTEMPTS) {
2866
- throw new Error(`temporal retry budget exhausted for attempt ${attemptId}`);
2867
- }
2868
- replacement = this.requeueTemporalWorkOrderInTransaction(context, workOrder, auditReason);
2869
- this.db.exec('COMMIT');
2870
- }
2871
- catch (error) {
2872
- this.db.exec('ROLLBACK');
2873
- throw error;
2874
- }
2875
- if (!replacement)
2876
- throw new Error(`temporal retry for attempt ${attemptId} produced no row`);
2877
- return replacement;
2878
- }
2879
- exhaustTemporalWorkOrder(attemptId, reason) {
2880
- this.assertTemporalReason(reason);
2881
- const auditReason = this.temporalAuditText('worker-failure', [`failure=${reason}`]);
2882
- this.db.exec('BEGIN IMMEDIATE');
2883
- try {
2884
- const context = this.loadTemporalWorkContextInternal(attemptId);
2885
- const workOrder = this.getWorkOrderById(attemptId);
2886
- if (workOrder.payload.attempts !== exports.TEMPORAL_WORKORDER_MAX_ATTEMPTS) {
2887
- throw new Error(`temporal exhaustion requires attempt ${exports.TEMPORAL_WORKORDER_MAX_ATTEMPTS}, got ${workOrder.payload.attempts}`);
2888
- }
2889
- this.exhaustTemporalWorkOrderInTransaction(context, auditReason);
2890
- this.db.exec('COMMIT');
2891
- }
2892
- catch (error) {
2893
- this.db.exec('ROLLBACK');
2894
- throw error;
2895
- }
2896
- }
2897
- failTemporalWorkOrder(attemptId, reason, allowRetry = true) {
2898
- this.assertTemporalReason(reason);
2899
- const auditReason = this.temporalAuditText('worker-failure', [`failure=${reason}`]);
2900
- let result = null;
2901
- this.db.exec('BEGIN IMMEDIATE');
2902
- try {
2903
- const repairedAttempt = this.repairClosedTemporalOwnershipInTransaction(attemptId);
2904
- if (repairedAttempt !== null) {
2905
- result = {
2906
- disposition: 'superseded',
2907
- attempt: repairedAttempt,
2908
- maxAttempts: exports.TEMPORAL_WORKORDER_MAX_ATTEMPTS,
2909
- };
2910
- this.db.exec('COMMIT');
2911
- return result;
2912
- }
2913
- const context = this.loadTemporalWorkContextInternal(attemptId);
2914
- const workOrder = this.getWorkOrderById(attemptId);
2915
- const attempt = workOrder.payload.attempts;
2916
- if (!allowRetry) {
2917
- this.exhaustTemporalWorkOrderInTransaction(context, auditReason);
2918
- result = {
2919
- disposition: 'exhausted',
2920
- attempt,
2921
- maxAttempts: exports.TEMPORAL_WORKORDER_MAX_ATTEMPTS,
2922
- retrySuppressed: true,
2923
- };
2924
- }
2925
- else if (attempt < exports.TEMPORAL_WORKORDER_MAX_ATTEMPTS) {
2926
- result = {
2927
- disposition: 'requeued',
2928
- replacement: this.requeueTemporalWorkOrderInTransaction(context, workOrder, auditReason),
2929
- attempt,
2930
- maxAttempts: exports.TEMPORAL_WORKORDER_MAX_ATTEMPTS,
2931
- };
2932
- }
2933
- else if (attempt === exports.TEMPORAL_WORKORDER_MAX_ATTEMPTS) {
2934
- this.exhaustTemporalWorkOrderInTransaction(context, auditReason);
2935
- result = {
2936
- disposition: 'exhausted',
2937
- attempt,
2938
- maxAttempts: exports.TEMPORAL_WORKORDER_MAX_ATTEMPTS,
2939
- };
2940
- }
2941
- else {
2942
- throw new Error(`temporal attempt ${attemptId} exceeds retry budget: ${attempt}`);
2943
- }
2944
- this.db.exec('COMMIT');
2945
- }
2946
- catch (error) {
2947
- this.db.exec('ROLLBACK');
2948
- throw error;
2949
- }
2950
- if (!result)
2951
- throw new Error(`temporal failure for attempt ${attemptId} produced no result`);
2952
- return result;
2953
- }
2954
- repairClosedTemporalOwnershipInTransaction(attemptId) {
2955
- const workOrder = this.getWorkOrderById(attemptId);
2956
- if (!workOrder || workOrder.workKind !== 'temporal') {
2957
- return null;
2958
- }
2959
- const generationKey = this.requirePayloadString(workOrder.payload, 'generationKey', attemptId);
2960
- const generation = this.getTemporalGeneration(generationKey);
2961
- if (!generation || generation.lastWorkOrderId !== attemptId) {
2962
- return null;
2963
- }
2964
- const task = this.getById(generation.taskId);
2965
- if (!task || (task.status !== 'done' && task.status !== 'cancelled')) {
2966
- return null;
2967
- }
2968
- const openAttempt = workOrder.status === 'pending' || workOrder.status === 'in_progress';
2969
- if (generation.disposition === 'active' && openAttempt) {
2970
- this.supersedeAllActiveTemporalGenerationsInTransaction(task.id);
2971
- }
2972
- else if (generation.disposition !== 'superseded' || workOrder.status !== 'cancelled') {
2973
- return null;
2974
- }
2975
- return workOrder.payload.attempts;
2976
- }
2977
- /** Repair pre-fix databases where a terminal owner still has active temporal ownership. */
2978
- repairClosedTemporalGenerations() {
2979
- let repaired = 0;
2980
- this.db.exec('BEGIN IMMEDIATE');
2981
- try {
2982
- const rows = this.db
2983
- .prepare(`SELECT DISTINCT generation.task_id
2984
- FROM operator_temporal_generations generation
2985
- JOIN operator_tasks owner ON owner.id = generation.task_id
2986
- WHERE generation.disposition = 'active'
2987
- AND owner.kind = 'owner'
2988
- AND owner.status IN ('done','cancelled')
2989
- ORDER BY generation.task_id ASC`)
2990
- .all();
2991
- const updatedAt = this.now();
2992
- for (const row of rows) {
2993
- this.supersedeAllActiveTemporalGenerationsInTransaction(row.task_id, updatedAt);
2994
- }
2995
- repaired = rows.length;
2996
- this.db.exec('COMMIT');
2997
- }
2998
- catch (error) {
2999
- this.db.exec('ROLLBACK');
3000
- throw error;
3001
- }
3002
- return repaired;
3003
- }
3004
- /** Control-plane pause: cancel open attempts but keep generations resumable. */
3005
- pauseActiveTemporalWork(reason) {
3006
- this.assertTemporalReason(reason);
3007
- let changed = 0;
3008
- this.db.exec('BEGIN IMMEDIATE');
3009
- try {
3010
- const result = this.db
3011
- .prepare(`UPDATE operator_tasks
3012
- SET status = 'cancelled', latest_event = ?, updated_at = ?
3013
- WHERE kind = 'system' AND source_channel = 'workorder:temporal'
3014
- AND status IN ('pending','in_progress')`)
3015
- .run(reason, this.now());
3016
- changed = result.changes;
3017
- this.db.exec('COMMIT');
3018
- }
3019
- catch (error) {
3020
- this.db.exec('ROLLBACK');
3021
- throw error;
3022
- }
3023
- return changed;
3024
- }
3025
- /** Resume paused active generations without spending another model attempt. */
3026
- resumePausedTemporalWork() {
3027
- const resumed = [];
3028
- this.db.exec('BEGIN IMMEDIATE');
3029
- try {
3030
- const rows = this.db
3031
- .prepare(`SELECT generation_key, last_workorder_id
3032
- FROM operator_temporal_generations generation
3033
- WHERE disposition = 'active' AND last_workorder_id IS NOT NULL
3034
- AND NOT EXISTS (
3035
- SELECT 1 FROM operator_tasks open_attempt
3036
- WHERE open_attempt.kind = 'system'
3037
- AND open_attempt.source_channel = 'workorder:temporal'
3038
- AND open_attempt.source_event_id = generation.generation_key
3039
- AND open_attempt.status IN ('pending','in_progress')
3040
- )
3041
- ORDER BY generation_key ASC`)
3042
- .all();
3043
- for (const row of rows) {
3044
- const generation = this.getTemporalGeneration(row.generation_key);
3045
- const previous = this.getWorkOrderById(row.last_workorder_id);
3046
- if (!generation || !previous || previous.status !== 'cancelled') {
3047
- throw new Error(`temporal resume: active generation '${row.generation_key}' has no paused attempt`);
3048
- }
3049
- this.assertTemporalPayloadMatches(previous, generation);
3050
- const { attempts, ...payload } = previous.payload;
3051
- const replacement = this.insertWorkOrder({
3052
- workKind: 'temporal',
3053
- idempotencyKey: generation.generationKey,
3054
- input: payload,
3055
- priority: previous.priority,
3056
- }, attempts);
3057
- const ownership = this.db
3058
- .prepare(`UPDATE operator_temporal_generations
3059
- SET last_workorder_id = ?, updated_at = ?
3060
- WHERE generation_key = ? AND disposition = 'active' AND last_workorder_id = ?`)
3061
- .run(replacement.id, this.now(), generation.generationKey, previous.id);
3062
- if (ownership.changes !== 1) {
3063
- throw new Error(`temporal resume lost ownership for generation '${generation.generationKey}'`);
3064
- }
3065
- resumed.push(replacement);
3066
- }
3067
- this.db.exec('COMMIT');
3068
- }
3069
- catch (error) {
3070
- this.db.exec('ROLLBACK');
3071
- throw error;
3072
- }
3073
- return resumed;
3074
- }
3075
- requeueTemporalWorkOrderInTransaction(context, workOrder, reason) {
3076
- this.transitionWorkOrder(workOrder.id, 'failed', reason);
3077
- const payload = publisherPayloadOfStoredWorkOrder(workOrder.payload);
3078
- const replacement = this.insertWorkOrder({
3079
- workKind: 'temporal',
3080
- idempotencyKey: context.generationKey,
3081
- input: payload,
3082
- priority: workOrder.priority,
3083
- }, workOrder.payload.attempts + 1);
3084
- const ownership = this.db
3085
- .prepare(`UPDATE operator_temporal_generations
3086
- SET last_workorder_id = ?, updated_at = ?
3087
- WHERE generation_key = ? AND disposition = 'active' AND last_workorder_id = ?`)
3088
- .run(replacement.id, this.now(), context.generationKey, workOrder.id);
3089
- if (ownership.changes !== 1) {
3090
- throw new Error(`temporal retry lost generation ownership for attempt ${workOrder.id}`);
3091
- }
3092
- return replacement;
3093
- }
3094
- exhaustTemporalWorkOrderInTransaction(context, reason) {
3095
- this.transitionWorkOrder(context.attemptId, 'failed', reason);
3096
- const update = this.db
3097
- .prepare(`UPDATE operator_temporal_generations
3098
- SET disposition = 'exhausted', reason = ?, updated_at = ?
3099
- WHERE generation_key = ? AND disposition = 'active' AND last_workorder_id = ?`)
3100
- .run(reason, this.now(), context.generationKey, context.attemptId);
3101
- if (update.changes !== 1) {
3102
- throw new Error(`temporal exhaustion lost ownership for attempt ${context.attemptId}`);
3103
- }
3104
- }
3105
- supersedeTemporalGenerations(taskId, currentEpoch, excludeGenerationKey) {
3106
- this.db.exec('BEGIN IMMEDIATE');
3107
- try {
3108
- this.supersedeTemporalGenerationsInTransaction(taskId, currentEpoch, excludeGenerationKey);
3109
- this.db.exec('COMMIT');
3110
- }
3111
- catch (error) {
3112
- this.db.exec('ROLLBACK');
3113
- throw error;
3114
- }
3115
- }
3116
- validateTemporalGenerationInput(input) {
3117
- const bounded = (value, field, max) => {
3118
- if (value.length < 1 || value.length > max) {
3119
- throw new Error(`temporal generation: ${field} must contain 1-${max} characters`);
3120
- }
3121
- };
3122
- bounded(input.generationKey, 'generationKey', 500);
3123
- bounded(input.occurrenceKey, 'occurrenceKey', 300);
3124
- if (!Number.isSafeInteger(input.taskId) || input.taskId < 1) {
3125
- throw new Error(`temporal generation: taskId must be a positive integer`);
3126
- }
3127
- if (!Number.isSafeInteger(input.temporalEpoch) || input.temporalEpoch < 0) {
3128
- throw new Error(`temporal generation: temporalEpoch must be a non-negative integer`);
3129
- }
3130
- if (!Number.isSafeInteger(input.checkAt)) {
3131
- throw new Error(`temporal generation: checkAt must be an epoch millisecond integer`);
3132
- }
3133
- const canonicalKey = (0, task_temporal_js_1.temporalGenerationKey)(input.taskId, input.occurrenceKey, input.checkAt);
3134
- if (input.generationKey !== canonicalKey) {
3135
- throw new Error(`temporal generation: generationKey must equal canonical identity key`);
3136
- }
3137
- for (const [field, value] of [
3138
- ['sourceChannel', input.sourceChannel],
3139
- ['sourceEventId', input.sourceEventId],
3140
- ]) {
3141
- if (value !== null && typeof value !== 'string') {
3142
- throw new Error(`temporal generation: ${field} must be a string or null`);
3143
- }
3144
- }
3145
- if (input.priority !== undefined)
3146
- assertEnum(input.priority, exports.TASK_PRIORITIES, 'priority');
3147
- }
3148
- /**
3149
- * Workorder payloads carry only bounded references to owner-source identifiers.
3150
- * Owner rows created by older releases may contain empty or arbitrarily long
3151
- * connector identifiers; hashing preserves exact identity without making one
3152
- * legacy row able to abort temporal boot or inflate every retry payload.
3153
- */
3154
- temporalSourceIdentifierRef(value) {
3155
- if (value === null)
3156
- return null;
3157
- return `sha256:${(0, node_crypto_1.createHash)('sha256').update(value).digest('hex')}`;
3158
- }
3159
- validateTemporalEffectInput(input, now) {
3160
- if (!input || typeof input !== 'object' || Array.isArray(input)) {
3161
- throw new Error('temporal effect input must be an object');
3162
- }
3163
- if (!Number.isSafeInteger(input.expected_revision) || input.expected_revision < 0) {
3164
- throw new Error('temporal effect expected_revision must be a non-negative integer');
3165
- }
3166
- this.assertTemporalReason(input.reason);
3167
- const baseKeys = ['expected_revision', 'outcome', 'reason'];
3168
- let allowedKeys;
3169
- if (input.outcome === 'resolved') {
3170
- allowedKeys = [...baseKeys, 'status', 'due_at'];
3171
- if (input.status !== undefined) {
3172
- assertEnum(input.status, exports.TASK_STATUSES, 'temporal effect status');
3173
- if (String(input.status) === 'failed') {
3174
- throw new Error(`temporal effect: 'failed' is a system-only status`);
3175
- }
3176
- }
3177
- if (input.due_at !== undefined && input.due_at !== null)
3178
- (0, task_temporal_js_1.parseExactDueAt)(input.due_at);
3179
- }
3180
- else if (input.outcome === 'final_no_update') {
3181
- allowedKeys = [...baseKeys, 'evidence_summary'];
3182
- if (typeof input.evidence_summary !== 'string' ||
3183
- input.evidence_summary.trim().length < 1 ||
3184
- input.evidence_summary.length > 1_000) {
3185
- throw new Error('temporal effect evidence_summary must contain 1-1000 characters');
3186
- }
3187
- }
3188
- else if (input.outcome === 'deferred') {
3189
- allowedKeys = [...baseKeys, 'next_temporal_check_at'];
3190
- if (typeof input.next_temporal_check_at !== 'string') {
3191
- throw new Error('temporal effect next_temporal_check_at must be RFC 3339');
3192
- }
3193
- const nextCheck = (0, task_temporal_js_1.parseExactDueAt)(input.next_temporal_check_at).dueAt;
3194
- if (nextCheck <= now) {
3195
- throw new Error('temporal effect deferred check must be strictly in the future');
3196
- }
3197
- }
3198
- else {
3199
- throw new Error(`temporal effect outcome is unknown or forbidden`);
3200
- }
3201
- const unknownKeys = Object.keys(input).filter((key) => !allowedKeys.includes(key));
3202
- if (unknownKeys.length > 0) {
3203
- throw new Error(`temporal effect contains unknown or forbidden fields: ${unknownKeys.join(', ')}`);
3204
- }
3205
- }
3206
- assertTemporalContextMatches(supplied, trusted) {
3207
- const fields = [
3208
- 'attemptId',
3209
- 'generationKey',
3210
- 'taskId',
3211
- 'temporalEpoch',
3212
- 'occurrenceKey',
3213
- 'checkAt',
3214
- 'revision',
3215
- 'sourceChannel',
3216
- 'sourceEventId',
3217
- ];
3218
- if (fields.some((field) => supplied[field] !== trusted[field])) {
3219
- throw new Error('temporal effect supplied context does not match trusted host context');
3220
- }
3221
- }
3222
- loadTemporalWorkContextInternal(attemptId) {
3223
- const workOrder = this.getWorkOrderById(attemptId);
3224
- if (!workOrder || workOrder.workKind !== 'temporal') {
3225
- throw new Error(`temporal context: no temporal attempt ${attemptId}`);
3226
- }
3227
- if (workOrder.status !== 'in_progress') {
3228
- throw new Error(`temporal context: attempt ${attemptId} is '${workOrder.status}', expected active attempt`);
3229
- }
3230
- const payload = workOrder.payload;
3231
- const generationKey = this.requirePayloadString(payload, 'generationKey', attemptId);
3232
- const taskId = this.requirePayloadInteger(payload, 'taskId', attemptId, 1);
3233
- const temporalEpoch = this.requirePayloadInteger(payload, 'temporalEpoch', attemptId, 0);
3234
- const occurrenceKey = this.requirePayloadString(payload, 'occurrenceKey', attemptId);
3235
- const checkAt = this.requirePayloadInteger(payload, 'checkAt', attemptId);
3236
- const sourceChannel = this.requireNullablePayloadString(payload, 'sourceChannel', attemptId);
3237
- const sourceEventId = this.requireNullablePayloadString(payload, 'sourceEventId', attemptId);
3238
- const generation = this.getTemporalGeneration(generationKey);
3239
- if (!generation || generation.disposition !== 'active') {
3240
- throw new Error(`temporal context: generation '${generationKey}' is not active`);
3241
- }
3242
- if (generation.lastWorkOrderId !== attemptId) {
3243
- throw new Error(`temporal context: attempt ${attemptId} no longer owns generation`);
3244
- }
3245
- this.assertTemporalPayloadMatches(workOrder, generation);
3246
- const task = this.getRowById(taskId);
3247
- if (!task || task.kind !== 'owner') {
3248
- throw new Error(`temporal context: owner task ${taskId} does not exist`);
3249
- }
3250
- if (task.status === 'done' || task.status === 'cancelled') {
3251
- throw new Error(`temporal context: owner task ${taskId} is closed`);
3252
- }
3253
- if (task.status === 'review' &&
3254
- (task.reviewStartedAt === null ||
3255
- !Number.isSafeInteger(task.reviewStartedAt) ||
3256
- typeof task.reviewAnchorEventId !== 'string' ||
3257
- task.reviewAnchorEventId.trim().length === 0)) {
3258
- throw new Error(`temporal context: review task ${taskId} has no verified review anchor`);
3259
- }
3260
- if (task.temporalEpoch !== temporalEpoch ||
3261
- (0, task_temporal_js_1.occurrenceKeyForTask)(task) !== occurrenceKey ||
3262
- this.temporalSourceIdentifierRef(task.status === 'review'
3263
- ? (task.reviewAnchorSourceChannel ?? task.sourceChannel)
3264
- : task.sourceChannel) !== sourceChannel ||
3265
- this.temporalSourceIdentifierRef(task.status === 'review' && task.reviewAnchorEventId
3266
- ? task.reviewAnchorEventId
3267
- : task.sourceEventId) !== sourceEventId ||
3268
- generation.taskId !== taskId ||
3269
- generation.temporalEpoch !== temporalEpoch ||
3270
- generation.occurrenceKey !== occurrenceKey ||
3271
- generation.checkAt !== checkAt) {
3272
- throw new Error(`temporal context: attempt ${attemptId} payload no longer matches ownership`);
3273
- }
3274
- return {
3275
- attemptId,
3276
- generationKey,
3277
- taskId,
3278
- temporalEpoch,
3279
- occurrenceKey,
3280
- checkAt,
3281
- revision: task.revision,
3282
- sourceChannel,
3283
- sourceEventId,
3284
- };
3285
- }
3286
- assertTemporalPayloadMatches(workOrder, generation) {
3287
- const payload = workOrder.payload;
3288
- if (payload.generationKey !== generation.generationKey ||
3289
- payload.taskId !== generation.taskId ||
3290
- payload.temporalEpoch !== generation.temporalEpoch ||
3291
- payload.occurrenceKey !== generation.occurrenceKey ||
3292
- payload.checkAt !== generation.checkAt) {
3293
- throw new Error(`temporal attempt ${workOrder.id} payload does not match generation ownership`);
3294
- }
3295
- }
3296
- requirePayloadString(payload, field, attemptId) {
3297
- const value = payload[field];
3298
- if (typeof value !== 'string' || value.length === 0) {
3299
- throw new Error(`temporal attempt ${attemptId}: ${field} must be a non-empty string`);
3300
- }
3301
- return value;
3302
- }
3303
- requireNullablePayloadString(payload, field, attemptId) {
3304
- const value = payload[field];
3305
- if (value !== null && typeof value !== 'string') {
3306
- throw new Error(`temporal attempt ${attemptId}: ${field} must be a string or null`);
3307
- }
3308
- return value;
3309
- }
3310
- requirePayloadInteger(payload, field, attemptId, minimum = Number.MIN_SAFE_INTEGER) {
3311
- const value = payload[field];
3312
- if (!Number.isSafeInteger(value) || value < minimum) {
3313
- throw new Error(`temporal attempt ${attemptId}: ${field} must be an integer`);
3314
- }
3315
- return value;
3316
- }
3317
- assertTemporalReason(reason) {
3318
- if (reason.trim().length < 1 || reason.length > 500) {
3319
- throw new Error('temporal workorder reason must contain 1-500 characters');
3320
- }
3321
- }
3322
- temporalAuditText(kind, values) {
3323
- const refs = values.map((value, index) => {
3324
- const separator = value.indexOf('=');
3325
- const label = separator > 0 ? value.slice(0, separator) : `value${index + 1}`;
3326
- const text = separator > 0 ? value.slice(separator + 1) : value;
3327
- const digest = (0, node_crypto_1.createHash)('sha256').update(text).digest('hex');
3328
- return `${label}_sha256=${digest};${label}_length=${text.length}`;
3329
- });
3330
- return `temporal-${kind};${refs.join(';')}`;
3331
- }
3332
- /**
3333
- * Claim the next pending workorder: priority high>normal>low, then id ASC
3334
- * (plan D2/E2 - CASE mapping, never lexicographic on the TEXT enum).
3335
- * pending -> in_progress. Single serial consumer; transaction for atomicity.
3336
- */
3337
- claimNextWorkOrder() {
3338
- let claimedId = null;
3339
- this.db.exec('BEGIN IMMEDIATE');
3340
- try {
3341
- const claimAt = this.now();
3342
- const row = this.db
3343
- .prepare(`SELECT * FROM operator_tasks
3344
- WHERE kind = 'system' AND status = 'pending'
3345
- AND source_channel IN (${KNOWN_WORKORDER_CHANNELS_SQL})
3346
- AND (due_at IS NULL OR due_at <= ?)
3347
- ORDER BY CASE priority WHEN 'high' THEN 0 WHEN 'normal' THEN 1 ELSE 2 END ASC,
3348
- id ASC
3349
- LIMIT 1`)
3350
- .get(...KNOWN_WORKORDER_CHANNELS, claimAt);
3351
- if (row) {
3352
- this.db
3353
- .prepare(`UPDATE operator_tasks SET status = 'in_progress', updated_at = ? WHERE id = ?`)
3354
- .run(claimAt, row.id);
3355
- claimedId = row.id;
3356
- }
3357
- this.db.exec('COMMIT');
3358
- }
3359
- catch (error) {
3360
- this.db.exec('ROLLBACK');
3361
- throw error;
3362
- }
3363
- // Read-back OUTSIDE the try: a throw here (corrupt payload) must not
3364
- // trigger ROLLBACK after COMMIT (PR bot round - masked error class).
3365
- return claimedId === null ? null : this.getWorkOrderById(claimedId);
3366
- }
3367
- /**
3368
- * Atomic fail-and-requeue (PR bot round): the failure mark and the
3369
- * replacement row commit together - a crash between the two would lose
3370
- * the retry (the old row terminal, the new one never inserted). The
3371
- * replacement can only be inserted AFTER the old row leaves the partial
3372
- * unique index, hence one transaction, not two calls.
3373
- */
3374
- requeueWorkOrder(wo, reason) {
3375
- if (wo.workKind === 'temporal') {
3376
- return this.requeueTemporalWorkOrder(wo.id, reason);
3377
- }
3378
- this.db.exec('BEGIN IMMEDIATE');
3379
- try {
3380
- const current = this.getWorkOrderById(wo.id);
3381
- if (!current || current.workKind !== wo.workKind) {
3382
- throw new Error(`workorder retry: claimed row ${wo.id} no longer matches input`);
3383
- }
3384
- this.transitionWorkOrder(current.id, 'failed', reason);
3385
- const input = publisherPayloadOfStoredWorkOrder(current.payload);
3386
- const replacement = this.insertWorkOrder({
3387
- workKind: current.workKind,
3388
- idempotencyKey: current.idempotencyKey,
3389
- input,
3390
- priority: current.priority,
3391
- }, current.payload.attempts + 1);
3392
- this.db.exec('COMMIT');
3393
- return replacement;
3394
- }
3395
- catch (error) {
3396
- this.db.exec('ROLLBACK');
3397
- throw error;
3398
- }
3399
- }
3400
- /**
3401
- * Record that a claimed attempt is waiting on a native subagent.
3402
- *
3403
- * The status stays `in_progress`, which is the truth: the attempt is open and its
3404
- * idempotency slot is still held, so nothing re-enqueues the same occurrence underneath
3405
- * the child. Only the durable verification (or the consumer's timeout) moves it on.
3406
- */
3407
- markWorkOrderDelegated(id, delegatedAt) {
3408
- if (!Number.isSafeInteger(delegatedAt) || delegatedAt < 0) {
3409
- throw new Error('workorder delegation timestamp must be a non-negative safe integer');
3410
- }
3411
- const row = this.getWorkOrderById(id);
3412
- if (!row)
3413
- throw new Error(`workorder delegation: no system row with id ${id}`);
3414
- if (row.status !== 'in_progress') {
3415
- throw new Error(`workorder delegation: row ${id} is '${row.status}', expected in_progress`);
3416
- }
3417
- const payload = { ...row.payload, [exports.WORKORDER_DELEGATED_AT_KEY]: delegatedAt };
3418
- const result = this.db
3419
- .prepare(`UPDATE operator_tasks SET payload = ?, latest_event = ?, updated_at = ?
3420
- WHERE id = ? AND kind = 'system' AND status = 'in_progress'`)
3421
- .run(JSON.stringify(payload), 'delegated to a native subagent', this.now(), id);
3422
- // The row can leave in_progress between the read above and this write. A no-op UPDATE
3423
- // is not a delegation: say so instead of reporting a mark that was never stored.
3424
- if (result.changes !== 1) {
3425
- throw new Error(`workorder delegation: row ${id} left in_progress before the mark`);
3426
- }
3427
- }
3428
- completeWorkOrder(id) {
3429
- this.transitionWorkOrder(id, 'done', null);
3430
- }
3431
- failWorkOrder(id, reason) {
3432
- this.transitionWorkOrder(id, 'failed', reason);
3433
- }
3434
- countPendingWorkOrders() {
3435
- const row = this.db
3436
- .prepare(`SELECT COUNT(*) AS count FROM operator_tasks
3437
- WHERE kind = 'system' AND status = 'pending'
3438
- AND source_channel IN (${KNOWN_WORKORDER_CHANNELS_SQL})`)
3439
- .get(...KNOWN_WORKORDER_CHANNELS);
3440
- return row.count;
3441
- }
3442
- countOpenWorkOrders(kind) {
3443
- const row = (kind
3444
- ? this.db
3445
- .prepare(`SELECT COUNT(*) AS count FROM operator_tasks
3446
- WHERE kind = 'system' AND status IN ('pending','in_progress')
3447
- AND source_channel = ?`)
3448
- .get(`${exports.WORKORDER_CHANNEL_PREFIX}${kind}`)
3449
- : this.db
3450
- .prepare(`SELECT COUNT(*) AS count FROM operator_tasks
3451
- WHERE kind = 'system' AND status IN ('pending','in_progress')`)
3452
- .get());
3453
- return row.count;
3454
- }
3455
- findTemporalGenerationKeys(generationKeys) {
3456
- if (generationKeys.length === 0)
3457
- return new Set();
3458
- if (generationKeys.length > 500) {
3459
- throw new Error('findTemporalGenerationKeys accepts at most 500 keys');
3460
- }
3461
- const rows = this.db
3462
- .prepare(`SELECT generation_key FROM operator_temporal_generations
3463
- WHERE generation_key IN (${generationKeys.map(() => '?').join(',')})`)
3464
- .all(...generationKeys);
3465
- return new Set(rows.map((row) => row.generation_key));
3466
- }
3467
- /** In-progress system rows at boot = crash artifacts (single serial consumer). */
3468
- listStaleClaims() {
3469
- const rows = this.db
3470
- .prepare(`SELECT * FROM operator_tasks
3471
- WHERE kind = 'system' AND status = 'in_progress'
3472
- AND source_channel IN (${KNOWN_WORKORDER_CHANNELS_SQL})`)
3473
- .all(...KNOWN_WORKORDER_CHANNELS);
3474
- return rows.map((row) => this.rowToWorkOrder(row));
3475
- }
3476
- /**
3477
- * Boot cleanup (plan D3 + review N4): open system rows -> cancelled. A
3478
- * rollback is not a failure - excluded from failed counters/alarms; caller
3479
- * logs ONE summary line with the returned count. `onlyKinds` scopes the
3480
- * cancellation.
3481
- */
3482
- cancelOpenWorkOrders(reason, onlyKinds) {
3483
- // An explicit empty scope means "cancel nothing", never "cancel all"
3484
- // (review F2 - the fall-through would silently widen a scoped call).
3485
- if (onlyKinds !== undefined && onlyKinds.length === 0) {
3486
- return 0;
3487
- }
3488
- const selectedKinds = onlyKinds ?? exports.WORKORDER_KINDS;
3489
- const kindFilter = ` AND source_channel IN (${selectedKinds.map(() => '?').join(',')})`;
3490
- const kindParams = selectedKinds.map((kind) => `${exports.WORKORDER_CHANNEL_PREFIX}${kind}`);
3491
- const result = this.db
3492
- .prepare(`UPDATE operator_tasks
3493
- SET status = 'cancelled', latest_event = ?, updated_at = ?
3494
- WHERE kind = 'system' AND status IN ('pending','in_progress')${kindFilter}`)
3495
- .run(reason, this.now(), ...kindParams);
3496
- return result.changes;
3497
- }
3498
- /** Per-kind last run and failure counts of the system lanes (operator UI and tests). */
3499
- workOrderStats() {
3500
- return exports.WORKORDER_KINDS.map((workKind) => {
3501
- const channel = `${exports.WORKORDER_CHANNEL_PREFIX}${workKind}`;
3502
- const last = this.db
3503
- .prepare(`SELECT status, updated_at FROM operator_tasks
3504
- WHERE kind = 'system' AND source_channel = ?
3505
- ORDER BY updated_at DESC, id DESC LIMIT 1`)
3506
- .get(channel);
3507
- const failed = this.db
3508
- .prepare(`SELECT COUNT(*) AS count FROM operator_tasks
3509
- WHERE kind = 'system' AND source_channel = ? AND status = 'failed'`)
3510
- .get(channel);
3511
- const lastFailure = this.db
3512
- .prepare(`SELECT latest_event FROM operator_tasks
3513
- WHERE kind = 'system' AND source_channel = ? AND status = 'failed'
3514
- ORDER BY updated_at DESC, id DESC LIMIT 1`)
3515
- .get(channel);
3516
- return {
3517
- workKind,
3518
- lastRunAt: last?.updated_at ?? null,
3519
- lastStatus: last?.status ?? null,
3520
- failedCount: failed.count,
3521
- lastFailureReason: lastFailure?.latest_event ?? null,
3522
- };
3523
- });
3524
- }
3525
- getWorkOrderById(id) {
3526
- const row = this.db
3527
- .prepare(`SELECT * FROM operator_tasks WHERE id = ? AND kind = 'system'`)
3528
- .get(id);
3529
- return row ? this.rowToWorkOrder(row) : null;
3530
- }
3531
- transitionWorkOrder(id, status, reason) {
3532
- const row = this.getWorkOrderById(id);
3533
- if (!row)
3534
- throw new Error(`workorder transition: no system row with id ${id}`);
3535
- if (row.status !== 'in_progress') {
3536
- throw new Error(`workorder transition: row ${id} is '${row.status}', expected in_progress`);
3537
- }
3538
- this.db
3539
- .prepare(`UPDATE operator_tasks SET status = ?, latest_event = COALESCE(?, latest_event),
3540
- updated_at = ? WHERE id = ?`)
3541
- .run(status, reason, this.now(), id);
3542
- }
3543
- rowToWorkOrder(row) {
3544
- const workKind = (row.source_channel ?? '').slice(exports.WORKORDER_CHANNEL_PREFIX.length);
3545
- assertEnum(workKind, exports.WORKORDER_KINDS, 'workKind');
3546
- let payload;
3547
- try {
3548
- payload = row.payload ? JSON.parse(row.payload) : {};
3549
- }
3550
- catch (error) {
3551
- // No-fallback: a corrupt payload is a real fault, surface it loudly.
3552
- throw new Error(`workorder ${row.id}: corrupt payload JSON (${error instanceof Error ? error.message : String(error)})`);
3553
- }
3554
- // Strict reads (PR bot round): silently normalizing corrupt ownership or
3555
- // retry metadata would mask a real fault - every row here was written by
3556
- // enqueueWorkOrder, which guarantees both fields.
3557
- if (typeof payload.attempts !== 'number' || payload.attempts < 1) {
3558
- throw new Error(`workorder ${row.id}: invalid attempts in payload (${String(payload.attempts)})`);
3559
- }
3560
- if (!row.source_event_id) {
3561
- throw new Error(`workorder ${row.id}: missing idempotency key (source_event_id)`);
3562
- }
3563
- return {
3564
- id: row.id,
3565
- workKind: workKind,
3566
- status: row.status,
3567
- priority: row.priority,
3568
- idempotencyKey: row.source_event_id,
3569
- payload: { ...payload, attempts: payload.attempts },
3570
- delegatedAt: typeof payload[exports.WORKORDER_DELEGATED_AT_KEY] === 'number'
3571
- ? payload[exports.WORKORDER_DELEGATED_AT_KEY]
3572
- : null,
3573
- createdAt: row.created_at,
3574
- updatedAt: row.updated_at,
3575
- };
3576
- }
3577
- /** contract_no_update: silence as a verifiable judgment, scoped to one reconcile run. */
3578
- recordNoUpdate(scope, reason) {
3579
- if (!scope || !reason) {
3580
- throw new Error('contract_no_update requires both scope and reason');
3581
- }
3582
- return this.insertNoUpdateNote(scope, reason, this.now());
3583
- }
3584
- insertNoUpdateNote(scope, reason, createdAt) {
3585
- const result = this.db
3586
- .prepare(`INSERT INTO operator_no_update_notes (scope, reason, created_at) VALUES (?, ?, ?)`)
3587
- .run(scope, reason, createdAt);
3588
- return { id: Number(result.lastInsertRowid) };
3589
- }
3590
- /** Max no-update note id, optionally scoped - the verifier's note snapshot. */
3591
- maxNoUpdateId(scope) {
3592
- const row = (scope
3593
- ? this.db
3594
- .prepare(`SELECT MAX(id) AS max_id FROM operator_no_update_notes WHERE scope = ?`)
3595
- .get(scope)
3596
- : this.db.prepare(`SELECT MAX(id) AS max_id FROM operator_no_update_notes`).get());
3597
- return row.max_id ?? 0;
3598
- }
3599
- }
3600
- exports.TaskLedger = TaskLedger;
3601
- //# sourceMappingURL=task-ledger.js.map