@wirecat/cli-memo 0.131.78 → 0.131.80

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 (174) hide show
  1. package/dist/bin/memo.js +2 -2
  2. package/dist/bundle/{all-profiles-ZEUEPNFD.js → all-profiles-RVKEGURX.js} +9 -9
  3. package/dist/bundle/{anthropic-VF75LSDZ.js → anthropic-FC6XUSWM.js} +6 -6
  4. package/dist/bundle/{app-server-Z4TY5VP5.js → app-server-IRNKU3IF.js} +41 -41
  5. package/dist/bundle/auto-GTL4YGZX.js +91 -0
  6. package/dist/bundle/{bun-OUR5UZAI.js → bun-TYBGE5BX.js} +2 -2
  7. package/dist/bundle/{bun-sqlite-26ZGEVH3.js → bun-sqlite-YENHHNPL.js} +10 -6
  8. package/dist/bundle/{chunk-DDPZY27T.js → chunk-2CJIZZSI.js} +16 -16
  9. package/dist/bundle/{chunk-3QBRLN6T.js → chunk-2EGS6BXF.js} +2 -2
  10. package/dist/bundle/{chunk-IFANDP3T.js → chunk-2FICCBKH.js} +14 -2
  11. package/dist/bundle/{chunk-OHMF7LWW.js → chunk-3H56E3VI.js} +5 -5
  12. package/dist/bundle/{chunk-WYSFOL74.js → chunk-4IKO3JAA.js} +4 -4
  13. package/dist/bundle/{chunk-6A37YXAL.js → chunk-5LEIPSJG.js} +24 -0
  14. package/dist/bundle/{chunk-VJLJFLKZ.js → chunk-666J5H2Z.js} +1 -1
  15. package/dist/bundle/{chunk-ELKRFQ5Y.js → chunk-6W6CLZKX.js} +12 -12
  16. package/dist/bundle/{chunk-22RYCAAO.js → chunk-BS5JBNGX.js} +9625 -9046
  17. package/dist/bundle/{chunk-5PCPPT43.js → chunk-C2FE62E5.js} +31 -31
  18. package/dist/bundle/{chunk-Z4TPRASF.js → chunk-C4TAEYDQ.js} +5 -5
  19. package/dist/bundle/{chunk-UIJBGS6K.js → chunk-CEGA7A35.js} +2 -2
  20. package/dist/bundle/{chunk-MUFU4LNS.js → chunk-CUWTYE5A.js} +2 -2
  21. package/dist/bundle/{chunk-EI7LYQQA.js → chunk-CVQJ7L4C.js} +4 -4
  22. package/dist/bundle/{chunk-EXFRC4OT.js → chunk-DCK5AT3D.js} +1 -1
  23. package/dist/bundle/{chunk-DAEPTQ6N.js → chunk-DS5SA5QP.js} +5 -5
  24. package/dist/bundle/{chunk-OMGNXKSH.js → chunk-EOXWI2EX.js} +4 -4
  25. package/dist/bundle/{chunk-EF33DKMR.js → chunk-F62N6QMI.js} +1 -1
  26. package/dist/bundle/{chunk-P3UQGKGY.js → chunk-FIJTCBPQ.js} +10 -10
  27. package/dist/bundle/{chunk-T37LLOZR.js → chunk-FR646D4S.js} +1 -1
  28. package/dist/bundle/{chunk-6GHBGGN7.js → chunk-GHYJW4ZH.js} +2 -2
  29. package/dist/bundle/{chunk-6ABWVQ4T.js → chunk-GNII3UL7.js} +1 -1
  30. package/dist/bundle/{chunk-YOM4PA3A.js → chunk-HFQXEMRG.js} +1 -1
  31. package/dist/bundle/{chunk-OMCET4QP.js → chunk-HHZMDFE2.js} +47 -47
  32. package/dist/bundle/{chunk-WETWQO6X.js → chunk-HKXACNLD.js} +2 -2
  33. package/dist/bundle/{chunk-QEJHNTCX.js → chunk-HXPU3ABX.js} +511 -349
  34. package/dist/bundle/{chunk-4LZLU2V3.js → chunk-IJUXHUNZ.js} +3 -3
  35. package/dist/bundle/{chunk-GXHPPHGB.js → chunk-IW6O2SAG.js} +11 -11
  36. package/dist/bundle/{chunk-N7CHOWDF.js → chunk-JDQSL2EY.js} +3 -3
  37. package/dist/bundle/{chunk-WHZJHUK6.js → chunk-JJ6ODCVQ.js} +2 -2
  38. package/dist/bundle/{chunk-7ENXMVT5.js → chunk-JPC7GSJO.js} +20 -11
  39. package/dist/bundle/{chunk-E5JVYVRX.js → chunk-JTQAMVZH.js} +15 -14
  40. package/dist/bundle/{chunk-Q2CQNT3A.js → chunk-K3JEAMTT.js} +1 -1
  41. package/dist/bundle/{chunk-AZIXZIXT.js → chunk-KDLOSANT.js} +7 -7
  42. package/dist/bundle/{chunk-D67YDJ35.js → chunk-KNRYIHUJ.js} +1049 -902
  43. package/dist/bundle/{chunk-B2ZAEF5Z.js → chunk-KVQY7R66.js} +2 -2
  44. package/dist/bundle/{chunk-H2AQV772.js → chunk-MDIXXKVU.js} +10 -10
  45. package/dist/bundle/{chunk-LJRXD44C.js → chunk-MLYPJ4EC.js} +7 -7
  46. package/dist/bundle/{chunk-Y2J52Y3A.js → chunk-NH7KIGIS.js} +3 -3
  47. package/dist/bundle/{chunk-XC26CUGL.js → chunk-NUKMYB65.js} +6 -6
  48. package/dist/bundle/{chunk-PTKJIA7M.js → chunk-OFRIG3CX.js} +3 -3
  49. package/dist/bundle/{chunk-WHMKYJZR.js → chunk-OH4AIBZF.js} +1 -1
  50. package/dist/bundle/{chunk-TWWYDJBW.js → chunk-OSE7GXAR.js} +1 -1
  51. package/dist/bundle/{chunk-QU7UPCW2.js → chunk-PX55CRD3.js} +86 -81
  52. package/dist/bundle/{chunk-7DKS4GIW.js → chunk-Q46O7KXY.js} +5 -5
  53. package/dist/bundle/chunk-R4XCBPD2.js +53 -0
  54. package/dist/bundle/{chunk-X2SA73EE.js → chunk-RK24IARI.js} +1 -1
  55. package/dist/bundle/{chunk-TT5RMHM6.js → chunk-RUM4GGHP.js} +5 -5
  56. package/dist/bundle/{chunk-5NBQOU5V.js → chunk-RWVB7SLQ.js} +26 -23
  57. package/dist/bundle/{chunk-MW6IAMUI.js → chunk-S2KXO7MO.js} +1 -1
  58. package/dist/bundle/{chunk-2IQWMWMC.js → chunk-SB3AOH3M.js} +3 -3
  59. package/dist/bundle/{chunk-NXQFVHG4.js → chunk-SGV2Z4BO.js} +165 -152
  60. package/dist/bundle/{chunk-XTCN3VUP.js → chunk-SKX3BNTE.js} +8 -8
  61. package/dist/bundle/{chunk-OUATPEPP.js → chunk-SULQCO3Y.js} +6 -6
  62. package/dist/bundle/{chunk-KUY35N7Q.js → chunk-TJ2B36VK.js} +7 -7
  63. package/dist/bundle/{chunk-ZKCAR2OL.js → chunk-UBUCTVHB.js} +1 -1
  64. package/dist/bundle/{chunk-T6LXUBXY.js → chunk-UTYGPWUY.js} +3 -3
  65. package/dist/bundle/{chunk-JHW2ARPA.js → chunk-VQJDYQ55.js} +34 -34
  66. package/dist/bundle/{chunk-F7MKFYYP.js → chunk-VTBIVTS5.js} +3 -3
  67. package/dist/bundle/{chunk-EIQ6HCIB.js → chunk-W26VONC6.js} +7 -7
  68. package/dist/bundle/{chunk-I6CZU7X7.js → chunk-X3NHAO6T.js} +1 -1
  69. package/dist/bundle/{chunk-3QV5JWFN.js → chunk-XZJUAG7B.js} +3 -3
  70. package/dist/bundle/{chunk-UWF6WXM7.js → chunk-ZMLDVE22.js} +7 -7
  71. package/dist/bundle/{chunk-NGWKI3E6.js → chunk-ZMSEKQQQ.js} +1 -1
  72. package/dist/bundle/command-contract-SR6ONYV4.js +34 -0
  73. package/dist/bundle/{command-server-entry-A7ZCZWHH.js → command-server-entry-2WXZVYIX.js} +21 -21
  74. package/dist/bundle/{decode-FO2ELPW6.js → decode-U7VFYQAA.js} +6 -6
  75. package/dist/bundle/{dispatch-N73TJNYM.js → dispatch-BRRZ6TLX.js} +1 -1
  76. package/dist/bundle/{echarts-HTY3OB2X.js → echarts-2PXBBLLJ.js} +2 -2
  77. package/dist/bundle/{embed-2DTGMR7Z.js → embed-DPA5QOIR.js} +7 -7
  78. package/dist/bundle/{embedder-N3IGQ2M6.js → embedder-IGI2UTFK.js} +10 -10
  79. package/dist/bundle/{entry-YDEKGRCA.js → entry-7PAYGIQO.js} +9 -9
  80. package/dist/bundle/{entry-Q7CIJ3TU.js → entry-IFOQTBXC.js} +9 -9
  81. package/dist/bundle/{failure-IPHFR3KW.js → failure-ECNGLVHX.js} +2 -2
  82. package/dist/bundle/failure-NAM37T2T.js +71 -0
  83. package/dist/bundle/{first-run-SAADMYEA.js → first-run-WHDDKA4V.js} +10 -10
  84. package/dist/bundle/first-screen-P5C57USR.js +32 -0
  85. package/dist/bundle/{instructions-XB5Y5DFA.js → instructions-W7F7OQZS.js} +1 -1
  86. package/dist/bundle/mcp-3LAFWOGW.js +92 -0
  87. package/dist/bundle/memo.js +6 -6
  88. package/dist/bundle/{node-4ZOD7X75.js → node-K6MWX3SW.js} +2 -2
  89. package/dist/bundle/{node-sqlite-DWXKYFW6.js → node-sqlite-WV6GCPEC.js} +11 -7
  90. package/dist/bundle/{oauth-GMIBNJQB.js → oauth-EH2Y54DG.js} +8 -8
  91. package/dist/bundle/{open-3DBI3MHV.js → open-PB4W3UAM.js} +6 -6
  92. package/dist/bundle/{openai-HFJAR7W5.js → openai-76OKHXWR.js} +11 -11
  93. package/dist/bundle/{process-2H5HNPHH.js → process-FMQ7Q7AI.js} +1 -1
  94. package/dist/bundle/{program-VXKN6DLP.js → program-BR2QHF36.js} +403 -142
  95. package/dist/bundle/{prompt-WETKFAQS.js → prompt-AW4T6CC2.js} +6 -6
  96. package/dist/bundle/{recognize-5LC3DQ2W.js → recognize-X5DMT3HH.js} +5 -5
  97. package/dist/bundle/{remote-FURTWZ25.js → remote-HVKKXNYZ.js} +8 -8
  98. package/dist/bundle/{rerank-CMQWT3WC.js → rerank-IXMWD7JV.js} +8 -8
  99. package/dist/bundle/{serve-LEF3PX34.js → serve-42XTYB26.js} +10 -10
  100. package/dist/bundle/server-HUEXB5QL.js +64 -0
  101. package/dist/bundle/{server-GYLFN6Y7.js → server-NNE7MUYT.js} +59 -59
  102. package/dist/bundle/server-YLXOJOTR.js +50 -0
  103. package/dist/bundle/{state-OVZT24JF.js → state-EOU37GAH.js} +7 -7
  104. package/dist/bundle/{store-SV46T732.js → store-F3REYMA6.js} +13 -13
  105. package/dist/bundle/store-maintenance-command-TOBBH3ZK.js +49 -0
  106. package/dist/bundle/update-3QB752NL.js +74 -0
  107. package/dist/examples.d.ts.map +1 -1
  108. package/dist/examples.js +13 -3
  109. package/dist/examples.js.map +1 -1
  110. package/dist/knowledge/command.d.ts.map +1 -1
  111. package/dist/knowledge/command.js +2 -0
  112. package/dist/knowledge/command.js.map +1 -1
  113. package/dist/knowledge/document-context.d.ts +14 -0
  114. package/dist/knowledge/document-context.d.ts.map +1 -0
  115. package/dist/knowledge/document-context.js +33 -0
  116. package/dist/knowledge/document-context.js.map +1 -0
  117. package/dist/knowledge/project-activity-command.d.ts +5 -0
  118. package/dist/knowledge/project-activity-command.d.ts.map +1 -0
  119. package/dist/knowledge/project-activity-command.js +71 -0
  120. package/dist/knowledge/project-activity-command.js.map +1 -0
  121. package/dist/knowledge/relationships.d.ts +4 -0
  122. package/dist/knowledge/relationships.d.ts.map +1 -1
  123. package/dist/knowledge/relationships.js +14 -0
  124. package/dist/knowledge/relationships.js.map +1 -1
  125. package/dist/knowledge/roles-command.d.ts.map +1 -1
  126. package/dist/knowledge/roles-command.js +7 -4
  127. package/dist/knowledge/roles-command.js.map +1 -1
  128. package/dist/mcp/catalogue.d.ts +4 -4
  129. package/dist/mcp/catalogue.d.ts.map +1 -1
  130. package/dist/mcp/catalogue.js +2 -2
  131. package/dist/mcp/catalogue.js.map +1 -1
  132. package/dist/people/doubts-command.d.ts +5 -0
  133. package/dist/people/doubts-command.d.ts.map +1 -0
  134. package/dist/people/doubts-command.js +46 -0
  135. package/dist/people/doubts-command.js.map +1 -0
  136. package/dist/people/identities-command.d.ts.map +1 -1
  137. package/dist/people/identities-command.js +52 -57
  138. package/dist/people/identities-command.js.map +1 -1
  139. package/dist/people/proposal-rows.d.ts +48 -0
  140. package/dist/people/proposal-rows.d.ts.map +1 -0
  141. package/dist/people/proposal-rows.js +61 -0
  142. package/dist/people/proposal-rows.js.map +1 -0
  143. package/dist/people/proposals-command.d.ts +5 -0
  144. package/dist/people/proposals-command.d.ts.map +1 -0
  145. package/dist/people/proposals-command.js +107 -0
  146. package/dist/people/proposals-command.js.map +1 -0
  147. package/dist/program.d.ts.map +1 -1
  148. package/dist/program.js +1 -0
  149. package/dist/program.js.map +1 -1
  150. package/dist/reasons.d.ts.map +1 -1
  151. package/dist/reasons.js +12 -0
  152. package/dist/reasons.js.map +1 -1
  153. package/dist/review/kinds.d.ts +1 -1
  154. package/dist/review/kinds.d.ts.map +1 -1
  155. package/dist/review/kinds.js +1 -0
  156. package/dist/review/kinds.js.map +1 -1
  157. package/dist/tasks/shared.d.ts.map +1 -1
  158. package/dist/tasks/shared.js +14 -2
  159. package/dist/tasks/shared.js.map +1 -1
  160. package/dist/version.d.ts +1 -1
  161. package/dist/version.js +1 -1
  162. package/package.json +2 -2
  163. package/skills/cli-memo/topics/proposals.md +10 -6
  164. package/dist/bundle/auto-SA667UAT.js +0 -91
  165. package/dist/bundle/chunk-VHA3LJQT.js +0 -35
  166. package/dist/bundle/command-contract-L5GTW74N.js +0 -34
  167. package/dist/bundle/failure-QL3RJILP.js +0 -71
  168. package/dist/bundle/first-screen-WXKAIMY6.js +0 -32
  169. package/dist/bundle/mcp-IRJS472M.js +0 -92
  170. package/dist/bundle/server-C2EVLJLW.js +0 -64
  171. package/dist/bundle/server-L7GHFXJF.js +0 -50
  172. package/dist/bundle/store-maintenance-command-TZYC5HVL.js +0 -49
  173. package/dist/bundle/update-PRBIV3RG.js +0 -74
  174. /package/dist/bundle/{chunk-DK3W4FPW.js → chunk-ID2I2X2Z.js} +0 -0
