@jungjaehoon/mama-os 0.78.0 → 0.79.1

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 (288) hide show
  1. package/CHANGELOG.md +341 -0
  2. package/README.md +38 -24
  3. package/db/migrations/002-model-runs-parent-index.sql +11 -0
  4. package/db/migrations/003-upkeep-settled.sql +15 -0
  5. package/dist/api/google-read-actions.d.ts +30 -0
  6. package/dist/api/google-read-actions.d.ts.map +1 -0
  7. package/dist/api/google-read-actions.js +256 -0
  8. package/dist/api/google-read-actions.js.map +1 -0
  9. package/dist/api/record-actions.d.ts.map +1 -1
  10. package/dist/api/record-actions.js +23 -5
  11. package/dist/api/record-actions.js.map +1 -1
  12. package/dist/api/report-handler.d.ts +0 -6
  13. package/dist/api/report-handler.d.ts.map +1 -1
  14. package/dist/api/report-handler.js +0 -54
  15. package/dist/api/report-handler.js.map +1 -1
  16. package/dist/api/security-events.d.ts +1 -1
  17. package/dist/api/security-events.d.ts.map +1 -1
  18. package/dist/api/security-events.js.map +1 -1
  19. package/dist/api/source-actions.d.ts +9 -0
  20. package/dist/api/source-actions.d.ts.map +1 -1
  21. package/dist/api/source-actions.js +49 -0
  22. package/dist/api/source-actions.js.map +1 -1
  23. package/dist/api/viewer-request-security.d.ts +14 -1
  24. package/dist/api/viewer-request-security.d.ts.map +1 -1
  25. package/dist/api/viewer-request-security.js +26 -3
  26. package/dist/api/viewer-request-security.js.map +1 -1
  27. package/dist/api/viewer-server.d.ts +7 -0
  28. package/dist/api/viewer-server.d.ts.map +1 -1
  29. package/dist/api/viewer-server.js +32 -0
  30. package/dist/api/viewer-server.js.map +1 -1
  31. package/dist/api/work-actions.d.ts +19 -2
  32. package/dist/api/work-actions.d.ts.map +1 -1
  33. package/dist/api/work-actions.js +15 -0
  34. package/dist/api/work-actions.js.map +1 -1
  35. package/dist/cli/commands/backup.d.ts +7 -6
  36. package/dist/cli/commands/backup.d.ts.map +1 -1
  37. package/dist/cli/commands/backup.js +44 -7
  38. package/dist/cli/commands/backup.js.map +1 -1
  39. package/dist/cli/commands/control.d.ts +22 -4
  40. package/dist/cli/commands/control.d.ts.map +1 -1
  41. package/dist/cli/commands/control.js +172 -11
  42. package/dist/cli/commands/control.js.map +1 -1
  43. package/dist/cli/commands/daemon.d.ts +13 -2
  44. package/dist/cli/commands/daemon.d.ts.map +1 -1
  45. package/dist/cli/commands/daemon.js +211 -5
  46. package/dist/cli/commands/daemon.js.map +1 -1
  47. package/dist/cli/commands/init-questions.d.ts +110 -0
  48. package/dist/cli/commands/init-questions.d.ts.map +1 -0
  49. package/dist/cli/commands/init-questions.js +445 -0
  50. package/dist/cli/commands/init-questions.js.map +1 -0
  51. package/dist/cli/commands/init-section.d.ts +13 -0
  52. package/dist/cli/commands/init-section.d.ts.map +1 -0
  53. package/dist/cli/commands/init-section.js +439 -0
  54. package/dist/cli/commands/init-section.js.map +1 -0
  55. package/dist/cli/commands/init.d.ts +56 -2
  56. package/dist/cli/commands/init.d.ts.map +1 -1
  57. package/dist/cli/commands/init.js +562 -351
  58. package/dist/cli/commands/init.js.map +1 -1
  59. package/dist/cli/commands/node-move.d.ts +20 -0
  60. package/dist/cli/commands/node-move.d.ts.map +1 -0
  61. package/dist/cli/commands/node-move.js +289 -0
  62. package/dist/cli/commands/node-move.js.map +1 -0
  63. package/dist/cli/commands/register-owner.d.ts +3 -0
  64. package/dist/cli/commands/register-owner.d.ts.map +1 -1
  65. package/dist/cli/commands/register-owner.js +2 -0
  66. package/dist/cli/commands/register-owner.js.map +1 -1
  67. package/dist/cli/commands/restore.d.ts +2 -0
  68. package/dist/cli/commands/restore.d.ts.map +1 -1
  69. package/dist/cli/commands/restore.js +7 -0
  70. package/dist/cli/commands/restore.js.map +1 -1
  71. package/dist/cli/commands/service.d.ts +16 -0
  72. package/dist/cli/commands/service.d.ts.map +1 -1
  73. package/dist/cli/commands/service.js +36 -8
  74. package/dist/cli/commands/service.js.map +1 -1
  75. package/dist/cli/commands/tools.d.ts +1 -1
  76. package/dist/cli/commands/tools.d.ts.map +1 -1
  77. package/dist/cli/commands/tools.js +8 -3
  78. package/dist/cli/commands/tools.js.map +1 -1
  79. package/dist/cli/commands/uninstall.d.ts.map +1 -1
  80. package/dist/cli/commands/uninstall.js +123 -15
  81. package/dist/cli/commands/uninstall.js.map +1 -1
  82. package/dist/cli/commands/update.d.ts +59 -0
  83. package/dist/cli/commands/update.d.ts.map +1 -0
  84. package/dist/cli/commands/update.js +948 -0
  85. package/dist/cli/commands/update.js.map +1 -0
  86. package/dist/cli/index.js +8 -4
  87. package/dist/cli/index.js.map +1 -1
  88. package/dist/cli/launch-files.d.ts +36 -0
  89. package/dist/cli/launch-files.d.ts.map +1 -1
  90. package/dist/cli/launch-files.js +94 -1
  91. package/dist/cli/launch-files.js.map +1 -1
  92. package/dist/cli/prompt.d.ts +2 -1
  93. package/dist/cli/prompt.d.ts.map +1 -1
  94. package/dist/cli/prompt.js +5 -2
  95. package/dist/cli/prompt.js.map +1 -1
  96. package/dist/cli/runtime/backup.d.ts +17 -1
  97. package/dist/cli/runtime/backup.d.ts.map +1 -1
  98. package/dist/cli/runtime/backup.js +32 -4
  99. package/dist/cli/runtime/backup.js.map +1 -1
  100. package/dist/cli/runtime/daemon-control.d.ts +92 -7
  101. package/dist/cli/runtime/daemon-control.d.ts.map +1 -1
  102. package/dist/cli/runtime/daemon-control.js +183 -8
  103. package/dist/cli/runtime/daemon-control.js.map +1 -1
  104. package/dist/cli/runtime/default-roots.d.ts +27 -0
  105. package/dist/cli/runtime/default-roots.d.ts.map +1 -0
  106. package/dist/cli/runtime/default-roots.js +61 -0
  107. package/dist/cli/runtime/default-roots.js.map +1 -0
  108. package/dist/cli/runtime/diagnostics.d.ts +25 -0
  109. package/dist/cli/runtime/diagnostics.d.ts.map +1 -1
  110. package/dist/cli/runtime/diagnostics.js +250 -63
  111. package/dist/cli/runtime/diagnostics.js.map +1 -1
  112. package/dist/cli/runtime/init-state.d.ts +20 -0
  113. package/dist/cli/runtime/init-state.d.ts.map +1 -0
  114. package/dist/cli/runtime/init-state.js +51 -0
  115. package/dist/cli/runtime/init-state.js.map +1 -0
  116. package/dist/cli/runtime/install-kind.d.ts +54 -0
  117. package/dist/cli/runtime/install-kind.d.ts.map +1 -0
  118. package/dist/cli/runtime/install-kind.js +164 -0
  119. package/dist/cli/runtime/install-kind.js.map +1 -0
  120. package/dist/cli/runtime/node-move-journal.d.ts +44 -0
  121. package/dist/cli/runtime/node-move-journal.d.ts.map +1 -0
  122. package/dist/cli/runtime/node-move-journal.js +48 -0
  123. package/dist/cli/runtime/node-move-journal.js.map +1 -0
  124. package/dist/cli/runtime/release-check.d.ts +94 -0
  125. package/dist/cli/runtime/release-check.d.ts.map +1 -0
  126. package/dist/cli/runtime/release-check.js +316 -0
  127. package/dist/cli/runtime/release-check.js.map +1 -0
  128. package/dist/cli/runtime/setup-page.d.ts +57 -0
  129. package/dist/cli/runtime/setup-page.d.ts.map +1 -0
  130. package/dist/cli/runtime/setup-page.js +266 -0
  131. package/dist/cli/runtime/setup-page.js.map +1 -0
  132. package/dist/cli/runtime/source-tools.d.ts +60 -0
  133. package/dist/cli/runtime/source-tools.d.ts.map +1 -0
  134. package/dist/cli/runtime/source-tools.js +170 -0
  135. package/dist/cli/runtime/source-tools.js.map +1 -0
  136. package/dist/cli/runtime/telegram-pairing.d.ts +73 -0
  137. package/dist/cli/runtime/telegram-pairing.d.ts.map +1 -0
  138. package/dist/cli/runtime/telegram-pairing.js +184 -0
  139. package/dist/cli/runtime/telegram-pairing.js.map +1 -0
  140. package/dist/cli/runtime/update-journal.d.ts +135 -0
  141. package/dist/cli/runtime/update-journal.d.ts.map +1 -0
  142. package/dist/cli/runtime/update-journal.js +144 -0
  143. package/dist/cli/runtime/update-journal.js.map +1 -0
  144. package/dist/cli/runtime/update-progress.d.ts +95 -0
  145. package/dist/cli/runtime/update-progress.d.ts.map +1 -0
  146. package/dist/cli/runtime/update-progress.js +154 -0
  147. package/dist/cli/runtime/update-progress.js.map +1 -0
  148. package/dist/cli/runtime/update-request.d.ts +58 -0
  149. package/dist/cli/runtime/update-request.d.ts.map +1 -0
  150. package/dist/cli/runtime/update-request.js +172 -0
  151. package/dist/cli/runtime/update-request.js.map +1 -0
  152. package/dist/connectors/calendar/index.d.ts +5 -1
  153. package/dist/connectors/calendar/index.d.ts.map +1 -1
  154. package/dist/connectors/calendar/index.js +19 -28
  155. package/dist/connectors/calendar/index.js.map +1 -1
  156. package/dist/connectors/chatwork/index.d.ts.map +1 -1
  157. package/dist/connectors/chatwork/index.js +7 -3
  158. package/dist/connectors/chatwork/index.js.map +1 -1
  159. package/dist/connectors/config-loader.d.ts +5 -0
  160. package/dist/connectors/config-loader.d.ts.map +1 -1
  161. package/dist/connectors/config-loader.js +8 -0
  162. package/dist/connectors/config-loader.js.map +1 -1
  163. package/dist/connectors/discord/index.d.ts.map +1 -1
  164. package/dist/connectors/discord/index.js +4 -3
  165. package/dist/connectors/discord/index.js.map +1 -1
  166. package/dist/connectors/drive/index.d.ts.map +1 -1
  167. package/dist/connectors/drive/index.js +15 -13
  168. package/dist/connectors/drive/index.js.map +1 -1
  169. package/dist/connectors/framework/gws-utils.d.ts +62 -0
  170. package/dist/connectors/framework/gws-utils.d.ts.map +1 -1
  171. package/dist/connectors/framework/gws-utils.js +133 -3
  172. package/dist/connectors/framework/gws-utils.js.map +1 -1
  173. package/dist/connectors/framework/types.d.ts +24 -0
  174. package/dist/connectors/framework/types.d.ts.map +1 -1
  175. package/dist/connectors/framework/types.js +9 -0
  176. package/dist/connectors/framework/types.js.map +1 -1
  177. package/dist/connectors/gmail/index.d.ts.map +1 -1
  178. package/dist/connectors/gmail/index.js +14 -13
  179. package/dist/connectors/gmail/index.js.map +1 -1
  180. package/dist/connectors/index.d.ts +4 -4
  181. package/dist/connectors/index.d.ts.map +1 -1
  182. package/dist/connectors/index.js +4 -10
  183. package/dist/connectors/index.js.map +1 -1
  184. package/dist/connectors/notion/index.d.ts.map +1 -1
  185. package/dist/connectors/notion/index.js +5 -3
  186. package/dist/connectors/notion/index.js.map +1 -1
  187. package/dist/connectors/sheets/index.d.ts.map +1 -1
  188. package/dist/connectors/sheets/index.js +17 -12
  189. package/dist/connectors/sheets/index.js.map +1 -1
  190. package/dist/connectors/slack/index.d.ts.map +1 -1
  191. package/dist/connectors/slack/index.js +9 -3
  192. package/dist/connectors/slack/index.js.map +1 -1
  193. package/dist/connectors/telegram/index.d.ts.map +1 -1
  194. package/dist/connectors/telegram/index.js +4 -3
  195. package/dist/connectors/telegram/index.js.map +1 -1
  196. package/dist/connectors/trello/index.d.ts +1 -1
  197. package/dist/connectors/trello/index.d.ts.map +1 -1
  198. package/dist/connectors/trello/index.js +10 -5
  199. package/dist/connectors/trello/index.js.map +1 -1
  200. package/dist/gateways/discord.d.ts +6 -0
  201. package/dist/gateways/discord.d.ts.map +1 -1
  202. package/dist/gateways/discord.js +38 -27
  203. package/dist/gateways/discord.js.map +1 -1
  204. package/dist/gateways/slack.d.ts +6 -0
  205. package/dist/gateways/slack.d.ts.map +1 -1
  206. package/dist/gateways/slack.js +38 -27
  207. package/dist/gateways/slack.js.map +1 -1
  208. package/dist/gateways/telegram-commands.d.ts +124 -0
  209. package/dist/gateways/telegram-commands.d.ts.map +1 -0
  210. package/dist/gateways/telegram-commands.js +131 -0
  211. package/dist/gateways/telegram-commands.js.map +1 -0
  212. package/dist/gateways/telegram.d.ts +20 -0
  213. package/dist/gateways/telegram.d.ts.map +1 -1
  214. package/dist/gateways/telegram.js +138 -34
  215. package/dist/gateways/telegram.js.map +1 -1
  216. package/dist/gateways/turn-contract.d.ts +11 -0
  217. package/dist/gateways/turn-contract.d.ts.map +1 -1
  218. package/dist/runtime/action-surface.d.ts +1 -1
  219. package/dist/runtime/action-surface.d.ts.map +1 -1
  220. package/dist/runtime/action-surface.js +10 -0
  221. package/dist/runtime/action-surface.js.map +1 -1
  222. package/dist/runtime/backend-security.d.ts +23 -2
  223. package/dist/runtime/backend-security.d.ts.map +1 -1
  224. package/dist/runtime/backend-security.js +50 -5
  225. package/dist/runtime/backend-security.js.map +1 -1
  226. package/dist/runtime/member-paths.d.ts +15 -7
  227. package/dist/runtime/member-paths.d.ts.map +1 -1
  228. package/dist/runtime/member-paths.js +64 -12
  229. package/dist/runtime/member-paths.js.map +1 -1
  230. package/dist/runtime/member-session.d.ts +4 -0
  231. package/dist/runtime/member-session.d.ts.map +1 -1
  232. package/dist/runtime/member-session.js +23 -2
  233. package/dist/runtime/member-session.js.map +1 -1
  234. package/dist/runtime/native-session.d.ts +2 -0
  235. package/dist/runtime/native-session.d.ts.map +1 -1
  236. package/dist/runtime/native-session.js +1 -0
  237. package/dist/runtime/native-session.js.map +1 -1
  238. package/dist/runtime/owner-runtime.d.ts +63 -1
  239. package/dist/runtime/owner-runtime.d.ts.map +1 -1
  240. package/dist/runtime/owner-runtime.js +180 -3
  241. package/dist/runtime/owner-runtime.js.map +1 -1
  242. package/dist/runtime/owner-system-prompt.d.ts.map +1 -1
  243. package/dist/runtime/owner-system-prompt.js +0 -1
  244. package/dist/runtime/owner-system-prompt.js.map +1 -1
  245. package/dist/runtime/principal-access.d.ts +2 -0
  246. package/dist/runtime/principal-access.d.ts.map +1 -1
  247. package/dist/runtime/principal-access.js +7 -0
  248. package/dist/runtime/principal-access.js.map +1 -1
  249. package/dist/runtime/principal-sessions.d.ts.map +1 -1
  250. package/dist/runtime/principal-sessions.js +8 -1
  251. package/dist/runtime/principal-sessions.js.map +1 -1
  252. package/dist/runtime/record-orders.d.ts.map +1 -1
  253. package/dist/runtime/record-orders.js +3 -29
  254. package/dist/runtime/record-orders.js.map +1 -1
  255. package/dist/runtime/report-scheduler.d.ts +9 -2
  256. package/dist/runtime/report-scheduler.d.ts.map +1 -1
  257. package/dist/runtime/report-scheduler.js +37 -10
  258. package/dist/runtime/report-scheduler.js.map +1 -1
  259. package/dist/runtime/stimulus-delivery.d.ts +3 -0
  260. package/dist/runtime/stimulus-delivery.d.ts.map +1 -1
  261. package/dist/runtime/stimulus-delivery.js +19 -3
  262. package/dist/runtime/stimulus-delivery.js.map +1 -1
  263. package/dist/runtime/tools-paths.d.ts +7 -0
  264. package/dist/runtime/tools-paths.d.ts.map +1 -1
  265. package/dist/runtime/tools-paths.js +11 -5
  266. package/dist/runtime/tools-paths.js.map +1 -1
  267. package/dist/runtime/upkeep-close.d.ts +17 -0
  268. package/dist/runtime/upkeep-close.d.ts.map +1 -0
  269. package/dist/runtime/upkeep-close.js +127 -0
  270. package/dist/runtime/upkeep-close.js.map +1 -0
  271. package/dist/runtime/upkeep-orders.d.ts +124 -0
  272. package/dist/runtime/upkeep-orders.d.ts.map +1 -0
  273. package/dist/runtime/upkeep-orders.js +310 -0
  274. package/dist/runtime/upkeep-orders.js.map +1 -0
  275. package/dist/runtime/upkeep-reconcile.d.ts +25 -0
  276. package/dist/runtime/upkeep-reconcile.d.ts.map +1 -0
  277. package/dist/runtime/upkeep-reconcile.js +231 -0
  278. package/dist/runtime/upkeep-reconcile.js.map +1 -0
  279. package/dist/runtime/upkeep-writeback.d.ts +22 -0
  280. package/dist/runtime/upkeep-writeback.d.ts.map +1 -0
  281. package/dist/runtime/upkeep-writeback.js +203 -0
  282. package/dist/runtime/upkeep-writeback.js.map +1 -0
  283. package/dist/utils/untrusted-content.d.ts.map +1 -1
  284. package/dist/utils/untrusted-content.js +8 -1
  285. package/dist/utils/untrusted-content.js.map +1 -1
  286. package/install/install.sh +457 -0
  287. package/install/node.json +9 -0
  288. package/package.json +3 -4
@@ -0,0 +1,310 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UPKEEP_SCAN_PAGE = exports.UPKEEP_WINDOW_MS = exports.UPKEEP_MAX_ATTEMPTS = void 0;
4
+ exports.upkeepOrderIdPrefix = upkeepOrderIdPrefix;
5
+ exports.parseUpkeepOrder = parseUpkeepOrder;
6
+ exports.orderRunIds = orderRunIds;
7
+ exports.noUpdateCites = noUpdateCites;
8
+ exports.runningChildren = runningChildren;
9
+ exports.createUpkeepOrders = createUpkeepOrders;
10
+ const node_crypto_1 = require("node:crypto");
11
+ /**
12
+ * Ledger upkeep orders (docs/development/work/ledger-upkeep.md). The host chooses the subjects,
13
+ * the agent judges and writes in the common session, and the host checks each subject when the
14
+ * order's run ends. Record orders (record-orders.ts) stay a separate lane: they follow live deltas
15
+ * and carry batches; upkeep follows the ledger's own state.
16
+ *
17
+ * tick(kind) ── scan ──> subjects not checked, not in an open order, under the attempt limit
18
+ * │ │
19
+ * │ accept(order on kind.channel)
20
+ * ▼ ▼
21
+ * onResult / onLost ──> per subject: checked │ waiting (picked by the next tick) │ lost
22
+ *
23
+ * Checked and lost subjects are also written to upkeep_settled: the mailbox deletes acked order
24
+ * rows after seven days, and a settled subject must never be ordered again.
25
+ */
26
+ /** A subject is ordered at most this many times; then it is reported lost and left alone. */
27
+ exports.UPKEEP_MAX_ATTEMPTS = 3;
28
+ /** How far back stored orders are read to count a subject's attempts. */
29
+ exports.UPKEEP_WINDOW_MS = 7 * 24 * 60 * 60 * 1000;
30
+ /** Candidates per scan page. */
31
+ exports.UPKEEP_SCAN_PAGE = 200;
32
+ /** Every order of a kind has an id with this prefix; its runs carry it as sourceMessageRef. */
33
+ function upkeepOrderIdPrefix(kindName) {
34
+ return `upkeep:${kindName}:`;
35
+ }
36
+ function parseUpkeepOrder(payload) {
37
+ const value = payload;
38
+ if (!value ||
39
+ value.order !== 'upkeep' ||
40
+ typeof value.kind !== 'string' ||
41
+ !Array.isArray(value.subjects) ||
42
+ value.subjects.length === 0 ||
43
+ value.subjects.some((subject) => typeof subject?.key !== 'string' || subject.key === ''))
44
+ throw new Error('Upkeep order requires { order: upkeep, kind, subjects: [{ key }] }');
45
+ return value;
46
+ }
47
+ /** The runs an order produced: its own turn and the child runs that turn started. */
48
+ function orderRunIds(adapter, orderIds) {
49
+ if (orderIds.length === 0)
50
+ return [];
51
+ const marks = orderIds.map(() => '?').join(',');
52
+ return adapter
53
+ .prepare(`SELECT r.model_run_id AS id FROM model_runs r
54
+ WHERE json_extract(r.input_refs_json, '$.sourceMessageRef') IN (${marks})
55
+ UNION
56
+ SELECT c.model_run_id FROM model_runs c JOIN model_runs p ON c.parent_model_run_id = p.model_run_id
57
+ WHERE json_extract(p.input_refs_json, '$.sourceMessageRef') IN (${marks})`)
58
+ .all(...orderIds, ...orderIds).map((row) => row.id);
59
+ }
60
+ /**
61
+ * A completed work.no_update in these runs. With `cites`, the no-update must name one of the
62
+ * values in that input field (`commitmentIds` for a work item, `observationRefs` for a source);
63
+ * with `cites` null, any no-update in the runs counts. The field name is a fixed union, never
64
+ * caller text, so it interpolates into the json path safely.
65
+ */
66
+ function noUpdateCites(adapter, runIds, cites) {
67
+ if (runIds.length === 0)
68
+ return false;
69
+ if (cites !== null && cites.values.length === 0)
70
+ return false;
71
+ const citing = cites === null
72
+ ? ''
73
+ : `AND EXISTS (
74
+ SELECT 1 FROM json_each(CASE WHEN json_valid(t.input_summary)
75
+ THEN json_extract(t.input_summary, '$.${cites.field}') END) ref
76
+ WHERE ref.value IN (${cites.values.map(() => '?').join(',')}))`;
77
+ return (adapter
78
+ .prepare(`SELECT 1 FROM tool_traces t
79
+ WHERE t.tool_name = 'work.no_update' AND t.execution_status = 'completed'
80
+ AND t.model_run_id IN (${runIds.map(() => '?').join(',')})
81
+ ${citing}
82
+ LIMIT 1`)
83
+ .get(...runIds, ...(cites?.values ?? [])) !== undefined);
84
+ }
85
+ /** The kind's subjects as its stored orders of the last week show them. */
86
+ function storedSubjects(adapter, kind, now) {
87
+ const rows = adapter
88
+ .prepare(`SELECT m.stimulus_id, m.payload_json, m.status, n.state AS native_state
89
+ FROM mailbox_inputs m LEFT JOIN native_input_deliveries n ON n.input_id = m.id
90
+ WHERE m.kind = 'scheduled' AND m.channel_key = ? AND m.created_at >= ?
91
+ ORDER BY m.created_at, m.id`)
92
+ .all(kind.channel, now - exports.UPKEEP_WINDOW_MS);
93
+ const states = new Map();
94
+ let anyOpen = false;
95
+ for (const row of rows) {
96
+ const order = parseUpkeepOrder(JSON.parse(row.payload_json));
97
+ // A row parked uncertain stays claimed; it is settled through onLost, not left open.
98
+ const open = (row.status === 'pending' || row.status === 'claimed') && row.native_state !== 'uncertain';
99
+ anyOpen ||= open;
100
+ for (const subject of order.subjects) {
101
+ const current = states.get(subject.key);
102
+ states.set(subject.key, {
103
+ subject,
104
+ orders: [...(current?.orders ?? []), row.stimulus_id],
105
+ open: (current?.open ?? false) || open,
106
+ });
107
+ }
108
+ }
109
+ return { states, anyOpen };
110
+ }
111
+ /** A subject settled for good (upkeep_settled); a later write keeps the latest state. */
112
+ function recordSettled(adapter) {
113
+ return adapter.prepare(`INSERT OR REPLACE INTO upkeep_settled (kind, subject_key, state, settled_at) VALUES (?, ?, ?, ?)`);
114
+ }
115
+ /** Child runs of an order run that this process started and that have not ended yet. */
116
+ function runningChildren(adapter, modelRunId, startedAt) {
117
+ const row = adapter
118
+ .prepare(`SELECT count(*) AS n FROM model_runs
119
+ WHERE parent_model_run_id = ? AND status NOT IN ('committed', 'failed') AND created_at >= ?`)
120
+ .get(modelRunId, startedAt);
121
+ return row?.n ?? 0;
122
+ }
123
+ function createUpkeepOrders(options) {
124
+ const now = options.now ?? Date.now;
125
+ const sleep = options.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
126
+ const childWaitMs = options.childWaitMs ?? 10 * 60 * 1000;
127
+ const byName = new Map(options.kinds.map((kind) => [kind.name, kind]));
128
+ const byChannel = new Map(options.kinds.map((kind) => [kind.channel, kind]));
129
+ const timers = [];
130
+ // Orders whose check is still waiting for child runs: their subjects are not ordered again yet.
131
+ const checking = new Set();
132
+ // An order is settled once: a row parked uncertain and then closed reports here twice.
133
+ const settledOrders = new Set();
134
+ let stopped = false;
135
+ const kindOf = (row) => {
136
+ const kind = byChannel.get(row.channelKey);
137
+ if (!kind)
138
+ throw new Error(`No upkeep kind serves channel ${row.channelKey}`);
139
+ return kind;
140
+ };
141
+ const settle = (kind, orderId, order, reason) => {
142
+ if (settledOrders.has(orderId))
143
+ return;
144
+ settledOrders.add(orderId);
145
+ const at = now();
146
+ const { states } = storedSubjects(options.adapter, kind, at);
147
+ const record = recordSettled(options.adapter);
148
+ for (const subject of order.subjects) {
149
+ const orders = states.get(subject.key)?.orders ?? [];
150
+ if (kind.checked(options.adapter, subject, orderRunIds(options.adapter, orders))) {
151
+ record.run(kind.name, subject.key, 'checked', at);
152
+ options.onEvent?.({ type: 'checked', kind: kind.name, subject: subject.key });
153
+ continue;
154
+ }
155
+ const attempt = orders.length;
156
+ if (attempt >= exports.UPKEEP_MAX_ATTEMPTS) {
157
+ record.run(kind.name, subject.key, 'lost', at);
158
+ options.onEvent?.({ type: 'lost', kind: kind.name, subject: subject.key, attempt, reason });
159
+ }
160
+ else
161
+ options.onEvent?.({
162
+ type: 'waiting',
163
+ kind: kind.name,
164
+ subject: subject.key,
165
+ attempt,
166
+ reason,
167
+ });
168
+ }
169
+ };
170
+ const tick = (kindName) => {
171
+ const kind = byName.get(kindName);
172
+ if (!kind)
173
+ throw new Error(`Unknown upkeep kind ${kindName}`);
174
+ if (stopped)
175
+ return;
176
+ const at = now();
177
+ const { states, anyOpen } = storedSubjects(options.adapter, kind, at);
178
+ // One order of a kind at a time keeps the common session's queue for the owner; an order whose
179
+ // child runs may still write is not over yet.
180
+ if (anyOpen || [...checking].some((id) => id.startsWith(upkeepOrderIdPrefix(kind.name))))
181
+ return;
182
+ const settled = new Set(options.adapter
183
+ .prepare(`SELECT subject_key FROM upkeep_settled WHERE kind = ?`)
184
+ .all(kind.name).map((row) => row.subject_key));
185
+ const record = recordSettled(options.adapter);
186
+ const due = [];
187
+ const perGroup = new Map();
188
+ const candidates = function* () {
189
+ for (let page = 0;; page += 1) {
190
+ const rows = kind.scan(options.adapter, at, page);
191
+ yield* rows;
192
+ if (rows.length < exports.UPKEEP_SCAN_PAGE)
193
+ return;
194
+ }
195
+ };
196
+ for (const subject of candidates()) {
197
+ if (kind.group === undefined && due.length >= kind.maxPerOrder)
198
+ break;
199
+ const group = kind.group?.(subject);
200
+ if (group !== undefined && (perGroup.get(group) ?? 0) >= kind.maxPerOrder)
201
+ continue;
202
+ if (settled.has(subject.key))
203
+ continue;
204
+ const state = states.get(subject.key);
205
+ const orders = state?.orders ?? [];
206
+ // No order of the kind is open here, so these orders are over. Their settlement is recorded
207
+ // again: a stop during the child-run wait, a failed check or a crash in settle() leaves it
208
+ // unwritten, and the stored orders that show it are deleted after seven days.
209
+ if (orders.length > 0 &&
210
+ kind.checked(options.adapter, subject, orderRunIds(options.adapter, orders))) {
211
+ record.run(kind.name, subject.key, 'checked', at);
212
+ continue;
213
+ }
214
+ // Reported lost when its last order was settled; it is never ordered again.
215
+ if (orders.length >= exports.UPKEEP_MAX_ATTEMPTS) {
216
+ record.run(kind.name, subject.key, 'lost', at);
217
+ continue;
218
+ }
219
+ due.push(subject);
220
+ if (group !== undefined)
221
+ perGroup.set(group, (perGroup.get(group) ?? 0) + 1);
222
+ }
223
+ if (due.length === 0)
224
+ return;
225
+ const id = `${upkeepOrderIdPrefix(kind.name)}${at}:${(0, node_crypto_1.randomUUID)().slice(0, 8)}`;
226
+ const payload = { order: 'upkeep', kind: kind.name, subjects: due };
227
+ const receipt = options.accept({
228
+ id,
229
+ kind: 'scheduled',
230
+ channelKey: kind.channel,
231
+ occurredAt: at,
232
+ payload: payload,
233
+ });
234
+ if (receipt.state !== 'duplicate')
235
+ options.onEvent?.({ type: 'ordered', kind: kind.name, order: id, subjects: due.length });
236
+ };
237
+ return {
238
+ isUpkeepRow: (row) => row.kind === 'scheduled' && byChannel.has(row.channelKey),
239
+ render: (row, at) => kindOf(row).render(parseUpkeepOrder(row.payload).subjects, at),
240
+ // The check waits for child runs in the background so the owner's queue is never held.
241
+ onResult: (row, modelRunId) => {
242
+ const kind = kindOf(row);
243
+ const order = parseUpkeepOrder(row.payload);
244
+ checking.add(row.stimulusId);
245
+ void (async () => {
246
+ if (modelRunId !== null) {
247
+ const deadline = Date.now() + childWaitMs;
248
+ while (!stopped &&
249
+ runningChildren(options.adapter, modelRunId, options.processStartedAt) > 0 &&
250
+ Date.now() < deadline)
251
+ await sleep(5_000);
252
+ }
253
+ if (stopped)
254
+ return;
255
+ settle(kind, row.stimulusId, order, 'the order ended without the expected write or a no-update naming it');
256
+ })()
257
+ .catch((error) => {
258
+ // A check cut off by shutdown is not a loss: the next tick finds the subject again.
259
+ if (stopped)
260
+ return;
261
+ for (const subject of order.subjects)
262
+ options.onEvent?.({
263
+ type: 'lost',
264
+ kind: kind.name,
265
+ subject: subject.key,
266
+ attempt: 0,
267
+ reason: `upkeep check failed: ${error instanceof Error ? error.message : String(error)}`,
268
+ });
269
+ })
270
+ .finally(() => checking.delete(row.stimulusId));
271
+ },
272
+ onLost: (row, reason) => {
273
+ const kind = kindOf(row);
274
+ settle(kind, row.stimulusId, parseUpkeepOrder(row.payload), reason);
275
+ },
276
+ tick,
277
+ start: () => {
278
+ if (timers.length > 0 || stopped)
279
+ return;
280
+ for (const kind of options.kinds) {
281
+ const run = () => {
282
+ try {
283
+ tick(kind.name);
284
+ }
285
+ catch (error) {
286
+ // A scan that fails names its kind; no subject was ordered, so the next scan retries.
287
+ options.onEvent?.({
288
+ type: 'lost',
289
+ kind: kind.name,
290
+ subject: '*',
291
+ attempt: 0,
292
+ reason: `upkeep scan failed: ${error instanceof Error ? error.message : String(error)}`,
293
+ });
294
+ }
295
+ };
296
+ const first = setTimeout(run, options.firstTickDelayMs ?? 60_000);
297
+ const every = setInterval(run, kind.intervalMs);
298
+ first.unref?.();
299
+ every.unref?.();
300
+ timers.push({ cancel: () => clearTimeout(first) }, { cancel: () => clearInterval(every) });
301
+ }
302
+ },
303
+ stop: () => {
304
+ stopped = true;
305
+ for (const timer of timers.splice(0))
306
+ timer.cancel();
307
+ },
308
+ };
309
+ }
310
+ //# sourceMappingURL=upkeep-orders.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upkeep-orders.js","sourceRoot":"","sources":["../../src/runtime/upkeep-orders.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import type { JudgmentAccess } from '@jungjaehoon/mama-core/knowledge';
2
+ import { type WorkListViewContext } from '../api/work-actions.js';
3
+ import { type UpkeepKind } from './upkeep-orders.js';
4
+ export declare const RECONCILE_ORDER_CHANNEL = "operator:reconcile";
5
+ export interface ReconcileKindOptions {
6
+ knowledge: WorkListViewContext['knowledge'];
7
+ /** The common session's access: only work it can read is chosen. */
8
+ access: () => JudgmentAccess;
9
+ timeZone: () => string;
10
+ /** reports.full_report_hours, read at each scan: the first after midnight is the morning one. */
11
+ fullReportHours: () => readonly number[];
12
+ }
13
+ /**
14
+ * U3, board reconcile. Once a day before the morning report the host orders two groups of
15
+ * subject, at most ten of each:
16
+ * - an open item with cited cards that moved after the item's latest revision, all its moved cards
17
+ * in one subject keyed by the item and its latest move, so a new move is a new subject;
18
+ * - an item in progress or in review whose latest source event is over 30 days old, chosen the way
19
+ * work.list lastEventBefore chooses it, oldest first, keyed by the item and its latest revision
20
+ * from outside the reconcile orders.
21
+ * A subject is checked by a revision on the item from the order's runs, or a work.no_update
22
+ * naming it. The runner keeps settled subjects past the mailbox's retention (upkeep_settled).
23
+ */
24
+ export declare function reconcileUpkeepKind(options: ReconcileKindOptions): UpkeepKind;
25
+ //# sourceMappingURL=upkeep-reconcile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upkeep-reconcile.d.ts","sourceRoot":"","sources":["../../src/runtime/upkeep-reconcile.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAkB,cAAc,EAAE,MAAM,kCAAkC,CAAC;AACvF,OAAO,EAIL,KAAK,mBAAmB,EACzB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EAKL,KAAK,UAAU,EAEhB,MAAM,oBAAoB,CAAC;AAE5B,eAAO,MAAM,uBAAuB,uBAAuB,CAAC;AAO5D,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,mBAAmB,CAAC,WAAW,CAAC,CAAC;IAC5C,oEAAoE;IACpE,MAAM,EAAE,MAAM,cAAc,CAAC;IAC7B,QAAQ,EAAE,MAAM,MAAM,CAAC;IACvB,iGAAiG;IACjG,eAAe,EAAE,MAAM,SAAS,MAAM,EAAE,CAAC;CAC1C;AAoID;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,UAAU,CAsI7E"}
@@ -0,0 +1,231 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RECONCILE_ORDER_CHANNEL = void 0;
4
+ exports.reconcileUpkeepKind = reconcileUpkeepKind;
5
+ const work_actions_js_1 = require("../api/work-actions.js");
6
+ const untrusted_content_js_1 = require("../utils/untrusted-content.js");
7
+ const timezone_js_1 = require("./timezone.js");
8
+ const upkeep_orders_js_1 = require("./upkeep-orders.js");
9
+ exports.RECONCILE_ORDER_CHANNEL = 'operator:reconcile';
10
+ const KIND = 'reconcile';
11
+ /** The stale step the daily page carried until U3: items in progress or in review. */
12
+ const STALE_STATUSES = ['in_progress', 'review'];
13
+ /** An item whose latest source event is older than this is stale. */
14
+ const STALE_AFTER_MS = 30 * 24 * 60 * 60 * 1000;
15
+ /**
16
+ * Whether the day's order is due: from local midnight until the first full report after midnight
17
+ * (or the next midnight when there is none), once a local day. The hourly tick finds it due at its
18
+ * first run of the day; a restart in the same morning finds the order already placed, and a
19
+ * subject the order missed waits for the next day.
20
+ */
21
+ function due(adapter, now, zone, hours) {
22
+ const day = (0, timezone_js_1.localDateKey)(now, zone);
23
+ const midnight = (0, timezone_js_1.epochAtLocalDateTime)(`${day}T00:00:00`, zone);
24
+ const after = hours.filter((hour) => hour > 0);
25
+ if (after.length > 0) {
26
+ const morning = String(Math.min(...after)).padStart(2, '0');
27
+ if (now >= (0, timezone_js_1.epochAtLocalDateTime)(`${day}T${morning}:00:00`, zone))
28
+ return false;
29
+ }
30
+ return (adapter
31
+ .prepare(`SELECT 1 FROM mailbox_inputs
32
+ WHERE kind = 'scheduled' AND channel_key = ? AND created_at >= ? LIMIT 1`)
33
+ .get(exports.RECONCILE_ORDER_CHANNEL, midnight) === undefined);
34
+ }
35
+ /**
36
+ * The time of an item's latest revision on the source timeline: its event time, or its write time
37
+ * when it has none, as work.list's event spans read a revision. A backfill writes an earlier
38
+ * period after later revisions, so the last-written revision is not always the latest one.
39
+ */
40
+ function latestRevisionAt(item) {
41
+ return Math.max(...(item.chain ?? []).map((entry) => entry.eventDatetime ?? entry.createdAt));
42
+ }
43
+ /**
44
+ * The card ids among the observations each item's revisions cite. Card ids are read from the
45
+ * observation's metadata (`cardId`), which only the Trello connector writes today; it stores the
46
+ * board id there for a board-level action, which names no card. Read from the item side, every
47
+ * join is on a key (an edge's object is the observation id).
48
+ */
49
+ function citedCards(adapter) {
50
+ const rows = adapter
51
+ .prepare(`SELECT DISTINCT a.commitment_id AS commitmentId, o.source AS connector,
52
+ json_extract(o.metadata_json, '$.cardId') AS card
53
+ FROM commitment_assignments a
54
+ JOIN twin_edges e ON e.subject_kind = 'memory' AND e.subject_id = a.record_id
55
+ AND e.edge_type = 'derived_from' AND e.object_kind = 'observation'
56
+ JOIN observation_versions o ON o.observation_id = e.object_id
57
+ WHERE json_extract(o.metadata_json, '$.cardId') IS NOT NULL
58
+ AND json_extract(o.metadata_json, '$.cardId') IS NOT json_extract(o.metadata_json, '$.boardId')
59
+ ORDER BY commitmentId, connector, card`)
60
+ .all();
61
+ const cards = new Map();
62
+ for (const row of rows)
63
+ cards.set(row.commitmentId, [
64
+ ...(cards.get(row.commitmentId) ?? []),
65
+ { connector: row.connector, card: row.card },
66
+ ]);
67
+ return cards;
68
+ }
69
+ /**
70
+ * Stored list moves in the attempt window, oldest first: a stored board event whose action data
71
+ * names the list the card went to (`data.listAfter`). A subject older than the window would count
72
+ * its attempts from zero again.
73
+ */
74
+ function windowMoves(adapter, since, now) {
75
+ return adapter
76
+ .prepare(`SELECT source_connector AS connector, json_extract(metadata_json, '$.cardId') AS card,
77
+ source_id AS event, current_observation_id AS ref, event_datetime AS at
78
+ FROM connector_event_index
79
+ WHERE event_datetime >= ? AND event_datetime <= ?
80
+ AND json_extract(metadata_json, '$.data.listAfter') IS NOT NULL
81
+ AND json_extract(metadata_json, '$.cardId') IS NOT NULL
82
+ AND current_observation_id IS NOT NULL
83
+ ORDER BY event_datetime, source_id`)
84
+ .all(since, now);
85
+ }
86
+ /**
87
+ * Each item's latest revision not written by a reconcile order's run or its child runs. A stale
88
+ * subject is keyed by it: an order that keeps the item with a work.revise does not make it a new
89
+ * subject the next morning, while a revision from anywhere else does.
90
+ */
91
+ function outsideRevisions(adapter, ids) {
92
+ if (ids.length === 0)
93
+ return new Map();
94
+ const prefix = `${(0, upkeep_orders_js_1.upkeepOrderIdPrefix)(KIND)}%`;
95
+ const rows = adapter
96
+ .prepare(`WITH order_runs AS (
97
+ SELECT model_run_id FROM model_runs
98
+ WHERE json_extract(input_refs_json, '$.sourceMessageRef') LIKE ?
99
+ UNION
100
+ SELECT c.model_run_id FROM model_runs c JOIN model_runs p ON c.parent_model_run_id = p.model_run_id
101
+ WHERE json_extract(p.input_refs_json, '$.sourceMessageRef') LIKE ?)
102
+ SELECT commitment_id AS commitmentId, MAX(revision) AS revision FROM commitment_assignments
103
+ WHERE commitment_id IN (${ids.map(() => '?').join(',')})
104
+ AND (model_run_id IS NULL OR model_run_id NOT IN (SELECT model_run_id FROM order_runs))
105
+ GROUP BY commitment_id`)
106
+ .all(prefix, prefix, ...ids);
107
+ return new Map(rows.map((row) => [row.commitmentId, row.revision]));
108
+ }
109
+ function title(item) {
110
+ return typeof item.values.title === 'string' ? item.values.title : '';
111
+ }
112
+ /**
113
+ * U3, board reconcile. Once a day before the morning report the host orders two groups of
114
+ * subject, at most ten of each:
115
+ * - an open item with cited cards that moved after the item's latest revision, all its moved cards
116
+ * in one subject keyed by the item and its latest move, so a new move is a new subject;
117
+ * - an item in progress or in review whose latest source event is over 30 days old, chosen the way
118
+ * work.list lastEventBefore chooses it, oldest first, keyed by the item and its latest revision
119
+ * from outside the reconcile orders.
120
+ * A subject is checked by a revision on the item from the order's runs, or a work.no_update
121
+ * naming it. The runner keeps settled subjects past the mailbox's retention (upkeep_settled).
122
+ */
123
+ function reconcileUpkeepKind(options) {
124
+ return {
125
+ name: KIND,
126
+ channel: exports.RECONCILE_ORDER_CHANNEL,
127
+ intervalMs: 60 * 60 * 1000,
128
+ maxPerOrder: 10,
129
+ group: (subject) => subject.group,
130
+ scan: (adapter, now, page) => {
131
+ const zone = options.timeZone();
132
+ if (!due(adapter, now, zone, options.fullReportHours()))
133
+ return [];
134
+ const ledger = (0, work_actions_js_1.workListLedger)({ knowledge: options.knowledge, access: options.access(), timeZone: zone, now: () => now }, { status: STALE_STATUSES, lastEventBefore: now - STALE_AFTER_MS });
135
+ const open = new Map(ledger
136
+ .filter((entry) => work_actions_js_1.OPEN_WORK_STATUSES.includes(entry.status))
137
+ .map((entry) => [entry.item.commitmentId, entry]));
138
+ const cards = citedCards(adapter);
139
+ const citing = new Map();
140
+ for (const [commitmentId, list] of cards)
141
+ for (const card of list) {
142
+ const at = `${card.connector}\n${card.card}`;
143
+ citing.set(at, [...(citing.get(at) ?? []), commitmentId]);
144
+ }
145
+ // Per item, each cited card's latest move that the item's revisions have not caught up with.
146
+ const movesOf = new Map();
147
+ for (const move of windowMoves(adapter, now - upkeep_orders_js_1.UPKEEP_WINDOW_MS, now))
148
+ for (const commitmentId of citing.get(`${move.connector}\n${move.card}`) ?? []) {
149
+ const entry = open.get(commitmentId);
150
+ if (!entry || move.at <= latestRevisionAt(entry.item))
151
+ continue;
152
+ const byCard = movesOf.get(commitmentId) ?? new Map();
153
+ byCard.set(`${move.connector}\n${move.card}`, move);
154
+ movesOf.set(commitmentId, byCard);
155
+ }
156
+ const moved = [...movesOf].map(([commitmentId, byCard]) => {
157
+ const entry = open.get(commitmentId);
158
+ const moves = [...byCard.values()].sort((a, b) => a.at - b.at);
159
+ return {
160
+ key: `move:${commitmentId}:${moves.at(-1).connector}:${moves.at(-1).event}`,
161
+ group: 'move',
162
+ commitmentId,
163
+ title: title(entry.item),
164
+ status: entry.status,
165
+ lastEventAt: null,
166
+ cards: [],
167
+ moves,
168
+ revisedAt: latestRevisionAt(entry.item),
169
+ };
170
+ });
171
+ moved.sort((a, b) => a.moves.at(-1).at - b.moves.at(-1).at || a.key.localeCompare(b.key));
172
+ const staleEntries = ledger
173
+ .filter((entry) => entry.stale)
174
+ .sort((a, b) => a.lastEvent - b.lastEvent || a.item.commitmentId.localeCompare(b.item.commitmentId));
175
+ const revisions = outsideRevisions(adapter, staleEntries.map((entry) => entry.item.commitmentId));
176
+ const stale = staleEntries.map((entry) => ({
177
+ // An item the orders themselves created has no outside revision: revision 0.
178
+ key: `stale:${entry.item.commitmentId}:${revisions.get(entry.item.commitmentId) ?? 0}`,
179
+ group: 'stale',
180
+ commitmentId: entry.item.commitmentId,
181
+ title: title(entry.item),
182
+ status: entry.status,
183
+ lastEventAt: entry.lastEvent,
184
+ cards: cards.get(entry.item.commitmentId) ?? [],
185
+ moves: [],
186
+ revisedAt: null,
187
+ }));
188
+ return [...moved, ...stale].slice(page * upkeep_orders_js_1.UPKEEP_SCAN_PAGE, (page + 1) * upkeep_orders_js_1.UPKEEP_SCAN_PAGE);
189
+ },
190
+ checked: (adapter, subject, runIds) => {
191
+ const { commitmentId } = subject;
192
+ if (runIds.length === 0)
193
+ return false;
194
+ const revised = adapter
195
+ .prepare(`SELECT 1 FROM commitment_assignments
196
+ WHERE commitment_id = ? AND model_run_id IN (${runIds.map(() => '?').join(',')})
197
+ LIMIT 1`)
198
+ .get(commitmentId, ...runIds) !== undefined;
199
+ return (revised ||
200
+ (0, upkeep_orders_js_1.noUpdateCites)(adapter, runIds, { field: 'commitmentIds', values: [commitmentId] }));
201
+ },
202
+ render: (subjects, now) => {
203
+ const zone = options.timeZone();
204
+ const all = subjects;
205
+ const at = (ms) => (0, timezone_js_1.localNow)(ms, zone);
206
+ const lines = all.map((subject) => subject.group === 'move'
207
+ ? `- moved ${subject.commitmentId} (${subject.status}), after the item's latest revision ${at(subject.revisedAt)}: ${subject.moves
208
+ .map((move) => `card ${move.card} (${move.connector}) moved ${at(move.at)}, event ${move.ref}`)
209
+ .join('; ')}`
210
+ : `- stale ${subject.commitmentId} (${subject.status}): latest source event ${at(subject.lastEventAt)}; ${subject.cards.length === 0
211
+ ? 'cites no card'
212
+ : `cards ${subject.cards.map((card) => `${card.card} (${card.connector})`).join(', ')}`}`);
213
+ // Titles come from stored work, which sources can shape: they are data, never instructions.
214
+ const titles = all.map((subject) => `${subject.commitmentId}: ${subject.title.replace(/\s+/g, ' ').slice(0, 200)}`);
215
+ return [
216
+ `[upkeep_reconcile] ${all.length} work item${all.length === 1 ? '' : 's'} to reconcile with the board`,
217
+ `Current time: ${at(now.getTime())} (${zone})`,
218
+ 'Each item below may no longer match its source: a card it cites moved after its latest revision, or it is still in progress or in review with no source event in over 30 days (work.list lastEventBefore, not changedBefore: a backfill or correction rewrote many items later without a new event). Settle each one, so the ledger matches the board:',
219
+ "1. Read each item with work.list view=detail with ids (up to 4 per call), and its last originals with source.read (a moved item's move events first).",
220
+ '2. Read each listed card live with its connector: trello.read view=card id=<card id>. An item that cites no card but is board work: find its card with trello.read view=search (by its title), and say so when none exists. A stored move only chose the item; the live card decides. When the live card differs from its stored events, the collection has a gap: say so in the reason.',
221
+ '3. Close, cancel, change or keep each item: work.revise with what changed and why, linking what it rests on with derived_from; or, when it stays as it is, work.no_update with commitmentIds naming it and why it stays.',
222
+ '4. The order is checked when it ends: each item needs step 3. Correct a refused write (help gives its contract) and write it again.',
223
+ '5. Reply exactly [ack].',
224
+ 'Items, at most ten moved and ten stale a day, stale oldest first; the rest come in the next days:',
225
+ ...lines,
226
+ (0, untrusted_content_js_1.wrapUntrustedContent)('work_titles', titles.join('\n')),
227
+ ].join('\n');
228
+ },
229
+ };
230
+ }
231
+ //# sourceMappingURL=upkeep-reconcile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upkeep-reconcile.js","sourceRoot":"","sources":["../../src/runtime/upkeep-reconcile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import { type UpkeepKind } from './upkeep-orders.js';
2
+ export declare const WRITEBACK_ORDER_CHANNEL = "operator:writeback";
3
+ export interface WritebackKindOptions {
4
+ /**
5
+ * The non-chat connectors the common session reads in full (ownerAccess.connectorWideRead).
6
+ * Their observations carry no memory scope, and the owner read path admits them by connector
7
+ * (observations.ts isObservationVisibilityRowVisible), so the same list decides they are common.
8
+ */
9
+ wideReadConnectors: () => readonly string[];
10
+ /** The common session's principal: its question turns qualify, and its chat scope is common. */
11
+ ownerPrincipalId: string;
12
+ timeZone: () => string;
13
+ }
14
+ /**
15
+ * U2, write-back orders. A subject is one question turn (a committed owner_message run of the
16
+ * common session or an owner-role principal) that read common-scope sources and recorded nothing
17
+ * from them. The order carries only common-scope handles; the question text is never carried. It
18
+ * is checked when the order's run writes a revision or a fact/lesson citing one of the handles, or
19
+ * declares work.no_update naming them.
20
+ */
21
+ export declare function writebackUpkeepKind(options: WritebackKindOptions): UpkeepKind;
22
+ //# sourceMappingURL=upkeep-writeback.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upkeep-writeback.d.ts","sourceRoot":"","sources":["../../src/runtime/upkeep-writeback.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,UAAU,EAEhB,MAAM,oBAAoB,CAAC;AAE5B,eAAO,MAAM,uBAAuB,uBAAuB,CAAC;AAK5D,MAAM,WAAW,oBAAoB;IACnC;;;;OAIG;IACH,kBAAkB,EAAE,MAAM,SAAS,MAAM,EAAE,CAAC;IAC5C,gGAAgG;IAChG,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,MAAM,CAAC;CACxB;AAgGD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,UAAU,CA0I7E"}