@@ -6,18 +6,18 @@ import {
6
6
  autoState,
7
7
  lastAutoRun,
8
8
  recordAutoRun
9
- } from "./chunk-OHMF7LWW.js";
9
+ } from "./chunk-3H56E3VI.js";
10
10
  import {
11
11
  installer,
12
12
  latest,
13
13
  upgradeCommand
14
- } from "./chunk-AZIXZIXT.js";
14
+ } from "./chunk-KDLOSANT.js";
15
15
  import {
16
16
  mcpOwnerAllowed,
17
17
  memoLevels,
18
18
  readOnlyAvailability,
19
19
  refuseWritesUnderLock
20
- } from "./chunk-7DKS4GIW.js";
20
+ } from "./chunk-Q46O7KXY.js";
21
21
  import {
22
22
  answers,
23
23
  atDetail,
@@ -29,7 +29,7 @@ import {
29
29
  trackAnswers,
30
30
  wholeList,
31
31
  withStore
32
- } from "./chunk-EIQ6HCIB.js";
32
+ } from "./chunk-W26VONC6.js";
33
33
  import {
34
34
  ATTACHMENT_CHARS,
35
35
  DIALECTS,
@@ -66,15 +66,15 @@ import {
66
66
  showMail,
67
67
  unsetConfigKey,
68
68
  updateConfig
69
- } from "./chunk-JHW2ARPA.js";
69
+ } from "./chunk-VQJDYQ55.js";
70
70
  import "./chunk-QP3KNC5D.js";
71
- import "./chunk-MUFU4LNS.js";
72
- import "./chunk-XTCN3VUP.js";
73
- import "./chunk-PTKJIA7M.js";
71
+ import "./chunk-CUWTYE5A.js";
72
+ import "./chunk-SKX3BNTE.js";
73
+ import "./chunk-OFRIG3CX.js";
74
74
  import {
75
75
  errorObject,
76
76
  recognisable
77
- } from "./chunk-XC26CUGL.js";
77
+ } from "./chunk-NUKMYB65.js";
78
78
  import {
79
79
  provideTerminal,
80
80
  terminalOf
@@ -151,34 +151,34 @@ import {
151
151
  thisMachine,
152
152
  withSqliteSidecars,
153
153
  writeSchedule
154
- } from "./chunk-D67YDJ35.js";
155
- import "./chunk-T37LLOZR.js";
154
+ } from "./chunk-KNRYIHUJ.js";
155
+ import "./chunk-FR646D4S.js";
156
156
  import "./chunk-A3QZXQI3.js";
157
- import "./chunk-6ABWVQ4T.js";
157
+ import "./chunk-GNII3UL7.js";
158
158
  import {
159
159
  allHitItem,
160
160
  coverageGaps,
161
161
  messageHitItem,
162
162
  noteHitItem,
163
163
  shownOf
164
- } from "./chunk-5NBQOU5V.js";
165
- import "./chunk-YOM4PA3A.js";
164
+ } from "./chunk-RWVB7SLQ.js";
165
+ import "./chunk-HFQXEMRG.js";
166
166
  import {
167
167
  REASONS as REASONS2,
168
168
  SKILL_TARGETS,
169
169
  skillCommand,
170
170
  skillPath,
171
171
  skillVersion
172
- } from "./chunk-7ENXMVT5.js";
173
- import "./chunk-EI7LYQQA.js";
172
+ } from "./chunk-JPC7GSJO.js";
173
+ import "./chunk-CVQJ7L4C.js";
174
174
  import {
175
175
  recoveryNotes,
176
176
  storeInfo,
177
177
  storeRecoveryCheck,
178
178
  storeRecoveryRun,
179
179
  storeSummary
180
- } from "./chunk-OMCET4QP.js";
181
- import "./chunk-E5JVYVRX.js";
180
+ } from "./chunk-HHZMDFE2.js";
181
+ import "./chunk-JTQAMVZH.js";
182
182
  import {
183
183
  LIST_QUERY_GUIDE,
184
184
  RESOURCES_SEARCHED,
@@ -229,6 +229,7 @@ import {
229
229
  personBusiness,
230
230
  personContext,
231
231
  previewProjectAnnotationSnapshot,
232
+ projectActivity,
232
233
  projectStatus,
233
234
  proposalRegistry,
234
235
  purposeList,
@@ -255,33 +256,35 @@ import {
255
256
  timeLimit,
256
257
  typedQuery,
257
258
  withQuery
258
- } from "./chunk-QEJHNTCX.js";
259
+ } from "./chunk-HXPU3ABX.js";
259
260
  import {
260
261
  readBoundedUtf8File,
261
262
  writeFileAtomic
262
- } from "./chunk-ELKRFQ5Y.js";
263
+ } from "./chunk-6W6CLZKX.js";
263
264
  import {
264
265
  releaseLock,
265
266
  servingProfiles,
266
267
  takeLock
267
- } from "./chunk-N7CHOWDF.js";
268
- import "./chunk-6GHBGGN7.js";
268
+ } from "./chunk-JDQSL2EY.js";
269
+ import "./chunk-GHYJW4ZH.js";
269
270
  import {
270
271
  commandsText,
271
272
  inSection,
272
273
  installHelp
273
- } from "./chunk-UWF6WXM7.js";
274
+ } from "./chunk-ZMLDVE22.js";
274
275
  import "./chunk-HTQTIKWP.js";
275
- import "./chunk-GXHPPHGB.js";
276
+ import "./chunk-IW6O2SAG.js";
276
277
  import {
277
278
  isNewer
278
- } from "./chunk-3QBRLN6T.js";
279
+ } from "./chunk-2EGS6BXF.js";
279
280
  import "./chunk-OYKQX4H3.js";
280
- import "./chunk-H2AQV772.js";
281
- import "./chunk-WETWQO6X.js";
282
- import "./chunk-ZKCAR2OL.js";
281
+ import "./chunk-MDIXXKVU.js";
282
+ import "./chunk-HKXACNLD.js";
283
+ import "./chunk-UBUCTVHB.js";
283
284
  import {
284
285
  EVIDENCE_FINDINGS_KIND,
286
+ IDENTITY_LINK_KIND,
287
+ IDENTITY_SPLIT_KIND,
285
288
  MAIL_FINDINGS_KIND,
286
289
  MAX_FILE_BYTES,
287
290
  MAX_TEXT_CHARS,
@@ -319,25 +322,25 @@ import {
319
322
  refLabel,
320
323
  storedProfilesFor,
321
324
  writesWithOf
322
- } from "./chunk-22RYCAAO.js";
323
- import "./chunk-KUY35N7Q.js";
324
- import "./chunk-VJLJFLKZ.js";
325
- import "./chunk-4LZLU2V3.js";
326
- import "./chunk-Z4TPRASF.js";
325
+ } from "./chunk-BS5JBNGX.js";
326
+ import "./chunk-TJ2B36VK.js";
327
+ import "./chunk-666J5H2Z.js";
328
+ import "./chunk-IJUXHUNZ.js";
329
+ import "./chunk-C4TAEYDQ.js";
327
330
  import {
328
331
  APP,
329
332
  REASONS,
330
333
  STORE_CLIENT,
331
334
  VERSION
332
- } from "./chunk-IFANDP3T.js";
335
+ } from "./chunk-2FICCBKH.js";
333
336
  import "./chunk-NT5IOEEK.js";
334
337
  import "./chunk-D72URWJE.js";
335
- import "./chunk-OUATPEPP.js";
336
- import "./chunk-EF33DKMR.js";
337
- import "./chunk-3QV5JWFN.js";
338
- import "./chunk-DAEPTQ6N.js";
339
- import "./chunk-MW6IAMUI.js";
340
- import "./chunk-Y2J52Y3A.js";
338
+ import "./chunk-SULQCO3Y.js";
339
+ import "./chunk-F62N6QMI.js";
340
+ import "./chunk-XZJUAG7B.js";
341
+ import "./chunk-DS5SA5QP.js";
342
+ import "./chunk-S2KXO7MO.js";
343
+ import "./chunk-NH7KIGIS.js";
341
344
  import {
342
345
  Command,
343
346
  DEFAULT_TEXT_MODEL,
@@ -377,11 +380,11 @@ import {
377
380
  snakeKeys,
378
381
  textModels,
379
382
  textModelsFile
380
- } from "./chunk-NXQFVHG4.js";
381
- import "./chunk-LJRXD44C.js";
382
- import "./chunk-Q2CQNT3A.js";
383
- import "./chunk-F7MKFYYP.js";
384
- import "./chunk-NGWKI3E6.js";
383
+ } from "./chunk-SGV2Z4BO.js";
384
+ import "./chunk-MLYPJ4EC.js";
385
+ import "./chunk-K3JEAMTT.js";
386
+ import "./chunk-VTBIVTS5.js";
387
+ import "./chunk-ZMSEKQQQ.js";
385
388
  import {
386
389
  CATALOG_KINDS,
387
390
  CATEGORIES,
@@ -408,6 +411,7 @@ import {
408
411
  PROJECT_ROLES,
409
412
  REF_KINDS,
410
413
  RELATION_KINDS,
414
+ ROLE_LISTS,
411
415
  SOURCE_REVIEW_KIND,
412
416
  STANDINGS,
413
417
  SUBSCRIPTION_STATUSES,
@@ -454,16 +458,16 @@ import {
454
458
  timezoneOf,
455
459
  validateQuery,
456
460
  walkQuery
457
- } from "./chunk-QU7UPCW2.js";
458
- import "./chunk-WHZJHUK6.js";
459
- import "./chunk-TT5RMHM6.js";
461
+ } from "./chunk-PX55CRD3.js";
462
+ import "./chunk-JJ6ODCVQ.js";
463
+ import "./chunk-RUM4GGHP.js";
460
464
  import {
461
465
  sharedModelsDirectory
462
- } from "./chunk-T6LXUBXY.js";
466
+ } from "./chunk-UTYGPWUY.js";
467
+ import "./chunk-G5GW3FFJ.js";
463
468
  import {
464
469
  storePath
465
- } from "./chunk-VHA3LJQT.js";
466
- import "./chunk-G5GW3FFJ.js";
470
+ } from "./chunk-R4XCBPD2.js";
467
471
  import {
468
472
  Credentials,
469
473
  configFilePath,
@@ -477,9 +481,9 @@ import {
477
481
  readBatchInput,
478
482
  resolvePaths,
479
483
  writeSecurely
480
- } from "./chunk-2IQWMWMC.js";
481
- import "./chunk-EXFRC4OT.js";
482
- import "./chunk-X2SA73EE.js";
484
+ } from "./chunk-SB3AOH3M.js";
485
+ import "./chunk-DCK5AT3D.js";
486
+ import "./chunk-RK24IARI.js";
483
487
  import {
484
488
  MAX_NEXT_STEPS,
485
489
  array,
@@ -501,7 +505,7 @@ import {
501
505
  trim,
502
506
  union,
503
507
  unknown
504
- } from "./chunk-6A37YXAL.js";
508
+ } from "./chunk-5LEIPSJG.js";
505
509
  import "./chunk-Y5E2WNWB.js";
506
510
  import {
507
511
  CliError,
@@ -887,7 +891,7 @@ var readScope = /* @__PURE__ */ __name((command, help = ONE_ACCOUNT_HELP) => sou
887
891
  var writeScope = /* @__PURE__ */ __name((command, help) => writeOptions(command, help).option("--json", "print JSON; --json=id,title keeps only those fields"), "writeScope");
888
892
  var jsonOption = /* @__PURE__ */ __name((command, fields = "ref,title") => command.option("--json", `print JSON; --json=${fields} keeps only those fields`), "jsonOption");
889
893
 
890
- // node_modules/.pnpm/@wirecat+cli-core@0.630.0_@wirecat+cli-base@0.95.0_commander@15.0.0_esbuild@0.28.2_type_1b546a322b3713cdbc9690b4e675a304/node_modules/@wirecat/cli-core/dist/mail/sender-scores.js
894
+ // node_modules/.pnpm/@wirecat+cli-core@0.634.0_@wirecat+cli-base@0.95.0_commander@15.0.0_esbuild@0.28.2_type_c47469194f2825719a552db4a380e89c/node_modules/@wirecat/cli-core/dist/mail/sender-scores.js
891
895
  var SCORED = "mail_sender_scores";
892
896
  var DAY = 864e5;
893
897
  var RECENT = 2 * 365 * DAY;
@@ -903,7 +907,7 @@ var demotedSenders = /* @__PURE__ */ __name(async (store) => {
903
907
  return senders;
904
908
  }, "demotedSenders");
905
909
 
906
- // node_modules/.pnpm/@wirecat+cli-core@0.630.0_@wirecat+cli-base@0.95.0_commander@15.0.0_esbuild@0.28.2_type_1b546a322b3713cdbc9690b4e675a304/node_modules/@wirecat/cli-core/dist/mail/sync.js
910
+ // node_modules/.pnpm/@wirecat+cli-core@0.634.0_@wirecat+cli-base@0.95.0_commander@15.0.0_esbuild@0.28.2_type_c47469194f2825719a552db4a380e89c/node_modules/@wirecat/cli-core/dist/mail/sync.js
907
911
  var DAY2 = 864e5;
908
912
  var EDGE = 2 * DAY2;
909
913
 
@@ -927,7 +931,8 @@ var REVIEW_KINDS = [
927
931
  "subscription",
928
932
  "subscription_price",
929
933
  "transaction",
930
- "identity_link"
934
+ "identity_link",
935
+ "identity_split"
931
936
  ];
932
937
  var BY_ACCOUNT = [MEETING_FINDINGS_KIND, MAIL_FINDINGS_KIND];
933
938
  var reviewRegistry = /* @__PURE__ */ __name((store) => {
@@ -1799,23 +1804,23 @@ var notesReaching = /* @__PURE__ */ __name(async (store, subject) => {
1799
1804
  const linking = await live((await Promise.all(refs.map((to) => store.notes.links({ to })))).flat().filter((link2) => link2.kind === "links-to"), "link");
1800
1805
  const through = await live((await Promise.all(about.map(({ note }) => store.notes.links({ to: note.ref })))).flat().filter((link2) => link2.kind === "links-to"), "through");
1801
1806
  const names = new Set([subject.person?.name, ...subject.person?.identities.map(({ name: name2 }) => name2) ?? []].filter((name2) => !!name2?.trim()).map(fold));
1802
- const waiting2 = names.size === 0 ? [] : await live((await store.notes.links({ unresolved: true })).filter((link2) => names.has(fold(link2.targetText ?? ""))), "name");
1803
- return [...about, ...linking, ...through, ...waiting2];
1807
+ const waiting3 = names.size === 0 ? [] : await live((await store.notes.links({ unresolved: true })).filter((link2) => names.has(fold(link2.targetText ?? ""))), "name");
1808
+ return [...about, ...linking, ...through, ...waiting3];
1804
1809
  }, "notesReaching");
1805
1810
  var notesAbout = /* @__PURE__ */ __name(async (store, subject, limit = 20) => {
1806
1811
  const found = await notesReaching(store, subject);
1807
1812
  const unique = /* @__PURE__ */ __name((via) => [
1808
1813
  ...new Map(found.filter((item) => item.via === via).map((item) => [`${item.note.ref}#${item.anchor ?? ""}`, item])).values()
1809
1814
  ].sort((a, b) => refOf(b.note).modifiedAt.localeCompare(refOf(a.note).modifiedAt)), "unique");
1810
- const [about, linking, through, waiting2] = ["about", "link", "through", "name"].map(unique);
1815
+ const [about, linking, through, waiting3] = ["about", "link", "through", "name"].map(unique);
1811
1816
  return {
1812
1817
  subject: subject.ref,
1813
1818
  name: subject.person?.name ?? null,
1814
1819
  about: (about ?? []).slice(0, limit).map(({ note }) => refOf(note)),
1815
1820
  linking: (linking ?? []).slice(0, limit).map(({ note, anchor }) => refOf(note, anchor)),
1816
1821
  throughNotes: (through ?? []).slice(0, limit).map(({ note, anchor }) => refOf(note, anchor)),
1817
- waiting: (waiting2 ?? []).slice(0, limit).map(({ note, text: text3 }) => ({ ...refOf(note), text: text3 ?? "" })),
1818
- hasMore: [about, linking, through, waiting2].some((list) => (list ?? []).length > limit)
1822
+ waiting: (waiting3 ?? []).slice(0, limit).map(({ note, text: text3 }) => ({ ...refOf(note), text: text3 ?? "" })),
1823
+ hasMore: [about, linking, through, waiting3].some((list) => (list ?? []).length > limit)
1819
1824
  };
1820
1825
  }, "notesAbout");
1821
1826
 
@@ -2348,7 +2353,7 @@ import { createHash } from "node:crypto";
2348
2353
  import { existsSync, readFileSync as readFileSync2, statSync } from "node:fs";
2349
2354
  import { basename, extname, relative, sep } from "node:path";
2350
2355
 
2351
- // node_modules/.pnpm/@wirecat+cli-core@0.630.0_@wirecat+cli-base@0.95.0_commander@15.0.0_esbuild@0.28.2_type_1b546a322b3713cdbc9690b4e675a304/node_modules/@wirecat/cli-core/dist/services/documents/extraction.js
2356
+ // node_modules/.pnpm/@wirecat+cli-core@0.634.0_@wirecat+cli-base@0.95.0_commander@15.0.0_esbuild@0.28.2_type_c47469194f2825719a552db4a380e89c/node_modules/@wirecat/cli-core/dist/services/documents/extraction.js
2352
2357
  var Proposal = object({
2353
2358
  kind: picklist(["summary", "digest", "fact", "preference"]),
2354
2359
  body: pipe(string(), trim(), minLength(1), maxLength(15e3)),
@@ -2356,13 +2361,13 @@ var Proposal = object({
2356
2361
  });
2357
2362
  var Proposals = object({ items: pipe(array(Proposal), maxLength(20)) });
2358
2363
 
2359
- // node_modules/.pnpm/@wirecat+cli-core@0.630.0_@wirecat+cli-base@0.95.0_commander@15.0.0_esbuild@0.28.2_type_1b546a322b3713cdbc9690b4e675a304/node_modules/@wirecat/cli-core/dist/services/documents/mirrors.js
2364
+ // node_modules/.pnpm/@wirecat+cli-core@0.634.0_@wirecat+cli-base@0.95.0_commander@15.0.0_esbuild@0.28.2_type_c47469194f2825719a552db4a380e89c/node_modules/@wirecat/cli-core/dist/services/documents/mirrors.js
2360
2365
  var ID = pipe(string(), regex(/^[A-Za-z0-9_-]{1,200}$/));
2361
2366
 
2362
- // node_modules/.pnpm/@wirecat+cli-core@0.630.0_@wirecat+cli-base@0.95.0_commander@15.0.0_esbuild@0.28.2_type_1b546a322b3713cdbc9690b4e675a304/node_modules/@wirecat/cli-core/dist/services/documents/sync.js
2367
+ // node_modules/.pnpm/@wirecat+cli-core@0.634.0_@wirecat+cli-base@0.95.0_commander@15.0.0_esbuild@0.28.2_type_c47469194f2825719a552db4a380e89c/node_modules/@wirecat/cli-core/dist/services/documents/sync.js
2363
2368
  var MAX_PICTURE_BYTES = 25 * 1024 * 1024;
2364
2369
 
2365
- // node_modules/.pnpm/@wirecat+cli-core@0.630.0_@wirecat+cli-base@0.95.0_commander@15.0.0_esbuild@0.28.2_type_1b546a322b3713cdbc9690b4e675a304/node_modules/@wirecat/cli-core/dist/fetch/addresses.js
2370
+ // node_modules/.pnpm/@wirecat+cli-core@0.634.0_@wirecat+cli-base@0.95.0_commander@15.0.0_esbuild@0.28.2_type_c47469194f2825719a552db4a380e89c/node_modules/@wirecat/cli-core/dist/fetch/addresses.js
2366
2371
  import { isIP } from "node:net";
2367
2372
  var within3 = /* @__PURE__ */ __name((address, [prefix, bits]) => {
2368
2373
  for (let bit = 0; bit < bits; bit++) {
@@ -2433,7 +2438,7 @@ var isPublicAddress = /* @__PURE__ */ __name((address) => {
2433
2438
  return within3(bytes, [[32], 3]) && !V6_PRIVATE.some((prefix) => within3(bytes, prefix));
2434
2439
  }, "isPublicAddress");
2435
2440
 
2436
- // node_modules/.pnpm/@wirecat+cli-core@0.630.0_@wirecat+cli-base@0.95.0_commander@15.0.0_esbuild@0.28.2_type_1b546a322b3713cdbc9690b4e675a304/node_modules/@wirecat/cli-core/dist/fetch/page.js
2441
+ // node_modules/.pnpm/@wirecat+cli-core@0.634.0_@wirecat+cli-base@0.95.0_commander@15.0.0_esbuild@0.28.2_type_c47469194f2825719a552db4a380e89c/node_modules/@wirecat/cli-core/dist/fetch/page.js
2437
2442
  import { lookup as dnsLookup } from "node:dns/promises";
2438
2443
  import { request as httpRequest } from "node:http";
2439
2444
  import { request as httpsRequest } from "node:https";
@@ -2928,9 +2933,9 @@ var importNotes = /* @__PURE__ */ __name(async (store, folder, { ignore = [], sk
2928
2933
  const documents = [...stored.values()].map(documentOf);
2929
2934
  const relink = new Map(parsed2);
2930
2935
  if (renamed + deleted + added > 0) {
2931
- const waiting2 = new Set((await store.notes.links({ unresolved: true })).map(({ from }) => from.replace(/^note:/, "")));
2936
+ const waiting3 = new Set((await store.notes.links({ unresolved: true })).map(({ from }) => from.replace(/^note:/, "")));
2932
2937
  for (const note of stored.values())
2933
- if (waiting2.has(note.id) && !relink.has(note.path) && TEXT_NOTE.test(note.path))
2938
+ if (waiting3.has(note.id) && !relink.has(note.path) && TEXT_NOTE.test(note.path))
2934
2939
  relink.set(note.path, dialect.parse(note.text, note.path));
2935
2940
  }
2936
2941
  for (const [id, note] of relink) {
@@ -5099,13 +5104,13 @@ var cutsOf = /* @__PURE__ */ __name((items) => {
5099
5104
  }
5100
5105
  return [...cuts.values()].sort((a, b) => Number.parseInt(a.cursor, 10) - Number.parseInt(b.cursor, 10));
5101
5106
  }, "cutsOf");
5102
- var lines = /* @__PURE__ */ __name((source, review, { key, cursor, items, waiting: waiting2 }) => {
5107
+ var lines = /* @__PURE__ */ __name((source, review, { key, cursor, items, waiting: waiting3 }) => {
5103
5108
  const left = (review.missing ?? []).map((one2) => one2.why).filter(Boolean);
5104
5109
  return [
5105
5110
  `## ${source}`,
5106
5111
  ...key ? [`key: ${key}`] : [],
5107
5112
  `cursor: ${cursor ?? "none"}`,
5108
- waiting2 > 0 ? `more mail waits past the cursor: true \u2014 ${waiting2} emails did not fit this input; the next run reads them, do not review this mailbox again now` : `more mail waits past the cursor: ${review.meta?.complete === false}`,
5113
+ waiting3 > 0 ? `more mail waits past the cursor: true \u2014 ${waiting3} emails did not fit this input; the next run reads them, do not review this mailbox again now` : `more mail waits past the cursor: ${review.meta?.complete === false}`,
5109
5114
  ...left.length ? [`left out: ${left.join("; ")}`] : [],
5110
5115
  ...items.some((item) => item.text_cut) ? [
5111
5116
  "text_cut: only the start of that email's text fits here; read it whole with `memo messages show '<ref>' --trimmed --json` before you stage a finding from it"
@@ -6248,7 +6253,7 @@ var gatherDigest = /* @__PURE__ */ __name(async (store, env, { since, now: clock
6248
6253
  why: "changed since a memory or fact cited it; no findings batch reads it yet"
6249
6254
  }
6250
6255
  });
6251
- const waiting2 = await counted2(store, env, { status: "proposed" });
6256
+ const waiting3 = await counted2(store, env, { status: "proposed" });
6252
6257
  const proposed = await listReview(store, env, [], { limit, page: 1 });
6253
6258
  const proposals = proposed.items.map((row) => ({
6254
6259
  item: {
@@ -6283,7 +6288,7 @@ var gatherDigest = /* @__PURE__ */ __name(async (store, env, { since, now: clock
6283
6288
  ...reviewCount > 0 ? [`# decide them: ${REVIEW_SOURCES}`] : [],
6284
6289
  ...sourceItems.length > reviewCount ? [`# read changed sources again: memo memories check --since-time ${days2} --json`] : []
6285
6290
  ]),
6286
- await section("proposals", upTo(proposals), limit, ["memo review list"], waiting2.total)
6291
+ await section("proposals", upTo(proposals), limit, ["memo review list"], waiting3.total)
6287
6292
  ];
6288
6293
  const providerCount = /* @__PURE__ */ __name((provider) => accounts.filter((key) => key.provider === provider).length, "providerCount");
6289
6294
  const meetingAccounts = accounts.filter((key) => kindOf(key.provider) === "meetings").length;
@@ -6968,7 +6973,7 @@ var doctorCommand = /* @__PURE__ */ __name((...args) => {
6968
6973
  }, SHELL_OVERRIDES.doctor);
6969
6974
  }, "doctorCommand");
6970
6975
 
6971
- // node_modules/.pnpm/@wirecat+cli-core@0.630.0_@wirecat+cli-base@0.95.0_commander@15.0.0_esbuild@0.28.2_type_1b546a322b3713cdbc9690b4e675a304/node_modules/@wirecat/cli-core/dist/calendar/sync.js
6976
+ // node_modules/.pnpm/@wirecat+cli-core@0.634.0_@wirecat+cli-base@0.95.0_commander@15.0.0_esbuild@0.28.2_type_c47469194f2825719a552db4a380e89c/node_modules/@wirecat/cli-core/dist/calendar/sync.js
6972
6977
  var DAY8 = 864e5;
6973
6978
  var SLOTS_EVERY = 7 * DAY8;
6974
6979
  var isWindow = /* @__PURE__ */ __name((value) => typeof value?.from === "number" && typeof value.to === "number", "isWindow");
@@ -7048,10 +7053,10 @@ var calendarStatus = /* @__PURE__ */ __name(async (store, accountId, { profile,
7048
7053
  return { items, page: 1, limit: Math.max(1, items.length), hasMore: false };
7049
7054
  }, "calendarStatus");
7050
7055
 
7051
- // node_modules/.pnpm/@wirecat+cli-core@0.630.0_@wirecat+cli-base@0.95.0_commander@15.0.0_esbuild@0.28.2_type_1b546a322b3713cdbc9690b4e675a304/node_modules/@wirecat/cli-core/dist/calendar/feeds.js
7056
+ // node_modules/.pnpm/@wirecat+cli-core@0.634.0_@wirecat+cli-base@0.95.0_commander@15.0.0_esbuild@0.28.2_type_c47469194f2825719a552db4a380e89c/node_modules/@wirecat/cli-core/dist/calendar/feeds.js
7052
7057
  var FEED_LIMITS = { maxBytes: 10 * 1024 * 1024, timeoutMs: 3e4, redirects: 5 };
7053
7058
 
7054
- // node_modules/.pnpm/@wirecat+cli-core@0.630.0_@wirecat+cli-base@0.95.0_commander@15.0.0_esbuild@0.28.2_type_1b546a322b3713cdbc9690b4e675a304/node_modules/@wirecat/cli-core/dist/calendar/reads.js
7059
+ // node_modules/.pnpm/@wirecat+cli-core@0.634.0_@wirecat+cli-base@0.95.0_commander@15.0.0_esbuild@0.28.2_type_c47469194f2825719a552db4a380e89c/node_modules/@wirecat/cli-core/dist/calendar/reads.js
7055
7060
  var LIST = "events list";
7056
7061
  var EVENT_TYPES = [
7057
7062
  "default",
@@ -7128,7 +7133,7 @@ var accountsMeta = /* @__PURE__ */ __name(async (store, accounts, skipped, now)
7128
7133
  };
7129
7134
  }, "accountsMeta");
7130
7135
 
7131
- // node_modules/.pnpm/@wirecat+cli-core@0.630.0_@wirecat+cli-base@0.95.0_commander@15.0.0_esbuild@0.28.2_type_1b546a322b3713cdbc9690b4e675a304/node_modules/@wirecat/cli-core/dist/calendar/writer.js
7136
+ // node_modules/.pnpm/@wirecat+cli-core@0.634.0_@wirecat+cli-base@0.95.0_commander@15.0.0_esbuild@0.28.2_type_c47469194f2825719a552db4a380e89c/node_modules/@wirecat/cli-core/dist/calendar/writer.js
7132
7137
  var EVENTS_NOTIFY_KEY = "events.notify";
7133
7138
  var EVENTS_DELETE_SERIES_KEY = "events.delete.series";
7134
7139
  var EVENTS_REMIND_HOOK_KEY = "events.remind.hook";
@@ -7500,14 +7505,23 @@ var EXAMPLES = {
7500
7505
  "people check": ["memo people check ivan petrov --json"],
7501
7506
  "people add": ["memo people add Lena Example"],
7502
7507
  "people show": ["memo people show person:12", "memo people show telegram:Lena --json"],
7503
- "people review": ["memo people review", "memo people review --json"],
7508
+ "people review": ["memo people review", "memo people review --kind split --json"],
7509
+ "people confirm": ["memo people confirm 17080 17082-17085", "memo people confirm all --kind split --yes"],
7510
+ "people reject": [
7511
+ "memo people reject 17081 --reason 'two people'",
7512
+ "memo people reject all --kind link --reason 'not one'"
7513
+ ],
7514
+ "people links check": ["memo people links check", "memo people links check --page 2 --json"],
7504
7515
  "people scan": ["memo people scan"],
7505
7516
  "people link": [
7506
7517
  "memo people link max:Lena telegram:Lena",
7507
7518
  "memo people link max:Lena telegram:Lena --reason 'same phone in her signature'"
7508
7519
  ],
7509
- "people unlink": ["memo people unlink telegram:12345", "memo people unlink email:lena@example.com max:6789"],
7510
- "people unmerge": ["memo people unmerge merge:12-34"],
7520
+ "people unlink": [
7521
+ "memo people unlink telegram:12345",
7522
+ "memo people unlink email:lena@example.com max:6789 --reason 'her husband's mailbox'"
7523
+ ],
7524
+ "people unmerge": ["memo people unmerge merge:12-34", "memo people unmerge merge:12-34 --reason 'a shared mailbox'"],
7511
7525
  "tasks agenda": [
7512
7526
  "memo tasks agenda --source telegram:1",
7513
7527
  "memo tasks agenda --source max:1 --waiting 3d --within 90d --json"
@@ -7515,6 +7529,7 @@ var EXAMPLES = {
7515
7529
  "tasks claim": ["memo tasks claim HRB-1 --lease 2h --account telegram:1"],
7516
7530
  "tasks release": ["memo tasks release HRB-1 --account telegram:1"],
7517
7531
  "tasks show": ["memo tasks show 1a2b3c4d --source telegram:1 --json"],
7532
+ "stats projects show": ["memo stats projects show", "memo stats projects show --since-time 7d --json"],
7518
7533
  "stats tasks show": [
7519
7534
  "memo stats tasks show --source telegram:1",
7520
7535
  "memo stats tasks show --type question --source telegram:1 --json"
@@ -9627,6 +9642,52 @@ var projectActionsCommand = /* @__PURE__ */ __name((projects, streams, env) => {
9627
9642
  }
9628
9643
  }, "projectActionsCommand");
9629
9644
 
9645
+ // dist/knowledge/project-activity-command.js
9646
+ var DAY9 = 864e5;
9647
+ var sinceOf2 = /* @__PURE__ */ __name((value, now) => {
9648
+ if (value.trim().toLowerCase() === "all")
9649
+ return 0;
9650
+ const window = projectWindowOf(value);
9651
+ return "days" in window ? now - window.days * DAY9 : window.after;
9652
+ }, "sinceOf");
9653
+ var textOf = /* @__PURE__ */ __name((one2) => [
9654
+ `${one2.key ?? one2.ref} ${one2.name} \xB7 ${one2.chats} chats${one2.muted ? ` (${one2.muted} muted, not counted)` : ""} \xB7 ${one2.messages} messages (${one2.sent} yours)${one2.lastAt ? ` \xB7 last ${one2.lastAt.slice(0, 10)}` : ""}` + (one2.partial ? " \xB7 some sub-projects not counted" : ""),
9655
+ ...one2.top.map((chat) => ` ${chat.messages} ${chat.title ?? chat.ref}`)
9656
+ ].join("\n"), "textOf");
9657
+ var projectActivityCommand = /* @__PURE__ */ __name((program, streams, env) => {
9658
+ const { print } = answers(program, streams, env);
9659
+ const stats = program.commands.find((command) => command.name() === "stats") ?? program.command("stats").description("statistics about what the store holds");
9660
+ const projects = new Command("projects").description("project statistics");
9661
+ stats.addCommand(projects);
9662
+ annotate(projects.command("show"), { effects: LOCAL_READ }).summary("each project's linked chats: messages in a period, last activity, busiest chats").description("for each of your projects, the chats linked to it or its child projects (every confirmed link, any purpose, no chat limit, unlike projects status): how many, how many are muted, messages and yours in the period by when they were sent, the newest message and the three busiest chats; a muted chat's messages are not counted. Busiest first. One read for all projects; projects status <project> says where one stands").option("--since-time <time>", "how far back: days (30d, at most 730d), a start date (2026-09-01) or all", "30d").option("--limit <n>", "most projects on a page, up to 200", positive, 20).option("--page <n>", "which page, from 1", positive, 1).option("--json", "print JSON; --json=id,title keeps only those fields").action(async (options) => {
9663
+ const now = Date.now();
9664
+ const since = sinceOf2(options.sinceTime, now);
9665
+ const limit = Math.min(options.limit, 200);
9666
+ const found = await withStore(env, async (store) => {
9667
+ const scope = await groupScopeOf(store, env);
9668
+ return projectActivity(store, {
9669
+ since,
9670
+ until: now,
9671
+ limit,
9672
+ offset: (options.page - 1) * limit,
9673
+ ...scope === void 0 ? {} : { accounts: scope.accounts }
9674
+ });
9675
+ });
9676
+ print(options.json, listAnswer("stats projects show", {
9677
+ items: found.items,
9678
+ limit,
9679
+ page: options.page,
9680
+ has_more: found.hasMore,
9681
+ total: { value: found.total, relation: "eq" },
9682
+ args: { since_time: options.sinceTime, limit }
9683
+ }), [
9684
+ since === 0 ? "all time" : `since ${new Date(since).toISOString().slice(0, 10)}`,
9685
+ ...found.items.length ? found.items.map(textOf) : [options.page > 1 ? "no projects on this page" : "no projects"],
9686
+ ...found.hasMore ? [`more: --since-time ${options.sinceTime} --limit ${limit} --page ${options.page + 1}`] : []
9687
+ ].join("\n\n"));
9688
+ });
9689
+ }, "projectActivityCommand");
9690
+
9630
9691
  // dist/knowledge/project-findings.js
9631
9692
  var projectFindings = /* @__PURE__ */ __name(async (store, project, links) => {
9632
9693
  const ids = /* @__PURE__ */ new Set();
@@ -9674,7 +9735,7 @@ var projectContext = /* @__PURE__ */ __name(async (store, env, reference2) => {
9674
9735
  const documents = await keyDocuments(store, project);
9675
9736
  const proposals = await proposalsOf(store, env);
9676
9737
  const pending = /* @__PURE__ */ __name((kind) => proposals.list({ project: project.ref, kinds: [kind], status: "proposed", limit: 50, offset: 0 }), "pending");
9677
- const [facts, tasks, findings, keys, links, waiting2] = await Promise.all([
9738
+ const [facts, tasks, findings, keys, links, waiting3] = await Promise.all([
9678
9739
  store.facts.list({ project: project.ref, status: "proposed", limit: 21 }),
9679
9740
  store.tasks.find({ project: project.ref, status: "open", limit: 21 }),
9680
9741
  projectFindings(store, project.ref, relationships),
@@ -9691,7 +9752,7 @@ var projectContext = /* @__PURE__ */ __name(async (store, env, reference2) => {
9691
9752
  tags: await store.knowledge.tags(null, { type: "project", id: project.id }),
9692
9753
  review: {
9693
9754
  waiting: {
9694
- ...waiting2,
9755
+ ...waiting3,
9695
9756
  next: { command: "review list", args: { query: `project:${project.key ?? project.id}` } }
9696
9757
  },
9697
9758
  keyDocuments: keys.items.map((row) => ({
@@ -9744,7 +9805,7 @@ var projectContextText = /* @__PURE__ */ __name((context) => {
9744
9805
  }, "projectContextText");
9745
9806
 
9746
9807
  // dist/knowledge/relationships-scan.js
9747
- var DAY9 = 864e5;
9808
+ var DAY10 = 864e5;
9748
9809
  var SCAN_STEP = {
9749
9810
  id: "relationships.scan",
9750
9811
  kind: "command",
@@ -9818,7 +9879,7 @@ var relationshipsScanCommand = /* @__PURE__ */ __name((relations, print, env, wa
9818
9879
  if (options.limit > 50)
9819
9880
  throw new CliError("validation_error", "--limit is at most 50", { param: "limit" });
9820
9881
  const window = projectWindowOf(options.sinceTime);
9821
- const since = new Date("days" in window ? Date.now() - window.days * DAY9 : window.after).toISOString();
9882
+ const since = new Date("days" in window ? Date.now() - window.days * DAY10 : window.after).toISOString();
9822
9883
  const written2 = options.yes === true;
9823
9884
  const { body, text: text3 } = await withStore(env, async (store) => {
9824
9885
  const sources = await namedAccounts(store, env, options, warn);
@@ -10088,6 +10149,38 @@ var projectTransferCommand = /* @__PURE__ */ __name((projects, streams, env) =>
10088
10149
  }
10089
10150
  }, "projectTransferCommand");
10090
10151
 
10152
+ // dist/knowledge/document-context.js
10153
+ var MAX_DEPTH = 20;
10154
+ var documentContext = /* @__PURE__ */ __name(async (store, ref) => {
10155
+ const note = await store.notes.note(ref).catch(() => null);
10156
+ if (!note || note.deletedAt)
10157
+ return null;
10158
+ const { folderId } = note;
10159
+ const entryOf2 = /* @__PURE__ */ __name(async (externalId) => folderId === null ? void 0 : await store.catalog.get(folderId, externalId).catch(() => void 0), "entryOf");
10160
+ const entry = note.path === null ? void 0 : await entryOf2(note.path);
10161
+ if (!entry)
10162
+ return { ref: note.ref, title: note.title, path: null, url: null, modifiedAt: note.modifiedAt, mime: null };
10163
+ const names = [entry.name];
10164
+ const seen = /* @__PURE__ */ new Set([note.path]);
10165
+ let parent = entry.parents[0];
10166
+ for (let depth = 0; parent !== void 0 && !seen.has(parent) && depth < MAX_DEPTH; depth++) {
10167
+ seen.add(parent);
10168
+ const folder = await entryOf2(parent);
10169
+ if (!folder)
10170
+ break;
10171
+ names.unshift(folder.name);
10172
+ parent = folder.parents[0];
10173
+ }
10174
+ return {
10175
+ ref: note.ref,
10176
+ title: entry.name,
10177
+ path: names.join("/"),
10178
+ url: entry.url ?? null,
10179
+ modifiedAt: entry.modifiedAt ?? note.modifiedAt,
10180
+ mime: entry.mime ?? null
10181
+ };
10182
+ }, "documentContext");
10183
+
10091
10184
  // dist/knowledge/relationships.js
10092
10185
  var RELATIONSHIP_QUERY = {
10093
10186
  entity: "relationship",
@@ -10106,10 +10199,10 @@ var RELATIONSHIP_QUERY = {
10106
10199
  termField("include", "enum", "include:ended", { values: ["ended"] })
10107
10200
  ]
10108
10201
  };
10109
- var DAY10 = /^\d{4}-\d{2}-\d{2}$/;
10202
+ var DAY11 = /^\d{4}-\d{2}-\d{2}$/;
10110
10203
  var atOf = /* @__PURE__ */ __name((day2) => {
10111
10204
  const at2 = Date.parse(`${day2}T00:00:00Z`);
10112
- if (!DAY10.test(day2) || Number.isNaN(at2))
10205
+ if (!DAY11.test(day2) || Number.isNaN(at2))
10113
10206
  throw new CliError("validation_error", `at: takes a day, such as at:2026-10-01 \u2014 not "${day2}"`, {
10114
10207
  reason: "input.invalid"
10115
10208
  });
@@ -10140,6 +10233,18 @@ var listRelationships = /* @__PURE__ */ __name(async (store, env, words, { limit
10140
10233
  if (guard === void 0 || await guard.visible(one2.from) && await guard.visible(one2.to))
10141
10234
  rows.push(one2);
10142
10235
  const label = await labelsFor(store, rows.flatMap((one2) => [one2.from, one2.to]));
10236
+ const documents = /* @__PURE__ */ new Map();
10237
+ const documentOf2 = /* @__PURE__ */ __name((ref) => {
10238
+ if (!ref.startsWith("document:"))
10239
+ return void 0;
10240
+ if (!documents.has(ref))
10241
+ documents.set(ref, documentContext(store, ref));
10242
+ return documents.get(ref);
10243
+ }, "documentOf");
10244
+ const ends = /* @__PURE__ */ __name(async (one2) => {
10245
+ const [from, to] = await Promise.all([documentOf2(one2.from), documentOf2(one2.to)]);
10246
+ return { ...from === void 0 ? {} : { fromDocument: from }, ...to === void 0 ? {} : { toDocument: to } };
10247
+ }, "ends");
10143
10248
  return {
10144
10249
  hasMore: found.hasMore,
10145
10250
  limit,
@@ -10150,7 +10255,8 @@ var listRelationships = /* @__PURE__ */ __name(async (store, env, words, { limit
10150
10255
  // Who proposed it is the review's to name; the list says it beside the proposal.
10151
10256
  ...one2.source === "proposal" ? { proposer: proposerName((await store.proposedActions.get(one2.id)).proposedBy) } : {},
10152
10257
  fromTitle: label(one2.from),
10153
- toTitle: label(one2.to)
10258
+ toTitle: label(one2.to),
10259
+ ...await ends(one2)
10154
10260
  })))
10155
10261
  };
10156
10262
  }, "listRelationships");
@@ -10169,13 +10275,13 @@ var relationshipsText = /* @__PURE__ */ __name((items) => items.length ? items.m
10169
10275
  ].filter(Boolean).join(" ")).join("\n") : "no relationships", "relationshipsText");
10170
10276
 
10171
10277
  // dist/knowledge/roles-command.js
10172
- var LISTS = ["organization", "project", "deal"];
10278
+ var LISTS = Object.keys(ROLE_LISTS);
10173
10279
  var ROLES_QUERY = {
10174
10280
  entity: "relationship_role",
10175
10281
  backend: "native",
10176
10282
  fields: [termField("list", "enum", "list:organization", { values: LISTS })]
10177
10283
  };
10178
- var LIST_HELP = "organization (roles in an organization), project or deal (a deal's or a lead's)";
10284
+ var LIST_HELP = "organization (roles in an organization), project, deal (a deal's or a lead's), contract (a party's) or related (what a person or an organization is to another)";
10179
10285
  var ownerOnly = /* @__PURE__ */ __name(async (command, env, asOwner2, question) => {
10180
10286
  if (await whoRuns(command, env, { asOwner: asOwner2, question }) !== "owner")
10181
10287
  throw new CliError("permission_error", "only the owner changes the role lists; an agent uses the roles they hold", {
@@ -10187,9 +10293,9 @@ var relationshipRolesCommand = /* @__PURE__ */ __name((relations, { print }, env
10187
10293
  const rows = /* @__PURE__ */ __name(async (lists) => withStore(env, async (store) => (await Promise.all(lists.map(async (list) => (await store.knowledge.roles(list)).map((one2) => ({ list, ...one2 }))))).flat()), "rows");
10188
10294
  const show = /* @__PURE__ */ __name(async (json5, command, lists) => {
10189
10295
  const items = await rows(lists);
10190
- print(json5, listAnswer(command, { items, limit: Math.max(1, items.length), has_more: false }), items.map(({ list, id, label, builtIn }) => `${list} ${id}${label ? ` ${label}` : ""}${builtIn ? "" : " (yours)"}`).join("\n"));
10296
+ print(json5, listAnswer(command, { items, limit: Math.max(1, items.length), has_more: false }), items.map(({ list, id, label, labels, builtIn }) => `${list} ${id}${label ?? labels?.en ? ` ${label ?? labels?.en}` : ""}${builtIn ? "" : " (yours)"}`).join("\n"));
10191
10297
  }, "show");
10192
- withQuery(annotate(roles.command("list"), { effects: LOCAL_READ, output: { entity: "relationship_role" } }), ROLES_QUERY).description("the roles of every list, or of one with list:organization, list:project or list:deal; each built in or yours").summary("the roles a relationship may take").option("--json", "print JSON; --json=id,title keeps only those fields").action((words, options) => {
10298
+ withQuery(annotate(roles.command("list"), { effects: LOCAL_READ, output: { entity: "relationship_role" } }), ROLES_QUERY).description("the roles of every list, or of one with list:<name>; each built in (with labels in English, Russian and Spanish) or yours").summary("the roles a relationship may take").option("--json", "print JSON; --json=id,title keeps only those fields").action((words, options) => {
10193
10299
  const list = queryTerms(words, ROLES_QUERY, "relationships roles list").get("list");
10194
10300
  return show(options.json, "relationships roles list", list === void 0 ? LISTS : [list]);
10195
10301
  });
@@ -10313,6 +10419,7 @@ var knowledgeCommands = /* @__PURE__ */ __name((program, streams, env) => {
10313
10419
  });
10314
10420
  projectGatherCommand(projects, print, env, warn);
10315
10421
  projectStatusCommand(projects, print, env);
10422
+ projectActivityCommand(program, streams, env);
10316
10423
  projectActionsCommand(projects, streams, env);
10317
10424
  projectTransferCommand(projects, streams, env);
10318
10425
  const keys = projects.command("key-documents").description("the notes, files and messages to read first about a project, each with why");
@@ -10864,10 +10971,10 @@ var mcpCommandDefinition = /* @__PURE__ */ __name((program, streams, env, create
10864
10971
  }).summary("serve this profile's commands to an AI agent").description("serve memo commands over MCP on stdio or authenticated HTTP, limited by saved permissions").option("--permission <key=level>", "tighten one saved permission for this server; repeat for more keys", (value, previous = []) => [...previous, value]).option("--http", "serve on 127.0.0.1 behind an HTTPS tunnel with an owner access-code login").option("--port <port>", `local HTTP port (default ${DEFAULT_PORT}); requires --http`).option("--public-url <url>", "tunnel's HTTPS address without /mcp, or a path of it such as https://<name>.ts.net/memo; requires --http").action(async (options) => {
10865
10972
  if (!options.http && (options.port !== void 0 || options.publicUrl !== void 0))
10866
10973
  throw new CliError("validation_error", "--port and --public-url require --http");
10867
- const { createMemoServer } = await import("./server-GYLFN6Y7.js");
10974
+ const { createMemoServer } = await import("./server-NNE7MUYT.js");
10868
10975
  const build = /* @__PURE__ */ __name(() => createMemoServer(env, createProgram2, options.permission), "build");
10869
10976
  if (options.http) {
10870
- const { httpLockFile, mcpUrlOf, portOf, publicUrlOf, serveOverHttp } = await import("./mcp-IRJS472M.js");
10977
+ const { httpLockFile, mcpUrlOf, portOf, publicUrlOf, serveOverHttp } = await import("./mcp-3LAFWOGW.js");
10871
10978
  const publicUrl = publicUrlOf(options.publicUrl, {
10872
10979
  missing: "--http",
10873
10980
  reaches: "the browser apps reach memo",
@@ -10919,7 +11026,7 @@ var mcpCommandDefinition = /* @__PURE__ */ __name((program, streams, env, create
10919
11026
  });
10920
11027
  });
10921
11028
  annotate(mcp2.command("revoke"), { effects: LOCAL_WRITE, mcp: false, examples: ["memo mcp revoke --json"] }).summary("forget every login given to a browser app").description("forget every login `memo mcp serve --http` gave a browser app; each app must log in again").option("--json", "print JSON").action(async function() {
10922
- const { revokeAll } = await import("./mcp-IRJS472M.js");
11029
+ const { revokeAll } = await import("./mcp-3LAFWOGW.js");
10923
11030
  revokeAll(httpTokenFile(env));
10924
11031
  out.print(this.opts().json, itemAnswer({ revoked: true }));
10925
11032
  });
@@ -11414,7 +11521,7 @@ var refuseOverMcp = /* @__PURE__ */ __name((options, mcp2) => {
11414
11521
  param: "export"
11415
11522
  });
11416
11523
  }, "refuseOverMcp");
11417
- var textOf = /* @__PURE__ */ __name((options, given2) => {
11524
+ var textOf2 = /* @__PURE__ */ __name((options, given2) => {
11418
11525
  const sources = [given2, options.text, options.textFile].filter((value) => value !== void 0);
11419
11526
  if (sources.length !== 1)
11420
11527
  throw new CliError("validation_error", "give the text once: as an argument, --text or --text-file");
@@ -11510,7 +11617,7 @@ var notesCommandDefinition = /* @__PURE__ */ __name((program, streams, env) => {
11510
11617
  }).description("write a note of your own about messages, people, projects or other notes").argument("[text]", "the note; or --text, or --text-file").option("--text <text>", "the note").option("--text-file <path>", "read the note from a file; - reads stdin").option("--title <title>", "a title").option("--subject <ref>", "what it is about: <messenger>:<name or id>, msg:, chat:, person:, organization:, project:, task:, note:, document:, meeting:; repeat for more", collect).option("--meeting <id>", "also about this meeting, by its store id, with --account");
11511
11618
  writeOptions(noteAdd, `the account of --meeting: ${MEETING_WRITE_HELP}`).option("--export [dir]", "also write it as a file \u2014 to this folder, or notes.export.dir").option("--format <format>", `the file's format: ${DIALECTS.join(", ")}`, formatOf).option("--json", "print JSON; --json=id,title keeps only those fields").action(async (given2, options, command) => {
11512
11619
  refuseOverMcp(options, isMcpRun(command, env));
11513
- const body = textOf(options, given2);
11620
+ const body = textOf2(options, given2);
11514
11621
  const value = writeAccountOf(options, (text3) => streams.diagnostic(text3));
11515
11622
  if (options.meeting === void 0 && value !== void 0)
11516
11623
  throw new CliError("validation_error", "--account selects the account of --meeting");
@@ -11532,7 +11639,7 @@ var notesCommandDefinition = /* @__PURE__ */ __name((program, streams, env) => {
11532
11639
  });
11533
11640
  annotate(notes2.command("edit"), { effects: LOCAL_WRITE, output: { entity: "note" }, literal_after_dashes: true }).description("change a note you wrote here; a file's note is edited in its file").argument("<id>", "note:<id>").requiredOption("--revision <n>", "its current revision, so an edit made meanwhile is not lost", positive).option("--text <text>", "the new text").option("--text-file <path>", "read the new text from a file; - reads stdin").option("--export [dir]", "also rewrite its file \u2014 in this folder, or notes.export.dir").option("--format <format>", `the file's format: ${DIALECTS.join(", ")}`, formatOf).option("--json", "print JSON; --json=id,title keeps only those fields").action(async (id, options, command) => {
11534
11641
  refuseOverMcp(options, isMcpRun(command, env));
11535
- const body = textOf(options);
11642
+ const body = textOf2(options);
11536
11643
  const answer = await withNotes(async (store) => {
11537
11644
  await refuseBareNumber(store, id, ["note"]);
11538
11645
  const note = await store.notes.editNote(id.replace(/^note:/, ""), body, options.revision);
@@ -11713,11 +11820,164 @@ var foldersCommand = /* @__PURE__ */ __name((program, streams, env) => {
11713
11820
  // dist/people/command.js
11714
11821
  import { join as join13 } from "node:path";
11715
11822
 
11823
+ // dist/people/doubts-command.js
11824
+ var textOf3 = /* @__PURE__ */ __name((doubt) => [
11825
+ `${doubt.person}${doubt.name ? ` ${doubt.name}` : ""}${doubt.owner ? " (you)" : ""} \xB7 ${doubt.reason}`,
11826
+ ` ${doubt.why}`,
11827
+ ...doubt.identities.map(({ identity, name: name2, method, by, at: at2 }) => ` ${identity}${name2 ? ` ${name2}` : ""} (${method} by ${by}, ${at2.slice(0, 10)})`),
11828
+ ...doubt.fix.map((command) => ` fix: memo ${command}`)
11829
+ ].join("\n"), "textOf");
11830
+ var doubtsCommand = /* @__PURE__ */ __name((people, program, streams, env) => {
11831
+ const { print } = answers(program, streams, env);
11832
+ const links = people.commands.find((command) => command.name() === "links") ?? people.command("links").description("who is who: the links that make identities one person");
11833
+ annotate(links.command("check"), { effects: LOCAL_READ }).summary("people that may be wrong, with why and the command that fixes each").description("people that may be wrong, you first: your person holding an identity under another name, test data, an identity joined by an address a person of another name has, one person with different names and nothing in common. Each says why and gives the unlink or unmerge that fixes it; an agent adds --reason and it waits for you in people review. What you linked by hand, or kept together by turning a split down, is left out").option("--limit <n>", "most people on a page, up to 200", positive, 20).option("--page <n>", "which page, from 1", positive, 1).option("--json", "print JSON; --json=id,title keeps only those fields").action(async (options) => {
11834
+ const limit = Math.min(options.limit, 200);
11835
+ const counted3 = groupOf(env) === void 0;
11836
+ const found = await withStore(env, async (store) => {
11837
+ const page = await store.people.doubts({ limit, offset: (options.page - 1) * limit });
11838
+ return { ...page, items: await keepInGroup(store, env, page.items, ({ person }) => person) };
11839
+ });
11840
+ print(options.json, listAnswer("people links check", {
11841
+ items: found.items,
11842
+ limit,
11843
+ page: options.page,
11844
+ has_more: found.hasMore,
11845
+ ...counted3 ? { total: { value: found.total, relation: "eq" } } : {}
11846
+ }), [
11847
+ found.items.map(textOf3).join("\n\n") || (found.hasMore ? "none on this page" : "no person looks wrong"),
11848
+ ...found.hasMore ? [`more: --page ${options.page + 1}`] : []
11849
+ ].join("\n\n"));
11850
+ });
11851
+ }, "doubtsCommand");
11852
+
11853
+ // dist/people/proposal-rows.js
11854
+ var asOwner = /* @__PURE__ */ __name(async (command, env, question) => {
11855
+ const options = command.opts();
11856
+ const who = await whoRuns(command, env, { asOwner: options.asOwner, question });
11857
+ if (who !== "owner")
11858
+ throw new CliError("permission_error", `only the owner can ${question.replace(/\?$/, "")}`, {
11859
+ reason: "identity.owner-only"
11860
+ });
11861
+ return who;
11862
+ }, "asOwner");
11863
+ var matchAnswer = /* @__PURE__ */ __name((row) => ({
11864
+ id: row.id,
11865
+ kind: "identity_link",
11866
+ persons: row.persons,
11867
+ joins: row.joins,
11868
+ identity: row.identity,
11869
+ with: row.with,
11870
+ signal: row.signal,
11871
+ score: row.score,
11872
+ candidates: row.candidates,
11873
+ reason: row.reason,
11874
+ evidence: row.evidence,
11875
+ proposedBy: row.proposedBy,
11876
+ createdAt: row.createdAt
11877
+ }), "matchAnswer");
11878
+ var splitAnswer = /* @__PURE__ */ __name((row) => ({
11879
+ id: row.id,
11880
+ kind: "identity_split",
11881
+ split: row.split,
11882
+ person: row.person,
11883
+ identities: row.identities,
11884
+ merge: row.merge,
11885
+ reason: row.reason,
11886
+ evidence: row.evidence,
11887
+ proposedBy: row.proposedBy,
11888
+ createdAt: row.createdAt
11889
+ }), "splitAnswer");
11890
+ var summaryOf2 = /* @__PURE__ */ __name((row) => {
11891
+ if (row.kind === "identity_link")
11892
+ return `${row.identity} may be the same person as ${row.with ?? row.persons[1]} (${row.signal})`;
11893
+ return row.split === "unmerge" ? `undo ${row.merge}: ${row.identities.join(" ")} go back to their own person` : `take ${row.identities.join(" ")} off ${row.person}`;
11894
+ }, "summaryOf");
11895
+ var PROPOSAL_KINDS = ["all", "link", "split"];
11896
+ var waiting2 = /* @__PURE__ */ __name(async (store, { kind, limit }) => {
11897
+ const none = { items: [], hasMore: false };
11898
+ const page = { status: "proposed", limit, offset: 0 };
11899
+ const links = kind === "split" ? none : await store.people.linkProposals(page);
11900
+ const splits = kind === "link" ? none : await store.people.splitProposals(page);
11901
+ const rows = [...links.items.map(matchAnswer), ...splits.items.map(splitAnswer)].sort((a, b) => b.createdAt.localeCompare(a.createdAt) || Number(b.id) - Number(a.id));
11902
+ return { items: rows.slice(0, limit), hasMore: links.hasMore || splits.hasMore || rows.length > limit };
11903
+ }, "waiting");
11904
+
11905
+ // dist/people/proposals-command.js
11906
+ var PEOPLE_KINDS = [IDENTITY_LINK_KIND, IDENTITY_SPLIT_KIND];
11907
+ var limitOf = /* @__PURE__ */ __name((limit) => {
11908
+ if (limit > 500)
11909
+ throw new CliError("validation_error", "--limit takes 1\u2013500", { param: "limit" });
11910
+ return limit;
11911
+ }, "limitOf");
11912
+ var peopleIds = /* @__PURE__ */ __name(async (store, ids) => {
11913
+ const kept2 = [];
11914
+ const refused2 = [];
11915
+ for (const id of ids) {
11916
+ const kind = await store.proposedActions.get(id).then((action) => action.kind, () => void 0);
11917
+ if (kind === void 0)
11918
+ refused2.push({ id, code: "not_found", reason: "proposal.not-found", message: `no proposal ${id}` });
11919
+ else if (!PEOPLE_KINDS.includes(kind))
11920
+ refused2.push({
11921
+ id,
11922
+ code: "validation_error",
11923
+ reason: "proposal.not-people",
11924
+ message: `${id} is a ${kind} proposal; memo review decides it`
11925
+ });
11926
+ else
11927
+ kept2.push(id);
11928
+ }
11929
+ return { ids: kept2, refused: refused2 };
11930
+ }, "peopleIds");
11931
+ var peopleProposalCommands = /* @__PURE__ */ __name((people, program, streams, env) => {
11932
+ const { print } = answers(program, streams, env);
11933
+ annotate(people.command("review"), { effects: LOCAL_READ }).summary("people that may be one, and splits an agent proposed, waiting for you").description("what waits for the owner about who is who: matches (people that may be one) and splits (identities an agent says are not this person), newest first; people confirm or people reject answers them").option("--kind <kind>", `${PROPOSAL_KINDS.join(", ")} (default all)`, oneOf(PROPOSAL_KINDS), "all").option("--limit <n>", "most proposals, up to 500", positive, 50).option("--json", "print JSON; --json=id,title keeps only those fields").action(async (options) => {
11934
+ const limit = limitOf(options.limit);
11935
+ const found = await withStore(env, (store) => waiting2(store, { kind: options.kind, limit }));
11936
+ print(options.json, listAnswer("people review", { items: found.items, limit, has_more: found.hasMore }), [
11937
+ ...found.items.map((row) => `${row.id} ${summaryOf2(row)}${row.reason ? ` \u2014 ${row.reason}` : ""}`),
11938
+ ...found.hasMore ? [`more wait: --limit ${Math.min(500, limit * 2)}`] : []
11939
+ ].join("\n") || "nothing about people waits for you");
11940
+ });
11941
+ for (const name2 of ["confirm", "reject"]) {
11942
+ const confirm = name2 === "confirm";
11943
+ const command = byOption(annotate(people.command(name2), { effects: LOCAL_WRITE }).summary(confirm ? "confirm matches and splits by id, or all that people review lists; only you" : "turn down matches and splits by id, or all that people review lists; only you").description(confirm ? "confirm matches (the people become one) and splits (the identities leave their person) by id or range as people review lists them, or `all` of what it lists with the same --kind and --limit; each is decided on its own, so a refusal leaves the others decided. `all` shows what it would do until --yes" : "turn down matches and splits by id or range, or `all` of what people review lists; a turned-down match comes back only on new evidence, a turned-down split not while its identities stay on that person. `all` shows what it would do until --yes").argument("<ids...>", "ids or ranges as people review lists them (17080 17082-17085), or all")).option("--kind <kind>", `with all: ${PROPOSAL_KINDS.join(", ")} (default all)`, oneOf(PROPOSAL_KINDS), "all").option("--limit <n>", "with all: as many as people review lists, up to 500", positive, 50).option("--yes", "with all: do it, not only show what would be done");
11944
+ if (confirm)
11945
+ command.option("--reason <text>", "why, in a few words");
11946
+ else
11947
+ command.requiredOption("--reason <text>", "why they are turned down, in a few words");
11948
+ command.option("--json", "print JSON; --json=id,title keeps only those fields");
11949
+ command.action(async (words, options) => {
11950
+ const everything = words.length === 1 && words[0]?.toLowerCase() === "all";
11951
+ const limit = limitOf(options.limit);
11952
+ await asOwner(command, env, `${name2} ${everything ? "all waiting" : words.join(" ")} people proposals?`);
11953
+ const result = await withStore(env, async (store) => {
11954
+ const listed2 = everything ? await waiting2(store, { kind: options.kind, limit }) : void 0;
11955
+ const chosen3 = listed2 ? { ids: listed2.items.map(({ id }) => id), refused: [] } : await peopleIds(store, parseProposalIds(words));
11956
+ const more2 = listed2?.hasMore ?? false;
11957
+ if (everything && !options.yes)
11958
+ return { kind: "preview", preview: chosen3.ids, more: more2 };
11959
+ const done = await (await reviewOf(store, env)).decide(chosen3.ids, decisionOf(confirm, "owner", options.reason));
11960
+ return { kind: "decided", ...done, refused: [...chosen3.refused, ...done.refused], more: more2 };
11961
+ });
11962
+ const moreText = result.more ? `
11963
+ more wait than --limit ${limit}; run it again for the rest` : "";
11964
+ if (result.kind === "preview") {
11965
+ const count = result.preview.length;
11966
+ print(options.json, itemAnswer({ outcome: "preview", would: name2, ids: result.preview, has_more: result.more }), count === 0 ? "nothing about people waits for you" : `would ${name2} ${count}: ${result.preview.join(" ")}
11967
+ nothing changed; add --yes to ${name2} them${moreText}`);
11968
+ return;
11969
+ }
11970
+ const { more, kind: _, ...decided } = result;
11971
+ const issues = decided.refused.map((one2) => ({ code: one2.code, source: one2.id, reason: one2.reason }));
11972
+ print(options.json, itemAnswer({ ...decided, has_more: more }, issues.length ? { meta: { complete: false, issues } } : void 0), decidedText(decided) + moreText);
11973
+ });
11974
+ }
11975
+ }, "peopleProposalCommands");
11976
+
11716
11977
  // dist/people/identities-command.js
11717
- var OWNER_ONLY = "identity.owner-only";
11718
11978
  var PERSON = /^person:([1-9]\d*)$/;
11719
11979
  var personOf = /* @__PURE__ */ __name(async (store, who) => {
11720
- const uid = PERSON.exec(who.trim())?.[1];
11980
+ const uid = PERSON.exec((await withOwner(store, who)).trim())?.[1];
11721
11981
  const found = uid === void 0 ? await store.people.personOf(await identityOf(store, who)) : await store.people.personByUid(uid);
11722
11982
  if (found === void 0)
11723
11983
  throw new CliError("not_found", `the store has no person for "${who}"`, { reason: "person.not-found" });
@@ -11739,28 +11999,6 @@ var personAnswer = /* @__PURE__ */ __name((person) => ({
11739
11999
  linkedAt: identity.linkedAt
11740
12000
  }))
11741
12001
  }), "personAnswer");
11742
- var matchAnswer = /* @__PURE__ */ __name((row) => ({
11743
- id: row.id,
11744
- persons: row.persons,
11745
- joins: row.joins,
11746
- identity: row.identity,
11747
- with: row.with,
11748
- signal: row.signal,
11749
- score: row.score,
11750
- candidates: row.candidates,
11751
- reason: row.reason,
11752
- evidence: row.evidence,
11753
- proposedBy: row.proposedBy,
11754
- createdAt: row.createdAt
11755
- }), "matchAnswer");
11756
- var summaryOf2 = /* @__PURE__ */ __name(({ identity, with: other, persons, signal }) => `${identity} may be the same person as ${other ?? persons[1]} (${signal})`, "summaryOf");
11757
- var asOwner = /* @__PURE__ */ __name(async (command, env, question) => {
11758
- const options = command.opts();
11759
- const who = await whoRuns(command, env, { asOwner: options.asOwner, question });
11760
- if (who !== "owner")
11761
- throw new CliError("permission_error", `only the owner can ${question.replace(/\?$/, "")}`, { reason: OWNER_ONLY });
11762
- return who;
11763
- }, "asOwner");
11764
12002
  var identitiesOf = /* @__PURE__ */ __name(async (store, refs) => {
11765
12003
  const found = [];
11766
12004
  for (const ref of refs)
@@ -11782,20 +12020,12 @@ var identitiesCommands = /* @__PURE__ */ __name((people, program, streams, env)
11782
12020
  print(options.json, itemAnswer(shown3), [
11783
12021
  `${shown3.ref} ${shown3.name ?? ""}`.trim(),
11784
12022
  ...shown3.identities.map(({ identity, name: name2 }) => ` ${identity}${name2 ? ` ${name2}` : ""}`),
11785
- ...shown3.merges.map(({ id, from }) => ` merged: ${id} (person:${from})`),
12023
+ ...shown3.merges.map(({ id, from, method, by, at: at2 }) => ` merged: ${id} (person:${from}) by ${by} via ${method}, ${at2.slice(0, 10)}`),
11786
12024
  ...shown3.matches.map((match) => ` match ${match.id}: ${summaryOf2(match)}`)
11787
12025
  ].join("\n"));
11788
12026
  });
11789
- annotate(people.command("review"), { effects: LOCAL_READ }).summary("people that may be one person, waiting for the owner").description("people that may be one person, waiting for the owner; memo review confirms or rejects them").option("--limit <n>", "most matches, up to 500", positive, 50).option("--json", "print JSON; --json=id,title keeps only those fields").action(async (options) => {
11790
- if (options.limit > 500)
11791
- throw new CliError("validation_error", "--limit takes 1\u2013500", { param: "limit" });
11792
- const found = await withStore(env, (store) => store.people.linkProposals({ status: "proposed", limit: options.limit, offset: 0 }));
11793
- const items = found.items.map(matchAnswer);
11794
- print(options.json, listAnswer("people review", { items, limit: options.limit, has_more: found.hasMore }), [
11795
- ...items.map((match) => `${match.id} ${summaryOf2(match)}`),
11796
- ...found.hasMore ? [`more wait: --limit ${Math.min(500, options.limit * 2)}`] : []
11797
- ].join("\n") || "no matches wait for you");
11798
- });
12027
+ peopleProposalCommands(people, program, streams, env);
12028
+ doubtsCommand(people, program, streams, env);
11799
12029
  annotate(people.command("scan"), { effects: LOCAL_WRITE }).summary("match people across sources now; memo sync does it too").description("match people across sources now: the same address or a phone two people share joins them, the rest waits in people review; memo sync runs it too").option("--json", "print JSON; --json=id,title keeps only those fields").action(async (options) => {
11800
12030
  const scan = await withStore(env, (store) => store.people.scanMatches());
11801
12031
  print(options.json, itemAnswer(scan), `${scan.merged.length} joined, ${scan.proposed.filter(({ opened }) => opened).length} new matches, ${scan.skipped.length} left apart`);
@@ -11827,12 +12057,26 @@ var identitiesCommands = /* @__PURE__ */ __name((people, program, streams, env)
11827
12057
  });
11828
12058
  print(options.json, itemAnswer(done), done.outcome === "linked" ? `linked: ${done.person}` : `waits for the owner as match ${done.proposal}`);
11829
12059
  });
11830
- byOption(annotate(people.command("unlink"), { effects: LOCAL_WRITE }).summary("take identities off a person, to one new person; only you").description("take identities off their person: one gets a person of its own again, several move together to one new person; only you, and no automatic match joins them back").argument("<identities...>", "the identities that leave, each <messenger>:<id> exactly, all of one person")).option("--json", "print JSON; --json=id,title keeps only those fields").action(async (refs, options, command) => {
11831
- await asOwner(command, env, `unlink ${refs.join(" ")}?`);
11832
- const person = await withStore(env, async (store) => {
12060
+ const separation = /* @__PURE__ */ __name(async (command, question, reason) => {
12061
+ const who = await whoRuns(command, env, { asOwner: command.opts().asOwner, question });
12062
+ if (who !== "owner" && !reason?.trim())
12063
+ throw new CliError("validation_error", "an agent's split waits for the owner; say why with --reason", {
12064
+ reason: "proposal.reason-required",
12065
+ param: "reason"
12066
+ });
12067
+ return who;
12068
+ }, "separation");
12069
+ const proposed = /* @__PURE__ */ __name((json5, proposal) => print(json5, itemAnswer({ outcome: "proposed", proposal }), `waits for the owner as split ${proposal}: memo people review`), "proposed");
12070
+ reasonOption(byOption(annotate(people.command("unlink"), { effects: LOCAL_WRITE }).summary("take identities off a person, to one new person; an agent's waits for you").description("take identities off their person: one gets a person of its own again, several move together to one new person, and no automatic match joins them back; yours applies at once, an agent's waits for you in people review").argument("<identities...>", "the identities that leave, each <messenger>:<id> exactly, all of one person"))).option("--json", "print JSON; --json=id,title keeps only those fields").action(async (refs, options, command) => {
12071
+ const who = await separation(command, `unlink ${refs.join(" ")}?`, options.reason);
12072
+ const done = await withStore(env, async (store) => {
11833
12073
  const chosen3 = [];
11834
12074
  for (const ref of refs)
11835
12075
  chosen3.push(await exactIdentityOf(store, ref));
12076
+ if (who !== "owner") {
12077
+ const reason = options.reason?.trim();
12078
+ return { proposal: (await store.people.proposeSplit({ identities: chosen3, by: who, reason })).id };
12079
+ }
11836
12080
  const [first] = chosen3;
11837
12081
  if (chosen3.length === 1)
11838
12082
  return store.people.unlinkIdentity(first, { method: "unlink", by: "owner" });
@@ -11841,11 +12085,20 @@ var identitiesCommands = /* @__PURE__ */ __name((people, program, streams, env)
11841
12085
  throw new CliError("not_found", `the store has no person for "${refs[0]}"`, { reason: "person.not-found" });
11842
12086
  return store.people.split(held.uid, chosen3, "owner");
11843
12087
  });
11844
- print(options.json, itemAnswer(personAnswer(person)), `person:${person.uid}`);
12088
+ if ("proposal" in done)
12089
+ proposed(options.json, done.proposal);
12090
+ else
12091
+ print(options.json, itemAnswer(personAnswer(done)), `person:${done.uid}`);
11845
12092
  });
11846
- byOption(annotate(people.command("unmerge"), { effects: LOCAL_WRITE }).summary("undo a merge: its identities go back to their person; only you").description("give the identities a merge brought back to the person they came from; only you").argument("<merge>", "merge:<to>-<from>, as people show lists it")).option("--json", "print JSON; --json=id,title keeps only those fields").action(async (merge, options, command) => {
12093
+ reasonOption(byOption(annotate(people.command("unmerge"), { effects: LOCAL_WRITE }).summary("undo a merge: its identities go back to their person; an agent's waits for you").description("give the identities a merge brought back to the person they came from; yours applies at once, an agent's waits for you in people review").argument("<merge>", "merge:<to>-<from>, as people show lists it"))).option("--json", "print JSON; --json=id,title keeps only those fields").action(async (merge, options, command) => {
11847
12094
  const { to, from } = parseMergeId(merge);
11848
- await asOwner(command, env, `undo ${merge}?`);
12095
+ const who = await separation(command, `undo ${merge}?`, options.reason);
12096
+ if (who !== "owner") {
12097
+ const reason = options.reason?.trim();
12098
+ const proposal = await withStore(env, (store) => store.people.proposeSplit({ merge, by: who, reason }));
12099
+ proposed(options.json, proposal.id);
12100
+ return;
12101
+ }
11849
12102
  const person = await withStore(env, (store) => store.people.undoMerge(to, from, "owner"));
11850
12103
  print(options.json, itemAnswer(personAnswer(person)), `person:${person.uid}`);
11851
12104
  });
@@ -14894,6 +15147,7 @@ var WRITES = /* @__PURE__ */ new Set(["update", "link", "claim", "release"]);
14894
15147
  var TASKISH = /^(task:.+|\d+|[A-Z][A-Z0-9]*-\d+)$/;
14895
15148
  var settings = settingsFor({ ...APP, appName: "cli-memo-tasks", envPrefix: "MEMO_TASKS" });
14896
15149
  var resolved = /* @__PURE__ */ new WeakMap();
15150
+ var across = /* @__PURE__ */ new WeakMap();
14897
15151
  var messenger = {
14898
15152
  app: APP,
14899
15153
  provider: "memo",
@@ -14902,7 +15156,8 @@ var messenger = {
14902
15156
  connect: /* @__PURE__ */ __name(async () => {
14903
15157
  throw new CliError("validation_error", "memo reads no messenger: these commands answer from the store");
14904
15158
  }, "connect"),
14905
- accountOf: /* @__PURE__ */ __name((command) => resolved.get(command), "accountOf")
15159
+ accountOf: /* @__PURE__ */ __name((command) => resolved.get(command), "accountOf"),
15160
+ accountsOf: /* @__PURE__ */ __name((command) => across.get(command), "accountsOf")
14906
15161
  };
14907
15162
  var requireAccount = /* @__PURE__ */ __name((env, warn) => async (_, command) => {
14908
15163
  const writes = WRITES.has(command.name());
@@ -14916,6 +15171,10 @@ var requireAccount = /* @__PURE__ */ __name((env, warn) => async (_, command) =>
14916
15171
  resolved.set(command, await oneAccountOf(store, env, value, option));
14917
15172
  return;
14918
15173
  }
15174
+ if (isTaskStats(command) && command.opts().chat === void 0) {
15175
+ across.set(command, await scopedAccounts(store, env));
15176
+ return;
15177
+ }
14919
15178
  if (command.name() === "link" && targets.length > 0 && chats.length === 0 && targets.every((one2) => TASKISH.test(one2)))
14920
15179
  return;
14921
15180
  if (["show", "update", "claim", "release"].includes(command.name()) && first !== void 0 && await store.tasks.projectTask(first))
@@ -14926,9 +15185,10 @@ var requireAccount = /* @__PURE__ */ __name((env, warn) => async (_, command) =>
14926
15185
  await store.close();
14927
15186
  }
14928
15187
  }, "requireAccount");
15188
+ var isTaskStats = /* @__PURE__ */ __name((command) => command.name() === "show" && command.parent?.name() === "tasks" && command.parent.parent?.name() === "stats", "isTaskStats");
14929
15189
  var scoped2 = /* @__PURE__ */ __name((command, env, warn) => overrideSharedContract(command, "Memo names stored accounts with --source or --account and uses command-local JSON without messenger profiles.", (one2) => {
14930
15190
  ;
14931
- (WRITES.has(one2.name()) ? writeOptions(one2, "the account it acts as: telegram:<account>, email:<account>, notes:<id>") : sourceOptions(one2, "the account: telegram:<account>, email:<account>, notes:<id>, or group:<name> of one")).option("--json", "print JSON").hook("preAction", requireAccount(env, warn));
15191
+ (WRITES.has(one2.name()) ? writeOptions(one2, "the account it acts as: telegram:<account>, email:<account>, notes:<id>") : sourceOptions(one2, isTaskStats(one2) ? "only this account: telegram:<account>, email:<account>, notes:<id>, or group:<name>; every stored account without it" : "the account: telegram:<account>, email:<account>, notes:<id>, or group:<name> of one")).option("--json", "print JSON").hook("preAction", requireAccount(env, warn));
14932
15192
  }), "scoped");
14933
15193
  var sharedTaskCommands = /* @__PURE__ */ __name((program, tasks, streams, env) => {
14934
15194
  provide(program, { streams, env });
@@ -15818,7 +16078,8 @@ var GROUP_AWARE = [
15818
16078
  "projects add",
15819
16079
  "projects context",
15820
16080
  "projects status",
15821
- "projects key-documents"
16081
+ "projects key-documents",
16082
+ "stats projects show"
15822
16083
  ];
15823
16084
  var isSimpleKind = /* @__PURE__ */ __name((name2) => REF_KINDS.some(({ type }) => type === name2), "isSimpleKind");
15824
16085
  var REF_KINDS_OF = {