@wirecat/cli-memo 0.131.63 → 0.131.64

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 (151) hide show
  1. package/dist/bin/memo.js +2 -2
  2. package/dist/bundle/{app-server-QBJG7OGQ.js → app-server-7KM4MSDA.js} +9 -9
  3. package/dist/bundle/{auto-LGA3VXKQ.js → auto-V3FUD6RW.js} +16 -16
  4. package/dist/bundle/{chunk-LK6D26RK.js → chunk-3SCHFNUH.js} +5 -5
  5. package/dist/bundle/{chunk-HGNWJJDT.js → chunk-3YNJBKGV.js} +13 -1
  6. package/dist/bundle/{chunk-Q3VEUHC7.js → chunk-6OS7PTOC.js} +3 -3
  7. package/dist/bundle/{chunk-2UCLF4AO.js → chunk-DXTNBVLV.js} +394 -115
  8. package/dist/bundle/{chunk-5Q534L4I.js → chunk-EDBZEHAU.js} +5 -4
  9. package/dist/bundle/{chunk-GNHDE7FH.js → chunk-FHZKHKBJ.js} +9 -9
  10. package/dist/bundle/{chunk-TBSWOVM3.js → chunk-FKUA3BTM.js} +14 -14
  11. package/dist/bundle/{chunk-TSKGEK2S.js → chunk-LVLFLWGY.js} +3 -3
  12. package/dist/bundle/{chunk-O2NQCWRM.js → chunk-ML46T7UC.js} +8 -8
  13. package/dist/bundle/{chunk-RSG7BRXI.js → chunk-MYXB2T77.js} +25 -1
  14. package/dist/bundle/{chunk-WDZOEBTE.js → chunk-NH3A5QTW.js} +2 -2
  15. package/dist/bundle/{chunk-6OZ2WI7Y.js → chunk-NIJZXGJN.js} +1 -1
  16. package/dist/bundle/{chunk-EGI6JHIA.js → chunk-NRHF7TQ4.js} +2 -2
  17. package/dist/bundle/{chunk-WDWKG7FJ.js → chunk-PVGK67AJ.js} +17 -0
  18. package/dist/bundle/{chunk-E5JQFEIQ.js → chunk-QHNAPLVB.js} +4 -4
  19. package/dist/bundle/{chunk-SJ55SMBE.js → chunk-QTF4ZXOL.js} +2 -1
  20. package/dist/bundle/{chunk-YVJAD5E7.js → chunk-T3LVSUNZ.js} +38 -5
  21. package/dist/bundle/{chunk-OXBETHGN.js → chunk-UXAP7MNL.js} +4 -4
  22. package/dist/bundle/{chunk-3ZXWLFUG.js → chunk-VLUDHCCX.js} +3 -3
  23. package/dist/bundle/{chunk-K4WCDPDL.js → chunk-WINH45XG.js} +4 -4
  24. package/dist/bundle/{chunk-4BKSE3CG.js → chunk-XPT5PX7H.js} +4 -4
  25. package/dist/bundle/{chunk-BOMHJR2E.js → chunk-ZX6SWNSR.js} +3 -3
  26. package/dist/bundle/{command-contract-SIXWLKAS.js → command-contract-PLB2JGFJ.js} +2 -2
  27. package/dist/bundle/{entry-SFLEGFSN.js → entry-MUE6HWX3.js} +1 -1
  28. package/dist/bundle/{failure-OGSLUNT6.js → failure-6SP64Q66.js} +14 -14
  29. package/dist/bundle/{first-run-ZKDGFY6P.js → first-run-3JYWLJCH.js} +1 -1
  30. package/dist/bundle/{first-screen-IQEU7XF2.js → first-screen-QH34AIFV.js} +3 -3
  31. package/dist/bundle/{mcp-Y4XMDC5Q.js → mcp-QX2D6EXA.js} +6 -6
  32. package/dist/bundle/memo.js +6 -6
  33. package/dist/bundle/{program-ZHLCEVWB.js → program-LXQLWUAG.js} +1755 -413
  34. package/dist/bundle/{server-IQILK5YP.js → server-L622PMVC.js} +9 -9
  35. package/dist/bundle/{server-I5BPRS5C.js → server-MVJU7QG4.js} +19 -19
  36. package/dist/bundle/{server-NKI7SVK5.js → server-SJVP2XXD.js} +6 -6
  37. package/dist/bundle/{store-6H4FPFTX.js → store-M5QSIRWJ.js} +1 -1
  38. package/dist/bundle/{store-maintenance-command-IFVWSQMJ.js → store-maintenance-command-PQCO5ICC.js} +5 -5
  39. package/dist/bundle/{update-YMILPFRY.js → update-MQUCCIBB.js} +15 -15
  40. package/dist/discovery/command.d.ts.map +1 -1
  41. package/dist/discovery/command.js +6 -0
  42. package/dist/discovery/command.js.map +1 -1
  43. package/dist/events/command.d.ts +4 -0
  44. package/dist/events/command.d.ts.map +1 -0
  45. package/dist/events/command.js +35 -0
  46. package/dist/events/command.js.map +1 -0
  47. package/dist/events/events.d.ts +52 -0
  48. package/dist/events/events.d.ts.map +1 -0
  49. package/dist/events/events.js +199 -0
  50. package/dist/events/events.js.map +1 -0
  51. package/dist/examples.d.ts.map +1 -1
  52. package/dist/examples.js +90 -3
  53. package/dist/examples.js.map +1 -1
  54. package/dist/finance/command.d.ts +1 -1
  55. package/dist/finance/command.d.ts.map +1 -1
  56. package/dist/finance/command.js +13 -30
  57. package/dist/finance/command.js.map +1 -1
  58. package/dist/finance/contracts-command.d.ts +12 -0
  59. package/dist/finance/contracts-command.d.ts.map +1 -0
  60. package/dist/finance/contracts-command.js +110 -0
  61. package/dist/finance/contracts-command.js.map +1 -0
  62. package/dist/finance/deals-command.d.ts.map +1 -1
  63. package/dist/finance/deals-command.js +5 -4
  64. package/dist/finance/deals-command.js.map +1 -1
  65. package/dist/finance/lines-command.d.ts +37 -0
  66. package/dist/finance/lines-command.d.ts.map +1 -0
  67. package/dist/finance/lines-command.js +70 -0
  68. package/dist/finance/lines-command.js.map +1 -0
  69. package/dist/finance/orders-command.d.ts.map +1 -1
  70. package/dist/finance/orders-command.js +5 -2
  71. package/dist/finance/orders-command.js.map +1 -1
  72. package/dist/finance/products-command.d.ts +12 -0
  73. package/dist/finance/products-command.d.ts.map +1 -0
  74. package/dist/finance/products-command.js +99 -0
  75. package/dist/finance/products-command.js.map +1 -0
  76. package/dist/finance/subscriptions-command.d.ts +12 -0
  77. package/dist/finance/subscriptions-command.d.ts.map +1 -0
  78. package/dist/finance/subscriptions-command.js +153 -0
  79. package/dist/finance/subscriptions-command.js.map +1 -0
  80. package/dist/finance/transactions-command.d.ts +12 -0
  81. package/dist/finance/transactions-command.d.ts.map +1 -0
  82. package/dist/finance/transactions-command.js +137 -0
  83. package/dist/finance/transactions-command.js.map +1 -0
  84. package/dist/finance/wallets-command.d.ts +12 -0
  85. package/dist/finance/wallets-command.d.ts.map +1 -0
  86. package/dist/finance/wallets-command.js +106 -0
  87. package/dist/finance/wallets-command.js.map +1 -0
  88. package/dist/finance/written.d.ts +37 -0
  89. package/dist/finance/written.d.ts.map +1 -0
  90. package/dist/finance/written.js +36 -0
  91. package/dist/finance/written.js.map +1 -0
  92. package/dist/knowledge/command.d.ts.map +1 -1
  93. package/dist/knowledge/command.js +3 -2
  94. package/dist/knowledge/command.js.map +1 -1
  95. package/dist/mcp/permissions.d.ts +1 -1
  96. package/dist/mcp/permissions.d.ts.map +1 -1
  97. package/dist/mcp/permissions.js +1 -0
  98. package/dist/mcp/permissions.js.map +1 -1
  99. package/dist/options.d.ts +2 -0
  100. package/dist/options.d.ts.map +1 -1
  101. package/dist/options.js +2 -0
  102. package/dist/options.js.map +1 -1
  103. package/dist/program.d.ts.map +1 -1
  104. package/dist/program.js +174 -0
  105. package/dist/program.js.map +1 -1
  106. package/dist/reasons.d.ts.map +1 -1
  107. package/dist/reasons.js +24 -0
  108. package/dist/reasons.js.map +1 -1
  109. package/dist/records/import.d.ts +2 -4
  110. package/dist/records/import.d.ts.map +1 -1
  111. package/dist/records/import.js +41 -41
  112. package/dist/records/import.js.map +1 -1
  113. package/dist/records/input.d.ts +20 -0
  114. package/dist/records/input.d.ts.map +1 -0
  115. package/dist/records/input.js +115 -0
  116. package/dist/records/input.js.map +1 -0
  117. package/dist/records/mapping.d.ts +16 -1
  118. package/dist/records/mapping.d.ts.map +1 -1
  119. package/dist/records/mapping.js +24 -11
  120. package/dist/records/mapping.js.map +1 -1
  121. package/dist/records/record-commands.d.ts +8 -0
  122. package/dist/records/record-commands.d.ts.map +1 -0
  123. package/dist/records/record-commands.js +89 -0
  124. package/dist/records/record-commands.js.map +1 -0
  125. package/dist/records/sources.d.ts +48 -0
  126. package/dist/records/sources.d.ts.map +1 -0
  127. package/dist/records/sources.js +72 -0
  128. package/dist/records/sources.js.map +1 -0
  129. package/dist/review/kinds.d.ts +1 -1
  130. package/dist/review/kinds.d.ts.map +1 -1
  131. package/dist/review/kinds.js +4 -0
  132. package/dist/review/kinds.js.map +1 -1
  133. package/dist/review/review.d.ts.map +1 -1
  134. package/dist/review/review.js +4 -0
  135. package/dist/review/review.js.map +1 -1
  136. package/dist/rows.d.ts.map +1 -1
  137. package/dist/rows.js +34 -0
  138. package/dist/rows.js.map +1 -1
  139. package/dist/search/lane-gates.js +1 -1
  140. package/dist/search/lane-gates.js.map +1 -1
  141. package/dist/show/command.d.ts +3 -0
  142. package/dist/show/command.d.ts.map +1 -1
  143. package/dist/show/command.js +21 -1
  144. package/dist/show/command.js.map +1 -1
  145. package/dist/version.d.ts +1 -1
  146. package/dist/version.js +1 -1
  147. package/package.json +1 -1
  148. package/skills/cli-memo/SKILL.md +8 -5
  149. package/skills/cli-memo/topics/money.md +20 -1
  150. package/skills/cli-memo/topics/proposals.md +8 -5
  151. package/skills/cli-memo/topics/search.md +7 -0
@@ -6,17 +6,17 @@ import {
6
6
  autoState,
7
7
  lastAutoRun,
8
8
  recordAutoRun
9
- } from "./chunk-4BKSE3CG.js";
9
+ } from "./chunk-XPT5PX7H.js";
10
10
  import {
11
11
  installer,
12
12
  latest,
13
13
  upgradeCommand
14
- } from "./chunk-K4WCDPDL.js";
14
+ } from "./chunk-WINH45XG.js";
15
15
  import {
16
16
  mcpOwnerAllowed,
17
17
  readOnlyAvailability,
18
18
  refuseWritesUnderLock
19
- } from "./chunk-5Q534L4I.js";
19
+ } from "./chunk-EDBZEHAU.js";
20
20
  import {
21
21
  answers,
22
22
  atDetail,
@@ -27,7 +27,7 @@ import {
27
27
  trackAnswers,
28
28
  wholeList,
29
29
  withStore
30
- } from "./chunk-YVJAD5E7.js";
30
+ } from "./chunk-T3LVSUNZ.js";
31
31
  import {
32
32
  ATTACHMENT_CHARS,
33
33
  DIALECTS,
@@ -59,7 +59,7 @@ import {
59
59
  showMail,
60
60
  unsetConfigKey,
61
61
  updateConfig
62
- } from "./chunk-GNHDE7FH.js";
62
+ } from "./chunk-FHZKHKBJ.js";
63
63
  import "./chunk-QP3KNC5D.js";
64
64
  import "./chunk-FWRBJAQZ.js";
65
65
  import "./chunk-MWAXS4BX.js";
@@ -67,7 +67,7 @@ import "./chunk-PKUBC2ME.js";
67
67
  import {
68
68
  errorObject,
69
69
  recognisable
70
- } from "./chunk-BOMHJR2E.js";
70
+ } from "./chunk-ZX6SWNSR.js";
71
71
  import {
72
72
  AGENT_INPUT_MAX_CHARS,
73
73
  DISCOVERY_DESCRIPTIONS,
@@ -106,7 +106,7 @@ import {
106
106
  tasksCommand,
107
107
  tasksStatsCommand,
108
108
  withSqliteSidecars
109
- } from "./chunk-TBSWOVM3.js";
109
+ } from "./chunk-FKUA3BTM.js";
110
110
  import "./chunk-RLX5SC2X.js";
111
111
  import "./chunk-SIBQ34LX.js";
112
112
  import {
@@ -115,22 +115,23 @@ import {
115
115
  messageHitItem,
116
116
  noteHitItem,
117
117
  shownOf
118
- } from "./chunk-LK6D26RK.js";
118
+ } from "./chunk-3SCHFNUH.js";
119
119
  import "./chunk-DKO7WEXJ.js";
120
120
  import {
121
+ REASONS as REASONS2,
121
122
  SKILL_TARGETS,
122
123
  skillCommand,
123
124
  skillPath,
124
125
  skillVersion
125
- } from "./chunk-SJ55SMBE.js";
126
+ } from "./chunk-QTF4ZXOL.js";
126
127
  import {
127
128
  recoveryNotes,
128
129
  storeInfo,
129
130
  storeRecoveryCheck,
130
131
  storeRecoveryRun,
131
132
  storeSummary
132
- } from "./chunk-E5JQFEIQ.js";
133
- import "./chunk-3ZXWLFUG.js";
133
+ } from "./chunk-QHNAPLVB.js";
134
+ import "./chunk-VLUDHCCX.js";
134
135
  import {
135
136
  LIST_QUERY_GUIDE,
136
137
  STATUS_SIGNALS,
@@ -148,6 +149,10 @@ import {
148
149
  gatherStoredProject,
149
150
  importEngine,
150
151
  ingest,
152
+ ingestLines,
153
+ ingestVcard,
154
+ isVcard,
155
+ jsonlLines,
151
156
  listQuery,
152
157
  mailTurn,
153
158
  meaningLane,
@@ -156,6 +161,8 @@ import {
156
161
  meetingSearchArguments,
157
162
  meetingSearchMeta,
158
163
  modelGateway,
164
+ nativeField,
165
+ nativeTerms,
159
166
  parseProposalIds,
160
167
  personContext,
161
168
  pickPerson,
@@ -182,7 +189,7 @@ import {
182
189
  termField,
183
190
  typedQuery,
184
191
  withQuery
185
- } from "./chunk-2UCLF4AO.js";
192
+ } from "./chunk-DXTNBVLV.js";
186
193
  import {
187
194
  readBoundedUtf8File,
188
195
  writeFileAtomic
@@ -191,9 +198,9 @@ import {
191
198
  commandsText,
192
199
  inSection,
193
200
  installHelp
194
- } from "./chunk-WDZOEBTE.js";
201
+ } from "./chunk-NH3A5QTW.js";
195
202
  import "./chunk-HTQTIKWP.js";
196
- import "./chunk-6OZ2WI7Y.js";
203
+ import "./chunk-NIJZXGJN.js";
197
204
  import {
198
205
  Command,
199
206
  DEFAULT_TEXT_MODEL,
@@ -220,6 +227,8 @@ import {
220
227
  outputFor,
221
228
  overrideSharedContract,
222
229
  parseDuration,
230
+ progressLine,
231
+ progressOf,
223
232
  proposesOnly,
224
233
  provide,
225
234
  runsDirFor,
@@ -228,15 +237,15 @@ import {
228
237
  snakeKeys,
229
238
  textModels,
230
239
  textModelsFile
231
- } from "./chunk-WDWKG7FJ.js";
240
+ } from "./chunk-PVGK67AJ.js";
232
241
  import "./chunk-SIJA2UYC.js";
233
- import "./chunk-TSKGEK2S.js";
242
+ import "./chunk-LVLFLWGY.js";
234
243
  import {
235
244
  isNewer
236
245
  } from "./chunk-ASWLM74P.js";
237
246
  import "./chunk-6G53ZFUT.js";
238
247
  import "./chunk-FH4P5UQA.js";
239
- import "./chunk-EGI6JHIA.js";
248
+ import "./chunk-NRHF7TQ4.js";
240
249
  import "./chunk-RP6VV35S.js";
241
250
  import "./chunk-RTLQHLHG.js";
242
251
  import {
@@ -257,6 +266,7 @@ import {
257
266
  PROJECT_TASK_FIELDS,
258
267
  PROJECT_TYPES,
259
268
  PROPOSAL_STATUSES,
269
+ RECORDS_SCHEMA_VERSION,
260
270
  REMINDERS_QUERY,
261
271
  SCOPES,
262
272
  TASK_RELATION_KINDS,
@@ -266,10 +276,11 @@ import {
266
276
  contextEvidenceFingerprint,
267
277
  decodeProjectAnnotationSnapshot,
268
278
  entriesOfList,
269
- envelopeOfJsonl,
279
+ envelopeOfText,
270
280
  formatLocator,
271
281
  formatReference,
272
282
  isFolderProvider,
283
+ isImportedProvider,
273
284
  kindOf,
274
285
  looksLikeReference,
275
286
  mailFindingFieldsHelp,
@@ -281,8 +292,11 @@ import {
281
292
  plainQuery,
282
293
  providerNamed,
283
294
  refLabel
284
- } from "./chunk-HGNWJJDT.js";
295
+ } from "./chunk-3YNJBKGV.js";
285
296
  import {
297
+ CATALOG_KINDS,
298
+ CONTRACT_KINDS,
299
+ CONTRACT_STATUSES,
286
300
  DEAL_KINDS,
287
301
  DEAL_ROLES,
288
302
  DEAL_STATUSES,
@@ -299,10 +313,17 @@ import {
299
313
  ORDER_PURPOSES,
300
314
  ORDER_STATUSES,
301
315
  PRIORITY_LABELS,
316
+ SUBSCRIPTION_STATUSES,
302
317
  TASK_STATES,
303
318
  TASK_TYPES,
319
+ TRANSACTION_STATUSES,
320
+ WALLET_KINDS,
304
321
  WORK_TASK_TYPES,
305
322
  createUpcomingMeetingReader,
323
+ dateRange,
324
+ dayBoundary,
325
+ event,
326
+ eventItem,
306
327
  formatMeetingReference,
307
328
  isClosedState,
308
329
  markStoreDamaged,
@@ -343,7 +364,7 @@ import {
343
364
  REASONS,
344
365
  STORE_CLIENT,
345
366
  VERSION
346
- } from "./chunk-RSG7BRXI.js";
367
+ } from "./chunk-MYXB2T77.js";
347
368
  import "./chunk-IK6KH3RE.js";
348
369
  import "./chunk-SW6C6WH5.js";
349
370
  import "./chunk-D72URWJE.js";
@@ -500,7 +521,7 @@ var messengers = /* @__PURE__ */ __name((entry) => new CliError("validation_erro
500
521
  var listedOf = /* @__PURE__ */ __name(async (store, value) => {
501
522
  const held = await store.accounts.storedAccounts();
502
523
  const holdsFiles = await filesAccounts(store);
503
- const named4 = /* @__PURE__ */ __name(async (entry) => {
524
+ const named5 = /* @__PURE__ */ __name(async (entry) => {
504
525
  const [provider = "", ...rest] = entry.trim().split(":");
505
526
  const account2 = rest.join(":");
506
527
  if (isFolderProvider(provider) && account2) {
@@ -513,7 +534,7 @@ var listedOf = /* @__PURE__ */ __name(async (store, value) => {
513
534
  return entry.trim();
514
535
  return `email:${(await mailboxOf(store, account2)).account}`;
515
536
  }, "named");
516
- const each = /* @__PURE__ */ __name((entries) => Promise.all(entries.filter((one2) => one2.trim()).map(named4)), "each");
537
+ const each = /* @__PURE__ */ __name((entries) => Promise.all(entries.filter((one2) => one2.trim()).map(named5)), "each");
517
538
  const groups = Object.fromEntries(await Promise.all(Object.entries(await store.accounts.accountGroups()).map(async ([name2, members]) => [name2, await each(members)])));
518
539
  return entriesOfList((await each(value.split(","))).join(","), {
519
540
  held,
@@ -523,9 +544,9 @@ var listedOf = /* @__PURE__ */ __name(async (store, value) => {
523
544
  });
524
545
  }, "listedOf");
525
546
  var sourceListOf = /* @__PURE__ */ __name(async (store, env, value) => {
526
- const listed = await listedOf(store, value);
547
+ const listed2 = await listedOf(store, value);
527
548
  const list = { mail: [], notes: false, documents: false };
528
- for (const { entry, accounts } of listed) {
549
+ for (const { entry, accounts } of listed2) {
529
550
  const word = entry.split(":")[0] ?? "";
530
551
  if (MESSENGERS.has(word))
531
552
  throw messengers(entry);
@@ -673,6 +694,7 @@ var oneOf = /* @__PURE__ */ __name((values) => (value) => {
673
694
  var collect = /* @__PURE__ */ __name((value, previous = []) => [...previous, value], "collect");
674
695
  var readScope = /* @__PURE__ */ __name((command, help = ONE_ACCOUNT_HELP) => sourceOptions(command, help).option("--json", "print JSON; --json=id,title keeps only those fields"), "readScope");
675
696
  var writeScope = /* @__PURE__ */ __name((command, help) => writeOptions(command, help).option("--json", "print JSON; --json=id,title keeps only those fields"), "writeScope");
697
+ var jsonOption = /* @__PURE__ */ __name((command, fields = "ref,title") => command.option("--json", `print JSON; --json=${fields} keeps only those fields`), "jsonOption");
676
698
 
677
699
  // node_modules/.pnpm/@wirecat+cli-core@0.613.0_@wirecat+cli-base@0.82.0_commander@15.0.0_esbuild@0.28.2_type_562287bbc40b862fa82b63f307e02b11/node_modules/@wirecat/cli-core/dist/mail/sender-scores.js
678
700
  var SCORED = "mail_sender_scores";
@@ -725,7 +747,11 @@ var REVIEW_KINDS = [
725
747
  "action",
726
748
  "invoice",
727
749
  "payment",
728
- "order"
750
+ "order",
751
+ "contract",
752
+ "subscription",
753
+ "subscription_price",
754
+ "transaction"
729
755
  ];
730
756
  var BY_ACCOUNT = [MEETING_FINDINGS_KIND, MAIL_FINDINGS_KIND];
731
757
  var reviewRegistry = /* @__PURE__ */ __name((store) => {
@@ -762,22 +788,22 @@ var REVIEW_QUERY = {
762
788
  ]
763
789
  };
764
790
  var filterOf = /* @__PURE__ */ __name(async (store, words) => {
765
- const terms = queryTerms(words, REVIEW_QUERY, "review");
766
- const project = terms.get("project");
767
- const kinds2 = terms.get("kind")?.split(",").map((one2) => one2.trim()).filter(Boolean);
791
+ const terms2 = queryTerms(words, REVIEW_QUERY, "review");
792
+ const project = terms2.get("project");
793
+ const kinds2 = terms2.get("kind")?.split(",").map((one2) => one2.trim()).filter(Boolean);
768
794
  const unknown2 = kinds2?.find((one2) => !REVIEW_KINDS.includes(one2));
769
795
  if (unknown2 !== void 0)
770
796
  throw new CliError("validation_error", `no proposal kind ${unknown2}; kinds: ${REVIEW_KINDS.join(", ")}`, {
771
797
  param: "kind"
772
798
  });
773
- const by = terms.get("by");
774
- const via = terms.get("via");
799
+ const by = terms2.get("by");
800
+ const via = terms2.get("via");
775
801
  return {
776
802
  ...project === void 0 ? {} : { project: await canonicalProject(store, project) },
777
803
  ...kinds2?.length ? { kinds: kinds2 } : {},
778
804
  ...by === void 0 ? {} : { by: by === "agent" || by === "rule" ? by : { bot: by } },
779
805
  ...via === void 0 ? {} : { via },
780
- status: terms.get("status") ?? "proposed"
806
+ status: terms2.get("status") ?? "proposed"
781
807
  };
782
808
  }, "filterOf");
783
809
  var proposerName = /* @__PURE__ */ __name((proposer) => proposer.type === "bot" ? proposer.name : proposer.type === "person" ? "you" : "unknown", "proposerName");
@@ -814,6 +840,10 @@ var titleOf = /* @__PURE__ */ __name((row, label) => {
814
840
  case "invoice":
815
841
  case "payment":
816
842
  case "order":
843
+ case "contract":
844
+ case "subscription":
845
+ case "subscription_price":
846
+ case "transaction":
817
847
  return row.summary ?? subject;
818
848
  default:
819
849
  return object2 === null ? subject : `${subject} \u2192 ${object2}`;
@@ -943,8 +973,8 @@ var reviewText = /* @__PURE__ */ __name((items, hasMore) => {
943
973
  ...item.status === "proposed" ? [] : [item.status]
944
974
  ].join(" ");
945
975
  const why = [item.reason && cut(item.reason, 100), item.evidence[0]].filter(Boolean).join(" \xB7 ");
946
- const parts = (item.parts ?? []).map((part) => `${pad} ${item.id}/${part.id} ${part.kind} ${cut(part.summary, 80)}${part.outcome ? ` ${part.outcome}` : ""}`);
947
- return [head, ...why ? [`${pad} ${why}`] : [], ...parts];
976
+ const parts2 = (item.parts ?? []).map((part) => `${pad} ${item.id}/${part.id} ${part.kind} ${cut(part.summary, 80)}${part.outcome ? ` ${part.outcome}` : ""}`);
977
+ return [head, ...why ? [`${pad} ${why}`] : [], ...parts2];
948
978
  })
949
979
  ]);
950
980
  return [...lines2, `${items.length} shown${hasMore ? ", more with --page" : ""}`].join("\n");
@@ -1044,19 +1074,19 @@ var partsOf = /* @__PURE__ */ __name((action, targetName) => {
1044
1074
  const text3 = [payload.text, payload.title].find((one2) => typeof one2 === "string" && one2.trim() !== "");
1045
1075
  return { verb: action.kind, targetName, text: text3 ?? null };
1046
1076
  }, "partsOf");
1047
- var summaryOf = /* @__PURE__ */ __name((action, parts) => {
1048
- const target = parts.targetName ?? action.target;
1049
- if ("counts" in parts && parts.counts) {
1050
- const { facts, tasks } = parts.counts;
1077
+ var summaryOf = /* @__PURE__ */ __name((action, parts2) => {
1078
+ const target = parts2.targetName ?? action.target;
1079
+ if ("counts" in parts2 && parts2.counts) {
1080
+ const { facts, tasks } = parts2.counts;
1051
1081
  const what = [facts && counted(facts, "fact"), tasks && counted(tasks, "task")].filter(Boolean).join(" and ");
1052
1082
  const word = action.kind === MEETING_FINDINGS_KIND ? "from" : action.target?.startsWith("project:") ? "in" : "about";
1053
1083
  return `Create ${what || "nothing"}${target === null ? "" : ` ${word} ${target}`}`;
1054
1084
  }
1055
- const words = parts.verb.replaceAll("_", " ");
1085
+ const words = parts2.verb.replaceAll("_", " ");
1056
1086
  return [
1057
1087
  `${words.charAt(0).toUpperCase()}${words.slice(1)}`,
1058
1088
  target === null ? "" : ` ${target}`,
1059
- parts.text === null ? "" : `: ${clip(parts.text)}`
1089
+ parts2.text === null ? "" : `: ${clip(parts2.text)}`
1060
1090
  ].join("");
1061
1091
  }, "summaryOf");
1062
1092
  var chatOf = /* @__PURE__ */ __name((reference2) => {
@@ -1119,11 +1149,11 @@ var actionItems = /* @__PURE__ */ __name(async (store, actions, { brief = false
1119
1149
  const project = batch?.project ?? (action.target?.startsWith("project:") ? action.target : null);
1120
1150
  const projectName = project === null ? null : names.get(project) ?? null;
1121
1151
  const targetName = action.target === null ? null : names.get(action.target) ?? null;
1122
- const parts = partsOf(action, targetName);
1152
+ const parts2 = partsOf(action, targetName);
1123
1153
  return {
1124
1154
  ...action,
1125
- summary: summaryOf(action, parts),
1126
- ...parts,
1155
+ summary: summaryOf(action, parts2),
1156
+ ...parts2,
1127
1157
  chatName: action.target === null ? null : chats.get(action.target) ?? null,
1128
1158
  project,
1129
1159
  projectName,
@@ -1171,8 +1201,8 @@ var decideBatch = /* @__PURE__ */ __name(async (store, id, decision) => {
1171
1201
  throw new CliError("validation_error", "the findings changed since they were read; stage a new batch", {
1172
1202
  reason: batch.stale
1173
1203
  });
1174
- const parts = decision.confirm && decision.accept.length ? decision.accept.map((one2) => `${id}/${one2}`) : [id];
1175
- const { decided, refused } = await proposalRegistry(store).decide(parts, decisionOf(decision.confirm, decision.by, decision.reason));
1204
+ const parts2 = decision.confirm && decision.accept.length ? decision.accept.map((one2) => `${id}/${one2}`) : [id];
1205
+ const { decided, refused } = await proposalRegistry(store).decide(parts2, decisionOf(decision.confirm, decision.by, decision.reason));
1176
1206
  const refusal = refused[0];
1177
1207
  if (refusal)
1178
1208
  throw new CliError(refusal.code, refusal.message, { reason: refusal.reason });
@@ -1240,9 +1270,9 @@ var AGENT_LOG_QUERY = {
1240
1270
  ]
1241
1271
  };
1242
1272
  var listAgentActions = /* @__PURE__ */ __name((store, query, limit) => {
1243
- const terms = queryTerms(query, AGENT_LOG_QUERY, "agents list");
1244
- const tool = terms.get("tool");
1245
- const agent = terms.get("agent");
1273
+ const terms2 = queryTerms(query, AGENT_LOG_QUERY, "agents list");
1274
+ const tool = terms2.get("tool");
1275
+ const agent = terms2.get("agent");
1246
1276
  return pageOf("agents list", limit, (most) => store.agentActions.list({
1247
1277
  ...tool === void 0 ? {} : { tool },
1248
1278
  ...agent === void 0 ? {} : { agent },
@@ -2010,8 +2040,8 @@ var fileLinks = /* @__PURE__ */ __name((source, links, documents) => links.map((
2010
2040
  const at = anchor === null ? {} : { anchor };
2011
2041
  if (isReference(target))
2012
2042
  return { to: target, kind: "links-to", ...at };
2013
- const named4 = notesNamed(source, target, documents);
2014
- return named4.length === 1 ? { to: `document:${named4[0].id}`, kind: "links-to", ...at } : { targetText: posix.basename(target.replace(/\\/g, "/")) || target, kind: "links-to", ...at };
2043
+ const named5 = notesNamed(source, target, documents);
2044
+ return named5.length === 1 ? { to: `document:${named5[0].id}`, kind: "links-to", ...at } : { targetText: posix.basename(target.replace(/\\/g, "/")) || target, kind: "links-to", ...at };
2015
2045
  }), "fileLinks");
2016
2046
 
2017
2047
  // dist/notes/renames.js
@@ -2145,11 +2175,11 @@ var importNotes = /* @__PURE__ */ __name(async (store, folder, { ignore = [], sk
2145
2175
  after.files[id] = `${stamp}${hash}`;
2146
2176
  read.push({ id, path, bytes, hash });
2147
2177
  }
2148
- const listed = /* @__PURE__ */ new Set([
2178
+ const listed2 = /* @__PURE__ */ new Set([
2149
2179
  ...Object.keys(after.files).filter((id) => !after.files[id]?.startsWith(MEMO2)),
2150
2180
  ...[...held].filter((id) => stored.has(id))
2151
2181
  ]);
2152
- const goneHashes = Object.fromEntries([...stored.values()].filter((note) => !listed.has(note.path) && note.contentHash !== null).map((note) => [note.path, note.contentHash]));
2182
+ const goneHashes = Object.fromEntries([...stored.values()].filter((note) => !listed2.has(note.path) && note.contentHash !== null).map((note) => [note.path, note.contentHash]));
2153
2183
  const newHashes = Object.fromEntries(read.filter(({ id }) => !stored.has(id)).map(({ id, hash }) => [id, hash]));
2154
2184
  let renamed = 0;
2155
2185
  for (const move of detectRenames(goneHashes, newHashes)) {
@@ -2199,7 +2229,7 @@ var importNotes = /* @__PURE__ */ __name(async (store, folder, { ignore = [], sk
2199
2229
  changed++;
2200
2230
  }
2201
2231
  onFile(files.length, files.length);
2202
- const gone = [...stored.keys()].filter((id) => !listed.has(id));
2232
+ const gone = [...stored.keys()].filter((id) => !listed2.has(id));
2203
2233
  let deleted = 0;
2204
2234
  let deletionsSkipped;
2205
2235
  if (gone.length >= MIN_DELETIONS_CAPPED && gone.length > stored.size * MAX_DELETED_SHARE) {
@@ -2243,7 +2273,7 @@ var importNotes = /* @__PURE__ */ __name(async (store, folder, { ignore = [], sk
2243
2273
  return {
2244
2274
  folder: folder.path,
2245
2275
  folderId: folder.id,
2246
- notes: listed.size - Object.keys(notReadNow).filter((id) => listed.has(id)).length,
2276
+ notes: listed2.size - Object.keys(notReadNow).filter((id) => listed2.has(id)).length,
2247
2277
  changed,
2248
2278
  renamed,
2249
2279
  deleted,
@@ -2441,9 +2471,9 @@ var anchorOf = /* @__PURE__ */ __name(async (store, uid, source) => {
2441
2471
  throw new CliError(matches2.length === 0 ? "not_found" : "validation_error", matches2.length === 0 ? `no account in the store has seen person:${uid}` : `person:${uid} was seen by ${accounts.length} accounts; give one with --source: ${accounts.join(", ")}`);
2442
2472
  }, "anchorOf");
2443
2473
  var memoContext = /* @__PURE__ */ __name(async (store, reference2, { limit = 20, source } = {}) => {
2444
- const named4 = (await withOwner(store, reference2)).trim();
2445
- if (named4.startsWith("person:")) {
2446
- const anchor = await anchorOf(store, named4.slice("person:".length), source);
2474
+ const named5 = (await withOwner(store, reference2)).trim();
2475
+ if (named5.startsWith("person:")) {
2476
+ const anchor = await anchorOf(store, named5.slice("person:".length), source);
2447
2477
  return memoContext(store, anchor.reference, { limit, source: anchor });
2448
2478
  }
2449
2479
  const [, provider, who] = /^([a-z][a-z0-9-]*):(.+)$/.exec(reference2.trim()) ?? [];
@@ -2509,7 +2539,7 @@ var withOwnMailText = /* @__PURE__ */ __name((context) => {
2509
2539
  // dist/context/command.js
2510
2540
  var MAX_TEXT2 = 160;
2511
2541
  var one = /* @__PURE__ */ __name((message) => message === null ? "\u2014" : `${message.timestamp.slice(0, 16).replace("T", " ")} ${message.provider} ${message.chatTitle ?? message.chatId}: ${message.text.replace(/\s+/g, " ").slice(0, MAX_TEXT2)} ${message.locator}`, "one");
2512
- var eventLine = /* @__PURE__ */ __name((event) => ` ${(event.allDay ? event.startsAt?.slice(0, 10) : event.startsAt?.slice(0, 16).replace("T", " ")) ?? "\u2014"} ${(event.title ?? "untitled").replace(/\s+/g, " ").slice(0, MAX_TEXT2)}${event.location ? ` ${event.location}` : ""} ${event.ref}`, "eventLine");
2542
+ var eventLine = /* @__PURE__ */ __name((event2) => ` ${(event2.allDay ? event2.startsAt?.slice(0, 10) : event2.startsAt?.slice(0, 16).replace("T", " ")) ?? "\u2014"} ${(event2.title ?? "untitled").replace(/\s+/g, " ").slice(0, MAX_TEXT2)}${event2.location ? ` ${event2.location}` : ""} ${event2.ref}`, "eventLine");
2513
2543
  var noteLine = /* @__PURE__ */ __name((note) => ` ${note.ref}${note.path ?? note.title ? ` ${note.path ?? note.title}` : ""}`, "noteLine");
2514
2544
  var fileLine = /* @__PURE__ */ __name((file) => ` ${file.ref} ${file.role ?? ""} ${file.title ?? ""} ${file.modifiedAt?.slice(0, 16).replace("T", " ") ?? ""} ${file.url ?? ""}`, "fileLine");
2515
2545
  var contextText = /* @__PURE__ */ __name(({ messages, events, notes: notes2, notRead, tasks, yourNotes, files, proposals }) => {
@@ -4083,6 +4113,7 @@ var SECTIONS = [
4083
4113
  ["notes remove", "write"],
4084
4114
  ["notes export", "write"],
4085
4115
  ["mail", "read"],
4116
+ ["events", "read"],
4086
4117
  ["agents", "read"],
4087
4118
  ["answers", "read"],
4088
4119
  ["memories", "write"],
@@ -4097,6 +4128,11 @@ var SECTIONS = [
4097
4128
  ["leads", "organise"],
4098
4129
  ["pipelines", "organise"],
4099
4130
  ["payments", "organise"],
4131
+ ["products", "organise"],
4132
+ ["contracts", "organise"],
4133
+ ["subscriptions", "organise"],
4134
+ ["wallets", "organise"],
4135
+ ["transactions", "organise"],
4100
4136
  ["records", "organise"],
4101
4137
  ["projects", "organise"],
4102
4138
  ["people", "organise"],
@@ -4285,10 +4321,387 @@ var doctorCommand = /* @__PURE__ */ __name((...args) => {
4285
4321
  }, SHELL_OVERRIDES.doctor);
4286
4322
  }, "doctorCommand");
4287
4323
 
4324
+ // node_modules/.pnpm/@wirecat+cli-core@0.613.0_@wirecat+cli-base@0.82.0_commander@15.0.0_esbuild@0.28.2_type_562287bbc40b862fa82b63f307e02b11/node_modules/@wirecat/cli-core/dist/calendar/sync.js
4325
+ var DAY3 = 864e5;
4326
+ var SLOTS_EVERY = 7 * DAY3;
4327
+ var isWindow = /* @__PURE__ */ __name((value) => typeof value?.from === "number" && typeof value.to === "number", "isWindow");
4328
+ var isToken = /* @__PURE__ */ __name((value) => value === null || typeof value === "string", "isToken");
4329
+ var roundOf = /* @__PURE__ */ __name((value) => {
4330
+ if (value === null || value === void 0)
4331
+ return null;
4332
+ const round = value;
4333
+ if (typeof round.full !== "boolean" || !isToken(round.from) || !isWindow(round.window) || typeof round.startedAt !== "number" || typeof round.reset !== "boolean" || !isToken(round.page) || typeof round.listed !== "boolean" || !isToken(round.next) || !Array.isArray(round.series) || round.series.some((id) => typeof id !== "string") || round.everySeries !== void 0 && typeof round.everySeries !== "boolean")
4334
+ return void 0;
4335
+ const { full, from, window, startedAt, reset, page, listed: listed2, next, series, everySeries, unchanged } = round;
4336
+ return {
4337
+ full,
4338
+ from,
4339
+ window,
4340
+ startedAt,
4341
+ reset,
4342
+ page,
4343
+ listed: listed2,
4344
+ next,
4345
+ series,
4346
+ ...everySeries === false ? { everySeries } : {},
4347
+ ...unchanged === true ? { unchanged } : {}
4348
+ };
4349
+ }, "roundOf");
4350
+ var parseCalendarCursor = /* @__PURE__ */ __name((value) => {
4351
+ if (value === null)
4352
+ return null;
4353
+ try {
4354
+ const cursor = JSON.parse(value);
4355
+ if (cursor?.v !== 1 && cursor?.v !== 2 || !isToken(cursor.token) || typeof cursor.fullAt !== "number" || !isWindow(cursor.window))
4356
+ return null;
4357
+ const { token, window, fullAt } = cursor;
4358
+ if (cursor.v === 1)
4359
+ return { v: 2, token, window, fullAt, updatedAt: null, done: 0, round: null };
4360
+ const round = roundOf(cursor.round);
4361
+ if (round === void 0 || cursor.updatedAt !== null && typeof cursor.updatedAt !== "number" || typeof cursor.done !== "number")
4362
+ return null;
4363
+ return {
4364
+ v: 2,
4365
+ token,
4366
+ window,
4367
+ fullAt,
4368
+ updatedAt: cursor.updatedAt ?? null,
4369
+ done: cursor.done,
4370
+ round,
4371
+ ...cursor.restored === true ? { restored: true } : {},
4372
+ ...typeof cursor.slotsTo === "number" ? { slotsTo: cursor.slotsTo } : {}
4373
+ };
4374
+ } catch {
4375
+ return null;
4376
+ }
4377
+ }, "parseCalendarCursor");
4378
+ var calendarStatus = /* @__PURE__ */ __name(async (store, accountId, { profile, now }) => {
4379
+ const items = [];
4380
+ for (const calendar of await store.calendars(accountId)) {
4381
+ if (!calendar.synced || calendar.deletedAt !== null)
4382
+ continue;
4383
+ const cursor = parseCalendarCursor(await store.cursor(calendar.id));
4384
+ const progress = progressOf({
4385
+ job: `calendar ${calendar.id}`,
4386
+ profile,
4387
+ done: cursor?.done ?? 0,
4388
+ complete: cursor !== null && cursor.round === null,
4389
+ ...cursor?.updatedAt == null ? {} : { updatedAt: new Date(cursor.updatedAt).toISOString() },
4390
+ now: new Date(now)
4391
+ });
4392
+ items.push({
4393
+ calendar_id: String(calendar.id),
4394
+ external_id: calendar.externalId,
4395
+ title: calendar.title,
4396
+ round: cursor?.round ? cursor.round.full ? "full" : "changes" : null,
4397
+ ...progress,
4398
+ line: progressLine(progress)
4399
+ });
4400
+ }
4401
+ return { items, page: 1, limit: Math.max(1, items.length), hasMore: false };
4402
+ }, "calendarStatus");
4403
+
4404
+ // node_modules/.pnpm/@wirecat+cli-core@0.613.0_@wirecat+cli-base@0.82.0_commander@15.0.0_esbuild@0.28.2_type_562287bbc40b862fa82b63f307e02b11/node_modules/@wirecat/cli-core/dist/calendar/feeds.js
4405
+ var FEED_LIMITS = { maxBytes: 10 * 1024 * 1024, timeoutMs: 3e4, redirects: 5 };
4406
+
4407
+ // node_modules/.pnpm/@wirecat+cli-core@0.613.0_@wirecat+cli-base@0.82.0_commander@15.0.0_esbuild@0.28.2_type_562287bbc40b862fa82b63f307e02b11/node_modules/@wirecat/cli-core/dist/calendar/reads.js
4408
+ var LIST = "events list";
4409
+ var EVENT_TYPES = [
4410
+ "default",
4411
+ "out-of-office",
4412
+ "focus",
4413
+ "working-location",
4414
+ "birthday",
4415
+ "from-mail",
4416
+ "call"
4417
+ ];
4418
+ var oneSided = /* @__PURE__ */ __name((field2, example) => (node) => {
4419
+ if (node.operator !== "range" || node.upper !== "*")
4420
+ queryError("query.unsupported-operator", node.span, `${field2} takes only an earliest moment, such as ${example}`, {
4421
+ command: LIST,
4422
+ guide: LIST_QUERY_GUIDE
4423
+ });
4424
+ }, "oneSided");
4425
+ var EVENTS_QUERY = {
4426
+ entity: "event",
4427
+ backend: "native",
4428
+ fields: queryFieldsOf(event, {
4429
+ native: ["id", "starts_at", "ends_at", "changed_at", "overlapping", "calendar", "person", "event_type"],
4430
+ negatable: ["event_type"],
4431
+ relations: {
4432
+ event_type: {
4433
+ type: "enum",
4434
+ values: EVENT_TYPES,
4435
+ example: "event_type:default",
4436
+ relation: "events with a copy of this kind; -event_type:<kind> leaves out events with one"
4437
+ },
4438
+ calendar: {
4439
+ type: "kw",
4440
+ example: "calendar:3",
4441
+ relation: "one calendar, by its id, the provider's id or its title"
4442
+ },
4443
+ person: {
4444
+ type: "kw",
4445
+ example: "person:ana@example.com",
4446
+ relation: "events one person attends: an address, or a person id from search"
4447
+ }
4448
+ },
4449
+ examples: {
4450
+ id: "id:42",
4451
+ starts_at: "starts_at:[2026-11-02 TO 2026-11-07}",
4452
+ ends_at: "ends_at>=2026-11-02",
4453
+ changed_at: "changed_at>=2026-10-01",
4454
+ overlapping: "overlapping:true"
4455
+ },
4456
+ validate: {
4457
+ ends_at: oneSided("ends_at", "ends_at>=2026-11-02; for the latest, write starts_at<2026-11-07"),
4458
+ changed_at: oneSided("changed_at", "changed_at>=2026-10-01")
4459
+ }
4460
+ }).map((field2) => field2.native ? {
4461
+ ...field2,
4462
+ operators: field2.type === "time" ? ["term", "range"] : field2.type === "bool" ? ["term"] : ["term", "phrase"]
4463
+ } : field2)
4464
+ };
4465
+ var nameOf = /* @__PURE__ */ __name(({ provider, account: account2 }) => `${provider}:${account2}`, "nameOf");
4466
+ var accountsMeta = /* @__PURE__ */ __name(async (store, accounts, skipped, now) => {
4467
+ const issues = [...skipped];
4468
+ for (const { id, key } of accounts) {
4469
+ if (isImportedProvider(key.provider))
4470
+ continue;
4471
+ const { items } = await calendarStatus(store, id, { profile: nameOf(key), now });
4472
+ if (items.length === 0)
4473
+ issues.push({ code: "not_found", reason: "calendar.unsynced", source: nameOf(key) });
4474
+ else if (items.some(({ state }) => state !== "complete"))
4475
+ issues.push({ code: "not_found", reason: "calendar.sync-incomplete", source: nameOf(key) });
4476
+ }
4477
+ return {
4478
+ accounts: accounts.map(({ key }) => nameOf(key)),
4479
+ complete: issues.length === 0,
4480
+ ...issues.length ? { issues } : {}
4481
+ };
4482
+ }, "accountsMeta");
4483
+
4484
+ // node_modules/.pnpm/@wirecat+cli-core@0.613.0_@wirecat+cli-base@0.82.0_commander@15.0.0_esbuild@0.28.2_type_562287bbc40b862fa82b63f307e02b11/node_modules/@wirecat/cli-core/dist/calendar/writer.js
4485
+ var EVENTS_NOTIFY_KEY = "events.notify";
4486
+ var EVENTS_DELETE_SERIES_KEY = "events.delete.series";
4487
+ var EVENTS_REMIND_HOOK_KEY = "events.remind.hook";
4488
+ var CALENDAR_WRITE_DEFAULTS = {
4489
+ "events.create": "allow",
4490
+ // One import writes a whole file of events, and may change events the calendar already holds under their UIDs.
4491
+ "events.import": "ask",
4492
+ "events.update": "allow",
4493
+ "events.respond": "allow",
4494
+ "events.move": "allow",
4495
+ "events.delete": "ask",
4496
+ [EVENTS_DELETE_SERIES_KEY]: "deny",
4497
+ [EVENTS_NOTIFY_KEY]: "deny",
4498
+ // Not ask: `--yes` answers ask, and anything that can type a gcal command can add it.
4499
+ [EVENTS_REMIND_HOOK_KEY]: "deny"
4500
+ };
4501
+
4502
+ // dist/events/events.js
4503
+ var LIST2 = "events list";
4504
+ var EVENT_TYPES2 = [
4505
+ "default",
4506
+ "out-of-office",
4507
+ "focus",
4508
+ "working-location",
4509
+ "birthday",
4510
+ "from-mail",
4511
+ "call"
4512
+ ];
4513
+ var EVENTS_QUERY2 = {
4514
+ entity: "event",
4515
+ backend: "native",
4516
+ fields: [
4517
+ nativeField({
4518
+ name: "starts_at",
4519
+ type: "time",
4520
+ operators: ["term", "range"],
4521
+ example: "starts_at:[2026-11-02 TO 2026-11-07}"
4522
+ }),
4523
+ termField("account", "kw", 'account:"phone:pixel"', {
4524
+ relation: "one calendar account, provider:account, or every account of a provider"
4525
+ }),
4526
+ termField("calendar", "kw", "calendar:Calls", { relation: "one calendar, by its id or its title" }),
4527
+ termField("event_type", "enum", "event_type:call", {
4528
+ values: EVENT_TYPES2,
4529
+ relation: "events with a copy of this kind; a phone's imported calls are call"
4530
+ })
4531
+ ]
4532
+ };
4533
+ var RECENT_DAYS = 30;
4534
+ var AHEAD_DAYS = 7;
4535
+ var EVENTS_NOTE = `
4536
+ Every calendar account in the store is read, phone imports included. Without starts_at: the last ${RECENT_DAYS} days and the next ${AHEAD_DAYS}. Latest start first.`;
4537
+ var UNTRUSTED = ["title", "description", "location", "in"];
4538
+ var readAccounts = /* @__PURE__ */ __name(async (store) => {
4539
+ const held = await calendarAccounts(store);
4540
+ const stored = await store.accounts.storedAccounts();
4541
+ const read = [];
4542
+ for (const key of held) {
4543
+ const one2 = stored.find(({ provider, account: account2 }) => provider === key.provider && account2 === key.account);
4544
+ if (one2)
4545
+ read.push({ id: one2.id, key, calendars: await store.calendar.calendars(one2.id) });
4546
+ }
4547
+ return read;
4548
+ }, "readAccounts");
4549
+ var narrowed = /* @__PURE__ */ __name((accounts, value) => {
4550
+ const chosen = accounts.filter(({ key }) => accountName(key) === value || key.provider === value);
4551
+ if (chosen.length === 0)
4552
+ throw new CliError("not_found", `account:${value} names no calendar account \u2014 the store holds ${accounts.map(({ key }) => accountName(key)).join(", ") || "none"}`, { reason: "events.account-unknown" });
4553
+ return chosen;
4554
+ }, "narrowed");
4555
+ var calendarOf = /* @__PURE__ */ __name((accounts, value) => {
4556
+ const all = accounts.flatMap((account2) => account2.calendars.map((calendar) => ({ account: account2, calendar })));
4557
+ const byId = all.filter(({ calendar }) => String(calendar.id) === value);
4558
+ const found = byId.length ? byId : all.filter(({ calendar }) => calendar.title === value);
4559
+ if (found.length === 1)
4560
+ return found[0];
4561
+ if (found.length === 0)
4562
+ throw new CliError("not_found", `calendar:${value} names no calendar in the accounts read`);
4563
+ throw new CliError("validation_error", `calendar:${value} names ${found.length} calendars; give one by its id: ` + found.map(({ account: account2, calendar }) => `calendar:${calendar.id} (${accountName(account2.key)})`).join(", "));
4564
+ }, "calendarOf");
4565
+ var localDate = /* @__PURE__ */ __name((at, zone) => new Intl.DateTimeFormat("en-CA", { timeZone: zone, year: "numeric", month: "2-digit", day: "2-digit" }).format(at), "localDate");
4566
+ var plusDays = /* @__PURE__ */ __name((date, days2) => {
4567
+ const [year, month, day2] = date.split("-").map(Number);
4568
+ return new Date(Date.UTC(year, month - 1, day2 + days2)).toISOString().slice(0, 10);
4569
+ }, "plusDays");
4570
+ var midnight = /* @__PURE__ */ __name((date, zone) => dayBoundary(date, zone, false, { start: 0, end: date.length }), "midnight");
4571
+ var startsWindow = /* @__PURE__ */ __name((node, zone, now) => {
4572
+ const range = node.operator === "range" ? dateRange(node.value, node.upper ?? "*", node.lower_inclusive !== false, node.upper_inclusive !== false, zone, node.span, now) : dateRange(node.value, node.value, true, true, zone, node.span, now);
4573
+ return {
4574
+ ...range.lower === void 0 ? {} : { lower: range.lower_inclusive ? range.lower : range.lower + 1 },
4575
+ ...range.upper === void 0 ? {} : { upper: range.upper_inclusive ? range.upper + 1 : range.upper }
4576
+ };
4577
+ }, "startsWindow");
4578
+ var dated = /* @__PURE__ */ __name((filter, zone) => {
4579
+ if (filter.from !== void 0)
4580
+ filter.fromDate = localDate(filter.from, zone);
4581
+ if (filter.to !== void 0)
4582
+ filter.toDate = plusDays(localDate(filter.to - 1, zone), 1);
4583
+ if (filter.startsFrom !== void 0) {
4584
+ const date = localDate(filter.startsFrom, zone);
4585
+ filter.startsFromDate = midnight(date, zone) < filter.startsFrom ? plusDays(date, 1) : date;
4586
+ }
4587
+ return filter;
4588
+ }, "dated");
4589
+ var windowMeta = /* @__PURE__ */ __name((filter, zone) => {
4590
+ const since = filter.startsFrom ?? filter.from;
4591
+ return {
4592
+ timezone: zone,
4593
+ window: {
4594
+ ...since === void 0 ? {} : { since: new Date(since).toISOString() },
4595
+ ...filter.to === void 0 ? {} : { until: new Date(filter.to - 1).toISOString() }
4596
+ }
4597
+ };
4598
+ }, "windowMeta");
4599
+ var rowOf = /* @__PURE__ */ __name((details, accounts) => {
4600
+ const live = details.entries.filter(({ deletedAt }) => deletedAt === null);
4601
+ const copies = live.length ? live : details.entries;
4602
+ const held = accounts.flatMap((account2) => account2.calendars.filter(({ id }) => copies.some(({ calendarId }) => calendarId === id)).map((calendar) => ({ account: accountName(account2.key), calendar: calendar.title ?? String(calendar.id) })));
4603
+ return {
4604
+ ...eventItem(details.event),
4605
+ ref: `event:${details.event.id}`,
4606
+ event_type: copies.find(({ eventType }) => eventType !== null)?.eventType ?? "default",
4607
+ accounts: [...new Set(held.map(({ account: account2 }) => account2))],
4608
+ in: held.map(({ account: account2, calendar }) => `${account2}/${calendar}`).join(", "),
4609
+ untrusted: UNTRUSTED
4610
+ };
4611
+ }, "rowOf");
4612
+ var listEvents = /* @__PURE__ */ __name(async (store, words, limit, { now = Date.now(), zone = timezoneOf() } = {}) => {
4613
+ const terms2 = nativeTerms(listQuery(typedQuery(words), EVENTS_QUERY2, LIST2), LIST2);
4614
+ const every = await readAccounts(store);
4615
+ const account2 = terms2.get("account");
4616
+ let accounts = account2 ? narrowed(every, account2.value) : every;
4617
+ const filter = { newest: true };
4618
+ const calendar = terms2.get("calendar");
4619
+ if (calendar) {
4620
+ const found = calendarOf(accounts, calendar.value);
4621
+ accounts = [found.account];
4622
+ filter.calendarId = found.calendar.id;
4623
+ }
4624
+ const kind = terms2.get("event_type");
4625
+ if (kind)
4626
+ filter.eventType = kind.value.toLowerCase();
4627
+ const starts = terms2.get("starts_at");
4628
+ if (starts) {
4629
+ const { lower, upper } = startsWindow(starts, zone, now);
4630
+ if (lower !== void 0)
4631
+ filter.startsFrom = lower;
4632
+ if (upper !== void 0)
4633
+ filter.to = upper;
4634
+ } else {
4635
+ const today2 = localDate(now, zone);
4636
+ filter.from = midnight(plusDays(today2, -RECENT_DAYS), zone);
4637
+ filter.to = midnight(plusDays(today2, AHEAD_DAYS + 1), zone);
4638
+ }
4639
+ dated(filter, zone);
4640
+ const read = accounts.map(({ id, key }) => ({ id, key }));
4641
+ const events = read.length ? await store.calendar.events({ ...filter, accountIds: read.map(({ id }) => id), limit: limit + 1 }) : [];
4642
+ const rows = [];
4643
+ for (const event2 of events.slice(0, limit)) {
4644
+ const details = await store.calendar.event(event2.id);
4645
+ if (details)
4646
+ rows.push(rowOf(details, accounts));
4647
+ }
4648
+ const body = listAnswer(LIST2, { items: rows, limit, has_more: events.length > limit });
4649
+ body.meta = {
4650
+ ...body.meta,
4651
+ ...await accountsMeta(store.calendar, read, [], now),
4652
+ ...windowMeta(filter, zone)
4653
+ };
4654
+ return body;
4655
+ }, "listEvents");
4656
+ var showEvent = /* @__PURE__ */ __name(async (store, reference2) => {
4657
+ const text3 = reference2.replace(/^event:/u, "");
4658
+ if (!/^[1-9]\d*$/u.test(text3))
4659
+ throw new CliError("validation_error", "an event is event:<id>");
4660
+ const details = await store.calendar.event(Number(text3));
4661
+ const accounts = await readAccounts(store);
4662
+ const row = details && rowOf(details, accounts);
4663
+ if (!details || !row?.accounts.length)
4664
+ throw new CliError("not_found", `no event ${text3} in any calendar account`);
4665
+ return {
4666
+ ...row,
4667
+ attendees: details.participants.map(({ email, name: name2, response, organizer }) => ({
4668
+ email,
4669
+ name: name2,
4670
+ response,
4671
+ organizer
4672
+ })),
4673
+ untrusted: [...UNTRUSTED, "attendees.name"]
4674
+ };
4675
+ }, "showEvent");
4676
+ var accountsLine = /* @__PURE__ */ __name((accounts) => accounts.length ? `calendar accounts read: ${accounts.join(", ")}` : "no calendar account in the store", "accountsLine");
4677
+
4678
+ // dist/events/command.js
4679
+ var upTo1000 = /* @__PURE__ */ __name((value) => {
4680
+ const number2 = Number(value);
4681
+ if (!Number.isInteger(number2) || number2 < 1 || number2 > 1e3)
4682
+ throw new InvalidArgumentError("a whole number, 1 to 1000");
4683
+ return number2;
4684
+ }, "upTo1000");
4685
+ var eventsCommand = /* @__PURE__ */ __name((program, streams, env) => {
4686
+ const { print } = answers(program, streams, env);
4687
+ const events = program.command("events").description("calendar events of every account in the store, phone calls included").summary("calendar events and phone calls of every account");
4688
+ withQuery(annotate(events.command("list"), { effects: LOCAL_READ, partial: true }).description("events of every calendar account in the store, latest start first: calendars and imported phone calls").summary("events and phone calls of every account, latest first"), EVENTS_QUERY2).addHelpText("after", EVENTS_NOTE).option("--limit <n>", "events at most, 1\u20131000", upTo1000, 100).option("--json", "print JSON; --json=ref,title keeps only those fields").action(async (words, { json: json5, limit }, command) => {
4689
+ const body = await withStore(env, (store) => listEvents(store, words, limit));
4690
+ const accounts = body.meta?.accounts ?? [];
4691
+ print(json5, body, `${accountsLine(accounts)}
4692
+ ${plainText(body, command)}`);
4693
+ });
4694
+ annotate(events.command("show"), { effects: LOCAL_READ, output: { entity: "event" } }).description("one event: its time, the accounts and calendars that hold it, and its attendees").argument("<ref>", "event:<id>").option("--json", "print JSON; --json=ref,title keeps only those fields").action(async (ref, { json: json5 }) => print(json5, itemAnswer(await withStore(env, (store) => showEvent(store, ref)))));
4695
+ }, "eventsCommand");
4696
+
4288
4697
  // dist/examples.js
4289
4698
  var EXAMPLES = {
4290
4699
  context: ["memo context telegram:'Kai Sample'", "memo context email:kai@example.com --limit 5 --json"],
4291
- show: ["memo show chat:max/500/-1001 document:413", "memo show note:12 msg:telegram/1/77/42 --json"],
4700
+ show: [
4701
+ "memo show chat:max/500/-1001 document:413",
4702
+ "memo show note:12 msg:telegram/1/77/42 --json",
4703
+ "memo show contract:2 invoice:4 --json"
4704
+ ],
4292
4705
  "notes show": ["memo notes show note:12", "memo notes show ~/notes/People/Kai.md --json"],
4293
4706
  "notes list": [
4294
4707
  `memo notes list 'about:"telegram:Kai Sample"'`,
@@ -4453,7 +4866,7 @@ var EXAMPLES = {
4453
4866
  "memo relationships update 12 --role contractor --reason 'builds the site'"
4454
4867
  ],
4455
4868
  "relationships add": [
4456
- "memo relationships add person:3 organization:1 --role cto",
4869
+ "memo relationships add person:3 organization:1 --role employee",
4457
4870
  "memo relationships add project:2 organization:1 --kind related-to --reason 'same client'"
4458
4871
  ],
4459
4872
  "relationships list": ['memo relationships list about:"person:3"', "memo relationships list confirmed:false"],
@@ -4517,6 +4930,11 @@ var EXAMPLES = {
4517
4930
  "memo orders add 'Shop One' 2499.00 RUB --kind personal --title A-1042",
4518
4931
  "memo orders add 'Office Supply' --kind client --organization organization:3"
4519
4932
  ],
4933
+ "events list": [
4934
+ "memo events list event_type:call",
4935
+ "memo events list account:phone:pixel 'starts_at:[2026-11-02 TO 2026-11-07}' --json"
4936
+ ],
4937
+ "events show": ["memo events show event:42"],
4520
4938
  "invoices list": ["memo invoices list project:HRB open:true", "memo invoices list review:proposed --json"],
4521
4939
  "invoices show": ["memo invoices show invoice:4"],
4522
4940
  "invoices add": [
@@ -4526,19 +4944,93 @@ var EXAMPLES = {
4526
4944
  "payments list": ["memo payments list project:HRB direction:in", "memo payments list review:proposed --json"],
4527
4945
  "payments show": ["memo payments show payment:9"],
4528
4946
  "payments add": [
4529
- "memo payments add 25000.00 RUB --kind in --organization organization:3 --occurred-time 2026-11-01 --project HRB"
4947
+ "memo payments add 25000.00 RUB --kind in --organization organization:3 --occurred-time 2026-11-01 --project HRB",
4948
+ "memo payments add 5000.00 RUB --kind out --organization organization:3 --refund-of payment:9"
4530
4949
  ],
4531
4950
  "records import": [
4532
4951
  "memo records import payments.jsonl --account rentals --dry-run",
4533
- "memo records import envelope.json --account rentals --json"
4952
+ "memo records import envelope.json --account rentals --json",
4953
+ "memo records import contacts.vcf --account phone:pixel"
4534
4954
  ],
4535
4955
  "records check": ["memo records check - --account rentals"],
4536
4956
  "records list": [
4537
4957
  "memo records list waiting:true --account sheet:rentals",
4538
- "memo records list type:organization --account sheet:rentals --json"
4958
+ "memo records list type:organization --account sheet:rentals --json",
4959
+ `memo records list 'entity:"organization:3"' deleted:false --account sheet:rentals`
4539
4960
  ],
4540
4961
  "records link": ["memo records link organization:client organization:3 --account sheet:rentals"],
4541
4962
  "payments allocate": ["memo payments allocate payment:9 invoice:4 25000.00"],
4963
+ "products list": ["memo products list kind:service", "memo products list archived:true --json"],
4964
+ "products show": ["memo products show product:4"],
4965
+ "products add": [
4966
+ "memo products add 'Bike rental, month' 10000.00 RUB --kind service --unit month",
4967
+ "memo products add 'Helmet' 2500.00 RUB --sku H-12 --supplier organization:3"
4968
+ ],
4969
+ "products update": [
4970
+ "memo products update product:4 --amount 12000.00 --currency RUB",
4971
+ "memo products update product:4 --archived on"
4972
+ ],
4973
+ "orders lines add": [
4974
+ "memo orders lines add order:3 12 --product product:4",
4975
+ "memo orders lines add order:3 1 Rental, first week --product product:4 --amount 2000.00",
4976
+ "memo orders lines add order:3 2 Helmet --amount 2500.00"
4977
+ ],
4978
+ "orders lines remove": ["memo orders lines remove order:3 2"],
4979
+ "invoices lines add": [
4980
+ "memo invoices lines add invoice:4 1 --product product:4",
4981
+ "memo invoices lines add invoice:4 2 Delivery --amount 1500.00"
4982
+ ],
4983
+ "invoices lines remove": ["memo invoices lines remove invoice:4 2"],
4984
+ "contracts list": ["memo contracts list status:active", "memo contracts list expires:2026-12-31 --json"],
4985
+ "contracts show": ["memo contracts show contract:2"],
4986
+ "contracts add": [
4987
+ "memo contracts add 'Rental agreement' --kind service --start-date 2026-11-01 --end-date 2027-10-31 --auto-renew on --notice-days 30 --amount 120000.00 --currency RUB",
4988
+ "memo contracts add 'NDA with the studio' --kind nda --project HRB"
4989
+ ],
4990
+ "contracts update": [
4991
+ "memo contracts update contract:2 --status terminated",
4992
+ "memo contracts update contract:2 --end-date 2027-12-31"
4993
+ ],
4994
+ "subscriptions list": [
4995
+ "memo subscriptions list status:active direction:payable",
4996
+ "memo subscriptions list renews:2026-12-01 --json"
4997
+ ],
4998
+ "subscriptions show": ["memo subscriptions show subscription:5"],
4999
+ "subscriptions add": [
5000
+ "memo subscriptions add Hosting 990.00 RUB --kind payable --supplier organization:3 --every 1-month --start-date 2026-11-01",
5001
+ "memo subscriptions add 'Bike rental' 10000.00 RUB --kind receivable --customer organization:3 --every 1-month --trial-end-date 2026-11-14 --status trial"
5002
+ ],
5003
+ "subscriptions update": [
5004
+ "memo subscriptions update subscription:5 --status paused",
5005
+ "memo subscriptions update subscription:5 --every 1-year"
5006
+ ],
5007
+ "subscriptions cancel": ["memo subscriptions cancel subscription:5 --occurred-time 2026-11-30"],
5008
+ "subscriptions prices add": ["memo subscriptions prices add subscription:5 1190.00 RUB --start-date 2027-01-01"],
5009
+ "wallets list": ["memo wallets list", "memo wallets list kind:card --json"],
5010
+ "wallets show": ["memo wallets show wallet:2", "memo wallets show wallet:2 --until-time 2026-10-31"],
5011
+ "wallets add": ["memo wallets add 'Main card' RUB --kind card --institution 'Bank One'"],
5012
+ "wallets update": ["memo wallets update wallet:2 --opening-balance 15000.00 --opening-date 2026-01-01"],
5013
+ "transactions list": [
5014
+ `memo transactions list 'wallet:"wallet:2"' status:pending`,
5015
+ "memo transactions list uncategorized:true --json"
5016
+ ],
5017
+ "transactions show": ["memo transactions show transaction:12"],
5018
+ "transactions add": [
5019
+ "memo transactions add wallet:2 500.00 --kind out --occurred-time 2026-11-14 --description 'Coffee shop'",
5020
+ "memo transactions add wallet:2 10000.00 --kind in --payment payment:9"
5021
+ ],
5022
+ "transactions update": [
5023
+ "memo transactions update transaction:12 --status booked",
5024
+ "memo transactions update transaction:12 --payment payment:9"
5025
+ ],
5026
+ "transactions splits add": ["memo transactions splits add transaction:12 300.00 Rent --project HRB"],
5027
+ "transactions splits remove": ["memo transactions splits remove transaction:12 1"],
5028
+ "records show": [
5029
+ "memo records show custom:quote:Q-7 --account example-erp:demo",
5030
+ "memo records show organization:client --account sheet:rentals --json"
5031
+ ],
5032
+ "records delete": ["memo records delete payment:sheet-12 --account sheet:rentals"],
5033
+ "records match": ["memo records match --account sheet:rentals"],
4542
5034
  "payments unlink": ["memo payments unlink payment:9 invoice:4"],
4543
5035
  "facts show": ["memo facts show fact:4 --sources"],
4544
5036
  "facts confirm": ["memo facts confirm fact:4"],
@@ -4608,7 +5100,11 @@ var EXAMPLES = {
4608
5100
  "mcp server start": ["memo mcp server start --public-url https://laptop.example.ts.net"],
4609
5101
  "mcp server status": ["memo mcp server status --json"],
4610
5102
  "mcp server stop": ["memo mcp server stop"],
4611
- "search all": ["memo search all 'budget harbour'", "memo search all 'content:invoice' --only mail,notes --json"],
5103
+ "search all": [
5104
+ "memo search all 'budget harbour'",
5105
+ "memo search all 'content:invoice' --only mail,notes --json",
5106
+ "memo search all 'Rental agreement' --only business"
5107
+ ],
4612
5108
  "search messages": ["memo search messages 'friday meeting has:voice'"],
4613
5109
  "search mail": ["memo search mail 'mailbox:important budget' --source email:me@example.com"],
4614
5110
  "search notes": ["memo search notes budget notes:2", "memo search notes kickoff --project HRB --json"],
@@ -4708,13 +5204,13 @@ var memoryItem = /* @__PURE__ */ __name(({ body, ...memory }) => ({
4708
5204
  updatedAt: memory.updatedAt
4709
5205
  }), "memoryItem");
4710
5206
  var listMemories = /* @__PURE__ */ __name(async (store, query, limit) => {
4711
- const terms = queryTerms(query, MEMORY_QUERY, "memories list");
4712
- const project = terms.get("project");
5207
+ const terms2 = queryTerms(query, MEMORY_QUERY, "memories list");
5208
+ const project = terms2.get("project");
4713
5209
  const filters = {
4714
- ...terms.has("kind") ? { kind: terms.get("kind") } : {},
4715
- ...terms.has("status") ? { status: terms.get("status") } : {},
4716
- ...terms.has("scope") ? { scope: terms.get("scope") } : {},
4717
- ...terms.has("subject") ? { subject: terms.get("subject") } : {},
5210
+ ...terms2.has("kind") ? { kind: terms2.get("kind") } : {},
5211
+ ...terms2.has("status") ? { status: terms2.get("status") } : {},
5212
+ ...terms2.has("scope") ? { scope: terms2.get("scope") } : {},
5213
+ ...terms2.has("subject") ? { subject: terms2.get("subject") } : {},
4718
5214
  ...project === void 0 ? {} : { project: await canonicalProject(store, project) }
4719
5215
  };
4720
5216
  return pageOf("memories list", limit, async (most) => (await store.memories.list({ ...filters, limit: most })).map(memoryItem));
@@ -4768,7 +5264,7 @@ var memoriesCommand = /* @__PURE__ */ __name((program, streams, env) => {
4768
5264
  ...options.supersedes === void 0 ? {} : { supersedes: options.supersedes }
4769
5265
  }, await by))));
4770
5266
  });
4771
- withQuery(annotate(memories.command("list"), { effects: LOCAL_READ }).description("memories, newest first"), MEMORY_QUERY).option("--limit <n>", "most memories, up to 500", positive, 100).option("--json", "print JSON; --json=id,title keeps only those fields").action((words, { json: json7, limit }) => run(json7, (store) => listMemories(store, words, limit)));
5267
+ withQuery(annotate(memories.command("list"), { effects: LOCAL_READ }).description("memories, newest first"), MEMORY_QUERY).option("--limit <n>", "most memories, up to 500", positive, 100).option("--json", "print JSON; --json=id,title keeps only those fields").action((words, { json: json5, limit }) => run(json5, (store) => listMemories(store, words, limit)));
4772
5268
  annotate(memories.command("show"), { effects: LOCAL_READ, output: { entity: "memory" } }).description("one memory with its evidence").argument("<ref>", "memory:<id>").option("--sources", "read each piece of evidence back: who, when, a short excerpt, and whether it is gone").option("--json", "print JSON; --json=id,title keeps only those fields").action((ref, options) => run(options.json, async (store) => itemAnswer({
4773
5269
  ...memoryItem(await store.memories.get(ref)),
4774
5270
  ...options.sources ? { sources: await store.memories.sources(ref) } : {}
@@ -4838,13 +5334,13 @@ var factItem = /* @__PURE__ */ __name(({ type, statement, source, confirmedBy, .
4838
5334
  confirmed_by: confirmedBy
4839
5335
  }), "factItem");
4840
5336
  var listFacts = /* @__PURE__ */ __name(async (store, query, limit) => {
4841
- const terms = queryTerms(query, FACT_QUERY, "facts list");
4842
- const project = terms.get("project");
5337
+ const terms2 = queryTerms(query, FACT_QUERY, "facts list");
5338
+ const project = terms2.get("project");
4843
5339
  const filters = {
4844
- ...terms.has("kind") ? { type: terms.get("kind") } : {},
4845
- ...terms.has("status") ? { status: terms.get("status") } : {},
5340
+ ...terms2.has("kind") ? { type: terms2.get("kind") } : {},
5341
+ ...terms2.has("status") ? { status: terms2.get("status") } : {},
4846
5342
  ...project === void 0 ? {} : { project: await canonicalProject(store, project) },
4847
- ...terms.has("subject") ? { subject: terms.get("subject") } : {}
5343
+ ...terms2.has("subject") ? { subject: terms2.get("subject") } : {}
4848
5344
  };
4849
5345
  return pageOf("facts list", limit, async (most) => (await store.facts.list({ ...filters, limit: most })).map(factItem));
4850
5346
  }, "listFacts");
@@ -4886,7 +5382,7 @@ var factsCommand = /* @__PURE__ */ __name((program, streams, env) => {
4886
5382
  ...options.supersedes === void 0 ? {} : { supersedes: options.supersedes }
4887
5383
  }))));
4888
5384
  });
4889
- withQuery(annotate(facts.command("list"), { effects: LOCAL_READ }).description("facts, latest first"), FACT_QUERY).option("--limit <n>", "most facts, up to 500", positive, 100).option("--json", "print JSON; --json=id,title keeps only those fields").action((words, { json: json7, limit }) => run(json7, (store) => listFacts(store, words, limit)));
5385
+ withQuery(annotate(facts.command("list"), { effects: LOCAL_READ }).description("facts, latest first"), FACT_QUERY).option("--limit <n>", "most facts, up to 500", positive, 100).option("--json", "print JSON; --json=id,title keeps only those fields").action((words, { json: json5, limit }) => run(json5, (store) => listFacts(store, words, limit)));
4890
5386
  annotate(facts.command("show"), { effects: LOCAL_READ, output: { entity: "fact" } }).description("one fact with its evidence").argument("<ref>", "fact:<id>").option("--sources", "read each piece of evidence back: who, when, a short excerpt, and whether it is gone").option("--json", "print JSON; --json=id,title keeps only those fields").action((ref, options) => run(options.json, async (store) => itemAnswer({
4891
5387
  ...factItem(await store.facts.get(ref)),
4892
5388
  ...options.sources ? { sources: await store.facts.sources(ref) } : {}
@@ -4916,6 +5412,67 @@ var factsCommand = /* @__PURE__ */ __name((program, streams, env) => {
4916
5412
  ${FORGET_HELP.replace("use invalidate", "use reject or reverse")}`);
4917
5413
  }, "factsCommand");
4918
5414
 
5415
+ // dist/records/sources.js
5416
+ var MOST = 100;
5417
+ var READS = {
5418
+ product: /* @__PURE__ */ __name((store, ref) => store.products.get(ref), "product"),
5419
+ contract: /* @__PURE__ */ __name((store, ref) => store.contracts.get(ref), "contract"),
5420
+ subscription: /* @__PURE__ */ __name((store, ref) => store.subscriptions.get(ref), "subscription"),
5421
+ wallet: /* @__PURE__ */ __name((store, ref) => store.wallets.get(ref), "wallet"),
5422
+ transaction: /* @__PURE__ */ __name((store, ref) => store.transactions.get(ref), "transaction"),
5423
+ invoice: /* @__PURE__ */ __name((store, ref) => store.finance.invoice(ref), "invoice"),
5424
+ payment: /* @__PURE__ */ __name((store, ref) => store.finance.payment(ref), "payment"),
5425
+ order: /* @__PURE__ */ __name((store, ref) => store.orders.get(ref), "order"),
5426
+ deal: /* @__PURE__ */ __name((store, ref) => store.deals.get(ref), "deal"),
5427
+ lead: /* @__PURE__ */ __name((store, ref) => store.deals.get(ref), "lead"),
5428
+ pipeline: /* @__PURE__ */ __name((store, ref) => store.deals.pipeline(ref), "pipeline")
5429
+ };
5430
+ var SOURCED = new Set(Object.keys(READS));
5431
+ var readSourced = /* @__PURE__ */ __name((store, kind, ref) => READS[kind]?.(store, ref), "readSourced");
5432
+ var IMPORT = "import:";
5433
+ var imported = /* @__PURE__ */ __name(({ source, account: account2 }) => (account2 ?? null) !== null || !!source?.startsWith(IMPORT), "imported");
5434
+ var sourceAccounts = /* @__PURE__ */ __name(async (store, { source, account: account2 }) => {
5435
+ if (account2)
5436
+ return [account2];
5437
+ if (!source?.startsWith(IMPORT))
5438
+ return [];
5439
+ const provider = source.slice(IMPORT.length);
5440
+ return (await store.accounts.accounts()).filter((key) => key.provider === provider);
5441
+ }, "sourceAccounts");
5442
+ var named2 = /* @__PURE__ */ __name((key) => ({
5443
+ record: `${key.type}:${key.externalId}`,
5444
+ account: `${key.provider}:${key.account}`
5445
+ }), "named");
5446
+ var sourcesOf = /* @__PURE__ */ __name(async (store, entity) => {
5447
+ const { ref } = entity;
5448
+ const records = [];
5449
+ for (const { provider, account: account2 } of await sourceAccounts(store, entity)) {
5450
+ if (records.length > MOST)
5451
+ break;
5452
+ for (const one2 of await store.records.list({ provider, account: account2, entity: ref, limit: MOST + 1 }))
5453
+ records.push({
5454
+ ...named2(one2),
5455
+ ...one2.flagged ? { flagged: true } : {},
5456
+ ...one2.deletedAt === null ? {} : { deleted: true }
5457
+ });
5458
+ }
5459
+ const incoming = await store.records.incoming({ entity: ref }, { limit: MOST + 1 });
5460
+ return {
5461
+ records: { items: records.slice(0, MOST), hasMore: records.length > MOST },
5462
+ incoming: {
5463
+ items: incoming.slice(0, MOST).map(({ record: record2, role, as }) => ({ ...named2(record2), role, as })),
5464
+ hasMore: incoming.length > MOST
5465
+ }
5466
+ };
5467
+ }, "sourcesOf");
5468
+ var sourcesText = /* @__PURE__ */ __name((ref, { records, incoming }, indent = " ") => [
5469
+ ...records.items.map((one2) => `${indent}from ${one2.account} ${one2.record}${one2.flagged ? " (flagged)" : ""}${one2.deleted ? " (deleted)" : ""}`),
5470
+ ...incoming.items.map((one2) => `${indent}named by ${one2.account} ${one2.record} as ${one2.role}${one2.as === null ? "" : ` (${one2.as})`}`),
5471
+ ...records.hasMore || incoming.hasMore ? [`${indent}more: memo records list entity:${ref} --account <account>`] : []
5472
+ ], "sourcesText");
5473
+ var recordsHidden = /* @__PURE__ */ __name((command) => grantedLevel(command, "records.show") === "deny", "recordsHidden");
5474
+ var withSources = /* @__PURE__ */ __name(async (command, store, item) => recordsHidden(command) ? item : { ...item, sources: await sourcesOf(store, item) }, "withSources");
5475
+
4919
5476
  // dist/finance/finance.js
4920
5477
  var INVOICE_QUERY = {
4921
5478
  entity: "invoice",
@@ -4943,25 +5500,25 @@ var PAYMENT_QUERY = {
4943
5500
  var projectTerm = /* @__PURE__ */ __name(async (store, project) => project === void 0 ? {} : { project: await canonicalProject(store, project) }, "projectTerm");
4944
5501
  var reviewTerm = /* @__PURE__ */ __name((review) => review === void 0 ? {} : { review }, "reviewTerm");
4945
5502
  var listInvoices = /* @__PURE__ */ __name(async (store, words, limit) => {
4946
- const terms = queryTerms(words, INVOICE_QUERY, "invoices list");
5503
+ const terms2 = queryTerms(words, INVOICE_QUERY, "invoices list");
4947
5504
  const filter = {
4948
- ...await projectTerm(store, terms.get("project")),
4949
- ...reviewTerm(terms.get("review")),
4950
- ...terms.has("direction") ? { direction: terms.get("direction") } : {},
4951
- ...terms.has("status") ? { status: terms.get("status") } : {},
4952
- ...terms.has("counterparty") ? { counterparty: terms.get("counterparty") } : {},
4953
- ...terms.has("number") ? { number: terms.get("number") } : {},
4954
- ...terms.has("open") ? { open: terms.get("open") === "true" } : {}
5505
+ ...await projectTerm(store, terms2.get("project")),
5506
+ ...reviewTerm(terms2.get("review")),
5507
+ ...terms2.has("direction") ? { direction: terms2.get("direction") } : {},
5508
+ ...terms2.has("status") ? { status: terms2.get("status") } : {},
5509
+ ...terms2.has("counterparty") ? { counterparty: terms2.get("counterparty") } : {},
5510
+ ...terms2.has("number") ? { number: terms2.get("number") } : {},
5511
+ ...terms2.has("open") ? { open: terms2.get("open") === "true" } : {}
4955
5512
  };
4956
5513
  return pageOf("invoices list", limit, (most) => store.finance.invoices({ ...filter, limit: most }));
4957
5514
  }, "listInvoices");
4958
5515
  var listPayments = /* @__PURE__ */ __name(async (store, words, limit) => {
4959
- const terms = queryTerms(words, PAYMENT_QUERY, "payments list");
5516
+ const terms2 = queryTerms(words, PAYMENT_QUERY, "payments list");
4960
5517
  const filter = {
4961
- ...await projectTerm(store, terms.get("project")),
4962
- ...reviewTerm(terms.get("review")),
4963
- ...terms.has("direction") ? { direction: terms.get("direction") } : {},
4964
- ...terms.has("party") ? { party: terms.get("party") } : {}
5518
+ ...await projectTerm(store, terms2.get("project")),
5519
+ ...reviewTerm(terms2.get("review")),
5520
+ ...terms2.has("direction") ? { direction: terms2.get("direction") } : {},
5521
+ ...terms2.has("party") ? { party: terms2.get("party") } : {}
4965
5522
  };
4966
5523
  return pageOf("payments list", limit, (most) => store.finance.payments({ ...filter, limit: most }));
4967
5524
  }, "listPayments");
@@ -5031,14 +5588,21 @@ var financeText = /* @__PURE__ */ __name((block) => block.length === 0 ? [] : [
5031
5588
  })
5032
5589
  ], "financeText");
5033
5590
 
5034
- // dist/finance/command.js
5035
- var json = /* @__PURE__ */ __name((command) => command.option("--json", "print JSON; --json=ref,title keeps only those fields"), "json");
5591
+ // dist/finance/written.js
5592
+ var json = /* @__PURE__ */ __name((command) => jsonOption(command), "json");
5036
5593
  var PROPOSES = "yours is confirmed at once; an agent's waits as proposed for you in memo review";
5037
- var kindOf2 = /* @__PURE__ */ __name((kind, kinds2) => {
5038
- if (kind === void 0 || !kinds2.includes(kind))
5039
- throw new CliError("validation_error", `--kind is one of ${kinds2.join(", ")}`, { param: "--kind" });
5040
- return kind;
5041
- }, "kindOf");
5594
+ var choice = /* @__PURE__ */ __name((value, allowed, flag) => {
5595
+ if (value === void 0 || !allowed.includes(value))
5596
+ throw new CliError("validation_error", `${flag} is one of ${allowed.join(", ")}`, { param: flag });
5597
+ return value;
5598
+ }, "choice");
5599
+ var needed = /* @__PURE__ */ __name((value, flag, what) => {
5600
+ if (value === void 0 || value.trim() === "")
5601
+ throw new CliError("validation_error", `name ${what}: ${flag}`, { param: flag });
5602
+ return value;
5603
+ }, "needed");
5604
+ var optionalChoice = /* @__PURE__ */ __name((value, allowed, flag) => value === void 0 ? void 0 : choice(value, allowed, flag), "optionalChoice");
5605
+ var onOff = /* @__PURE__ */ __name((value, flag) => value === void 0 ? void 0 : choice(value, ["on", "off"], flag) === "on", "onOff");
5042
5606
  var writtenBy = /* @__PURE__ */ __name(async (store, by, options) => ({
5043
5607
  by,
5044
5608
  ...options.project === void 0 ? {} : { project: await canonicalProject(store, options.project) },
@@ -5047,23 +5611,71 @@ var writtenBy = /* @__PURE__ */ __name(async (store, by, options) => ({
5047
5611
  }), "writtenBy");
5048
5612
  var party = /* @__PURE__ */ __name((command, what) => command.option("--person <uid>", `the person ${what}: person:<id>`).option("--organization <organization>", `the organization ${what}: organization:<id>`), "party");
5049
5613
  var writeMeta = /* @__PURE__ */ __name((command) => byOption(command.option("--project <project>", "the project it belongs to: its key or project:<id>").option("--reason <text>", "why an agent proposes it, for the owner who decides").option("--evidence <ref...>", "what shows it, up to 8: msg:, note:, document: or another reference")), "writeMeta");
5614
+ var given = /* @__PURE__ */ __name((fields) => Object.fromEntries(Object.entries(fields).filter(([, value]) => value !== void 0)), "given");
5615
+
5616
+ // dist/finance/lines-command.js
5617
+ var LINE_PARENTS = {
5618
+ order: {
5619
+ has: "an order that has a currency (orders add with an amount)",
5620
+ shown: "orders show",
5621
+ add: /* @__PURE__ */ __name((store, ref, line3) => store.orders.addLine(ref, line3), "add"),
5622
+ remove: /* @__PURE__ */ __name((store, ref, input) => store.orders.removeLine(ref, input), "remove")
5623
+ },
5624
+ invoice: {
5625
+ has: "an invoice that is not void; the total never falls below what confirmed payments settled",
5626
+ shown: "invoices show",
5627
+ add: /* @__PURE__ */ __name((store, ref, line3) => store.finance.addInvoiceLine(ref, line3), "add"),
5628
+ remove: /* @__PURE__ */ __name((store, ref, input) => store.finance.removeInvoiceLine(ref, input), "remove")
5629
+ }
5630
+ };
5631
+ var lineCommands = /* @__PURE__ */ __name((parent, kind, run, env) => {
5632
+ const { has, shown: shown2, add, remove } = LINE_PARENTS[kind];
5633
+ const one2 = kind === "order" ? "an order" : "an invoice";
5634
+ const who = `you change any ${kind}'s lines; an agent only those of ${one2} it proposed that is still proposed`;
5635
+ const lines2 = parent.command("lines").description(`the lines of ${one2}, each a quantity at a price; its total is their sum. ${who}`).summary(`the lines of ${one2}`);
5636
+ const asker = /* @__PURE__ */ __name((ref) => `change ${ref}'s lines as yours?`, "asker");
5637
+ json(byOption(annotate(lines2.command("add"), {
5638
+ effects: LOCAL_WRITE,
5639
+ output: { entity: kind },
5640
+ literal_after_dashes: true
5641
+ }).option("--product <product>", "the product or service it is: its name and price are copied onto the line").option("--amount <decimal>", "the price of one, such as 10000.00; the product's when left out with --product"))).description(`add a line at the end of ${has}: quantity \xD7 price, and the total becomes the sum of the lines. With --product its name and price are copied, so a later price change leaves the line as it is, and --amount sets another price; without --product, --amount is needed. ${who}`).summary(`add a line to ${one2}`).argument(`<${kind}>`, `${kind}:<id>`).argument("<quantity>", "how many, a decimal such as 12 or 1.5").argument("[description...]", "what the line is, in a few words; the product's name when left out").action(async (ref, quantity, words, options, command) => {
5642
+ if (options.product === void 0)
5643
+ needed(options.amount, "--amount", "the price of one, or --product");
5644
+ const by = await whoRuns(command, env, { asOwner: options.asOwner, question: asker(ref) });
5645
+ await run(options.json, async (store) => itemAnswer(await add(store, ref, {
5646
+ by,
5647
+ quantity,
5648
+ ...given({
5649
+ unitPrice: options.amount,
5650
+ description: words.length > 0 ? words.join(" ") : void 0,
5651
+ product: options.product
5652
+ })
5653
+ })));
5654
+ });
5655
+ json(byOption(annotate(lines2.command("remove"), { effects: LOCAL_WRITE, output: { entity: kind } }))).description(`take a line off ${one2}; the others keep their positions, and the last line stays. ${who}`).summary(`take a line off ${one2}`).argument(`<${kind}>`, `${kind}:<id>`).argument("<position>", `the line's position, from 1, as ${shown2} lists it`, positive).action(async (ref, position, options, command) => {
5656
+ const by = await whoRuns(command, env, { asOwner: options.asOwner, question: asker(ref) });
5657
+ await run(options.json, async (store) => itemAnswer(await remove(store, ref, { position, by })));
5658
+ });
5659
+ }, "lineCommands");
5660
+
5661
+ // dist/finance/command.js
5050
5662
  var financeCommands = /* @__PURE__ */ __name((program, streams, env) => {
5051
5663
  const { run } = answers(program, streams, env);
5052
5664
  const invoices = program.command("invoices").description("invoices you issued or received, with their lines and what paid them; amounts per currency").summary("invoices you issued or received, and what paid them");
5053
- withQuery(json(annotate(invoices.command("list"), { effects: LOCAL_READ })).description("invoices, newest first; review:proposed lists what waits for you"), INVOICE_QUERY).option("--limit <n>", "most invoices, up to 500", positive, 100).action((words, { json: json7, limit }) => run(json7, (store) => listInvoices(store, words, limit)));
5054
- json(annotate(invoices.command("show"), { effects: LOCAL_READ, output: { entity: "invoice" } })).description("one invoice with its lines and the payments allocated to it").argument("<ref>", "invoice:<id>").action((ref, options) => run(options.json, async (store) => itemAnswer(await store.finance.invoice(ref))));
5665
+ withQuery(json(annotate(invoices.command("list"), { effects: LOCAL_READ })).description("invoices, newest first; review:proposed lists what waits for you"), INVOICE_QUERY).option("--limit <n>", "most invoices, up to 500", positive, 100).action((words, { json: json5, limit }) => run(json5, (store) => listInvoices(store, words, limit)));
5666
+ json(annotate(invoices.command("show"), { effects: LOCAL_READ, output: { entity: "invoice" } })).description("one invoice with its lines and the payments allocated to it").argument("<ref>", "invoice:<id>").action((ref, options, command) => run(options.json, async (store) => itemAnswer(await withSources(command, store, await store.finance.invoice(ref)))));
5055
5667
  json(writeMeta(party(annotate(invoices.command("add"), {
5056
5668
  effects: LOCAL_WRITE,
5057
5669
  output: { entity: "invoice" },
5058
5670
  literal_after_dashes: true
5059
- }), "billed or billing").option("--kind <kind>", "receivable (you bill them) or payable (they bill you)").option("--title <title>", "the invoice's number, as printed on it").option("--occurred-time <time>", "the day it was issued, such as 2026-11-01").option("--due <time>", "the day it is due, such as 2026-11-15"))).description(`record an invoice of one line; ${PROPOSES}`).summary("record an invoice; an agent's waits for your review").argument("<amount>", "a decimal, such as 50000.00").argument("<currency>", "ISO 4217, such as RUB").argument("<description...>", "what it bills, in a few words").action(async (amount2, currency, words, options, command) => {
5671
+ }), "billed or billing").option("--kind <kind>", "receivable (you bill them) or payable (they bill you)").option("--title <title>", "the invoice's number, as printed on it").option("--occurred-time <time>", "the day it was issued, such as 2026-11-01").option("--due <time>", "the day it is due, such as 2026-11-15"))).description(`record an invoice of one line, and add more with invoices lines add; ${PROPOSES}`).summary("record an invoice; an agent's waits for your review").argument("<amount>", "a decimal, such as 50000.00").argument("<currency>", "ISO 4217, such as RUB").argument("<description...>", "what it bills, in a few words").action(async (amount2, currency, words, options, command) => {
5060
5672
  const by = await whoRuns(command, env, { asOwner: options.asOwner, question: "record this invoice as yours?" });
5061
5673
  await run(options.json, async (store) => {
5062
5674
  const issueDate = dayOf(options.occurredTime);
5063
5675
  const dueDate = dayOf(options.due);
5064
5676
  return itemAnswer(await store.finance.addInvoice({
5065
5677
  ...await writtenBy(store, by, options),
5066
- direction: kindOf2(options.kind, INVOICE_DIRECTIONS),
5678
+ direction: choice(options.kind, INVOICE_DIRECTIONS, "--kind"),
5067
5679
  counterparty: partyOf(options, true),
5068
5680
  currency,
5069
5681
  lines: [{ description: words.join(" "), amount: amount2 }],
@@ -5073,13 +5685,14 @@ var financeCommands = /* @__PURE__ */ __name((program, streams, env) => {
5073
5685
  }));
5074
5686
  });
5075
5687
  });
5688
+ lineCommands(invoices, "invoice", run, env);
5076
5689
  const payments = program.command("payments").description("money paid to you or by you, and the invoices each payment settles; amounts per currency").summary("money paid to you or by you, and what it settles");
5077
- withQuery(json(annotate(payments.command("list"), { effects: LOCAL_READ })).description("payments, newest first; review:proposed lists what waits for you"), PAYMENT_QUERY).option("--limit <n>", "most payments, up to 500", positive, 100).action((words, { json: json7, limit }) => run(json7, (store) => listPayments(store, words, limit)));
5078
- json(annotate(payments.command("show"), { effects: LOCAL_READ, output: { entity: "payment" } })).description("one payment with the invoices it is allocated to").argument("<ref>", "payment:<id>").action((ref, options) => run(options.json, async (store) => itemAnswer(await store.finance.payment(ref))));
5079
- json(writeMeta(party(annotate(payments.command("add"), { effects: LOCAL_WRITE, output: { entity: "payment" } }), "who paid or was paid").option("--kind <kind>", "in (paid to you) or out (paid by you)").option("--title <title>", "the payment's reference, such as the bank's purpose line").option("--occurred-time <time>", "the day it was paid, such as 2026-11-01; today when left out"))).description(`record a payment; ${PROPOSES}. payments allocate matches it to an invoice`).summary("record a payment; an agent's waits for your review").argument("<amount>", "a decimal, such as 50000.00").argument("<currency>", "ISO 4217, such as RUB").action(async (amount2, currency, options, command) => {
5690
+ withQuery(json(annotate(payments.command("list"), { effects: LOCAL_READ })).description("payments, newest first; review:proposed lists what waits for you"), PAYMENT_QUERY).option("--limit <n>", "most payments, up to 500", positive, 100).action((words, { json: json5, limit }) => run(json5, (store) => listPayments(store, words, limit)));
5691
+ json(annotate(payments.command("show"), { effects: LOCAL_READ, output: { entity: "payment" } })).description("one payment with the invoices it is allocated to").argument("<ref>", "payment:<id>").action((ref, options, command) => run(options.json, async (store) => itemAnswer(await withSources(command, store, await store.finance.payment(ref)))));
5692
+ json(writeMeta(party(annotate(payments.command("add"), { effects: LOCAL_WRITE, output: { entity: "payment" } }), "who paid or was paid").option("--kind <kind>", "in (paid to you) or out (paid by you)").option("--title <title>", "the payment's reference, such as the bank's purpose line").option("--occurred-time <time>", "the day it was paid, such as 2026-11-01; today when left out").option("--refund-of <payment>", "the payment this one gives money back for, going the other way: payment:<id>"))).description(`record a payment, or with --refund-of a refund of one; ${PROPOSES}. payments allocate matches it to an invoice`).summary("record a payment; an agent's waits for your review").argument("<amount>", "a decimal, such as 50000.00").argument("<currency>", "ISO 4217, such as RUB").action(async (amount2, currency, options, command) => {
5080
5693
  const by = await whoRuns(command, env, { asOwner: options.asOwner, question: "record this payment as yours?" });
5081
5694
  await run(options.json, async (store) => {
5082
- const direction = kindOf2(options.kind, MONEY_DIRECTIONS);
5695
+ const direction = choice(options.kind, MONEY_DIRECTIONS, "--kind");
5083
5696
  const counterparty = partyOf(options, false);
5084
5697
  return itemAnswer(await store.finance.addPayment({
5085
5698
  ...await writtenBy(store, by, options),
@@ -5088,7 +5701,8 @@ var financeCommands = /* @__PURE__ */ __name((program, streams, env) => {
5088
5701
  amount: amount2,
5089
5702
  currency,
5090
5703
  date: dayOf(options.occurredTime) ?? today(),
5091
- ...options.title === void 0 ? {} : { reference: options.title }
5704
+ ...options.title === void 0 ? {} : { reference: options.title },
5705
+ ...options.refundOf === void 0 ? {} : { refundOf: options.refundOf }
5092
5706
  }));
5093
5707
  });
5094
5708
  });
@@ -5105,6 +5719,78 @@ var financeCommands = /* @__PURE__ */ __name((program, streams, env) => {
5105
5719
  });
5106
5720
  }, "financeCommands");
5107
5721
 
5722
+ // dist/finance/contracts-command.js
5723
+ var CONTRACT_QUERY = {
5724
+ entity: "contract",
5725
+ backend: "native",
5726
+ fields: [
5727
+ termField("status", "enum", "status:active", { values: CONTRACT_STATUSES }),
5728
+ termField("kind", "enum", "kind:lease", { values: CONTRACT_KINDS }),
5729
+ termField("project", "kw", "project:PMED"),
5730
+ termField("review", "enum", "review:proposed", { values: FINANCE_REVIEWS }),
5731
+ termField("expires", "time", "expires:2026-12-31")
5732
+ ]
5733
+ };
5734
+ var listContracts = /* @__PURE__ */ __name(async (store, words, limit) => {
5735
+ const terms2 = queryTerms(words, CONTRACT_QUERY, "contracts list");
5736
+ const project = terms2.get("project");
5737
+ const filter = given({
5738
+ status: terms2.get("status"),
5739
+ kind: terms2.get("kind"),
5740
+ review: terms2.get("review"),
5741
+ expiresBy: dayOf(terms2.get("expires")),
5742
+ project: project === void 0 ? void 0 : await canonicalProject(store, project)
5743
+ });
5744
+ return pageOf("contracts list", limit, (most) => store.contracts.list({ ...filter, limit: most }));
5745
+ }, "listContracts");
5746
+ var days = /* @__PURE__ */ __name((value) => {
5747
+ const number2 = Number(value);
5748
+ if (!Number.isInteger(number2) || number2 < 0)
5749
+ throw new InvalidArgumentError("a whole number of days, 0 or more");
5750
+ return number2;
5751
+ }, "days");
5752
+ var terms = /* @__PURE__ */ __name((command) => command.option("--kind <kind>", `what it is: ${CONTRACT_KINDS.join(", ")}`).option("--status <state>", `${CONTRACT_STATUSES.join(", ")}; active when left out`).option("--start-date <date>", "the first day it is in force, YYYY-MM-DD").option("--end-date <date>", "the last day it is in force, YYYY-MM-DD; left out, it runs until ended").option("--auto-renew <on|off>", "it renews by itself at its end, or it does not").option("--notice-days <days>", "how many days before its end a party must say it will not go on", days).option("--amount <decimal>", "what it is worth, such as 120000.00, in --currency; with it, an agent's waits for you").option("--currency <code>", "an ISO 4217 code, such as RUB"), "terms");
5753
+ var fieldsOf2 = /* @__PURE__ */ __name((options) => given({
5754
+ status: optionalChoice(options.status, CONTRACT_STATUSES, "--status"),
5755
+ effectiveDate: dayOf(options.startDate),
5756
+ expirationDate: dayOf(options.endDate),
5757
+ autoRenew: onOff(options.autoRenew, "--auto-renew"),
5758
+ noticeDays: options.noticeDays,
5759
+ value: options.amount,
5760
+ currency: options.currency
5761
+ }), "fieldsOf");
5762
+ var VALUED = "one with no amount is written as it is, by anyone; with an amount yours is confirmed at once and an agent's waits as proposed for you in memo review";
5763
+ var contractCommands = /* @__PURE__ */ __name((program, streams, env) => {
5764
+ const { run } = answers(program, streams, env);
5765
+ const contracts = program.command("contracts").description("contracts you work under: their kind, dates, renewal, notice and what they are worth").summary("contracts you work under, with their dates and notice");
5766
+ withQuery(json(annotate(contracts.command("list"), { effects: LOCAL_READ })).description("contracts, newest first; expires:2026-12-31 lists those that end by then"), CONTRACT_QUERY).option("--limit <n>", "most contracts, up to 500", positive, 100).action((words, { json: json5, limit }) => run(json5, (store) => listContracts(store, words, limit)));
5767
+ json(annotate(contracts.command("show"), { effects: LOCAL_READ, output: { entity: "contract" } })).description("one contract with its dates, renewal and the last day to give notice").argument("<contract>", "contract:<id>").action((ref, options, command) => run(options.json, async (store) => itemAnswer(await withSources(command, store, await store.contracts.get(ref)))));
5768
+ json(writeMeta(terms(annotate(contracts.command("add"), {
5769
+ effects: LOCAL_WRITE,
5770
+ output: { entity: "contract" },
5771
+ literal_after_dashes: true
5772
+ })))).description(`record a contract; ${VALUED}`).summary("record a contract").argument("<name>", "what it is called, such as 'Rental agreement'").action(async (name2, options, command) => {
5773
+ const by = await whoRuns(command, env, { asOwner: options.asOwner, question: "record this contract as yours?" });
5774
+ await run(options.json, async (store) => itemAnswer(await store.contracts.add({
5775
+ ...await writtenBy(store, by, options),
5776
+ name: name2,
5777
+ kind: choice(options.kind, CONTRACT_KINDS, "--kind"),
5778
+ ...fieldsOf2(options)
5779
+ })));
5780
+ });
5781
+ json(byOption(terms(annotate(contracts.command("update"), { effects: LOCAL_WRITE, output: { entity: "contract" } })).option("--title <title>", "its new name"))).description("change a contract's dates, status, terms or worth; you change any, an agent only one it proposed that is still proposed, and a confirmed contract's worth only you").summary("change a contract").argument("<contract>", "contract:<id>").action(async (ref, options, command) => {
5782
+ const by = await whoRuns(command, env, { asOwner: options.asOwner, question: `change ${ref} as yours?` });
5783
+ await run(options.json, async (store) => itemAnswer(await store.contracts.update(ref, {
5784
+ by,
5785
+ ...fieldsOf2(options),
5786
+ ...given({
5787
+ name: options.title,
5788
+ kind: optionalChoice(options.kind, CONTRACT_KINDS, "--kind")
5789
+ })
5790
+ })));
5791
+ });
5792
+ }, "contractCommands");
5793
+
5108
5794
  // dist/finance/deals-command.js
5109
5795
  var queryOf = /* @__PURE__ */ __name((entity) => ({
5110
5796
  entity,
@@ -5125,14 +5811,14 @@ var PIPELINE_QUERY = {
5125
5811
  };
5126
5812
  var listDeals = /* @__PURE__ */ __name(async (store, kind, words, limit) => {
5127
5813
  const command = `${kind}s list`;
5128
- const terms = queryTerms(words, QUERIES[kind], command);
5814
+ const terms2 = queryTerms(words, QUERIES[kind], command);
5129
5815
  const filter = {
5130
5816
  kind,
5131
- ...terms.has("project") ? { project: await canonicalProject(store, terms.get("project")) } : {},
5132
- ...terms.has("status") ? { status: terms.get("status") } : {},
5133
- ...terms.has("stage") ? { stage: terms.get("stage") } : {},
5134
- ...terms.has("pipeline") ? { pipeline: terms.get("pipeline") } : {},
5135
- ...terms.has("organization") ? { organization: terms.get("organization") } : {}
5817
+ ...terms2.has("project") ? { project: await canonicalProject(store, terms2.get("project")) } : {},
5818
+ ...terms2.has("status") ? { status: terms2.get("status") } : {},
5819
+ ...terms2.has("stage") ? { stage: terms2.get("stage") } : {},
5820
+ ...terms2.has("pipeline") ? { pipeline: terms2.get("pipeline") } : {},
5821
+ ...terms2.has("organization") ? { organization: terms2.get("organization") } : {}
5136
5822
  };
5137
5823
  return pageOf(command, limit, (most) => store.deals.list({ ...filter, limit: most }));
5138
5824
  }, "listDeals");
@@ -5149,7 +5835,6 @@ var stageOf = /* @__PURE__ */ __name((stage) => {
5149
5835
  const at = stage.lastIndexOf("/");
5150
5836
  return at <= 0 ? { stage } : { pipeline: stage.slice(0, at), stage: stage.slice(at + 1) };
5151
5837
  }, "stageOf");
5152
- var json2 = /* @__PURE__ */ __name((command) => command.option("--json", "print JSON; --json=ref,title keeps only those fields"), "json");
5153
5838
  var WHAT = {
5154
5839
  deal: { one: "deal", hope: "what you hope to sell, such as 'Site for the clinic'" },
5155
5840
  lead: { one: "lead", hope: "who or what came in, such as 'Call from the site'" }
@@ -5157,9 +5842,9 @@ var WHAT = {
5157
5842
  var itemCommands = /* @__PURE__ */ __name((program, kind, run, env) => {
5158
5843
  const { one: one2, hope } = WHAT[kind];
5159
5844
  const group = program.command(`${kind}s`).description(kind === "deal" ? "deals you hope to win: the client, the expected amount, the stage and whether it was won or lost" : "leads: first contacts in a lead pipeline, before they are deals").summary(kind === "deal" ? "deals in your pipelines, open, won or lost" : "leads in your lead pipelines");
5160
- withQuery(json2(annotate(group.command("list"), { effects: LOCAL_READ })).description(`${one2}s, newest first; status:open is what is still in play`), QUERIES[kind]).summary(`${one2}s, newest first`).option("--limit <n>", `most ${one2}s, up to 500`, positive, 100).action((words, { json: json7, limit }) => run(json7, (store) => listDeals(store, kind, words, limit)));
5161
- json2(annotate(group.command("show"), { effects: LOCAL_READ, output: { entity: kind } })).description(`one ${one2} with its pipeline, stage, status, amount, the people on it and what it was read from`).summary(`one ${one2} with its stage, status, amount and people`).argument("<ref>", `${kind}:<id>`).action((ref, options) => run(options.json, async (store) => itemAnswer(await store.deals.get(ref))));
5162
- json2(annotate(group.command("add"), { effects: LOCAL_WRITE, output: { entity: kind }, literal_after_dashes: true }).option("--organization <organization>", "the client: organization:<id>").option("--person <uid>", `a person on the ${one2}: person:<id>; repeat for another, up to 20`, collect).option("--role <role>", `what those people are on it: ${DEAL_ROLES.join(", ")}; contact by default`).option("--due <time>", "the day you expect it to close, such as 2026-12-01").option("--project <project>", "the project it belongs to: its key or project:<id>").option("--reason <text>", "why an agent records it, kept with it").option("--evidence <ref...>", "what shows it, up to 8: msg:, note:, document: or another reference")).description(`record a ${one2} in a stage; it is written at once, whoever runs it`).summary(`record a ${one2} in a stage`).argument("<title>", hope).argument(kind === "deal" ? "<stage>" : "[stage]", kind === "deal" ? "the stage it is in; Sales/Quote or pipeline:3/Quote names the pipeline when two have that stage" : "the stage it is in; the first stage of the only lead pipeline when left out").argument("[amount]", "the expected amount, a decimal such as 500000.00").argument("[currency]", "ISO 4217, such as RUB; given with the amount").action(async (title, stage, amount2, currency, options) => {
5845
+ withQuery(json(annotate(group.command("list"), { effects: LOCAL_READ })).description(`${one2}s, newest first; status:open is what is still in play`), QUERIES[kind]).summary(`${one2}s, newest first`).option("--limit <n>", `most ${one2}s, up to 500`, positive, 100).action((words, { json: json5, limit }) => run(json5, (store) => listDeals(store, kind, words, limit)));
5846
+ json(annotate(group.command("show"), { effects: LOCAL_READ, output: { entity: kind } })).description(`one ${one2} with its pipeline, stage, status, amount, the people on it and what it was read from`).summary(`one ${one2} with its stage, status, amount and people`).argument("<ref>", `${kind}:<id>`).action((ref, options, command) => run(options.json, async (store) => itemAnswer(await withSources(command, store, await store.deals.get(ref)))));
5847
+ json(annotate(group.command("add"), { effects: LOCAL_WRITE, output: { entity: kind }, literal_after_dashes: true }).option("--organization <organization>", "the client: organization:<id>").option("--person <uid>", `a person on the ${one2}: person:<id>; repeat for another, up to 20`, collect).option("--role <role>", `what those people are on it: ${DEAL_ROLES.join(", ")}; contact by default`).option("--due <time>", "the day you expect it to close, such as 2026-12-01").option("--project <project>", "the project it belongs to: its key or project:<id>").option("--reason <text>", "why an agent records it, kept with it").option("--evidence <ref...>", "what shows it, up to 8: msg:, note:, document: or another reference")).description(`record a ${one2} in a stage; it is written at once, whoever runs it`).summary(`record a ${one2} in a stage`).argument("<title>", hope).argument(kind === "deal" ? "<stage>" : "[stage]", kind === "deal" ? "the stage it is in; Sales/Quote or pipeline:3/Quote names the pipeline when two have that stage" : "the stage it is in; the first stage of the only lead pipeline when left out").argument("[amount]", "the expected amount, a decimal such as 500000.00").argument("[currency]", "ISO 4217, such as RUB; given with the amount").action(async (title, stage, amount2, currency, options) => {
5163
5848
  const by = authorOf(env);
5164
5849
  const role = roleOf(options.role);
5165
5850
  await run(options.json, async (store) => {
@@ -5180,11 +5865,11 @@ var itemCommands = /* @__PURE__ */ __name((program, kind, run, env) => {
5180
5865
  }));
5181
5866
  });
5182
5867
  });
5183
- json2(annotate(group.command("move"), { effects: LOCAL_WRITE, output: { entity: kind } })).description(`move a ${one2} to another stage of its pipeline; a won or lost stage closes it, an open one reopens it`).summary(`move a ${one2} to another stage`).argument("<ref>", `${kind}:<id>`).argument("<stage>", `a stage of the ${one2}'s pipeline`).action(async (ref, stage, options) => {
5868
+ json(annotate(group.command("move"), { effects: LOCAL_WRITE, output: { entity: kind } })).description(`move a ${one2} to another stage of its pipeline; a won or lost stage closes it, an open one reopens it`).summary(`move a ${one2} to another stage`).argument("<ref>", `${kind}:<id>`).argument("<stage>", `a stage of the ${one2}'s pipeline`).action(async (ref, stage, options) => {
5184
5869
  const by = authorOf(env);
5185
5870
  await run(options.json, async (store) => itemAnswer(await store.deals.move(ref, { stage, by })));
5186
5871
  });
5187
- json2(annotate(group.command("close"), { effects: LOCAL_WRITE, output: { entity: kind } }).option("--occurred-time <time>", "the day it closed, such as 2026-11-20; today when left out").option("--reason <text>", "why it was won or lost, kept with it")).description(`close a ${one2} as won or lost; it moves to its pipeline's won or lost stage when there is one`).summary(`close a ${one2} as won or lost`).argument("<ref>", `${kind}:<id>`).argument("<outcome>", "won or lost").action(async (ref, outcome, options) => {
5872
+ json(annotate(group.command("close"), { effects: LOCAL_WRITE, output: { entity: kind } }).option("--occurred-time <time>", "the day it closed, such as 2026-11-20; today when left out").option("--reason <text>", "why it was won or lost, kept with it")).description(`close a ${one2} as won or lost; it moves to its pipeline's won or lost stage when there is one`).summary(`close a ${one2} as won or lost`).argument("<ref>", `${kind}:<id>`).argument("<outcome>", "won or lost").action(async (ref, outcome, options) => {
5188
5873
  if (outcome !== "won" && outcome !== "lost")
5189
5874
  throw new CliError("validation_error", `a ${one2} closes as won or lost`, { param: "outcome" });
5190
5875
  const by = authorOf(env);
@@ -5206,19 +5891,19 @@ var funnelText = /* @__PURE__ */ __name((report) => [
5206
5891
  var dealCommands = /* @__PURE__ */ __name((program, streams, env) => {
5207
5892
  const { run, print } = answers(program, streams, env);
5208
5893
  const pipelines = program.command("pipelines").description("sales pipelines: the stages a deal or a lead goes through, in order, and how many get through each").summary("sales pipelines, their stages and conversion");
5209
- withQuery(json2(annotate(pipelines.command("list"), { effects: LOCAL_READ })).description("every pipeline with its stages in order and how many open deals or leads stand in each"), PIPELINE_QUERY).summary("every pipeline with its stages").action((words, options) => run(options.json, async (store) => {
5210
- const terms = queryTerms(words, PIPELINE_QUERY, "pipelines list");
5211
- const name2 = terms.get("name")?.toLocaleLowerCase();
5212
- const kind = terms.get("kind");
5894
+ withQuery(json(annotate(pipelines.command("list"), { effects: LOCAL_READ })).description("every pipeline with its stages in order and how many open deals or leads stand in each"), PIPELINE_QUERY).summary("every pipeline with its stages").action((words, options) => run(options.json, async (store) => {
5895
+ const terms2 = queryTerms(words, PIPELINE_QUERY, "pipelines list");
5896
+ const name2 = terms2.get("name")?.toLocaleLowerCase();
5897
+ const kind = terms2.get("kind");
5213
5898
  const all = await store.deals.pipelines(kind === void 0 ? {} : { kind });
5214
5899
  return wholeList("pipelines list", name2 === void 0 ? all : all.filter((one2) => one2.name.toLocaleLowerCase() === name2));
5215
5900
  }));
5216
- json2(annotate(pipelines.command("show"), { effects: LOCAL_READ, output: { entity: "pipeline" } }).option("--since-time <time>", "count only deals or leads made since this day, such as 2026-09-01")).description("one pipeline's funnel: per stage the open deals or leads in it, how many reached it, and the share that went on to the next stage; then won, lost and the win rate").summary("one pipeline's stages with counts and conversion").argument("<pipeline>", "pipeline:<id>, or a name only one pipeline has").action(async (pipeline, options) => {
5901
+ json(annotate(pipelines.command("show"), { effects: LOCAL_READ, output: { entity: "pipeline" } }).option("--since-time <time>", "count only deals or leads made since this day, such as 2026-09-01")).description("one pipeline's funnel: per stage the open deals or leads in it, how many reached it, and the share that went on to the next stage; then won, lost and the win rate").summary("one pipeline's stages with counts and conversion").argument("<pipeline>", "pipeline:<id>, or a name only one pipeline has").action(async (pipeline, options, command) => {
5217
5902
  const since = dayOf(options.sinceTime);
5218
- const report = await withStore(env, (store) => store.deals.pipeline(pipeline, since === void 0 ? {} : { since }));
5903
+ const report = await withStore(env, async (store) => withSources(command, store, await store.deals.pipeline(pipeline, since === void 0 ? {} : { since })));
5219
5904
  print(options.json, itemAnswer(report), funnelText(report));
5220
5905
  });
5221
- json2(annotate(pipelines.command("add"), { effects: LOCAL_WRITE, literal_after_dashes: true }).option("--kind <kind>", "what it holds: deal or lead; deal by default")).description("make a pipeline with its stages in order; a stage named won or lost (any letter case) ends a deal or lead as that").summary("make a pipeline with its stages").argument("<name>", "the pipeline's name, such as Sales").argument("<stage...>", "its stages in order, such as Call Quote Contract won lost").action(async (name2, stages, options) => {
5906
+ json(annotate(pipelines.command("add"), { effects: LOCAL_WRITE, literal_after_dashes: true }).option("--kind <kind>", "what it holds: deal or lead; deal by default")).description("make a pipeline with its stages in order; a stage named won or lost (any letter case) ends a deal or lead as that").summary("make a pipeline with its stages").argument("<name>", "the pipeline's name, such as Sales").argument("<stage...>", "its stages in order, such as Call Quote Contract won lost").action(async (name2, stages, options) => {
5222
5907
  const kind = options.kind ?? "deal";
5223
5908
  if (!DEAL_KINDS.includes(kind))
5224
5909
  throw new CliError("validation_error", "--kind is deal or lead", { param: "--kind" });
@@ -5277,15 +5962,15 @@ var ORDER_QUERY = {
5277
5962
  ]
5278
5963
  };
5279
5964
  var listOrders = /* @__PURE__ */ __name(async (store, words, limit) => {
5280
- const terms = queryTerms(words, ORDER_QUERY, "orders list");
5965
+ const terms2 = queryTerms(words, ORDER_QUERY, "orders list");
5281
5966
  const filter = {
5282
- ...terms.has("project") ? { project: await canonicalProject(store, terms.get("project")) } : {},
5283
- ...terms.has("status") ? { status: terms.get("status") } : {},
5284
- ...terms.has("purpose") ? { purpose: terms.get("purpose") } : {},
5285
- ...terms.has("review") ? { review: terms.get("review") } : {},
5286
- ...terms.has("customer") ? { customer: terms.get("customer") } : {},
5287
- ...terms.has("supplier") ? { supplierName: terms.get("supplier") } : {},
5288
- ...terms.has("number") ? { number: terms.get("number") } : {}
5967
+ ...terms2.has("project") ? { project: await canonicalProject(store, terms2.get("project")) } : {},
5968
+ ...terms2.has("status") ? { status: terms2.get("status") } : {},
5969
+ ...terms2.has("purpose") ? { purpose: terms2.get("purpose") } : {},
5970
+ ...terms2.has("review") ? { review: terms2.get("review") } : {},
5971
+ ...terms2.has("customer") ? { customer: terms2.get("customer") } : {},
5972
+ ...terms2.has("supplier") ? { supplierName: terms2.get("supplier") } : {},
5973
+ ...terms2.has("number") ? { number: terms2.get("number") } : {}
5289
5974
  };
5290
5975
  return pageOf("orders list", limit, (most) => store.orders.list({ ...filter, limit: most }));
5291
5976
  }, "listOrders");
@@ -5294,13 +5979,12 @@ var oneOf2 = /* @__PURE__ */ __name((value, allowed, flag) => {
5294
5979
  throw new CliError("validation_error", `${flag} is one of ${allowed.join(", ")}`, { param: flag });
5295
5980
  return value;
5296
5981
  }, "oneOf");
5297
- var json3 = /* @__PURE__ */ __name((command) => command.option("--json", "print JSON; --json=ref,title keeps only those fields"), "json");
5298
5982
  var orderCommands = /* @__PURE__ */ __name((program, streams, env) => {
5299
5983
  const { run } = answers(program, streams, env);
5300
5984
  const orders = program.command("orders").description("orders you placed or took, for whom, from which shop, and how far delivery got").summary("orders you placed or took, and how far delivery got");
5301
- withQuery(json3(annotate(orders.command("list"), { effects: LOCAL_READ })).description("orders, newest first; review:proposed is what waits for you"), ORDER_QUERY).option("--limit <n>", "most orders, up to 500", positive, 100).action((words, { json: json7, limit }) => run(json7, (store) => listOrders(store, words, limit)));
5302
- json3(annotate(orders.command("show"), { effects: LOCAL_READ, output: { entity: "order" } })).description("one order with its customer, shop, amount, status and the mail it was read from").argument("<ref>", "order:<id>").action((ref, options) => run(options.json, async (store) => itemAnswer(await store.orders.get(ref))));
5303
- json3(byOption(annotate(orders.command("add"), { effects: LOCAL_WRITE, output: { entity: "order" }, literal_after_dashes: true }).option("--kind <kind>", `why it was ordered: ${ORDER_PURPOSES.join(", ")}`).option("--person <uid>", "whom it is for, when not you: person:<id>").option("--organization <organization>", "whom it is for, when not you: organization:<id>").option("--title <title>", "the shop's order number").option("--occurred-time <time>", "the day it was ordered, such as 2026-11-01").option("--project <project>", "the project it belongs to: its key or project:<id>").option("--reason <text>", "why an agent proposes it, for the owner who decides").option("--evidence <ref...>", "what shows it, up to 8: msg:, note:, document: or another reference"))).description("record a placed order; yours is confirmed at once, an agent's waits as proposed for you in memo review").summary("record an order; an agent's waits for your review").argument("<shop>", "the shop or supplier, as its mail names it").argument("[amount]", "the order's amount, a decimal such as 2499.00").argument("[currency]", "ISO 4217, such as RUB; given with the amount").action(async (shop, amount2, currency, options, command) => {
5985
+ withQuery(json(annotate(orders.command("list"), { effects: LOCAL_READ })).description("orders, newest first; review:proposed is what waits for you"), ORDER_QUERY).option("--limit <n>", "most orders, up to 500", positive, 100).action((words, { json: json5, limit }) => run(json5, (store) => listOrders(store, words, limit)));
5986
+ json(annotate(orders.command("show"), { effects: LOCAL_READ, output: { entity: "order" } })).description("one order with its customer, shop, amount, status and the mail it was read from").argument("<ref>", "order:<id>").action((ref, options, command) => run(options.json, async (store) => itemAnswer(await withSources(command, store, await store.orders.get(ref)))));
5987
+ json(byOption(annotate(orders.command("add"), { effects: LOCAL_WRITE, output: { entity: "order" }, literal_after_dashes: true }).option("--kind <kind>", `why it was ordered: ${ORDER_PURPOSES.join(", ")}`).option("--person <uid>", "whom it is for, when not you: person:<id>").option("--organization <organization>", "whom it is for, when not you: organization:<id>").option("--title <title>", "the shop's order number").option("--occurred-time <time>", "the day it was ordered, such as 2026-11-01").option("--project <project>", "the project it belongs to: its key or project:<id>").option("--reason <text>", "why an agent proposes it, for the owner who decides").option("--evidence <ref...>", "what shows it, up to 8: msg:, note:, document: or another reference"))).description("record a placed order; yours is confirmed at once, an agent's waits as proposed for you in memo review").summary("record an order; an agent's waits for your review").argument("<shop>", "the shop or supplier, as its mail names it").argument("[amount]", "the order's amount, a decimal such as 2499.00").argument("[currency]", "ISO 4217, such as RUB; given with the amount").action(async (shop, amount2, currency, options, command) => {
5304
5988
  const by = await whoRuns(command, env, { asOwner: options.asOwner, question: "record this order as yours?" });
5305
5989
  await run(options.json, async (store) => {
5306
5990
  const customer = partyOf(options, false);
@@ -5320,8 +6004,314 @@ var orderCommands = /* @__PURE__ */ __name((program, streams, env) => {
5320
6004
  }));
5321
6005
  });
5322
6006
  });
6007
+ lineCommands(orders, "order", run, env);
5323
6008
  }, "orderCommands");
5324
6009
 
6010
+ // dist/finance/products-command.js
6011
+ var PRODUCT_QUERY = {
6012
+ entity: "product",
6013
+ backend: "native",
6014
+ fields: [
6015
+ termField("kind", "enum", "kind:service", { values: CATALOG_KINDS }),
6016
+ termField("supplier", "ref", 'supplier:"organization:3"'),
6017
+ termField("archived", "bool", "archived:true"),
6018
+ termField("name", "kw", 'name:"Bike rental"')
6019
+ ]
6020
+ };
6021
+ var listProducts = /* @__PURE__ */ __name(async (store, words, limit) => {
6022
+ const terms2 = queryTerms(words, PRODUCT_QUERY, "products list");
6023
+ const filter = given({
6024
+ kind: terms2.get("kind"),
6025
+ supplier: terms2.get("supplier"),
6026
+ archived: terms2.has("archived") ? terms2.get("archived") === "true" : void 0,
6027
+ name: terms2.get("name")
6028
+ });
6029
+ return pageOf("products list", limit, (most) => store.products.list({ ...filter, limit: most }));
6030
+ }, "listProducts");
6031
+ var productCommands = /* @__PURE__ */ __name((program, streams, env) => {
6032
+ const { run } = answers(program, streams, env);
6033
+ const products = program.command("products").description("goods and services you sell or buy, with their prices; a line that names one copies its price, so a later price change leaves the line as it was").summary("goods and services you sell or buy, with their prices");
6034
+ withQuery(json(annotate(products.command("list"), { effects: LOCAL_READ })).description("products and services, by name; archived:true lists those no longer sold"), PRODUCT_QUERY).option("--limit <n>", "most products, up to 500", positive, 100).action((words, { json: json5, limit }) => run(json5, (store) => listProducts(store, words, limit)));
6035
+ json(annotate(products.command("show"), { effects: LOCAL_READ, output: { entity: "product" } })).description("one product or service with its price, unit, supplier and stock code").argument("<product>", "product:<id>").action((ref, options, command) => run(options.json, async (store) => itemAnswer(await withSources(command, store, await store.products.get(ref)))));
6036
+ json(annotate(products.command("add"), {
6037
+ effects: LOCAL_WRITE,
6038
+ output: { entity: "product" },
6039
+ literal_after_dashes: true
6040
+ }).option("--kind <kind>", `${CATALOG_KINDS.join(" or ")}; product when left out`).option("--unit <text>", "what one of it is counted in, such as hour or month").option("--sku <code>", "the stock code the seller gives it").option("--supplier <party>", "who supplies it, when not you: person:<uid> or organization:<id>").option("--description <text>", "what it is, in a sentence")).description("add a product or service you sell or buy; anyone adds one directly, as a price feeds no total").summary("add a product or service").argument("<name>", "its name, as an invoice or order line prints it").argument("[amount]", "the price of one unit, a decimal such as 10000.00").argument("[currency]", "ISO 4217, such as RUB; given with the amount").action((name2, amount2, currency, options) => run(options.json, async (store) => itemAnswer(await store.products.add({
6041
+ by: authorOf(env),
6042
+ name: name2,
6043
+ ...given({
6044
+ kind: optionalChoice(options.kind, CATALOG_KINDS, "--kind"),
6045
+ unitPrice: amount2,
6046
+ currency,
6047
+ unit: options.unit,
6048
+ sku: options.sku,
6049
+ supplier: options.supplier,
6050
+ description: options.description
6051
+ })
6052
+ }))));
6053
+ json(annotate(products.command("update"), { effects: LOCAL_WRITE, output: { entity: "product" } }).option("--amount <decimal>", "the new price of one unit, such as 12000.00; give --currency with it").option("--currency <code>", "an ISO 4217 code, such as RUB").option("--title <title>", "its new name").option("--unit <text>", "what one of it is counted in, such as hour or month").option("--description <text>", "what it is, in a sentence").option("--archived <on|off>", "on: no longer sold, and lines and subscriptions keep pointing at it; off: sold again")).description("change a product's price, name, unit or description, or archive it; lines already written keep theirs").summary("change or archive a product").argument("<product>", "product:<id>").action((ref, options) => run(options.json, async (store) => {
6054
+ const archived = onOff(options.archived, "--archived");
6055
+ return itemAnswer(await store.products.update(ref, {
6056
+ by: authorOf(env),
6057
+ ...given({
6058
+ name: options.title,
6059
+ unitPrice: options.amount,
6060
+ currency: options.currency,
6061
+ unit: options.unit,
6062
+ description: options.description,
6063
+ archivedDate: archived === void 0 ? void 0 : archived ? today() : null
6064
+ })
6065
+ }));
6066
+ }));
6067
+ }, "productCommands");
6068
+
6069
+ // dist/finance/subscriptions-command.js
6070
+ var SUBSCRIPTION_QUERY = {
6071
+ entity: "subscription",
6072
+ backend: "native",
6073
+ fields: [
6074
+ termField("status", "enum", "status:active", { values: SUBSCRIPTION_STATUSES }),
6075
+ termField("direction", "enum", "direction:payable", { values: INVOICE_DIRECTIONS }),
6076
+ termField("supplier", "ref", 'supplier:"organization:3"'),
6077
+ termField("customer", "ref", 'customer:"organization:3"'),
6078
+ termField("project", "kw", "project:PMED"),
6079
+ termField("review", "enum", "review:proposed", { values: FINANCE_REVIEWS }),
6080
+ termField("renews", "time", "renews:2026-12-01")
6081
+ ]
6082
+ };
6083
+ var listSubscriptions = /* @__PURE__ */ __name(async (store, words, limit) => {
6084
+ const terms2 = queryTerms(words, SUBSCRIPTION_QUERY, "subscriptions list");
6085
+ const project = terms2.get("project");
6086
+ const filter = given({
6087
+ status: terms2.get("status"),
6088
+ direction: terms2.get("direction"),
6089
+ supplier: terms2.get("supplier"),
6090
+ customer: terms2.get("customer"),
6091
+ review: terms2.get("review"),
6092
+ renewsBy: dayOf(terms2.get("renews")),
6093
+ project: project === void 0 ? void 0 : await canonicalProject(store, project)
6094
+ });
6095
+ return pageOf("subscriptions list", limit, (most) => store.subscriptions.list({ ...filter, limit: most }));
6096
+ }, "listSubscriptions");
6097
+ var parts = /* @__PURE__ */ __name((command) => command.option("--status <state>", `${SUBSCRIPTION_STATUSES.join(", ")}; trial needs --trial-end-date`).option("--supplier <party>", "who supplies it: person:<uid> or organization:<id>; you, when you bill it").option("--customer <party>", "who receives it and pays for it: person:<uid> or organization:<id>; you, when you pay").option("--product <product>", "the product or service it is for: product:<id>").option("--contract <contract>", "the contract it runs under: contract:<id>").option("--every <count-unit>", "how often it is charged: a count and a unit, such as 1-month or 1-year").option("--start-date <date>", "the first day it runs, YYYY-MM-DD").option("--trial-end-date <date>", "the day its free trial ends, YYYY-MM-DD"), "parts");
6098
+ var fieldsOf3 = /* @__PURE__ */ __name((options) => given({
6099
+ status: optionalChoice(options.status, SUBSCRIPTION_STATUSES, "--status"),
6100
+ supplier: options.supplier,
6101
+ customer: options.customer,
6102
+ product: options.product,
6103
+ contract: options.contract,
6104
+ every: options.every,
6105
+ startDate: dayOf(options.startDate),
6106
+ trialEndDate: dayOf(options.trialEndDate),
6107
+ endDate: dayOf(options.endDate)
6108
+ }), "fieldsOf");
6109
+ var subscriptionCommands = /* @__PURE__ */ __name((program, streams, env) => {
6110
+ const { run } = answers(program, streams, env);
6111
+ const subscriptions = program.command("subscriptions").description("subscriptions you bill or pay: who supplies it, who pays, how often, and every price it had; a price is never changed, a new one is added").summary("subscriptions you bill or pay, and their prices");
6112
+ withQuery(json(annotate(subscriptions.command("list"), { effects: LOCAL_READ })).description("subscriptions, newest first; renews:2026-12-01 lists those that renew by then"), SUBSCRIPTION_QUERY).option("--limit <n>", "most subscriptions, up to 500", positive, 100).action((words, { json: json5, limit }) => run(json5, (store) => listSubscriptions(store, words, limit)));
6113
+ json(annotate(subscriptions.command("show"), { effects: LOCAL_READ, output: { entity: "subscription" } })).description("one subscription with its parties, dates, current price and every price it had").argument("<subscription>", "subscription:<id>").action((ref, options, command) => run(options.json, async (store) => itemAnswer(await withSources(command, store, await store.subscriptions.get(ref)))));
6114
+ json(writeMeta(parts(annotate(subscriptions.command("add"), {
6115
+ effects: LOCAL_WRITE,
6116
+ output: { entity: "subscription" },
6117
+ literal_after_dashes: true
6118
+ })).option("--kind <kind>", "receivable (you bill it) or payable (you pay it)"))).description(`record a subscription and its first price; ${PROPOSES}`).summary("record a subscription; an agent's waits for your review").argument("<name>", "what it is, such as Hosting").argument("<amount>", "its price for one period, a decimal such as 990.00").argument("<currency>", "ISO 4217, such as RUB").action(async (name2, amount2, currency, options, command) => {
6119
+ const by = await whoRuns(command, env, {
6120
+ asOwner: options.asOwner,
6121
+ question: "record this subscription as yours?"
6122
+ });
6123
+ await run(options.json, async (store) => {
6124
+ const startDate = dayOf(options.startDate) ?? today();
6125
+ return itemAnswer(await store.subscriptions.add({
6126
+ ...await writtenBy(store, by, options),
6127
+ ...fieldsOf3(options),
6128
+ name: name2,
6129
+ direction: choice(options.kind, INVOICE_DIRECTIONS, "--kind"),
6130
+ every: needed(options.every, "--every", "how often it is charged, such as 1-month"),
6131
+ startDate,
6132
+ prices: [{ amount: amount2, currency, effectiveFrom: startDate }]
6133
+ }));
6134
+ });
6135
+ });
6136
+ json(byOption(parts(annotate(subscriptions.command("update"), { effects: LOCAL_WRITE, output: { entity: "subscription" } })).option("--title <title>", "its new name").option("--end-date <date>", "the last day it runs, YYYY-MM-DD"))).description("change a subscription's status, schedule, dates or parties; pause it with --status paused. You change any, an agent only one it proposed that is still proposed. A new price is subscriptions prices add").summary("change a subscription").argument("<subscription>", "subscription:<id>").action(async (ref, options, command) => {
6137
+ const by = await whoRuns(command, env, { asOwner: options.asOwner, question: `change ${ref} as yours?` });
6138
+ await run(options.json, async (store) => itemAnswer(await store.subscriptions.update(ref, { by, ...fieldsOf3(options), ...given({ name: options.title }) })));
6139
+ });
6140
+ json(byOption(annotate(subscriptions.command("cancel"), { effects: LOCAL_WRITE, output: { entity: "subscription" } }).option("--occurred-time <time>", "the day it was cancelled, such as 2026-11-01; today when left out"))).description("mark a subscription cancelled on a day; it stays, with its prices").summary("cancel a subscription").argument("<subscription>", "subscription:<id>").action(async (ref, options, command) => {
6141
+ const by = await whoRuns(command, env, { asOwner: options.asOwner, question: `cancel ${ref} as yours?` });
6142
+ await run(options.json, async (store) => itemAnswer(await store.subscriptions.update(ref, {
6143
+ by,
6144
+ status: "cancelled",
6145
+ cancelledDate: dayOf(options.occurredTime) ?? today()
6146
+ })));
6147
+ });
6148
+ const prices = subscriptions.command("prices").description("the prices a subscription had, each from a day on; one is never changed, a new one is added").summary("a subscription's prices");
6149
+ json(byOption(annotate(prices.command("add"), { effects: LOCAL_WRITE, output: { entity: "subscription_price" } }).option("--start-date <date>", "the first day the price holds, YYYY-MM-DD; the subscription's start when left out").option("--reason <text>", "why an agent proposes it, for the owner who decides"))).description(`add a price from a day on; the earlier ones stay as they were. ${PROPOSES}, and the subscription stays as it is`).summary("add a subscription's new price").argument("<subscription>", "subscription:<id>").argument("<amount>", "the price for one period, a decimal such as 1190.00").argument("<currency>", "ISO 4217, such as RUB").action(async (ref, amount2, currency, options, command) => {
6150
+ const by = await whoRuns(command, env, {
6151
+ asOwner: options.asOwner,
6152
+ question: `add a price to ${ref} as yours?`
6153
+ });
6154
+ await run(options.json, async (store) => itemAnswer(await store.subscriptions.addPrice(ref, {
6155
+ by,
6156
+ amount: amount2,
6157
+ currency,
6158
+ ...given({
6159
+ effectiveFrom: dayOf(options.startDate),
6160
+ reason: by === "owner" ? void 0 : options.reason
6161
+ })
6162
+ })));
6163
+ });
6164
+ }, "subscriptionCommands");
6165
+
6166
+ // dist/finance/transactions-command.js
6167
+ var TRANSACTION_QUERY = {
6168
+ entity: "transaction",
6169
+ backend: "native",
6170
+ fields: [
6171
+ termField("wallet", "ref", 'wallet:"wallet:2"'),
6172
+ termField("direction", "enum", "direction:out", { values: MONEY_DIRECTIONS }),
6173
+ termField("status", "enum", "status:pending", { values: TRANSACTION_STATUSES }),
6174
+ termField("category", "kw", "category:Rent"),
6175
+ termField("project", "kw", "project:PMED"),
6176
+ termField("review", "enum", "review:proposed", { values: FINANCE_REVIEWS }),
6177
+ termField("uncategorized", "bool", "uncategorized:true")
6178
+ ]
6179
+ };
6180
+ var listTransactions = /* @__PURE__ */ __name(async (store, words, limit) => {
6181
+ const terms2 = queryTerms(words, TRANSACTION_QUERY, "transactions list");
6182
+ const project = terms2.get("project");
6183
+ const filter = given({
6184
+ wallet: terms2.get("wallet"),
6185
+ direction: terms2.get("direction"),
6186
+ status: terms2.get("status"),
6187
+ category: terms2.get("category"),
6188
+ review: terms2.get("review"),
6189
+ uncategorized: terms2.has("uncategorized") ? terms2.get("uncategorized") === "true" : void 0,
6190
+ project: project === void 0 ? void 0 : await canonicalProject(store, project)
6191
+ });
6192
+ return pageOf("transactions list", limit, (most) => store.transactions.list({ ...filter, limit: most }));
6193
+ }, "listTransactions");
6194
+ var STATUS_HELP = `${TRANSACTION_STATUSES.join(" or ")}; only a booked one counts in a balance`;
6195
+ var transactionCommands = /* @__PURE__ */ __name((program, streams, env) => {
6196
+ const { run } = answers(program, streams, env);
6197
+ const transactions = program.command("transactions").description("money a wallet's statement shows moving in or out, the payment it settles, and the categories it is split into").summary("money moving in or out of your wallets");
6198
+ withQuery(json(annotate(transactions.command("list"), { effects: LOCAL_READ })).description("transactions, newest first; uncategorized:true lists those not fully split into categories"), TRANSACTION_QUERY).summary("transactions, newest first").option("--limit <n>", "most transactions, up to 500", positive, 100).action((words, { json: json5, limit }) => run(json5, (store) => listTransactions(store, words, limit)));
6199
+ json(annotate(transactions.command("show"), { effects: LOCAL_READ, output: { entity: "transaction" } })).description("one transaction with its wallet, payment, splits and what is not categorized").argument("<transaction>", "transaction:<id>").action((ref, options, command) => run(options.json, async (store) => itemAnswer(await withSources(command, store, await store.transactions.get(ref)))));
6200
+ json(writeMeta(annotate(transactions.command("add"), {
6201
+ effects: LOCAL_WRITE,
6202
+ output: { entity: "transaction" },
6203
+ literal_after_dashes: true
6204
+ }).option("--kind <kind>", "in (money came in) or out (money went out)").option("--occurred-time <time>", "the day the statement shows, such as 2026-11-01; today when left out").option("--description <text>", "what the statement says, as it says it").option("--status <state>", `${STATUS_HELP}; booked when left out`).option("--payment <payment>", "the payment it settles, same amount, currency and direction: payment:<id>"))).description(`record what a wallet's statement shows moved, in the wallet's currency; ${PROPOSES}`).summary("record a transaction; an agent's waits for your review").argument("<wallet>", "wallet:<id>").argument("<amount>", "a decimal above 0, such as 500.00").action(async (wallet, amount2, options, command) => {
6205
+ const by = await whoRuns(command, env, {
6206
+ asOwner: options.asOwner,
6207
+ question: "record this transaction as yours?"
6208
+ });
6209
+ await run(options.json, async (store) => itemAnswer(await store.transactions.add({
6210
+ ...await writtenBy(store, by, options),
6211
+ wallet,
6212
+ amount: amount2,
6213
+ direction: choice(options.kind, MONEY_DIRECTIONS, "--kind"),
6214
+ statementDate: dayOf(options.occurredTime) ?? today(),
6215
+ ...given({
6216
+ status: optionalChoice(options.status, TRANSACTION_STATUSES, "--status"),
6217
+ description: options.description,
6218
+ payment: options.payment
6219
+ })
6220
+ })));
6221
+ });
6222
+ json(byOption(annotate(transactions.command("update"), { effects: LOCAL_WRITE, output: { entity: "transaction" } }).option("--status <state>", STATUS_HELP).option("--payment <payment>", "the payment it settles, same amount, currency and direction: payment:<id>").option("--description <text>", "what the statement says, as it says it"))).description("book a pending transaction, link it to the payment it settles, or fix its text; you change any, an agent only one it proposed that is still proposed").summary("book a transaction or link it to its payment").argument("<transaction>", "transaction:<id>").action(async (ref, options, command) => {
6223
+ const by = await whoRuns(command, env, { asOwner: options.asOwner, question: `change ${ref} as yours?` });
6224
+ await run(options.json, async (store) => itemAnswer(await store.transactions.update(ref, {
6225
+ by,
6226
+ ...given({
6227
+ status: optionalChoice(options.status, TRANSACTION_STATUSES, "--status"),
6228
+ payment: options.payment,
6229
+ description: options.description
6230
+ })
6231
+ })));
6232
+ });
6233
+ const splits = transactions.command("splits").description("the categories a transaction's amount is split into; together never more than the amount, the rest is uncategorized").summary("a transaction's categories");
6234
+ const WHO2 = "you split any transaction; an agent only one it proposed that is still proposed";
6235
+ json(byOption(annotate(splits.command("add"), { effects: LOCAL_WRITE, output: { entity: "transaction" } }).option("--project <project>", "the project this part belongs to: its key or project:<id>"))).description(`put part of a transaction's amount under a category; ${WHO2}`).summary("put part of a transaction under a category").argument("<transaction>", "transaction:<id>").argument("<amount>", "a decimal above 0, such as 120.00").argument("<category...>", "the category, in a word or a few, such as Rent").action(async (ref, amount2, words, options, command) => {
6236
+ const by = await whoRuns(command, env, { asOwner: options.asOwner, question: `split ${ref} as yours?` });
6237
+ await run(options.json, async (store) => itemAnswer(await store.transactions.addSplit(ref, {
6238
+ by,
6239
+ amount: amount2,
6240
+ category: words.join(" "),
6241
+ ...options.project === void 0 ? {} : { project: await canonicalProject(store, options.project) }
6242
+ })));
6243
+ });
6244
+ json(byOption(annotate(splits.command("remove"), { effects: LOCAL_WRITE, output: { entity: "transaction" } }))).description(`take a split off a transaction; its amount is uncategorized again. ${WHO2}`).summary("take a split off a transaction").argument("<transaction>", "transaction:<id>").argument("<position>", "the split's position, from 1, as transactions show lists it", positive).action(async (ref, position, options, command) => {
6245
+ const by = await whoRuns(command, env, { asOwner: options.asOwner, question: `change ${ref}'s splits as yours?` });
6246
+ await run(options.json, async (store) => itemAnswer(await store.transactions.removeSplit(ref, { position, by })));
6247
+ });
6248
+ }, "transactionCommands");
6249
+
6250
+ // dist/finance/wallets-command.js
6251
+ var WALLET_QUERY = {
6252
+ entity: "wallet",
6253
+ backend: "native",
6254
+ fields: [
6255
+ termField("kind", "enum", "kind:card", { values: WALLET_KINDS }),
6256
+ termField("currency", "kw", "currency:RUB")
6257
+ ]
6258
+ };
6259
+ var listWallets = /* @__PURE__ */ __name(async (store, words, limit) => {
6260
+ const terms2 = queryTerms(words, WALLET_QUERY, "wallets list");
6261
+ const filter = given({
6262
+ kind: terms2.get("kind"),
6263
+ currency: terms2.get("currency")
6264
+ });
6265
+ return pageOf("wallets list", limit, (most) => store.wallets.list({ ...filter, limit: most }));
6266
+ }, "listWallets");
6267
+ var sourceSays = /* @__PURE__ */ __name(async (store, wallet) => {
6268
+ if (wallet.openingBalance !== null)
6269
+ return null;
6270
+ for (const { provider, account: account2 } of await sourceAccounts(store, wallet)) {
6271
+ const [record2] = await store.records.list({ provider, account: account2, entity: wallet.ref, limit: 1 });
6272
+ const { opening_balance: balance, opening_date: date } = record2?.fields ?? {};
6273
+ if (record2 && typeof balance === "string")
6274
+ return {
6275
+ openingBalance: balance,
6276
+ openingDate: typeof date === "string" ? date : null,
6277
+ record: `${record2.type}:${record2.externalId}`,
6278
+ account: `${provider}:${account2}`
6279
+ };
6280
+ }
6281
+ return null;
6282
+ }, "sourceSays");
6283
+ var walletCommands = /* @__PURE__ */ __name((program, streams, env) => {
6284
+ const { run } = answers(program, streams, env);
6285
+ const wallets = program.command("wallets").description("bank accounts, cards and cash you keep money in, one currency each; a balance is the opening balance plus confirmed, booked transactions, computed each time").summary("bank accounts, cards and cash, with their balances");
6286
+ withQuery(json(annotate(wallets.command("list"), { effects: LOCAL_READ })).description("wallets with their balances today; kind:card lists the cards"), WALLET_QUERY).option("--limit <n>", "most wallets, up to 500", positive, 100).action((words, { json: json5, limit }) => run(json5, (store) => listWallets(store, words, limit)));
6287
+ json(annotate(wallets.command("show"), { effects: LOCAL_READ, output: { entity: "wallet" } }).option("--until-time <time>", "the balance up to and including this day, such as 2026-10-31; today when left out")).description("one wallet with its balance, and beside it what is pending or proposed and not counted yet; for an imported wallet whose opening balance you have not set, source_says gives the one its source sent").summary("one wallet with its balance and what is pending").argument("<wallet>", "wallet:<id>").action((ref, options, command) => run(options.json, async (store) => {
6288
+ const until = dayOf(options.untilTime);
6289
+ const wallet = await store.wallets.get(ref, until === void 0 ? {} : { until });
6290
+ return itemAnswer(await withSources(command, store, { ...wallet, sourceSays: await sourceSays(store, wallet) }));
6291
+ }));
6292
+ json(annotate(wallets.command("add"), { effects: LOCAL_WRITE, output: { entity: "wallet" }, literal_after_dashes: true }).option("--kind <kind>", `${WALLET_KINDS.join(", ")}; bank when left out`).option("--institution <text>", "the bank or other company that holds it, by name")).description("add a wallet in one currency; anyone adds one directly, and only you set its opening balance, with wallets update").summary("add a bank account, card or cash wallet").argument("<name>", "what you call it, such as 'Main card'").argument("<currency>", "ISO 4217, such as RUB; a bank account in two currencies is two wallets").action((name2, currency, options) => run(options.json, async (store) => itemAnswer(await store.wallets.add({
6293
+ by: authorOf(env),
6294
+ name: name2,
6295
+ currency,
6296
+ ...given({
6297
+ kind: optionalChoice(options.kind, WALLET_KINDS, "--kind"),
6298
+ institution: options.institution
6299
+ })
6300
+ }))));
6301
+ json(byOption(annotate(wallets.command("update"), { effects: LOCAL_WRITE, output: { entity: "wallet" } }).option("--title <title>", "its new name").option("--institution <text>", "the bank or other company that holds it, by name").option("--opening-balance <decimal>", "what it held on --opening-date, such as 1500.50; only you set it").option("--opening-date <date>", "the day of the opening balance, YYYY-MM-DD"))).description("rename a wallet, or set the opening balance its balance counts from; the opening balance is yours alone, an agent is refused").summary("rename a wallet or set its opening balance").argument("<wallet>", "wallet:<id>").action(async (ref, options, command) => {
6302
+ const by = await whoRuns(command, env, { asOwner: options.asOwner, question: `change ${ref} as yours?` });
6303
+ await run(options.json, async (store) => itemAnswer(await store.wallets.update(ref, {
6304
+ by,
6305
+ ...given({
6306
+ name: options.title,
6307
+ institution: options.institution,
6308
+ openingBalance: options.openingBalance,
6309
+ openingDate: dayOf(options.openingDate)
6310
+ })
6311
+ })));
6312
+ });
6313
+ }, "walletCommands");
6314
+
5325
6315
  // dist/findings-input.js
5326
6316
  import { createReadStream, statSync as statSync2 } from "node:fs";
5327
6317
  var FINDINGS_INPUT_HELP = "the findings JSON itself (starts with {), a JSON file, or - for stdin; at most 65536 UTF-8 bytes";
@@ -5351,53 +6341,53 @@ var findingsCommand = /* @__PURE__ */ __name((program, streams, env) => {
5351
6341
  const group = program.command("meetings").description("stored meeting evidence and reviewed findings").command("actions").description("cited meeting facts and project tasks waiting for owner review");
5352
6342
  const { run } = answers(program, streams, env);
5353
6343
  const warn = /* @__PURE__ */ __name((text3) => streams.diagnostic(text3), "warn");
5354
- const scope = /* @__PURE__ */ __name((store, given) => theAccount(store, env, given, warn), "scope");
5355
- const acting = /* @__PURE__ */ __name((store, given) => writeAccount(store, env, given, warn), "acting");
6344
+ const scope = /* @__PURE__ */ __name((store, given2) => theAccount(store, env, given2, warn), "scope");
6345
+ const acting = /* @__PURE__ */ __name((store, given2) => writeAccount(store, env, given2, warn), "acting");
5356
6346
  const options = /* @__PURE__ */ __name((command) => sourceOptions(command, MEETING_ACCOUNT_HELP).option("--json", "print JSON; --json=id,status keeps only those fields"), "options");
5357
6347
  const writes = /* @__PURE__ */ __name((command) => writeOptions(command, MEETING_WRITE_HELP).option("--json", "print JSON; --json=id,status keeps only those fields"), "writes");
5358
- writes(annotate(group.command("add"), { effects: LOCAL_WRITE, output: { entity: "meeting_findings" } })).description("stage cited findings; facts and tasks wait for owner confirmation").argument("<file>", FINDINGS_INPUT_HELP).addHelpText("after", "\nInput: schema_version 1, key, extractor, findings. Every finding names id, kind, project and evidence (reference and fingerprint). Facts name type and statement; tasks name type, title, reason and commitment (explicit or inferred). At most 16 findings, each with 1\u20138 exact cues from Zoom evidence. Optional due_at is a real ISO timestamp with timezone and requires due_evidence; optional assignee is a person reference and requires assignee_evidence. Both support lists cite this finding's cue references.\n").action(async (file, given) => {
6348
+ writes(annotate(group.command("add"), { effects: LOCAL_WRITE, output: { entity: "meeting_findings" } })).description("stage cited findings; facts and tasks wait for owner confirmation").argument("<file>", FINDINGS_INPUT_HELP).addHelpText("after", "\nInput: schema_version 1, key, extractor, findings. Every finding names id, kind, project and evidence (reference and fingerprint). Facts name type and statement; tasks name type, title, reason and commitment (explicit or inferred). At most 16 findings, each with 1\u20138 exact cues from Zoom evidence. Optional due_at is a real ISO timestamp with timezone and requires due_evidence; optional assignee is a person reference and requires assignee_evidence. Both support lists cite this finding's cue references.\n").action(async (file, given2) => {
5359
6349
  const text3 = await readFindingsInput(file, environmentOf(program).stdin ?? process.stdin);
5360
6350
  const input = parseMeetingFindingsJson(text3);
5361
6351
  const author = await whoRuns(program, env, { question: "" });
5362
6352
  const agent = author === "owner" ? { bot: "memo-findings" } : author;
5363
- await run(given.json, async (store) => itemAnswer(await store.meetingFindings.stage(await acting(store, given), input, agent)));
6353
+ await run(given2.json, async (store) => itemAnswer(await store.meetingFindings.stage(await acting(store, given2), input, agent)));
5364
6354
  });
5365
- options(annotate(group.command("show"), { effects: LOCAL_READ, output: { entity: "meeting_findings" } })).description("one findings preview, prior decisions and its review receipt").argument("<id>", "stored findings batch ID").action((id, given) => run(given.json, async (store) => itemAnswer(await store.meetingFindings.get(await scope(store, given), id))));
5366
- withQuery(options(annotate(group.command("list"), { effects: LOCAL_READ, output: { entity: "meeting_findings" } })), FINDINGS_QUERY).description("findings batches in one meeting account, newest first").option("--limit <n>", "batches per page, at most 50", positive, 20).option("--page <n>", "which page, from 1", positive, 1).action((words, given) => run(given.json, async (store) => {
6355
+ options(annotate(group.command("show"), { effects: LOCAL_READ, output: { entity: "meeting_findings" } })).description("one findings preview, prior decisions and its review receipt").argument("<id>", "stored findings batch ID").action((id, given2) => run(given2.json, async (store) => itemAnswer(await store.meetingFindings.get(await scope(store, given2), id))));
6356
+ withQuery(options(annotate(group.command("list"), { effects: LOCAL_READ, output: { entity: "meeting_findings" } })), FINDINGS_QUERY).description("findings batches in one meeting account, newest first").option("--limit <n>", "batches per page, at most 50", positive, 20).option("--page <n>", "which page, from 1", positive, 1).action((words, given2) => run(given2.json, async (store) => {
5367
6357
  const status = queryTerms(words, FINDINGS_QUERY, "meetings actions list").get("status");
5368
- const key = await scope(store, given);
6358
+ const key = await scope(store, given2);
5369
6359
  const found = await store.meetingFindings.list(key, {
5370
- limit: given.limit,
5371
- offset: (given.page - 1) * given.limit,
6360
+ limit: given2.limit,
6361
+ offset: (given2.page - 1) * given2.limit,
5372
6362
  ...status === void 0 ? {} : { status }
5373
6363
  });
5374
6364
  return listAnswer("meetings actions list", {
5375
6365
  items: found.items,
5376
- limit: given.limit,
5377
- page: given.page,
6366
+ limit: given2.limit,
6367
+ page: given2.page,
5378
6368
  has_more: found.hasMore,
5379
- args: { query: words.join(" "), source: accountName(key), limit: given.limit }
6369
+ args: { query: words.join(" "), source: accountName(key), limit: given2.limit }
5380
6370
  });
5381
6371
  }));
5382
6372
  for (const name2 of ["confirm", "reject"]) {
5383
6373
  const command = writes(annotate(group.command(name2), { effects: LOCAL_WRITE, output: { entity: "meeting_findings" } })).description(name2 === "confirm" ? "owner only: create selected findings and reject the other new candidates" : "owner only: reject every new candidate in this batch").argument("<id>", "stored findings batch ID").requiredOption("--fingerprint <hash>", "the exact fingerprint shown in the preview");
5384
6374
  byOption(command);
5385
- const review = /* @__PURE__ */ __name(async (id, given, accept) => {
6375
+ const review = /* @__PURE__ */ __name(async (id, given2, accept) => {
5386
6376
  const key = `meetings.actions.${name2}`;
5387
- const who = await whoRuns(command, env, { asOwner: given.asOwner, question: `${name2} batch ${id} as you?` });
6377
+ const who = await whoRuns(command, env, { asOwner: given2.asOwner, question: `${name2} batch ${id} as you?` });
5388
6378
  const by = who === "owner" ? who : mcpOwnerAllowed(env, key) ? { bot: who.bot, reason: `the owner allows ${key}` } : void 0;
5389
6379
  if (by === void 0)
5390
6380
  throw new CliError("validation_error", "findings confirmation and rejection belong to the owner; agents must leave proposals for review");
5391
- return run(given.json, async (store) => itemAnswer(await store.meetingFindings.review(await acting(store, given), id, {
5392
- fingerprint: given.fingerprint,
6381
+ return run(given2.json, async (store) => itemAnswer(await store.meetingFindings.review(await acting(store, given2), id, {
6382
+ fingerprint: given2.fingerprint,
5393
6383
  accept,
5394
6384
  by
5395
6385
  })));
5396
6386
  }, "review");
5397
6387
  if (name2 === "confirm")
5398
- command.argument("<ids...>", "candidate IDs to accept; other new candidates are rejected").action((id, ids, given) => review(id, given, ids));
6388
+ command.argument("<ids...>", "candidate IDs to accept; other new candidates are rejected").action((id, ids, given2) => review(id, given2, ids));
5399
6389
  else
5400
- command.action((id, given) => review(id, given, []));
6390
+ command.action((id, given2) => review(id, given2, []));
5401
6391
  }
5402
6392
  }, "findingsCommand");
5403
6393
 
@@ -5478,18 +6468,18 @@ var meetingProjectsCommand = /* @__PURE__ */ __name((projects, streams, env) =>
5478
6468
  const key = await (writes ? writeAccount : theAccount)(store, env, options2, warn);
5479
6469
  return work(store, (await canonicalProject(store, project)).slice(8), key);
5480
6470
  }), "execute");
5481
- withQuery(options(annotate(group.command("list"), { effects: LOCAL_READ, output: { entity: "meeting_project" } }).description("meetings linked to a project in one account, or with confirmed:false proposed").argument("<project>", "project reference, key or explicit alias")), MEETING_PROJECTS_QUERY).option("--limit <n>", "meetings per page, at most 500", positive, 50).option("--page <n>", "which page, from 1", positive).action((project, words, given) => execute(project, given, async (store, projectId, key) => {
6471
+ withQuery(options(annotate(group.command("list"), { effects: LOCAL_READ, output: { entity: "meeting_project" } }).description("meetings linked to a project in one account, or with confirmed:false proposed").argument("<project>", "project reference, key or explicit alias")), MEETING_PROJECTS_QUERY).option("--limit <n>", "meetings per page, at most 500", positive, 50).option("--page <n>", "which page, from 1", positive).action((project, words, given2) => execute(project, given2, async (store, projectId, key) => {
5482
6472
  const confirmed = queryTerms(words, MEETING_PROJECTS_QUERY, "projects meetings list").get("confirmed");
5483
- const page = given.page ?? 1;
6473
+ const page = given2.page ?? 1;
5484
6474
  const found = await store.knowledge.meetingProjects(key, {
5485
6475
  projectId,
5486
6476
  confirmed: confirmed === "true",
5487
- limit: given.limit,
5488
- offset: (page - 1) * given.limit
6477
+ limit: given2.limit,
6478
+ offset: (page - 1) * given2.limit
5489
6479
  });
5490
6480
  return listAnswer("projects meetings list", {
5491
6481
  items: found.items,
5492
- limit: given.limit,
6482
+ limit: given2.limit,
5493
6483
  has_more: found.hasMore,
5494
6484
  page,
5495
6485
  args: {
@@ -5499,10 +6489,10 @@ var meetingProjectsCommand = /* @__PURE__ */ __name((projects, streams, env) =>
5499
6489
  }
5500
6490
  });
5501
6491
  }));
5502
- writeOptions(annotate(group.command("link"), { effects: LOCAL_WRITE }).description("link a stored meeting to a project, or confirm a proposed link").argument("<project>", "project reference, key or explicit alias").argument("<meeting-id>", "positive stored meeting id"), MEETING_WRITE_HELP).option("--json", "print JSON; --json=id,title keeps only those fields").option("--fingerprint <hash>", "required when confirming an existing proposal").option("--reason <text>", "why the reviewed meeting belongs to this project").action((project, meeting, given) => execute(project, given, async (store, projectId, key) => itemAnswer(await store.knowledge.linkMeetingProject(key, meeting, projectId, {
6492
+ writeOptions(annotate(group.command("link"), { effects: LOCAL_WRITE }).description("link a stored meeting to a project, or confirm a proposed link").argument("<project>", "project reference, key or explicit alias").argument("<meeting-id>", "positive stored meeting id"), MEETING_WRITE_HELP).option("--json", "print JSON; --json=id,title keeps only those fields").option("--fingerprint <hash>", "required when confirming an existing proposal").option("--reason <text>", "why the reviewed meeting belongs to this project").action((project, meeting, given2) => execute(project, given2, async (store, projectId, key) => itemAnswer(await store.knowledge.linkMeetingProject(key, meeting, projectId, {
5503
6493
  by: "owner",
5504
- ...given.fingerprint === void 0 ? {} : { expectedFingerprint: given.fingerprint },
5505
- ...given.reason === void 0 ? {} : { provenance: given.reason }
6494
+ ...given2.fingerprint === void 0 ? {} : { expectedFingerprint: given2.fingerprint },
6495
+ ...given2.reason === void 0 ? {} : { provenance: given2.reason }
5506
6496
  })), true));
5507
6497
  }, "meetingProjectsCommand");
5508
6498
 
@@ -5590,18 +6580,18 @@ var ACTIONS_QUERY = {
5590
6580
  fields: [termField("status", "enum", "status:proposed", { values: ["proposed", "reviewed"] })],
5591
6581
  defaults: ["status:proposed"]
5592
6582
  };
5593
- var json4 = /* @__PURE__ */ __name((command) => command.option("--json", "print JSON; --json=id,status keeps only those fields"), "json");
6583
+ var json2 = /* @__PURE__ */ __name((command) => command.option("--json", "print JSON; --json=id,status keeps only those fields"), "json");
5594
6584
  var projectActionsCommand = /* @__PURE__ */ __name((projects, streams, env) => {
5595
6585
  const group = projects.command("actions").description("cited key documents and findings an agent proposed for a project, with the evidence to decide them").summary("an agent's proposals for a project, and deciding them");
5596
6586
  const { run } = answers(projects, streams, env);
5597
- json4(annotate(group.command("add"), { effects: LOCAL_WRITE })).description("stage an agent's cited facts and follow-ups about one project for review").argument("<file>", FINDINGS_INPUT_HELP).addHelpText("after", "\nInput: schema_version 1, key, extractor, findings. Every finding names id, kind and evidence: 1\u20138 msg:, document: or note: references with the fingerprint projects evidence or notes show gives. A fact may name a project and a subject (person:, organization:, task: or project:), or neither; a task names its project. Facts name type and statement; tasks name type, title, reason and commitment (explicit or inferred). A due_at or assignee needs due_evidence or assignee_evidence citing this finding's references. A payment names payment {amount, currency, direction to_us|from_us, state paid|expected|cancelled, counterparty, paid_at}: an expected one becomes an invoice and needs a person: or organization: counterparty; a paid or cancelled one names in supersedes the invoice: it settles or voids. At most one project per batch. The same key and input returns the same batch; actions confirm and reject decide it by its id.\n").action(async (file, given, command) => {
6587
+ json2(annotate(group.command("add"), { effects: LOCAL_WRITE })).description("stage an agent's cited facts and follow-ups about one project for review").argument("<file>", FINDINGS_INPUT_HELP).addHelpText("after", "\nInput: schema_version 1, key, extractor, findings. Every finding names id, kind and evidence: 1\u20138 msg:, document: or note: references with the fingerprint projects evidence or notes show gives. A fact may name a project and a subject (person:, organization:, task: or project:), or neither; a task names its project. Facts name type and statement; tasks name type, title, reason and commitment (explicit or inferred). A due_at or assignee needs due_evidence or assignee_evidence citing this finding's references. A payment names payment {amount, currency, direction to_us|from_us, state paid|expected|cancelled, counterparty, paid_at}: an expected one becomes an invoice and needs a person: or organization: counterparty; a paid or cancelled one names in supersedes the invoice: it settles or voids. At most one project per batch. The same key and input returns the same batch; actions confirm and reject decide it by its id.\n").action(async (file, given2, command) => {
5598
6588
  const input = parseEvidenceFindingsJson(await readFindingsInput(file, environmentOf(projects).stdin ?? process.stdin));
5599
6589
  const author = await whoRuns(command, env, { question: "" });
5600
6590
  if (author === "owner")
5601
6591
  throw new CliError("validation_error", "findings are an agent's proposals; record your own with memo facts add");
5602
- await run(given.json, async (store) => itemAnswer(await store.evidenceFindings.stage(input, author)));
6592
+ await run(given2.json, async (store) => itemAnswer(await store.evidenceFindings.stage(input, author)));
5603
6593
  });
5604
- withQuery(json4(answerEntity(annotate(group.command("list"), { effects: LOCAL_READ }), "project_action", union([
6594
+ withQuery(json2(answerEntity(annotate(group.command("list"), { effects: LOCAL_READ }), "project_action", union([
5605
6595
  strictObject({
5606
6596
  kind: literal("key_document"),
5607
6597
  id: string(),
@@ -5622,39 +6612,39 @@ var projectActionsCommand = /* @__PURE__ */ __name((projects, streams, env) => {
5622
6612
  decision: unknown(),
5623
6613
  findings: array(unknown())
5624
6614
  })
5625
- ]))).argument("<project>", "the project's id, project:<id>, key, exact name or alias"), ACTIONS_QUERY).summary("a project's proposals with the evidence to decide them").description("a project's proposed key documents and findings, newest first, with source state, cited text and nearby messages or document paragraphs; key-document text is untracked because no fingerprint was saved").option("--limit <n>", "findings batches per page, at most 50", positive, 10).option("--page <n>", "which page, from 1; key documents come on the first", positive, 1).option("--brief", "only references and source state, without excerpts or nearby text").option("--before-n <n>", "messages or document paragraphs before the citation, at most 5", whole, 2).option("--after-n <n>", "messages or document paragraphs after the citation, at most 5", whole, 2).action((reference2, words, given) => run(given.json, async (store) => {
6615
+ ]))).argument("<project>", "the project's id, project:<id>, key, exact name or alias"), ACTIONS_QUERY).summary("a project's proposals with the evidence to decide them").description("a project's proposed key documents and findings, newest first, with source state, cited text and nearby messages or document paragraphs; key-document text is untracked because no fingerprint was saved").option("--limit <n>", "findings batches per page, at most 50", positive, 10).option("--page <n>", "which page, from 1; key documents come on the first", positive, 1).option("--brief", "only references and source state, without excerpts or nearby text").option("--before-n <n>", "messages or document paragraphs before the citation, at most 5", whole, 2).option("--after-n <n>", "messages or document paragraphs after the citation, at most 5", whole, 2).action((reference2, words, given2) => run(given2.json, async (store) => {
5626
6616
  const status = queryTerms(words, ACTIONS_QUERY, "projects actions list").get("status");
5627
6617
  const project = await projectOf(store, reference2);
5628
6618
  const found = await projectActions(store, project, {
5629
6619
  status,
5630
- limit: given.limit,
5631
- page: given.page,
5632
- brief: given.brief === true,
5633
- before: Math.min(given.beforeN, 5),
5634
- after: Math.min(given.afterN, 5)
6620
+ limit: given2.limit,
6621
+ page: given2.page,
6622
+ brief: given2.brief === true,
6623
+ before: Math.min(given2.beforeN, 5),
6624
+ after: Math.min(given2.afterN, 5)
5635
6625
  });
5636
6626
  return listAnswer("projects actions list", {
5637
6627
  items: found.items,
5638
- limit: given.limit,
5639
- page: given.page,
6628
+ limit: given2.limit,
6629
+ page: given2.page,
5640
6630
  has_more: found.hasMore,
5641
6631
  args: { project: reference2, query: words.join(" ") }
5642
6632
  });
5643
6633
  }));
5644
6634
  for (const name2 of ["confirm", "reject"]) {
5645
- const command = byOption(json4(annotate(group.command(name2), { effects: LOCAL_WRITE })).description(name2 === "confirm" ? "confirm a suggested key document, or create the named findings of a batch and reject its other new ones; an agent decides for you only when agent_decisions is true, and with --reason" : "reject a suggested key document, or every new finding of a batch").summary(name2 === "confirm" ? "confirm a proposal, yours or an agent's with --reason" : "reject a proposal").argument("<project>", "the project's id, project:<id>, key, exact name or alias").argument("<id>", "key:<id> for a key document, or a findings batch number, as projects actions list gives them"));
6635
+ const command = byOption(json2(annotate(group.command(name2), { effects: LOCAL_WRITE })).description(name2 === "confirm" ? "confirm a suggested key document, or create the named findings of a batch and reject its other new ones; an agent decides for you only when agent_decisions is true, and with --reason" : "reject a suggested key document, or every new finding of a batch").summary(name2 === "confirm" ? "confirm a proposal, yours or an agent's with --reason" : "reject a proposal").argument("<project>", "the project's id, project:<id>, key, exact name or alias").argument("<id>", "key:<id> for a key document, or a findings batch number, as projects actions list gives them"));
5646
6636
  if (name2 === "confirm")
5647
6637
  command.argument("[findings...]", "the finding IDs of a batch to create");
5648
6638
  command.option("--fingerprint <hash>", "a findings batch's fingerprint, as projects actions list gives it").option("--reason <text>", "why, in a few words; required when an agent decides for you").action(async (reference2, id, ...rest) => {
5649
6639
  const accept = name2 === "confirm" ? rest[0] : [];
5650
- const given = name2 === "confirm" ? rest[1] : rest[0];
5651
- const by = await deciderOf(command, env, { ...given, question: `${name2} ${id} as you, the owner?` });
5652
- await run(given.json, async (store) => {
6640
+ const given2 = name2 === "confirm" ? rest[1] : rest[0];
6641
+ const by = await deciderOf(command, env, { ...given2, question: `${name2} ${id} as you, the owner?` });
6642
+ await run(given2.json, async (store) => {
5653
6643
  const project = await projectOf(store, reference2);
5654
6644
  return itemAnswer(await decideAction(store, project, id, {
5655
6645
  confirm: name2 === "confirm",
5656
- ...given.fingerprint === void 0 ? {} : { fingerprint: given.fingerprint },
5657
- ...given.reason === void 0 ? {} : { reason: given.reason },
6646
+ ...given2.fingerprint === void 0 ? {} : { fingerprint: given2.fingerprint },
6647
+ ...given2.reason === void 0 ? {} : { reason: given2.reason },
5658
6648
  accept,
5659
6649
  by
5660
6650
  }));
@@ -5986,7 +6976,7 @@ var syncHint = /* @__PURE__ */ __name((chat, since, env, chosen = {}) => {
5986
6976
  }, "syncHint");
5987
6977
 
5988
6978
  // dist/knowledge/relationships-scan.js
5989
- var DAY3 = 864e5;
6979
+ var DAY4 = 864e5;
5990
6980
  var SCAN_STEP = {
5991
6981
  id: "relationships.scan",
5992
6982
  kind: "command",
@@ -6060,7 +7050,7 @@ var relationshipsScanCommand = /* @__PURE__ */ __name((relations, print, env, wa
6060
7050
  if (options.limit > 50)
6061
7051
  throw new CliError("validation_error", "--limit is at most 50", { param: "limit" });
6062
7052
  const window = projectWindowOf(options.sinceTime);
6063
- const since = new Date("days" in window ? Date.now() - window.days * DAY3 : window.after).toISOString();
7053
+ const since = new Date("days" in window ? Date.now() - window.days * DAY4 : window.after).toISOString();
6064
7054
  const written2 = options.yes === true;
6065
7055
  const { body, text: text3 } = await withStore(env, async (store) => {
6066
7056
  const sources = await namedAccounts(store, env, options, warn);
@@ -6108,14 +7098,14 @@ var projectGatherCommand = /* @__PURE__ */ __name((projects, print, env, warn) =
6108
7098
  });
6109
7099
  const since = new Date(found.window.after).toISOString().slice(0, 10);
6110
7100
  const syncs = found.linkedChats.map((one2) => one2.completeness === null || one2.completeness.state === "complete" ? null : chatSync(one2, since, env, chosen));
6111
- const parts = projectAnswerParts(options.sinceTime, found);
7101
+ const parts2 = projectAnswerParts(options.sinceTime, found);
6112
7102
  const blocked = [...new Set(syncs.flatMap((one2) => one2 && one2.command === null ? [one2.why] : []))];
6113
- const missing = [...parts.missing ?? [], ...blocked.map((why) => ({ field: "sync_command", why }))];
6114
- const next = [...parts.next ?? [], ...scan].slice(0, MAX_NEXT_STEPS);
7103
+ const missing = [...parts2.missing ?? [], ...blocked.map((why) => ({ field: "sync_command", why }))];
7104
+ const next = [...parts2.next ?? [], ...scan].slice(0, MAX_NEXT_STEPS);
6115
7105
  print(options.json, itemAnswer({
6116
7106
  ...found,
6117
7107
  linkedChats: found.linkedChats.map((one2, i) => ({ ...one2, syncCommand: syncs[i]?.command ?? null }))
6118
- }, { ...parts, ...missing.length ? { missing } : {}, ...next.length ? { next } : {} }), projectEvidenceText(found, {
7108
+ }, { ...parts2, ...missing.length ? { missing } : {}, ...next.length ? { next } : {} }), projectEvidenceText(found, {
6119
7109
  sync: /* @__PURE__ */ __name((chat, at) => syncHint(chat, at, env, chosen), "sync"),
6120
7110
  showDocument: "memo notes show"
6121
7111
  }));
@@ -6163,7 +7153,7 @@ var projectStatusCommand = /* @__PURE__ */ __name((projects, print, env) => answ
6163
7153
  param: "--compact"
6164
7154
  });
6165
7155
  const chosen = options.syncProfile ?? {};
6166
- const { found, finance, open } = await withStore(env, async (store) => {
7156
+ const { found, finance, open: open2 } = await withStore(env, async (store) => {
6167
7157
  const status = await projectStatus(store, {
6168
7158
  project,
6169
7159
  ...projectWindowOf(options.sinceTime),
@@ -6187,13 +7177,13 @@ var projectStatusCommand = /* @__PURE__ */ __name((projects, print, env) => answ
6187
7177
  print(options.json, itemOf({
6188
7178
  ...item,
6189
7179
  ...finance.length ? { finance } : {},
6190
- ...open.deals.length ? { deals: open.deals } : {},
6191
- ...open.more ? { deals_more: open.more } : {}
7180
+ ...open2.deals.length ? { deals: open2.deals } : {},
7181
+ ...open2.more ? { deals_more: open2.more } : {}
6192
7182
  }, {
6193
7183
  ...next.length ? { next: next.map(asAction) } : {},
6194
7184
  ...gaps.length ? { missing: gaps } : {},
6195
7185
  meta
6196
- }), [projectStatusText(found, hints), ...financeText(finance), ...dealsText(open)].join("\n"), options.compact === true);
7186
+ }), [projectStatusText(found, hints), ...financeText(finance), ...dealsText(open2)].join("\n"), options.compact === true);
6197
7187
  }), "projectStatusCommand");
6198
7188
 
6199
7189
  // dist/knowledge/project-transfer.js
@@ -6365,9 +7355,9 @@ var pending = /* @__PURE__ */ __name(async (store, about) => {
6365
7355
  };
6366
7356
  }, "pending");
6367
7357
  var listRelationships = /* @__PURE__ */ __name(async (store, words) => {
6368
- const terms = queryTerms(words, RELATIONSHIP_QUERY, "relationships list");
6369
- const about = terms.get("about");
6370
- const confirmed = terms.get("confirmed");
7358
+ const terms2 = queryTerms(words, RELATIONSHIP_QUERY, "relationships list");
7359
+ const about = terms2.get("about");
7360
+ const confirmed = terms2.get("confirmed");
6371
7361
  const found = confirmed === "false" ? await pending(store, about) : {
6372
7362
  hasMore: false,
6373
7363
  items: (await store.knowledge.relations(null, about)).filter((one2) => confirmed === void 0 || one2.confirmed).map((one2) => ({ ...one2, status: one2.confirmed ? "confirmed" : "proposed" }))
@@ -6473,7 +7463,7 @@ var knowledgeCommands = /* @__PURE__ */ __name((program, streams, env) => {
6473
7463
  return ownedList("projects key-documents list", options, async (store) => keyDocuments(store, await projectOf(store, project), id === void 0 ? {} : { id }));
6474
7464
  });
6475
7465
  const relations = program.command("relationships").description("relations between people, organizations and projects; never between identities");
6476
- byOption(annotate(relations.command("add"), { effects: LOCAL_WRITE }).description("state that a person, organization or project belongs to or relates to another, or that a chat is a project's (member-of only); an agent's waits for you to confirm it").summary("state that a person, organization, project or chat belongs or relates to another")).argument("<from>", "the person:, organization: or project: that belongs or relates, or chat:<provider>/<account>/<chat> of a project").argument("<to>", "the person:, organization: or project: it belongs or relates to").option("--json", "print JSON; --json=id,title keeps only those fields").option("--kind <kind>", "member-of or related-to", "member-of").option("--role <role>", "the role it has there, in a few words, such as cto").option("--reason <text>", "why you think so, in a sentence").action(async (from, to, options, command) => {
7466
+ byOption(annotate(relations.command("add"), { effects: LOCAL_WRITE }).description("state that a person, organization or project belongs to or relates to another, or that a chat is a project's (member-of only); an agent's waits for you to confirm it").summary("state that a person, organization, project or chat belongs or relates to another")).argument("<from>", "the person:, organization: or project: that belongs or relates, or chat:<provider>/<account>/<chat> of a project").argument("<to>", "the person:, organization: or project: it belongs or relates to").option("--json", "print JSON; --json=id,title keeps only those fields").option("--kind <kind>", "member-of or related-to", "member-of").option("--role <role>", "the role it has there; a person's role in an organization or a project is one from its list, such as employee or contributor").option("--reason <text>", "why you think so, in a sentence").action(async (from, to, options, command) => {
6477
7467
  const by = await whoRuns(command, env, { asOwner: options.asOwner, question: "state it as yours?" });
6478
7468
  return owned(options, async (store) => {
6479
7469
  const input = {
@@ -6490,7 +7480,7 @@ var knowledgeCommands = /* @__PURE__ */ __name((program, streams, env) => {
6490
7480
  const found = await withStore(env, (store) => listRelationships(store, words));
6491
7481
  print(options.json, listAnswer("relationships list", { items: found.items, limit: found.limit, has_more: found.hasMore }), relationshipsText(found.items));
6492
7482
  });
6493
- byOption(annotate(relations.command("update"), { effects: LOCAL_WRITE }).description("set what a relationship is: its role, or what a chat is for in a project (work, sales, support, other); an agent's change waits for you in memo review").summary("set a relationship's role or a chat's purpose in a project").argument("<id>", "the relationship's id, as relationships list gives it").option("--role <role>", "the role it has there, in a few words; an empty value clears it").option("--purpose <purpose>", "what the chat is for in the project: work, sales, support or other").option("--reason <text>", "why, in a sentence").option("--json", "print JSON; --json=id,title keeps only those fields")).action(async (id, options, command) => {
7483
+ byOption(annotate(relations.command("update"), { effects: LOCAL_WRITE }).description("set what a relationship is: its role, or what a chat is for in a project (work, sales, support, other); an agent's change waits for you in memo review").summary("set a relationship's role or a chat's purpose in a project").argument("<id>", "the relationship's id, as relationships list gives it").option("--role <role>", "the role it has there, from the same list as relationships add; an empty value clears it").option("--purpose <purpose>", "what the chat is for in the project: work, sales, support or other").option("--reason <text>", "why, in a sentence").option("--json", "print JSON; --json=id,title keeps only those fields")).action(async (id, options, command) => {
6494
7484
  const change = {
6495
7485
  ...options.role === void 0 ? {} : { role: options.role === "" ? null : options.role },
6496
7486
  ...options.purpose === void 0 ? {} : { purpose: options.purpose }
@@ -6582,7 +7572,7 @@ var party2 = /* @__PURE__ */ __name((reference2, name2) => [
6582
7572
  ...name2 && fold3(name2) ? [`name:${fold3(name2)}`] : []
6583
7573
  ], "party");
6584
7574
  var text = /* @__PURE__ */ __name((value) => typeof value === "string" && value.trim() ? value : void 0, "text");
6585
- var present = /* @__PURE__ */ __name((parts) => parts.filter((part) => part !== void 0), "present");
7575
+ var present = /* @__PURE__ */ __name((parts2) => parts2.filter((part) => part !== void 0), "present");
6586
7576
  var keysOf = /* @__PURE__ */ __name((finding) => {
6587
7577
  const raw = finding ?? {};
6588
7578
  const [shop, number2, url, id] = [raw.supplierName, raw.number, raw.sourceUrl, raw.externalId].map(text);
@@ -6714,7 +7704,7 @@ var oneMailboxOf = /* @__PURE__ */ __name(async (store, env, source) => {
6714
7704
  throw new CliError("validation_error", `${source} is not a mailbox \u2014 ${MAIL_SOURCES}`, { param: "source" });
6715
7705
  return key;
6716
7706
  }, "oneMailboxOf");
6717
- var named2 = /* @__PURE__ */ __name((commands2, name2) => {
7707
+ var named3 = /* @__PURE__ */ __name((commands2, name2) => {
6718
7708
  const found = commands2.find((command) => command.name() === name2);
6719
7709
  if (!found)
6720
7710
  throw new Error(`cli-core's mail commands have no ${name2}`);
@@ -6734,10 +7724,10 @@ var mailReviewCommands = /* @__PURE__ */ __name((mail, messages, env) => {
6734
7724
  }
6735
7725
  };
6736
7726
  const shared = mailReadCommands(reads);
6737
- const review = named2(shared, "review");
6738
- const sharedMessages = named2(shared, "messages").commands;
6739
- const acknowledge = named2(sharedMessages, "acknowledge");
6740
- const reset = named2(sharedMessages, "reset");
7727
+ const review = named3(shared, "review");
7728
+ const sharedMessages = named3(shared, "messages").commands;
7729
+ const acknowledge = named3(sharedMessages, "acknowledge");
7730
+ const reset = named3(sharedMessages, "reset");
6741
7731
  for (const command of [review, acknowledge, reset])
6742
7732
  overrideSharedContract(command, "memo holds several mailboxes and no profile, so --source names the one mailbox; its --json is per command.", (one2) => {
6743
7733
  one2.option("--source <accounts>", MAILBOX_HELP).option("--json", "print JSON; --json=id,title keeps only those fields");
@@ -6792,39 +7782,39 @@ var keyed = /* @__PURE__ */ __name((text3, key) => {
6792
7782
  }
6793
7783
  if (!raw || typeof raw !== "object" || Array.isArray(raw))
6794
7784
  return text3;
6795
- const named4 = raw.key;
6796
- if (named4 !== void 0 && named4 !== key)
6797
- throw new CliError("validation_error", `the batch's key ${String(named4)} is not --key ${key}; give the key once`, {
7785
+ const named5 = raw.key;
7786
+ if (named5 !== void 0 && named5 !== key)
7787
+ throw new CliError("validation_error", `the batch's key ${String(named5)} is not --key ${key}; give the key once`, {
6798
7788
  reason: "findings.key-mismatch",
6799
- key: String(named4),
7789
+ key: String(named5),
6800
7790
  given: key
6801
7791
  });
6802
7792
  return JSON.stringify({ ...raw, key });
6803
7793
  }, "keyed");
6804
- var json5 = /* @__PURE__ */ __name((command) => command.option("--json", "print JSON; --json=id,status keeps only those fields"), "json");
7794
+ var json3 = /* @__PURE__ */ __name((command) => command.option("--json", "print JSON; --json=id,status keeps only those fields"), "json");
6805
7795
  var mailFindingsCommand = /* @__PURE__ */ __name((program, mail, streams, env) => {
6806
7796
  const { run } = answers(program, streams, env);
6807
7797
  const findings = mail.command("findings").description("cited tasks, task updates, facts, memories, links, contacts, invoices, payments and orders an agent read in new mail").summary("what an agent read in new mail, cited, waiting for the owner");
6808
- json5(proposesOnly(annotate(findings.command("add"), { effects: LOCAL_WRITE, output: { entity: "mail_findings" } }))).description("stage one mailbox's findings for the owner; nothing is created until the owner confirms").summary("stage one mailbox's findings; the owner confirms them").argument("<file>", FINDINGS_INPUT_HELP).option("--source <accounts>", MAILBOX_HELP).option("--key <key>", "the findings key `mail review --holder` gave in its mail-findings.add step").option("--dry-run", "check the batch as staging would, invoices, payments and orders tried and rolled back, and stage nothing; answers valid and every finding's problem at once").addHelpText("after", INPUT_HELP).action(async (file, given) => {
7798
+ json3(proposesOnly(annotate(findings.command("add"), { effects: LOCAL_WRITE, output: { entity: "mail_findings" } }))).description("stage one mailbox's findings for the owner; nothing is created until the owner confirms").summary("stage one mailbox's findings; the owner confirms them").argument("<file>", FINDINGS_INPUT_HELP).option("--source <accounts>", MAILBOX_HELP).option("--key <key>", "the findings key `mail review --holder` gave in its mail-findings.add step").option("--dry-run", "check the batch as staging would, invoices, payments and orders tried and rolled back, and stage nothing; answers valid and every finding's problem at once").addHelpText("after", INPUT_HELP).action(async (file, given2) => {
6809
7799
  const read = await readFindingsInput(file, environmentOf(program).stdin ?? process.stdin);
6810
- const text3 = keyed(read, given.key);
6811
- const input = given.dryRun ? readMailFindingsJson(text3) : parseMailFindingsJson(text3);
7800
+ const text3 = keyed(read, given2.key);
7801
+ const input = given2.dryRun ? readMailFindingsJson(text3) : parseMailFindingsJson(text3);
6812
7802
  const author = await whoRuns(program, env, { question: "" });
6813
7803
  const agent = author === "owner" ? { bot: "memo-mail-findings" } : author;
6814
- await run(given.json, async (store) => {
6815
- const mailbox = await oneMailboxOf(store, env, given.source);
7804
+ await run(given2.json, async (store) => {
7805
+ const mailbox = await oneMailboxOf(store, env, given2.source);
6816
7806
  const { input: kept, duplicates } = await withoutDuplicates(store, input);
6817
7807
  const noted = duplicates.length ? { duplicates } : {};
6818
7808
  if (duplicates.length > 0 && kept.findings.length === 0)
6819
7809
  return itemAnswer({
6820
- dryRun: Boolean(given.dryRun),
7810
+ dryRun: Boolean(given2.dryRun),
6821
7811
  valid: true,
6822
7812
  staged: false,
6823
7813
  findings: 0,
6824
7814
  problems: [],
6825
7815
  ...noted
6826
7816
  });
6827
- if (!given.dryRun)
7817
+ if (!given2.dryRun)
6828
7818
  return itemAnswer({ ...await store.mailFindings.stage(mailbox, kept, agent), ...noted });
6829
7819
  const checked = await store.mailFindings.check(mailbox, kept, agent);
6830
7820
  const issues = checked.problems.map((one2) => ({
@@ -6835,22 +7825,22 @@ var mailFindingsCommand = /* @__PURE__ */ __name((program, mail, streams, env) =
6835
7825
  return itemAnswer({ dryRun: true, ...checked, ...noted }, issues.length ? { meta: { complete: false, issues } } : void 0);
6836
7826
  });
6837
7827
  });
6838
- json5(annotate(findings.command("show"), { effects: LOCAL_READ, output: { entity: "mail_findings" } })).description("one findings batch: its findings with their evidence, earlier decisions and the review receipt").summary("one findings batch with its evidence and decisions").argument("<id>", "the batch id `mail findings add` or `list` gave").action((id, given) => run(given.json, async (store) => itemAnswer(await store.mailFindings.get(id))));
6839
- withQuery(json5(annotate(findings.command("list"), { effects: LOCAL_READ, output: { entity: "mail_findings" } })), FINDINGS_QUERY2).description("mail findings batches, newest first; status:proposed is what waits for the owner").option("--source <accounts>", "only this mailbox's batches: email:<address>").option("--limit <n>", "batches per page, at most 50", positive, 20).option("--page <n>", "which page, from 1", positive, 1).action((words, given) => run(given.json, async (store) => {
7828
+ json3(annotate(findings.command("show"), { effects: LOCAL_READ, output: { entity: "mail_findings" } })).description("one findings batch: its findings with their evidence, earlier decisions and the review receipt").summary("one findings batch with its evidence and decisions").argument("<id>", "the batch id `mail findings add` or `list` gave").action((id, given2) => run(given2.json, async (store) => itemAnswer(await store.mailFindings.get(id))));
7829
+ withQuery(json3(annotate(findings.command("list"), { effects: LOCAL_READ, output: { entity: "mail_findings" } })), FINDINGS_QUERY2).description("mail findings batches, newest first; status:proposed is what waits for the owner").option("--source <accounts>", "only this mailbox's batches: email:<address>").option("--limit <n>", "batches per page, at most 50", positive, 20).option("--page <n>", "which page, from 1", positive, 1).action((words, given2) => run(given2.json, async (store) => {
6840
7830
  const status = queryTerms(words, FINDINGS_QUERY2, "mail findings list").get("status");
6841
- const account2 = given.source ? await oneMailboxOf(store, env, given.source) : void 0;
7831
+ const account2 = given2.source ? await oneMailboxOf(store, env, given2.source) : void 0;
6842
7832
  const found = await store.mailFindings.list({
6843
- limit: given.limit,
6844
- offset: (given.page - 1) * given.limit,
7833
+ limit: given2.limit,
7834
+ offset: (given2.page - 1) * given2.limit,
6845
7835
  ...account2 === void 0 ? {} : { account: account2 },
6846
7836
  ...status === void 0 ? {} : { status }
6847
7837
  });
6848
7838
  return listAnswer("mail findings list", {
6849
7839
  items: found.items,
6850
- limit: given.limit,
6851
- page: given.page,
7840
+ limit: given2.limit,
7841
+ page: given2.page,
6852
7842
  has_more: found.hasMore,
6853
- args: { query: words.join(" "), ...given.source ? { source: given.source } : {}, limit: given.limit }
7843
+ args: { query: words.join(" "), ...given2.source ? { source: given2.source } : {}, limit: given2.limit }
6854
7844
  });
6855
7845
  }));
6856
7846
  }, "mailFindingsCommand");
@@ -6976,10 +7966,10 @@ var mcpCommandDefinition = /* @__PURE__ */ __name((program, streams, env, create
6976
7966
  }).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) => {
6977
7967
  if (!options.http && (options.port !== void 0 || options.publicUrl !== void 0))
6978
7968
  throw new CliError("validation_error", "--port and --public-url require --http");
6979
- const { createMemoServer } = await import("./server-I5BPRS5C.js");
7969
+ const { createMemoServer } = await import("./server-MVJU7QG4.js");
6980
7970
  const build = /* @__PURE__ */ __name(() => createMemoServer(env, createProgram2, options.permission), "build");
6981
7971
  if (options.http) {
6982
- const { httpLockFile, mcpUrlOf, portOf, publicUrlOf, serveOverHttp } = await import("./mcp-Y4XMDC5Q.js");
7972
+ const { httpLockFile, mcpUrlOf, portOf, publicUrlOf, serveOverHttp } = await import("./mcp-QX2D6EXA.js");
6983
7973
  const publicUrl = publicUrlOf(options.publicUrl, {
6984
7974
  missing: "--http",
6985
7975
  reaches: "the browser apps reach memo",
@@ -7031,7 +8021,7 @@ var mcpCommandDefinition = /* @__PURE__ */ __name((program, streams, env, create
7031
8021
  });
7032
8022
  });
7033
8023
  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() {
7034
- const { revokeAll } = await import("./mcp-Y4XMDC5Q.js");
8024
+ const { revokeAll } = await import("./mcp-QX2D6EXA.js");
7035
8025
  revokeAll(httpTokenFile(env));
7036
8026
  out.print(this.opts().json, itemAnswer({ revoked: true }));
7037
8027
  });
@@ -7094,28 +8084,28 @@ var readStoredMeetingPassage = /* @__PURE__ */ __name(async (store, env, source,
7094
8084
  // dist/meetings/command.js
7095
8085
  var meetingReadCommands = /* @__PURE__ */ __name((program, streams, env) => {
7096
8086
  const { print } = answers(program, streams, env);
7097
- const source = /* @__PURE__ */ __name((given) => sourceOf(given, (text3) => streams.diagnostic(text3)), "source");
8087
+ const source = /* @__PURE__ */ __name((given2) => sourceOf(given2, (text3) => streams.diagnostic(text3)), "source");
7098
8088
  const output = /* @__PURE__ */ __name((command) => sourceOptions(command, MEETING_ACCOUNT_HELP).option("--json", "print the standard JSON answer"), "output");
7099
8089
  const grammar = createMeetingSearchCommand(program);
7100
8090
  const search2 = overrideSharedContract(grammar, "Memo selects an explicit stored source and uses native tag: queries instead of a tag flag, with command-local JSON output.", (command) => {
7101
8091
  Reflect.set(command, "options", command.options.filter((option) => option.long !== "--tag"));
7102
8092
  output(command);
7103
8093
  });
7104
- search2.action(async (query, given) => {
7105
- const input = meetingHitSearchRequest(query, given);
7106
- const result = await withStore(env, (store) => searchStoredMeetings(store, env, source(given), query, input, meetingSearchArguments(query, given), {
7107
- ...given,
8094
+ search2.action(async (query, given2) => {
8095
+ const input = meetingHitSearchRequest(query, given2);
8096
+ const result = await withStore(env, (store) => searchStoredMeetings(store, env, source(given2), query, input, meetingSearchArguments(query, given2), {
8097
+ ...given2,
7108
8098
  timesReadIn: grammar.getOptionValue("timesReadIn")
7109
8099
  }));
7110
- print(given.json, result);
8100
+ print(given2.json, result);
7111
8101
  });
7112
8102
  overrideSharedContract(createMeetingPassageCommand(program), "Memo passage reads an explicitly selected stored source and exposes command-local JSON output.", (command) => {
7113
8103
  output(command);
7114
- }).action(async (reference2, given) => {
7115
- const format = given.json ? "json" : given.format ?? "text";
7116
- const input = meetingPassageRequest(reference2, { ...given, format });
7117
- const result = await withStore(env, (store) => readStoredMeetingPassage(store, env, source(given), reference2, input));
7118
- print(given.json, itemAnswer(result.packet), result.content);
8104
+ }).action(async (reference2, given2) => {
8105
+ const format = given2.json ? "json" : given2.format ?? "text";
8106
+ const input = meetingPassageRequest(reference2, { ...given2, format });
8107
+ const result = await withStore(env, (store) => readStoredMeetingPassage(store, env, source(given2), reference2, input));
8108
+ print(given2.json, itemAnswer(result.packet), result.content);
7119
8109
  });
7120
8110
  }, "meetingReadCommands");
7121
8111
 
@@ -7128,13 +8118,13 @@ var communicationSource = /* @__PURE__ */ __name(async (store, env, id) => {
7128
8118
  });
7129
8119
  const key = await oneAccountOf(store, env, `${id.slice(0, dot)}:${id.slice(dot + 1)}`, "--context-source");
7130
8120
  const held = await store.accounts.storedAccount(key);
7131
- const listed = entriesOfList(accountName(key), {
8121
+ const listed2 = entriesOfList(accountName(key), {
7132
8122
  held: [held],
7133
8123
  profiles: {},
7134
8124
  groups: {},
7135
8125
  running: { provider: "email", command: "memo" }
7136
8126
  })[0]?.accounts[0];
7137
- const kind = listed?.kind === "messages" ? "message" : listed?.kind === "mail" ? "mail" : void 0;
8127
+ const kind = listed2?.kind === "messages" ? "message" : listed2?.kind === "mail" ? "mail" : void 0;
7138
8128
  if (kind === void 0)
7139
8129
  throw new CliError("validation_error", `${id}: select one stored messenger profile or mailbox`, {
7140
8130
  param: "communications.sources"
@@ -7512,8 +8502,8 @@ var refuseOverMcp = /* @__PURE__ */ __name((options, mcp2) => {
7512
8502
  param: "export"
7513
8503
  });
7514
8504
  }, "refuseOverMcp");
7515
- var textOf = /* @__PURE__ */ __name((options, given) => {
7516
- const sources = [given, options.text, options.textFile].filter((value) => value !== void 0);
8505
+ var textOf = /* @__PURE__ */ __name((options, given2) => {
8506
+ const sources = [given2, options.text, options.textFile].filter((value) => value !== void 0);
7517
8507
  if (sources.length !== 1)
7518
8508
  throw new CliError("validation_error", "give the text once: as an argument, --text or --text-file");
7519
8509
  if (options.textFile !== void 0)
@@ -7577,14 +8567,14 @@ var notesCommandDefinition = /* @__PURE__ */ __name((program, streams, env) => {
7577
8567
  ...answer.backlinks.length ? [`linked from: ${answer.backlinks.map(({ from }) => from).join(", ")}`] : []
7578
8568
  ].join("\n"));
7579
8569
  });
7580
- withQuery(annotate(notes2.command("list"), { effects: LOCAL_READ }).description("notes, newest first"), NOTES_LIST_QUERY).option("--limit <n>", "most notes, at most 500", positive, 20).option("--page <n>", "which page, from 1", positive, 1).option("--json", "print JSON; --json=id,title keeps only those fields").action(async (words, { json: json7, ...paging }) => {
7581
- const terms = queryTerms(words, NOTES_LIST_QUERY, "notes list");
7582
- const about = terms.get("about");
7583
- const source = terms.get("source");
7584
- const search2 = terms.get("text");
7585
- if (about !== void 0 && terms.size > 1)
8570
+ withQuery(annotate(notes2.command("list"), { effects: LOCAL_READ }).description("notes, newest first"), NOTES_LIST_QUERY).option("--limit <n>", "most notes, at most 500", positive, 20).option("--page <n>", "which page, from 1", positive, 1).option("--json", "print JSON; --json=id,title keeps only those fields").action(async (words, { json: json5, ...paging }) => {
8571
+ const terms2 = queryTerms(words, NOTES_LIST_QUERY, "notes list");
8572
+ const about = terms2.get("about");
8573
+ const source = terms2.get("source");
8574
+ const search2 = terms2.get("text");
8575
+ if (about !== void 0 && terms2.size > 1)
7586
8576
  throw new CliError("validation_error", "about: stands alone in notes list: its notes are found through links");
7587
- const options = { ...paging, json: json7 };
8577
+ const options = { ...paging, json: json5 };
7588
8578
  const page = await withNotes(async (store) => listNotes(store, {
7589
8579
  limit: options.limit,
7590
8580
  offset: (options.page - 1) * options.limit,
@@ -7603,9 +8593,9 @@ var notesCommandDefinition = /* @__PURE__ */ __name((program, streams, env) => {
7603
8593
  output: { entity: "note" },
7604
8594
  literal_after_dashes: true
7605
8595
  }).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");
7606
- 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 (given, options, command) => {
8596
+ 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) => {
7607
8597
  refuseOverMcp(options, isMcpRun(command, env));
7608
- const body = textOf(options, given);
8598
+ const body = textOf(options, given2);
7609
8599
  const value = writeAccountOf(options, (text3) => streams.diagnostic(text3));
7610
8600
  if (options.meeting === void 0 && value !== void 0)
7611
8601
  throw new CliError("validation_error", "--account selects the account of --meeting");
@@ -7886,8 +8876,105 @@ var peopleCommand = /* @__PURE__ */ __name((program, streams, env) => {
7886
8876
  });
7887
8877
  }, "peopleCommand");
7888
8878
 
7889
- // dist/records/import.js
7890
- import { readFile } from "node:fs/promises";
8879
+ // dist/records/input.js
8880
+ import { open } from "node:fs/promises";
8881
+ var PHONE = "phone";
8882
+ var BOM = /^\uFEFF/;
8883
+ var errnoOf = /* @__PURE__ */ __name((error) => typeof error === "object" && error !== null && "code" in error ? String(error.code) : void 0, "errnoOf");
8884
+ var linesOf = /* @__PURE__ */ __name(async (file, stdin) => {
8885
+ if (file === "-")
8886
+ return jsonlLines(stdin);
8887
+ try {
8888
+ const handle = await open(file);
8889
+ if (!(await handle.stat()).isFile()) {
8890
+ await handle.close();
8891
+ throw Object.assign(new Error(`${file} is a folder`), { code: "EISDIR" });
8892
+ }
8893
+ return jsonlLines(handle.createReadStream({ encoding: "utf8" }));
8894
+ } catch (error) {
8895
+ if (errnoOf(error) === "ENOENT")
8896
+ throw new CliError("not_found", `no records file ${file}: give a file that exists, or - for stdin`, {
8897
+ reason: "records.file-missing",
8898
+ path: file
8899
+ });
8900
+ const why = errnoOf(error) === "EISDIR" ? "it is a folder" : errnoOf(error) === "EACCES" ? "no permission" : "unreadable";
8901
+ throw new CliError("validation_error", `the records file ${file} cannot be read: ${why}`, {
8902
+ reason: "records.file-unreadable",
8903
+ path: file,
8904
+ why
8905
+ });
8906
+ }
8907
+ }, "linesOf");
8908
+ var headerOf = /* @__PURE__ */ __name((line3) => {
8909
+ try {
8910
+ const value = JSON.parse(line3);
8911
+ return value && typeof value === "object" && !Array.isArray(value) && !("records" in value) ? value : void 0;
8912
+ } catch {
8913
+ return void 0;
8914
+ }
8915
+ }, "headerOf");
8916
+ var accountIn = /* @__PURE__ */ __name((envelope, given2) => {
8917
+ const provider = envelope?.source?.provider;
8918
+ return typeof provider === "string" && given2.startsWith(`${provider}:`) ? given2.slice(provider.length + 1) : given2;
8919
+ }, "accountIn");
8920
+ var deviceOf = /* @__PURE__ */ __name((given2) => {
8921
+ const at = given2.indexOf(":");
8922
+ if (at < 0)
8923
+ return given2;
8924
+ if (given2.slice(0, at) !== PHONE)
8925
+ throw new CliError("validation_error", "a vCard file holds a phone's contacts: --account phone:<device>", {
8926
+ param: "--account"
8927
+ });
8928
+ return given2.slice(at + 1);
8929
+ }, "deviceOf");
8930
+ var importRecords = /* @__PURE__ */ __name(async (store, { file, stdin, account: account2, dryRun, onIssue }) => {
8931
+ const iterator = (await linesOf(file, stdin))[Symbol.asyncIterator]();
8932
+ const before = [];
8933
+ let next = await iterator.next();
8934
+ while (!next.done && next.value.replace(BOM, "").trim() === "") {
8935
+ before.push(next.value);
8936
+ next = await iterator.next();
8937
+ }
8938
+ async function* rest() {
8939
+ for (let line3 = await iterator.next(); !line3.done; line3 = await iterator.next())
8940
+ yield line3.value;
8941
+ }
8942
+ __name(rest, "rest");
8943
+ const whole2 = /* @__PURE__ */ __name(async (first2) => {
8944
+ const lines2 = [...before, ...first2];
8945
+ for await (const line3 of rest())
8946
+ lines2.push(line3);
8947
+ return lines2.join("\n");
8948
+ }, "whole");
8949
+ if (next.done)
8950
+ return ingest(store, envelopeOfText(before.join("\n")), { account: account2, dryRun, onIssue });
8951
+ const first = next.value.replace(BOM, "");
8952
+ if (isVcard(first)) {
8953
+ const { vcard, ...receipt } = await ingestVcard(store, await whole2([first]), {
8954
+ account: deviceOf(account2),
8955
+ provider: PHONE,
8956
+ batchId: `vcard-${(/* @__PURE__ */ new Date()).toISOString()}`,
8957
+ dryRun,
8958
+ onIssue
8959
+ });
8960
+ return { ...receipt, vcard: vcard.map((one2) => ({ ...one2, card: one2.card + 1 })) };
8961
+ }
8962
+ const header = headerOf(first);
8963
+ if (header !== void 0) {
8964
+ async function* all() {
8965
+ try {
8966
+ yield first;
8967
+ yield* rest();
8968
+ } finally {
8969
+ await iterator.return?.();
8970
+ }
8971
+ }
8972
+ __name(all, "all");
8973
+ return ingestLines(store, all(), { account: accountIn(header, account2), dryRun, onIssue });
8974
+ }
8975
+ const envelope = envelopeOfText(await whole2([first]));
8976
+ return ingest(store, envelope, { account: accountIn(envelope, account2), dryRun, onIssue });
8977
+ }, "importRecords");
7891
8978
 
7892
8979
  // dist/records/mapping.js
7893
8980
  var RECORD_QUERY = {
@@ -7896,7 +8983,11 @@ var RECORD_QUERY = {
7896
8983
  fields: [
7897
8984
  termField("type", "kw", "type:organization"),
7898
8985
  termField("waiting", "bool", "waiting:true"),
7899
- termField("flagged", "bool", "flagged:true")
8986
+ termField("flagged", "bool", "flagged:true"),
8987
+ termField("unmatched", "bool", "unmatched:true"),
8988
+ termField("entity", "ref", 'entity:"organization:3"'),
8989
+ termField("batch", "kw", "batch:2026-11-07"),
8990
+ termField("deleted", "bool", "deleted:true")
7900
8991
  ]
7901
8992
  };
7902
8993
  var sourceOf4 = /* @__PURE__ */ __name((account2) => {
@@ -7909,84 +9000,149 @@ var sourceOf4 = /* @__PURE__ */ __name((account2) => {
7909
9000
  return { provider, account: name2 };
7910
9001
  }, "sourceOf");
7911
9002
  var recordOf = /* @__PURE__ */ __name((record2) => {
7912
- const at = record2.indexOf(":");
7913
- if (at < 1 || at === record2.length - 1)
7914
- throw new CliError("validation_error", `${record2} is not <type>:<external_id>, such as organization:client`, {
7915
- param: "record"
7916
- });
9003
+ const from = record2.startsWith("custom:") ? "custom:".length : 0;
9004
+ const at = record2.indexOf(":", from);
9005
+ if (at <= from || at === record2.length - 1)
9006
+ throw new CliError("validation_error", `${record2} is not <type>:<external_id>, such as organization:client or custom:quote:Q-7`, { param: "record" });
7917
9007
  return { type: record2.slice(0, at), externalId: record2.slice(at + 1) };
7918
9008
  }, "recordOf");
9009
+ var RECORD_HELP = "<type>:<external_id> as the source names it, such as organization:client or custom:quote:Q-7";
7919
9010
  var ACCOUNT_HELP = "the source, <provider>:<account> as the envelope's source names it, such as sheet:rentals";
7920
9011
  var recordMappingCommands = /* @__PURE__ */ __name((records, program, streams, env) => {
7921
9012
  const { run } = answers(program, streams, env);
7922
- withQuery(annotate(records.command("list"), { effects: LOCAL_READ }).description("a source's records, newest first; waiting:true lists those whose invoice or payment waits for records link"), RECORD_QUERY).summary("a source's records; waiting:true lists what needs records link").option("--account <account>", ACCOUNT_HELP).option("--limit <n>", "most records, up to 500", positive, 100).option("--json", "print JSON; --json=type,external_id,entity keeps only those fields").action((words, given) => run(given.json, async (store) => {
7923
- const source = sourceOf4(given.account);
7924
- const terms = queryTerms(words, RECORD_QUERY, "records list");
9013
+ withQuery(annotate(records.command("list"), { effects: LOCAL_READ }).description("a source's records, newest first; waiting:true lists those that wait for a record they name, unmatched:true the people, organizations and projects whose identifiers fit more than one of yours, entity: those mapped to one of your entries"), RECORD_QUERY).summary("a source's records; waiting:true lists what needs records link").option("--account <account>", ACCOUNT_HELP).option("--limit <n>", "most records, up to 500", positive, 100).option("--json", "print JSON; --json=type,external_id,entity keeps only those fields").action((words, given2) => run(given2.json, async (store) => {
9014
+ const source = sourceOf4(given2.account);
9015
+ const terms2 = queryTerms(words, RECORD_QUERY, "records list");
7925
9016
  const filter = {
7926
9017
  ...source,
7927
- ...terms.has("type") ? { type: terms.get("type") } : {},
7928
- ...terms.get("waiting") === "true" ? { waiting: true } : {},
7929
- ...terms.get("flagged") === "true" ? { flagged: true } : {}
9018
+ ...terms2.has("type") ? { type: terms2.get("type") } : {},
9019
+ ...terms2.get("waiting") === "true" ? { waiting: true } : {},
9020
+ ...terms2.get("flagged") === "true" ? { flagged: true } : {},
9021
+ ...terms2.get("unmatched") === "true" ? { unmatched: true } : {},
9022
+ ...terms2.has("entity") ? { entity: terms2.get("entity") } : {},
9023
+ ...terms2.has("batch") ? { batch: terms2.get("batch") } : {},
9024
+ ...terms2.has("deleted") ? { deleted: terms2.get("deleted") === "true" } : {}
7930
9025
  };
7931
- return pageOf("records list", given.limit, (most) => store.records.list({ ...filter, limit: most }));
9026
+ return pageOf("records list", given2.limit, (most) => store.records.list({ ...filter, limit: most }));
7932
9027
  }));
7933
- byOption(annotate(records.command("link"), { effects: LOCAL_WRITE, output: { entity: "source_record" } }).description("say which of your entries a source's record is (organization:client is organization:3); never done by name. Records that waited for it become proposals in memo review. Only you link; an agent is refused").summary("say which of your entries a source's record is").argument("<record>", "<type>:<external_id> as the source names it, such as organization:client").argument("<ref>", "your entry of the same type: person:<id>, organization:<id> or project:<id>").option("--account <account>", ACCOUNT_HELP).option("--json", "print JSON; --json=type,external_id,entity keeps only those fields")).action(async (record2, ref, given, command) => {
7934
- const by = await whoRuns(command, env, { asOwner: given.asOwner, question: `link ${record2} to ${ref} as you?` });
7935
- await run(given.json, async (store) => itemAnswer(await store.records.map({ ...sourceOf4(given.account), ...recordOf(record2) }, ref, by)));
9028
+ byOption(annotate(records.command("link"), { effects: LOCAL_WRITE, output: { entity: "source_record" } }).description("say which of your entries a source's record is (organization:client is organization:3); never done by name. Records that waited for it become proposals in memo review. Only you link; an agent is refused").summary("say which of your entries a source's record is").argument("<record>", RECORD_HELP).argument("<ref>", "your entry of the same type: person:<id>, organization:<id> or project:<id>").option("--account <account>", ACCOUNT_HELP).option("--json", "print JSON; --json=type,external_id,entity keeps only those fields")).action(async (record2, ref, given2, command) => {
9029
+ const by = await whoRuns(command, env, { asOwner: given2.asOwner, question: `link ${record2} to ${ref} as you?` });
9030
+ await run(given2.json, async (store) => itemAnswer(await store.records.map({ ...sourceOf4(given2.account), ...recordOf(record2) }, ref, by)));
7936
9031
  });
7937
9032
  }, "recordMappingCommands");
7938
9033
 
9034
+ // dist/records/record-commands.js
9035
+ var INCOMING = 100;
9036
+ var codeOf = /* @__PURE__ */ __name((reason) => {
9037
+ const code = REASONS2.find((one2) => one2.reason === reason)?.code;
9038
+ return code === void 0 || code === "internal_error" ? "validation_error" : code;
9039
+ }, "codeOf");
9040
+ var storedRecord = /* @__PURE__ */ __name(async (store, account2, record2) => {
9041
+ const key = { ...sourceOf4(account2), ...recordOf(record2) };
9042
+ const found = await store.records.get(key);
9043
+ if (found === void 0)
9044
+ throw new CliError("not_found", `no record ${record2} from ${key.provider}:${key.account}; records list shows them`, {
9045
+ reason: "records.not-stored",
9046
+ record: record2
9047
+ });
9048
+ return found;
9049
+ }, "storedRecord");
9050
+ var matchText = /* @__PURE__ */ __name((run) => [
9051
+ `matched ${run.linked}, created ${run.created}`,
9052
+ ...run.proposed.length ? [`proposed for your review: ${run.proposed.join(" ")}`] : [],
9053
+ ...run.unmatched.map((one2) => `unmatched ${one2.key.type}:${one2.key.externalId}: ${one2.candidates.length ? `could be ${one2.candidates.join(" or ")}` : one2.reason}`),
9054
+ ...run.errors.map((one2) => `refused ${one2.pointer} \xB7 ${one2.message} (${one2.code})`),
9055
+ ...run.truncated ? ["the lists stop at 1000 entries each; the counts are exact"] : []
9056
+ ].join("\n"), "matchText");
9057
+ var recordCommands = /* @__PURE__ */ __name((records, { run, print }, withStore2) => {
9058
+ jsonOption(annotate(records.command("show"), { effects: LOCAL_READ, output: { entity: "source_record" } }).argument("<record>", RECORD_HELP).option("--account <account>", ACCOUNT_HELP), "fields,relations,incoming,entity").description(`one record as its source said it: its fields, the records it names, the records that name it (incoming, the first ${INCOMING}) and the entry made from it`).summary("one record as its source said it").action((record2, given2) => run(given2.json, async (store) => {
9059
+ const found = await storedRecord(store, given2.account, record2);
9060
+ const incoming = await store.records.incoming(found, { limit: INCOMING + 1 });
9061
+ return itemAnswer({
9062
+ ...found,
9063
+ incoming: { items: incoming.slice(0, INCOMING), hasMore: incoming.length > INCOMING }
9064
+ });
9065
+ }));
9066
+ jsonOption(annotate(records.command("delete"), { effects: LOCAL_WRITE, output: { entity: "records_receipt" } }).argument("<record>", RECORD_HELP).option("--account <account>", ACCOUNT_HELP), "deleted,flagged,errors").description("say a source no longer has a record, as an import's delete does: the record is kept as deleted, and the entry made from it stays, flagged for you to reject or keep").summary("mark a source's record deleted").action(async (record2, given2) => {
9067
+ const receipt = await withStore2(async (store) => {
9068
+ const found = await storedRecord(store, given2.account, record2);
9069
+ return ingest(store, {
9070
+ schema_version: RECORDS_SCHEMA_VERSION,
9071
+ source: {
9072
+ provider: found.provider,
9073
+ account: found.account,
9074
+ batch_id: `delete-${(/* @__PURE__ */ new Date()).toISOString()}`
9075
+ },
9076
+ records: [
9077
+ {
9078
+ key: "delete",
9079
+ type: found.type,
9080
+ external_id: found.externalId,
9081
+ operation: "delete",
9082
+ ...found.revision === null ? {} : { revision: found.revision }
9083
+ }
9084
+ ]
9085
+ }, { account: found.account });
9086
+ });
9087
+ const [refused] = receipt.errors;
9088
+ if (refused)
9089
+ throw new CliError(codeOf(refused.code), refused.message, { reason: refused.code });
9090
+ print(given2.json, itemAnswer(receipt), receipt.deleted === 0 ? `${record2} was already deleted` : `deleted ${record2}${receipt.flagged.length ? `; ${receipt.flagged.map((one2) => one2.entity).join(" ")} kept, flagged for you` : ""}`);
9091
+ });
9092
+ jsonOption(annotate(records.command("match"), { effects: LOCAL_WRITE, output: { entity: "records_match" } }).option("--account <account>", ACCOUNT_HELP), "linked,created,unmatched").description("link every waiting person, organization and project of a source to the one entry its e-mail, phone or other identifier names, or make one, as an import does; never by name. Two or more fits wait for records link").summary("match a source's waiting people and organizations").action((given2) => withStore2(async (store) => store.records.match(sourceOf4(given2.account))).then((found) => print(given2.json, itemAnswer(found), matchText(found))));
9093
+ }, "recordCommands");
9094
+
7939
9095
  // dist/records/import.js
7940
- var readAll = /* @__PURE__ */ __name(async (file, stdin) => {
7941
- if (file !== "-")
7942
- return readFile(file, "utf8");
7943
- let text3 = "";
7944
- stdin.setEncoding("utf8");
7945
- for await (const chunk of stdin)
7946
- text3 += chunk;
7947
- return text3;
7948
- }, "readAll");
7949
- var envelopeOf = /* @__PURE__ */ __name((text3) => {
7950
- try {
7951
- const whole2 = JSON.parse(text3);
7952
- if (whole2 && typeof whole2 === "object" && "records" in whole2)
7953
- return whole2;
7954
- } catch {
7955
- }
7956
- return envelopeOfJsonl(text3);
7957
- }, "envelopeOf");
7958
- var accountIn = /* @__PURE__ */ __name((envelope, given) => {
7959
- const provider = envelope?.source?.provider;
7960
- return typeof provider === "string" && given.startsWith(`${provider}:`) ? given.slice(provider.length + 1) : given;
7961
- }, "accountIn");
9096
+ var kindsOf = /* @__PURE__ */ __name((proposed) => [...new Set(proposed.map((ref) => ref.slice(0, ref.indexOf(":"))))], "kindsOf");
9097
+ var pointerOf = /* @__PURE__ */ __name((pointer) => pointer || "/", "pointerOf");
9098
+ var refusedLine = /* @__PURE__ */ __name((one2) => `refused ${pointerOf(one2.pointer)} \xB7 ${one2.message} (${one2.code})`, "refusedLine");
7962
9099
  var receiptText = /* @__PURE__ */ __name((receipt) => [
7963
9100
  `${receipt.dryRun ? "would import" : "imported"} ${receipt.source?.batchId ?? "nothing"}: ${receipt.created} created, ${receipt.updated} updated, ${receipt.unchanged} unchanged, ${receipt.deleted} deleted, ${receipt.refused} refused`,
7964
- ...receipt.proposed.length ? [`proposed for your review (memo review kind:invoice,payment): ${receipt.proposed.join(" ")}`] : [],
9101
+ ...receipt.proposed.length ? [
9102
+ `proposed for your review (memo review list kind:${kindsOf(receipt.proposed).join(",")}): ` + receipt.proposed.join(" ")
9103
+ ] : [],
7965
9104
  ...receipt.waiting.map((one2) => `waiting ${one2.key}: no entity yet for ${one2.missing.join(", ")}`),
9105
+ ...receipt.unmatched.map((one2) => `unmatched ${one2.key}: ${one2.candidates.length ? `could be ${one2.candidates.join(" or ")}` : one2.reason}; you say which with memo records link`),
7966
9106
  ...receipt.flagged.map((one2) => `changed at the source ${one2.key}: ${one2.entity} kept as it was`),
7967
- ...receipt.errors.map((one2) => `refused ${one2.pointer} \xB7 ${one2.message} (${one2.code})`)
9107
+ ...receipt.ignored.map((one2) => `kept as data only ${one2.key} ${one2.pointer} (${one2.reason})`),
9108
+ ...(receipt.vcard ?? []).map((one2) => `notice card ${one2.card}: ${one2.message}`),
9109
+ ...receipt.errors.map(refusedLine),
9110
+ ...receipt.truncated ? ["the lists stop at 1000 entries each; the counts are exact"] : []
7968
9111
  ].join("\n"), "receiptText");
9112
+ var HOLDS_LOCK = "a dry run holds the store's write lock and grows the write-ahead log for its length";
7969
9113
  var recordsCommand = /* @__PURE__ */ __name((program, streams, env) => {
7970
- const { print } = answers(program, streams, env);
7971
- const records = program.command("records").description("what a source said, kept per account; invoices and payments from it wait for your review").summary("what a source said, kept per account");
7972
- const importing = /* @__PURE__ */ __name((command, dryRun) => command.argument("<file>", "a records envelope as JSON, or JSONL (a header line, then a record per line); - for stdin").option("--account <account>", "the source the envelope is for: <provider>:<account> (sheet:rentals) or its source.account alone").option("--json", "print JSON; --json=created,errors keeps only those fields").action(async (file, given) => {
7973
- const account2 = given.account?.trim();
9114
+ const answered = answers(program, streams, env);
9115
+ const { print } = answered;
9116
+ const records = program.command("records").description("what a source said, kept per account; what it says about money waits for your review").summary("what a source said, kept per account");
9117
+ const importing = /* @__PURE__ */ __name((command, dryRun) => command.argument("<file>", "a records envelope as JSON, JSONL (a header line, then a record per line, read as it streams) or a vCard address book (.vcf, into phone:<device>); - for stdin").option("--account <account>", "the source the envelope is for: <provider>:<account> (sheet:rentals) or its source.account alone; phone:<device> for a vCard file").option("--json", "print JSON; --json=created,errors keeps only those fields").action(async (file, given2) => {
9118
+ const account2 = given2.account?.trim();
7974
9119
  if (!account2)
7975
9120
  throw new CliError("validation_error", "name the source account the envelope is for: --account <account>", {
7976
9121
  param: "--account"
7977
9122
  });
7978
- const envelope = envelopeOf(await readAll(file, environmentOf(program).stdin ?? process.stdin));
7979
- const receipt = await withStore(env, (store) => ingest(store, envelope, { account: accountIn(envelope, account2), dryRun: dryRun ?? given.dryRun === true }));
9123
+ const receipt = await withStore(env, (store) => importRecords(store, {
9124
+ file,
9125
+ stdin: environmentOf(program).stdin ?? process.stdin,
9126
+ account: account2,
9127
+ dryRun: dryRun ?? given2.dryRun === true,
9128
+ onIssue: /* @__PURE__ */ __name((issue) => streams.diagnostic(`${refusedLine(issue)}
9129
+ `), "onIssue")
9130
+ }));
7980
9131
  const issues = receipt.errors.map((one2) => ({
7981
9132
  code: "validation_error",
7982
- source: one2.pointer,
9133
+ source: pointerOf(one2.pointer),
7983
9134
  reason: one2.code
7984
9135
  }));
7985
- print(given.json, itemAnswer(receipt, issues.length ? { meta: { complete: false, issues } } : void 0), receiptText(receipt));
9136
+ print(given2.json, itemAnswer(receipt, issues.length ? { meta: { complete: false, issues } } : void 0), receiptText(receipt));
7986
9137
  }), "importing");
7987
- importing(annotate(records.command("import"), { effects: LOCAL_WRITE, output: { entity: "records_receipt" } }).description("bring a source's records into the store, once: the same file twice changes nothing, a lower revision is refused, and an invoice or a payment becomes a proposal for you, never confirmed money").summary("import a source's records; money waits for your review").option("--dry-run", "check and plan the import; write nothing"), void 0);
7988
- importing(annotate(records.command("check"), { effects: LOCAL_READ, output: { entity: "records_receipt" } }).description("what records import would do with the file, as its receipt, writing nothing").summary("check a records file against the store; write nothing"), true);
9138
+ importing(annotate(records.command("import"), { effects: LOCAL_WRITE, output: { entity: "records_receipt" } }).description("bring a source's records into the store, once: the same file twice changes nothing, a lower revision is refused, and anything that feeds money totals becomes a proposal for you, never confirmed money. Each refusal is also printed on stderr as it happens, one line each, past the receipt's 1000").summary("import a source's records; money waits for your review").option("--dry-run", `check and plan the import; write nothing. ${HOLDS_LOCK}`), void 0);
9139
+ importing(
9140
+ // A dry run holds the write lock for its length, so MCP gates it as a write.
9141
+ annotate(records.command("check"), { effects: LOCAL_WRITE, output: { entity: "records_receipt" } }).description(`what records import would do with the file, as its receipt, writing nothing; ${HOLDS_LOCK}`).summary("check a records file against the store; write nothing"),
9142
+ true
9143
+ );
7989
9144
  recordMappingCommands(records, program, streams, env);
9145
+ recordCommands(records, answered, (work) => withStore(env, work));
7990
9146
  }, "recordsCommand");
7991
9147
 
7992
9148
  // dist/digest/known.js
@@ -8086,8 +9242,8 @@ var syncRunsOf = /* @__PURE__ */ __name((env) => {
8086
9242
  };
8087
9243
  }, "syncRunsOf");
8088
9244
  var HOUR = 36e5;
8089
- var DAY4 = 24 * HOUR;
8090
- var QUIET_AFTER = 3 * DAY4;
9245
+ var DAY5 = 24 * HOUR;
9246
+ var QUIET_AFTER = 3 * DAY5;
8091
9247
  var QUIET_GAPS = 3;
8092
9248
  var hours = /* @__PURE__ */ __name((from, now) => Math.max(0, Math.floor((now - from) / HOUR)), "hours");
8093
9249
  var healthOf = /* @__PURE__ */ __name((sync, activity, now) => {
@@ -8109,7 +9265,7 @@ var healthOf = /* @__PURE__ */ __name((sync, activity, now) => {
8109
9265
  };
8110
9266
  if (activity.newest === null || activity.moved30d === 0)
8111
9267
  return void 0;
8112
- const usual = Math.max(QUIET_AFTER, QUIET_GAPS * 30 * DAY4 / activity.moved30d);
9268
+ const usual = Math.max(QUIET_AFTER, QUIET_GAPS * 30 * DAY5 / activity.moved30d);
8113
9269
  if (activity.newest < now - usual)
8114
9270
  return { reason: "quiet", since: new Date(activity.newest).toISOString(), staleHours: hours(activity.newest, now) };
8115
9271
  return void 0;
@@ -8284,13 +9440,13 @@ var countTasks = /* @__PURE__ */ __name(async (store, words) => {
8284
9440
 
8285
9441
  // dist/digest/tasks.js
8286
9442
  var DIGEST_SCHEDULE = "morning-digest";
8287
- var DAY5 = 864e5;
9443
+ var DAY6 = 864e5;
8288
9444
  var previousDigestAt = /* @__PURE__ */ __name((env, now) => {
8289
9445
  const state = resolvePaths({ appName: APP.appName, prefix: APP.envPrefix, env }).state;
8290
9446
  const digest = schedulesOf(state).find((one2) => one2.name === DIGEST_SCHEDULE || one2.kind === "agent" && one2.argv.join(" ").includes(DIGEST_SCHEDULE));
8291
9447
  const last = digest?.last;
8292
9448
  if (!last)
8293
- return new Date(now - DAY5).toISOString();
9449
+ return new Date(now - DAY6).toISOString();
8294
9450
  return last.exitCode === 0 ? last.at : last.failingSince ?? last.at;
8295
9451
  }, "previousDigestAt");
8296
9452
  var dayOf2 = /* @__PURE__ */ __name((zone) => {
@@ -8332,7 +9488,7 @@ var gatherTasks = /* @__PURE__ */ __name(async (store, keys, { now, newSince })
8332
9488
  const zone = timezoneOf();
8333
9489
  const day2 = dayOf2(zone);
8334
9490
  const today2 = day2(now);
8335
- const tomorrow = day2(now + DAY5);
9491
+ const tomorrow = day2(now + DAY6);
8336
9492
  const since = Date.parse(newSince);
8337
9493
  const seen = /* @__PURE__ */ new Map();
8338
9494
  let accounts = 0;
@@ -8378,7 +9534,7 @@ var gatherTasks = /* @__PURE__ */ __name(async (store, keys, { now, newSince })
8378
9534
 
8379
9535
  // dist/digest/digest.js
8380
9536
  var WATCH_TAG = "watch";
8381
- var DAY6 = 864e5;
9537
+ var DAY7 = 864e5;
8382
9538
  var MESSENGERS2 = /* @__PURE__ */ new Set(["telegram", "max", "whatsapp"]);
8383
9539
  var HEALTH_ORDER = HEALTH_REASONS;
8384
9540
  var UNNAMED = "unnamed account";
@@ -8407,8 +9563,8 @@ var labelsOf = /* @__PURE__ */ __name(async (store, keys) => {
8407
9563
  }
8408
9564
  const person = await store.people.personOf({ provider: key.provider, id: key.account });
8409
9565
  const username = person?.identities.find((one2) => one2.provider === key.provider && one2.id === key.account)?.username;
8410
- const given = stored.get(name(key));
8411
- const label = [given && given !== key.account ? given : null, username ? `@${username}` : null].filter(Boolean).join(" ");
9566
+ const given2 = stored.get(name(key));
9567
+ const label = [given2 && given2 !== key.account ? given2 : null, username ? `@${username}` : null].filter(Boolean).join(" ");
8412
9568
  const profile = profileOf(key);
8413
9569
  labels.set(name(key), label || (profile ? `profile ${profile}` : UNNAMED));
8414
9570
  }
@@ -8463,8 +9619,8 @@ var statusLine = /* @__PURE__ */ __name((data) => {
8463
9619
  }, "statusLine");
8464
9620
  var personal = /* @__PURE__ */ __name((newest) => !newest.bulk && !newest.list && !newest.envelope && !newest.demoted, "personal");
8465
9621
  var gatherDigest = /* @__PURE__ */ __name(async (store, env, { since, now = Date.now(), limit, excerpt: excerpt2, owedWithin, newSince }) => {
8466
- const window = (now - since) / DAY6;
8467
- const days = `${Math.max(1, Math.ceil(window))}d`;
9622
+ const window = (now - since) / DAY7;
9623
+ const days2 = `${Math.max(1, Math.ceil(window))}d`;
8468
9624
  const accounts = await store.accounts.accounts();
8469
9625
  const messengers2 = accounts.filter((key) => MESSENGERS2.has(key.provider));
8470
9626
  const mailboxes = accounts.filter((key) => key.provider === "email");
@@ -8520,7 +9676,7 @@ var gatherDigest = /* @__PURE__ */ __name(async (store, env, { since, now = Date
8520
9676
  let mailMoved = 0;
8521
9677
  for (const key of messengers2) {
8522
9678
  const { chats, storedAt } = await store.chats.chatActivity(key, owedSince);
8523
- const month = (await store.chats.chatActivity(key, now - 30 * DAY6)).chats;
9679
+ const month = (await store.chats.chatActivity(key, now - 30 * DAY7)).chats;
8524
9680
  checkHealth(key, {
8525
9681
  newest: month.reduce((most, chat) => Math.max(most ?? 0, Date.parse(chat.lastMessageAt)), null),
8526
9682
  moved30d: month.length
@@ -8546,7 +9702,7 @@ var gatherDigest = /* @__PURE__ */ __name(async (store, env, { since, now = Date
8546
9702
  owedHere++;
8547
9703
  }
8548
9704
  if (owedHere)
8549
- owedNext.push(`memo tasks agenda --source ${name(key)} --unanswered 1m --within ${Math.ceil(owedWithin / DAY6)}d`);
9705
+ owedNext.push(`memo tasks agenda --source ${name(key)} --unanswered 1m --within ${Math.ceil(owedWithin / DAY7)}d`);
8550
9706
  for (const chatId of watched.chats.get(name(key)) ?? []) {
8551
9707
  const page = await store.messages.messages(key, chatId, { limit, since: iso(since) });
8552
9708
  for (const message of page.items)
@@ -8569,12 +9725,12 @@ var gatherDigest = /* @__PURE__ */ __name(async (store, env, { since, now = Date
8569
9725
  }
8570
9726
  for (const key of mailboxes) {
8571
9727
  const stored = await store.accounts.storedAccount(key);
8572
- const threads = await store.mail.threadActivity(stored.id, Math.min(owedSince, now - OWED_DAYS * DAY6));
9728
+ const threads = await store.mail.threadActivity(stored.id, Math.min(owedSince, now - OWED_DAYS * DAY7));
8573
9729
  const ref = /* @__PURE__ */ __name((thread) => formatReference({ type: "chat", provider: "email", account: key.account, chat: thread }), "ref");
8574
9730
  const newest = threads.reduce((most, thread) => Math.max(most, thread.lastEmailAt), 0);
8575
9731
  checkHealth(key, {
8576
9732
  newest: newest || null,
8577
- moved30d: threads.filter((thread) => thread.lastEmailAt >= now - 30 * DAY6).length
9733
+ moved30d: threads.filter((thread) => thread.lastEmailAt >= now - 30 * DAY7).length
8578
9734
  });
8579
9735
  mailMoved += threads.filter((thread) => thread.lastEmailAt >= since && thread.newest !== null && personal(thread.newest)).length;
8580
9736
  coverage.push({
@@ -8631,7 +9787,7 @@ var gatherDigest = /* @__PURE__ */ __name(async (store, env, { since, now = Date
8631
9787
  if (strangers.length)
8632
9788
  unknown2.next.push(`memo mail review --source ${name(key)} --unanswered 1m bulk:false`);
8633
9789
  if (newHere)
8634
- mailNext.push(`memo mail review --source ${name(key)} date>${days} bulk:false`);
9790
+ mailNext.push(`memo mail review --source ${name(key)} date>${days2} bulk:false`);
8635
9791
  }
8636
9792
  for (const uid of watched.people) {
8637
9793
  const person = await store.people.personByUid(uid);
@@ -8705,7 +9861,7 @@ var gatherDigest = /* @__PURE__ */ __name(async (store, env, { since, now = Date
8705
9861
  const isWatched = watched.projects.has(project.id) || watched.projects.has(project.ref);
8706
9862
  if (fresh.length === 0 && !isWatched)
8707
9863
  continue;
8708
- projectNext.push(`memo projects status ${project.key ?? project.ref} --since-time ${days}`);
9864
+ projectNext.push(`memo projects status ${project.key ?? project.ref} --since-time ${days2}`);
8709
9865
  if (fresh.length === 0)
8710
9866
  projects.push({
8711
9867
  item: { ref: project.ref, who: null, at: iso(since), excerpt: project.name, why: "watched project, quiet" }
@@ -8833,21 +9989,21 @@ var sinceOf = /* @__PURE__ */ __name((value, now = Date.now()) => {
8833
9989
  return since;
8834
9990
  }, "sinceOf");
8835
9991
  var reviewAgendaCommand = /* @__PURE__ */ __name((review, print, streams, env) => {
8836
- annotate(review.command("agenda"), { effects: LOCAL_READ }).summary("the morning digest: watch list, owed replies, mail, meetings, tasks, projects").description(`the morning digest, from the store alone with no model call: everything new in what you tagged ${WATCH_TAG} (chats, mail threads, people, projects, a meeting's series), replies you owe to people in messengers and personal mail (not bots or service chats), new personal mail, meetings that ended, tasks, projects that moved, proposals waiting. Tasks are the open ones created since the last morning-digest run (a day back when none ran) and those overdue, due today or due tomorrow, each with who asked and who does it. Replies owed reach back 7 days; owed mail lists only senders you know (linked to a person with other identities, or written to before), and mail from new senders is one count with the command that lists it. Each item has its reference, who, when, one line of text and why it is there; a section cut by --limit or --max-output-bytes says how many it left out and the command that reads them. \`scope\` says what was read (the window, sources, counts), \`tasks\` counts each task group, and \`health\` names each account whose sync failed, that nothing syncs, or that is quiet for longer than usual, so an unsynced account does not read as a quiet day`).option("--since-time <time>", "how far back: hours or days (12h, 7d) or a start date (2026-11-01)", "1d").option("--limit <n>", "items per section before the size budget", positive, 25).option("--max-output-bytes <bytes>", "the text answer's size budget in bytes; 40000 with --compact, else 80000", positive).option("--compact", "one line per item, shorter excerpts, the smaller budget: for an agent").option("--json", "print JSON").action(async (given) => {
8837
- if (given.compact && given.json)
9992
+ annotate(review.command("agenda"), { effects: LOCAL_READ }).summary("the morning digest: watch list, owed replies, mail, meetings, tasks, projects").description(`the morning digest, from the store alone with no model call: everything new in what you tagged ${WATCH_TAG} (chats, mail threads, people, projects, a meeting's series), replies you owe to people in messengers and personal mail (not bots or service chats), new personal mail, meetings that ended, tasks, projects that moved, proposals waiting. Tasks are the open ones created since the last morning-digest run (a day back when none ran) and those overdue, due today or due tomorrow, each with who asked and who does it. Replies owed reach back 7 days; owed mail lists only senders you know (linked to a person with other identities, or written to before), and mail from new senders is one count with the command that lists it. Each item has its reference, who, when, one line of text and why it is there; a section cut by --limit or --max-output-bytes says how many it left out and the command that reads them. \`scope\` says what was read (the window, sources, counts), \`tasks\` counts each task group, and \`health\` names each account whose sync failed, that nothing syncs, or that is quiet for longer than usual, so an unsynced account does not read as a quiet day`).option("--since-time <time>", "how far back: hours or days (12h, 7d) or a start date (2026-11-01)", "1d").option("--limit <n>", "items per section before the size budget", positive, 25).option("--max-output-bytes <bytes>", "the text answer's size budget in bytes; 40000 with --compact, else 80000", positive).option("--compact", "one line per item, shorter excerpts, the smaller budget: for an agent").option("--json", "print JSON").action(async (given2) => {
9993
+ if (given2.compact && given2.json)
8838
9994
  throw new CliError("validation_error", "--compact and --json ask for different output \u2014 pick one", {
8839
9995
  reason: "output.conflict",
8840
9996
  param: "--compact"
8841
9997
  });
8842
- const since = sinceOf(given.sinceTime);
9998
+ const since = sinceOf(given2.sinceTime);
8843
9999
  const gathered = await withStore(env, (store) => gatherDigest(store, env, {
8844
10000
  since,
8845
- limit: given.limit,
8846
- excerpt: given.compact ? 100 : 200,
10001
+ limit: given2.limit,
10002
+ excerpt: given2.compact ? 100 : 200,
8847
10003
  owedWithin: OWED_WITHIN
8848
10004
  }));
8849
- const digest = fitDigest(gathered, given.maxOutputBytes ?? (given.compact ? COMPACT_BYTES : FULL_BYTES));
8850
- if (given.json)
10005
+ const digest = fitDigest(gathered, given2.maxOutputBytes ?? (given2.compact ? COMPACT_BYTES : FULL_BYTES));
10006
+ if (given2.json)
8851
10007
  print(true, itemAnswer(digest));
8852
10008
  else
8853
10009
  streams.data(`${digestText(digest)}
@@ -8910,32 +10066,32 @@ var ROW = {
8910
10066
  ],
8911
10067
  text: ["reason"]
8912
10068
  };
8913
- var json6 = /* @__PURE__ */ __name((command) => command.option("--json", "print JSON; --json=id,title keeps only those fields"), "json");
10069
+ var json4 = /* @__PURE__ */ __name((command) => command.option("--json", "print JSON; --json=id,title keeps only those fields"), "json");
8914
10070
  var reviewCommand = /* @__PURE__ */ __name((program, streams, env) => {
8915
10071
  const { print } = answers(program, streams, env);
8916
10072
  const review = program.command("review").description("every proposal waiting for your decision, across projects: links, key documents, facts, invoices, payments and more").summary("every proposal waiting for your decision, across projects");
8917
- json6(answerEntity(withQuery(annotate(review.command("list", { isDefault: true }), { effects: LOCAL_READ }).description("what waits for the owner's decision, newest first, with titles, who proposed it, why and the evidence").summary("what waits for your decision, newest first, with titles and evidence"), REVIEW_QUERY), "memo_proposal", PROPOSAL, { row: ROW })).option("--limit <n>", "proposals per page, at most 50", positive, 20).option("--page <n>", "which page, from 1", positive, 1).option("--compact", "one line per proposal").action(async (words, given) => {
8918
- if (given.limit > 50)
10073
+ json4(answerEntity(withQuery(annotate(review.command("list", { isDefault: true }), { effects: LOCAL_READ }).description("what waits for the owner's decision, newest first, with titles, who proposed it, why and the evidence").summary("what waits for your decision, newest first, with titles and evidence"), REVIEW_QUERY), "memo_proposal", PROPOSAL, { row: ROW })).option("--limit <n>", "proposals per page, at most 50", positive, 20).option("--page <n>", "which page, from 1", positive, 1).option("--compact", "one line per proposal").action(async (words, given2) => {
10074
+ if (given2.limit > 50)
8919
10075
  throw new CliError("validation_error", "--limit is at most 50", { param: "limit" });
8920
- const found = await withStore(env, (store) => listReview(store, env, words, given));
10076
+ const found = await withStore(env, (store) => listReview(store, env, words, given2));
8921
10077
  const steps = reviewSteps(found.items);
8922
10078
  const body = listAnswer("review list", {
8923
10079
  items: found.items,
8924
- limit: given.limit,
8925
- page: given.page,
10080
+ limit: given2.limit,
10081
+ page: given2.page,
8926
10082
  has_more: found.hasMore,
8927
- args: { query: words.join(" "), limit: given.limit },
10083
+ args: { query: words.join(" "), limit: given2.limit },
8928
10084
  ...steps.length ? { next: steps } : {}
8929
10085
  });
8930
- print(given.json, body, reviewText(found.items, found.hasMore), given.compact);
10086
+ print(given2.json, body, reviewText(found.items, found.hasMore), given2.compact);
8931
10087
  });
8932
- json6(annotate(review.command("show"), { effects: LOCAL_READ })).description("one proposal with its titles, signals and the text around each piece of evidence").argument("<id>", "the proposal's id, as review lists it: 17070, fact:512, memory:88, link:17, payment:4, close:Q-15").option("--brief", "only references and their titles, without excerpts or nearby text").option("--before-n <n>", "messages or document paragraphs before the evidence, at most 5", whole, 2).option("--after-n <n>", "messages or document paragraphs after the evidence, at most 5", whole, 2).option("--compact", "one line, as review prints it").action(async (id, given) => {
10088
+ json4(annotate(review.command("show"), { effects: LOCAL_READ })).description("one proposal with its titles, signals and the text around each piece of evidence").argument("<id>", "the proposal's id, as review lists it: 17070, fact:512, memory:88, link:17, payment:4, close:Q-15").option("--brief", "only references and their titles, without excerpts or nearby text").option("--before-n <n>", "messages or document paragraphs before the evidence, at most 5", whole, 2).option("--after-n <n>", "messages or document paragraphs after the evidence, at most 5", whole, 2).option("--compact", "one line, as review prints it").action(async (id, given2) => {
8933
10089
  const body = await withStore(env, async (store) => {
8934
10090
  const shown2 = await showReview(store, env, id);
8935
10091
  const window = {
8936
- brief: given.brief === true,
8937
- before: Math.min(given.beforeN, 5),
8938
- after: Math.min(given.afterN, 5)
10092
+ brief: given2.brief === true,
10093
+ before: Math.min(given2.beforeN, 5),
10094
+ after: Math.min(given2.afterN, 5)
8939
10095
  };
8940
10096
  const evidence = await Promise.all(shown2.evidence.map(async (one2) => {
8941
10097
  const sender = window.brief ? null : await senderOf(store, one2.ref);
@@ -8948,35 +10104,35 @@ var reviewCommand = /* @__PURE__ */ __name((program, streams, env) => {
8948
10104
  }));
8949
10105
  return itemAnswer({ ...shown2, evidence });
8950
10106
  });
8951
- print(given.json, body, void 0, given.compact);
10107
+ print(given2.json, body, void 0, given2.compact);
8952
10108
  });
8953
10109
  for (const name2 of ["confirm", "reject"]) {
8954
- const command = byOption(json6(annotate(review.command(name2), { effects: LOCAL_WRITE }))).description(name2 === "confirm" ? "confirm proposals by id or range (17070-17079,fact:500-502,17080/f1); each is decided on its own, so a refusal leaves the others decided. An agent decides only with --reason, never its own or a scan's" : "turn proposals down by id or range, with why; each is decided on its own").summary(name2 === "confirm" ? "confirm proposals by id or range; each on its own" : "turn proposals down, with why").argument("<ids...>", name2 === "confirm" ? "ids or ranges as review lists them; 17080/f1 accepts that finding and rejects the batch's others" : "ids or ranges as review lists them; a batch is turned down whole");
10110
+ const command = byOption(json4(annotate(review.command(name2), { effects: LOCAL_WRITE }))).description(name2 === "confirm" ? "confirm proposals by id or range (17070-17079,fact:500-502,17080/f1); each is decided on its own, so a refusal leaves the others decided. An agent decides only with --reason, never its own or a scan's" : "turn proposals down by id or range, with why; each is decided on its own").summary(name2 === "confirm" ? "confirm proposals by id or range; each on its own" : "turn proposals down, with why").argument("<ids...>", name2 === "confirm" ? "ids or ranges as review lists them; 17080/f1 accepts that finding and rejects the batch's others" : "ids or ranges as review lists them; a batch is turned down whole");
8955
10111
  if (name2 === "confirm")
8956
10112
  command.option("--reason <text>", "why, in a few words; required when an agent decides");
8957
10113
  else
8958
10114
  command.requiredOption("--reason <text>", "why it is turned down, in a few words");
8959
10115
  command.option("--compact", "one line per decision");
8960
- command.action(async (words, given) => {
10116
+ command.action(async (words, given2) => {
8961
10117
  const ids = parseProposalIds(words);
8962
10118
  const by = await deciderOf(command, env, {
8963
- ...given,
10119
+ ...given2,
8964
10120
  question: `${name2} ${ids.length} proposal${ids.length === 1 ? "" : "s"} as you, the owner?`
8965
10121
  });
8966
- const result = await withStore(env, (store) => reviewRegistry(store).decide(ids, decisionOf(name2 === "confirm", by, given.reason)));
10122
+ const result = await withStore(env, (store) => reviewRegistry(store).decide(ids, decisionOf(name2 === "confirm", by, given2.reason)));
8967
10123
  const issues = result.refused.map((one2) => ({
8968
10124
  code: one2.code,
8969
10125
  source: one2.id,
8970
10126
  ...one2.reason.includes(".") ? { reason: one2.reason } : {}
8971
10127
  }));
8972
- print(given.json, itemAnswer(result, issues.length ? { meta: { complete: false, issues } } : void 0), decidedText(result), given.compact);
10128
+ print(given2.json, itemAnswer(result, issues.length ? { meta: { complete: false, issues } } : void 0), decidedText(result), given2.compact);
8973
10129
  });
8974
10130
  }
8975
10131
  reviewAgendaCommand(review, print, streams, env);
8976
- json6(answerEntity(annotate(review.command("status"), { effects: LOCAL_READ }), "review_status", REVIEW_STATUS)).summary("since yesterday: new mail, what is owed and waiting, what agents proposed").description("the owner's daily look, with no model call: per mail account the threads with new mail, what you owe and wait for, and how far each agent's processing mark has read; then what was proposed and what waits").option("--since-time <time>", "how far back: hours or days (12h, 7d) or a start date (2026-11-01)", "1d").action(async (given) => {
8977
- const since = sinceOf(given.sinceTime);
10132
+ json4(answerEntity(annotate(review.command("status"), { effects: LOCAL_READ }), "review_status", REVIEW_STATUS)).summary("since yesterday: new mail, what is owed and waiting, what agents proposed").description("the owner's daily look, with no model call: per mail account the threads with new mail, what you owe and wait for, and how far each agent's processing mark has read; then what was proposed and what waits").option("--since-time <time>", "how far back: hours or days (12h, 7d) or a start date (2026-11-01)", "1d").action(async (given2) => {
10133
+ const since = sinceOf(given2.sinceTime);
8978
10134
  const status = await withStore(env, (store) => reviewStatus(store, env, since));
8979
- print(given.json, itemAnswer(status), reviewStatusText(status));
10135
+ print(given2.json, itemAnswer(status), reviewStatusText(status));
8980
10136
  });
8981
10137
  }, "reviewCommand");
8982
10138
 
@@ -8990,10 +10146,10 @@ var embedPerRun = /* @__PURE__ */ __name((env = process.env) => {
8990
10146
  return Math.max(8, Math.min(EMBED_PER_RUN, Math.round(EMBED_PER_RUN * ratio)));
8991
10147
  }, "embedPerRun");
8992
10148
  var missingModel = /* @__PURE__ */ __name((error, env) => {
8993
- const named4 = isCliError(error) ? error.details.model : void 0;
8994
- const id = typeof named4 === "string" ? named4 : chosenTextModel(env).id;
8995
- const terms = textModels(env).find((model) => model.id === id)?.terms;
8996
- return `the ${id} model is not downloaded \u2014 memo models download ${id}${terms ? " --accept-terms" : ""}`;
10149
+ const named5 = isCliError(error) ? error.details.model : void 0;
10150
+ const id = typeof named5 === "string" ? named5 : chosenTextModel(env).id;
10151
+ const terms2 = textModels(env).find((model) => model.id === id)?.terms;
10152
+ return `the ${id} model is not downloaded \u2014 memo models download ${id}${terms2 ? " --accept-terms" : ""}`;
8997
10153
  }, "missingModel");
8998
10154
  var isMissingModel = /* @__PURE__ */ __name((error) => isCliError(error) && error.details.reason === "model.not-downloaded", "isMissingModel");
8999
10155
  var reportOf = /* @__PURE__ */ __name((run) => {
@@ -9025,18 +10181,18 @@ var reportOf = /* @__PURE__ */ __name((run) => {
9025
10181
  ...run.reason === void 0 ? {} : { reason: run.reason }
9026
10182
  };
9027
10183
  }, "reportOf");
9028
- var combinedEnrichment = /* @__PURE__ */ __name((...parts) => {
9029
- const present2 = parts.filter((part) => part !== void 0);
10184
+ var combinedEnrichment = /* @__PURE__ */ __name((...parts2) => {
10185
+ const present2 = parts2.filter((part) => part !== void 0);
9030
10186
  if (present2.length === 0)
9031
10187
  return void 0;
9032
10188
  const rank = { done: 0, stopped: 1, failed: 2 };
9033
10189
  const worst = present2.reduce((a, b) => rank[b.status] > rank[a.status] ? b : a);
9034
- const named4 = present2.find((part) => part.provider !== void 0);
10190
+ const named5 = present2.find((part) => part.provider !== void 0);
9035
10191
  const costs = present2.map((part) => part.costUsd);
9036
10192
  return {
9037
10193
  status: worst.status,
9038
- ...named4?.provider === void 0 ? {} : { provider: named4.provider },
9039
- ...named4?.model === void 0 ? {} : { model: named4.model },
10194
+ ...named5?.provider === void 0 ? {} : { provider: named5.provider },
10195
+ ...named5?.model === void 0 ? {} : { model: named5.model },
9040
10196
  sent: present2.reduce((sum, part) => sum + part.sent, 0),
9041
10197
  enriched: present2.reduce((sum, part) => sum + part.enriched, 0),
9042
10198
  failed: present2.reduce((sum, part) => sum + part.failed, 0),
@@ -9100,10 +10256,10 @@ var embedMailChunks = /* @__PURE__ */ __name(async (store, { embed = true, env,
9100
10256
 
9101
10257
  // dist/progress.js
9102
10258
  var EVERY_MS = 500;
9103
- var progressLine = /* @__PURE__ */ __name((diagnostic, json7, { step, unit, label }) => {
10259
+ var progressLine2 = /* @__PURE__ */ __name((diagnostic, json5, { step, unit, label }) => {
9104
10260
  let last = Number.NEGATIVE_INFINITY;
9105
10261
  return (done, total) => {
9106
- if (!json7)
10262
+ if (!json5)
9107
10263
  return;
9108
10264
  const now = Date.now();
9109
10265
  if (done !== total && now - last < EVERY_MS)
@@ -9230,7 +10386,7 @@ var syncCommand = /* @__PURE__ */ __name((program, streams, env, signal, keyring
9230
10386
  const skip = options.ignore ?? [];
9231
10387
  for (const folder of folders)
9232
10388
  await attempt(`notes ${folder.path}`, async () => {
9233
- const onFile = progressLine(streams.diagnostic, Boolean(options.json), {
10389
+ const onFile = progressLine2(streams.diagnostic, Boolean(options.json), {
9234
10390
  step: "notes",
9235
10391
  unit: "files",
9236
10392
  label: folder.id
@@ -9397,20 +10553,20 @@ var mailTriageInput = /* @__PURE__ */ __name((mailboxes) => async (schedule, run
9397
10553
  if (!holder)
9398
10554
  return void 0;
9399
10555
  const skill2 = await run(["skill", "show", SKILL]);
9400
- const parts = [PREAMBLE, "# The skill", skill2.trim(), "# The review"];
10556
+ const parts2 = [PREAMBLE, "# The skill", skill2.trim(), "# The review"];
9401
10557
  const separator = "\n\n";
9402
- let used = parts.join(separator).length + separator.length * 2;
10558
+ let used = parts2.join(separator).length + separator.length * 2;
9403
10559
  let alone = true;
9404
10560
  for (const address of await mailboxes()) {
9405
10561
  const source = `email:${address}`;
9406
10562
  const review = JSON.parse(await run(["mail", "review", "--holder", holder, "--source", source, `--json=${FIELDS}`]));
9407
10563
  const block = mailboxBlock(source, review, INPUT_BUDGET - used - separator.length, alone);
9408
- parts.push(block);
10564
+ parts2.push(block);
9409
10565
  used += block.length + separator.length;
9410
10566
  if (block.includes("\nemails, one JSON per line:"))
9411
10567
  alone = false;
9412
10568
  }
9413
- return [...parts, ""].join(separator);
10569
+ return [...parts2, ""].join(separator);
9414
10570
  }, "mailTriageInput");
9415
10571
 
9416
10572
  // dist/schedule/command.js
@@ -9456,7 +10612,7 @@ var BRIEF = ["ref", "chat_title", "timestamp", "sender_name", "excerpt", "score"
9456
10612
  var briefHit = /* @__PURE__ */ __name((hit) => Object.fromEntries(BRIEF.flatMap((key) => hit[key] === void 0 || hit[key] === null ? [] : [[key, hit[key]]])), "briefHit");
9457
10613
 
9458
10614
  // dist/search/answers.js
9459
- var named3 = /* @__PURE__ */ __name((accounts) => [
10615
+ var named4 = /* @__PURE__ */ __name((accounts) => [
9460
10616
  ...new Set(accounts.map(({ provider, account: account2 }) => `${provider}:${account2}`))
9461
10617
  ], "named");
9462
10618
  var metaOf2 = /* @__PURE__ */ __name((accounts, skipped = [], heldInPart = false) => {
@@ -9467,7 +10623,7 @@ var metaOf2 = /* @__PURE__ */ __name((accounts, skipped = [], heldInPart = false
9467
10623
  source: one2.source ?? one2.resource ?? ""
9468
10624
  }));
9469
10625
  return {
9470
- accounts: named3(accounts),
10626
+ accounts: named4(accounts),
9471
10627
  ...heldInPart ? { complete: false } : {},
9472
10628
  ...issues.length ? { issues } : {}
9473
10629
  };
@@ -9721,8 +10877,8 @@ For an agent: read with --compact, one line per hit with its reference. Never wr
9721
10877
  for (const { source, reason } of answer.skipped)
9722
10878
  streams.diagnostic(`${source} not searched: ${reason}
9723
10879
  `);
9724
- const { limit, page, json: json7, ...rest } = options;
9725
- print(json7, notesAnswer(answer, limit, page, { query: words.join(" "), ...rest }), searchText(answer, (page - 1) * limit));
10880
+ const { limit, page, json: json5, ...rest } = options;
10881
+ print(json5, notesAnswer(answer, limit, page, { query: words.join(" "), ...rest }), searchText(answer, (page - 1) * limit));
9726
10882
  });
9727
10883
  searchMemoriesCommand(group, streams, env);
9728
10884
  annotate(group.command("people"), { effects: LOCAL_READ, output: { entity: "person" } }).description("people whose name, username or alias holds every word, in every account unless --source narrows it; each with its person:<id> for --contact and its identities").summary("people by name across every account").argument("<name...>", "parts of the name, username or alias; case and accents do not matter").option("--source <accounts>", ACCOUNTS_HELP).option("--limit <n>", "most people, at most 100", (value) => {
@@ -9766,7 +10922,13 @@ var LOCAL_OPENS = {
9766
10922
  order: ["memo", "orders", "show"],
9767
10923
  deal: ["memo", "deals", "show"],
9768
10924
  lead: ["memo", "leads", "show"],
9769
- pipeline: ["memo", "pipelines", "show"]
10925
+ pipeline: ["memo", "pipelines", "show"],
10926
+ product: ["memo", "products", "show"],
10927
+ contract: ["memo", "contracts", "show"],
10928
+ subscription: ["memo", "subscriptions", "show"],
10929
+ wallet: ["memo", "wallets", "show"],
10930
+ transaction: ["memo", "transactions", "show"],
10931
+ event: ["memo", "events", "show"]
9770
10932
  };
9771
10933
  var openKeyOf = /* @__PURE__ */ __name((kind) => LOCAL_OPENS[kind]?.slice(1).join("."), "openKeyOf");
9772
10934
  var refuseDenied = /* @__PURE__ */ __name((command, summaries) => {
@@ -9781,12 +10943,12 @@ var refuseDenied = /* @__PURE__ */ __name((command, summaries) => {
9781
10943
  }, "refuseDenied");
9782
10944
  var OTHERS = /* @__PURE__ */ new Set(["message", "chat", "contact", "email", "email_thread", "document", "event", "meeting", "bot"]);
9783
10945
  var ACCOUNT_KEY = /^[a-z][a-z-]*:\S+$/;
9784
- var taskOpen = /* @__PURE__ */ __name((summary, open) => {
9785
- if (summary.kind !== "task" || open.argv === null)
9786
- return open;
9787
- const argv = [...open.argv.slice(0, -1), summary.ref.slice("task:".length)];
10946
+ var taskOpen = /* @__PURE__ */ __name((summary, open2) => {
10947
+ if (summary.kind !== "task" || open2.argv === null)
10948
+ return open2;
10949
+ const argv = [...open2.argv.slice(0, -1), summary.ref.slice("task:".length)];
9788
10950
  return {
9789
- ...open,
10951
+ ...open2,
9790
10952
  argv: summary.in !== null && ACCOUNT_KEY.test(summary.in) ? [...argv, "--source", summary.in] : argv
9791
10953
  };
9792
10954
  }, "taskOpen");
@@ -9807,7 +10969,7 @@ var showReferences = /* @__PURE__ */ __name(async (store, env, texts, command) =
9807
10969
  if (command !== void 0)
9808
10970
  refuseDenied(command, [...summaries.values()]);
9809
10971
  const ports = { profilesFor: profilesFor(env), local: LOCAL_OPENS };
9810
- return texts.map((text3) => {
10972
+ const shown2 = texts.map((text3) => {
9811
10973
  const summary = summaries.get(text3) ?? {
9812
10974
  ref: text3,
9813
10975
  kind: "unknown",
@@ -9819,7 +10981,7 @@ var showReferences = /* @__PURE__ */ __name(async (store, env, texts, command) =
9819
10981
  tool: null,
9820
10982
  state: "unavailable"
9821
10983
  };
9822
- const open = taskOpen(summary, openOf(summary, ports));
10984
+ const open2 = taskOpen(summary, openOf(summary, ports));
9823
10985
  return {
9824
10986
  ref: summary.ref,
9825
10987
  kind: summary.kind,
@@ -9827,19 +10989,31 @@ var showReferences = /* @__PURE__ */ __name(async (store, env, texts, command) =
9827
10989
  in: summary.in,
9828
10990
  at: summary.at,
9829
10991
  provider: summary.provider,
9830
- tool: summary.tool ?? open.argv?.[0] ?? null,
10992
+ tool: summary.tool ?? open2.argv?.[0] ?? null,
9831
10993
  state: summary.state,
9832
- open: { ...open, line: open.argv?.map(shellWord).join(" ") ?? null },
10994
+ open: { ...open2, line: open2.argv?.map(shellWord).join(" ") ?? null },
9833
10995
  ...OTHERS.has(summary.kind) ? { untrusted: ["title", "in"] } : {}
9834
10996
  };
9835
10997
  });
10998
+ const withRecords = command === void 0 || !recordsHidden(command);
10999
+ for (const one2 of shown2) {
11000
+ const entity = one2.state === "available" ? await readSourced(store, one2.kind, one2.ref) : void 0;
11001
+ if (entity === void 0)
11002
+ continue;
11003
+ if (withRecords)
11004
+ one2.sources = await sourcesOf(store, entity);
11005
+ if (imported(entity))
11006
+ one2.untrusted = ["title"];
11007
+ }
11008
+ return shown2;
9836
11009
  }, "showReferences");
9837
11010
  var minute2 = /* @__PURE__ */ __name((at) => at === null ? null : at.slice(0, 16).replace("T", " "), "minute");
9838
11011
  var blockOf = /* @__PURE__ */ __name((one2) => [
9839
11012
  `${one2.ref} ${one2.title ?? ""}`.trimEnd(),
9840
11013
  ` ${[one2.kind, one2.in, one2.state, minute2(one2.at)].filter((part) => part !== null).join(" \xB7 ")}`,
9841
11014
  ` open: ${one2.open.line ?? "none"}`,
9842
- ...one2.open.why === null ? [] : [` ${one2.open.why}`]
11015
+ ...one2.open.why === null ? [] : [` ${one2.open.why}`],
11016
+ ...one2.sources === void 0 ? [] : sourcesText(one2.ref, one2.sources)
9843
11017
  ].join("\n"), "blockOf");
9844
11018
  var showCommand = /* @__PURE__ */ __name((program, streams, env) => {
9845
11019
  const { print } = answers(program, streams, env);
@@ -9933,7 +11107,7 @@ var tagsCommand = /* @__PURE__ */ __name((program, streams, env) => {
9933
11107
  const tags = program.command("tags").description("your labels on stored sources and folders or threads");
9934
11108
  const { print } = answers(program, streams, env);
9935
11109
  const warn = /* @__PURE__ */ __name((text3) => streams.diagnostic(text3), "warn");
9936
- const mutate = /* @__PURE__ */ __name(async (operation, given, { account: account2, ...options }) => {
11110
+ const mutate = /* @__PURE__ */ __name(async (operation, given2, { account: account2, ...options }) => {
9937
11111
  const value = writeAccountOf({ account: account2 }, warn);
9938
11112
  const scoped3 = /* @__PURE__ */ __name(async (store) => value === void 0 ? {} : oneAccountOf(store, env, value, "--account"), "scoped");
9939
11113
  const target = options.note !== void 0 ? options.note.startsWith("document:") ? { type: "document", id: options.note.slice("document:".length) } : { type: "note", id: options.note.replace(/^note:/, "") } : options.person !== void 0 ? { type: "person", id: options.person.replace(/^person:/, "") } : options.organization !== void 0 ? { type: "organization", id: options.organization.replace(/^organization:/, "") } : options.project !== void 0 ? { type: "project", id: options.project } : options.task !== void 0 ? { type: "task", id: options.task.replace(/^task:/, "") } : options.folder !== void 0 ? { type: "folder", id: options.folder, path: options.subfolder ?? null } : void 0;
@@ -9949,7 +11123,7 @@ var tagsCommand = /* @__PURE__ */ __name((program, streams, env) => {
9949
11123
  throw new CliError("not_found", `no folder of notes ${target.id}`, { reason: "folder.not-found" });
9950
11124
  target.id = id;
9951
11125
  }
9952
- const changed = await (operation === "add" ? store.knowledge.addTags : store.knowledge.removeTags)(null, target, given);
11126
+ const changed = await (operation === "add" ? store.knowledge.addTags : store.knowledge.removeTags)(null, target, given2);
9953
11127
  print(options.json, itemAnswer({ target, [operation === "add" ? "added" : "removed"]: changed }), `${operation}: ${changed.join(", ") || "no labels changed"}`);
9954
11128
  });
9955
11129
  return;
@@ -9957,14 +11131,14 @@ var tagsCommand = /* @__PURE__ */ __name((program, streams, env) => {
9957
11131
  if (options.contact !== void 0 || options.meeting !== void 0) {
9958
11132
  await withStore(env, async (store) => {
9959
11133
  const { key, target: target2 } = await selectTarget(store, { ...options, ...await scoped3(store) });
9960
- const changed = await (operation === "add" ? store.knowledge.addTags : store.knowledge.removeTags)(key, target2, given);
11134
+ const changed = await (operation === "add" ? store.knowledge.addTags : store.knowledge.removeTags)(key, target2, given2);
9961
11135
  print(options.json, itemAnswer({ ...key, target: target2, [operation === "add" ? "added" : "removed"]: changed }), `${operation}: ${changed.join(", ") || "no labels changed"}`);
9962
11136
  });
9963
11137
  return;
9964
11138
  }
9965
11139
  if (options.message !== void 0 && value !== void 0)
9966
11140
  throw new CliError("validation_error", "a message locator names its account and chat \u2014 use --message alone");
9967
- const labels = [...new Set(given.map(normalizeTag))];
11141
+ const labels = [...new Set(given2.map(normalizeTag))];
9968
11142
  await withStore(env, async (store) => {
9969
11143
  const selected = sourceTarget({ ...options, ...await scoped3(store) });
9970
11144
  const changed = await (operation === "add" ? store.tags.addTags : store.tags.removeTags)(selected.key, selected.target, labels);
@@ -9980,17 +11154,17 @@ var tagsCommand = /* @__PURE__ */ __name((program, streams, env) => {
9980
11154
  });
9981
11155
  }, "mutate");
9982
11156
  for (const operation of ["add", "remove"])
9983
- targetOptions(annotate(tags.command(operation), { effects: LOCAL_WRITE }).description(operation === "add" ? "put labels on one source" : "remove labels from one source")).action((given, options) => mutate(operation, given, options));
11157
+ targetOptions(annotate(tags.command(operation), { effects: LOCAL_WRITE }).description(operation === "add" ? "put labels on one source" : "remove labels from one source")).action((given2, options) => mutate(operation, given2, options));
9984
11158
  const tagsList = withQuery(annotate(tags.command("list"), { effects: LOCAL_READ, output: { entity: "source_tag" } }).description("list source labels, of every account or of the ones --source names"), TAG_QUERY);
9985
- sourceOptions(tagsList, `only these accounts (default: every one): ${ACCOUNTS_HELP}`).option("--limit <n>", "most labels to show", positive, 100).option("--json", "print JSON; --json=id,title keeps only those fields").action(async (words, given) => {
9986
- const terms = queryTerms(words, TAG_QUERY, "tags list");
9987
- const tag = terms.get("tag");
9988
- const value = sourceOf(given, warn);
11159
+ sourceOptions(tagsList, `only these accounts (default: every one): ${ACCOUNTS_HELP}`).option("--limit <n>", "most labels to show", positive, 100).option("--json", "print JSON; --json=id,title keeps only those fields").action(async (words, given2) => {
11160
+ const terms2 = queryTerms(words, TAG_QUERY, "tags list");
11161
+ const tag = terms2.get("tag");
11162
+ const value = sourceOf(given2, warn);
9989
11163
  const options = {
9990
- limit: given.limit,
9991
- ...given.json === void 0 ? {} : { json: given.json },
11164
+ limit: given2.limit,
11165
+ ...given2.json === void 0 ? {} : { json: given2.json },
9992
11166
  ...tag === void 0 ? {} : { tag: normalizeTag(tag) },
9993
- ...terms.has("type") ? { type: terms.get("type") } : {}
11167
+ ...terms2.has("type") ? { type: terms2.get("type") } : {}
9994
11168
  };
9995
11169
  await withStore(env, async (store) => {
9996
11170
  const keys = value === void 0 ? await store.accounts.accounts() : await accountsOf(store, env, value);
@@ -10065,8 +11239,8 @@ var requireAccount = /* @__PURE__ */ __name((env, warn) => async (_, command) =>
10065
11239
  return;
10066
11240
  if (["show", "update", "claim", "release"].includes(command.name()) && first !== void 0 && await store.tasks.projectTask(first))
10067
11241
  return;
10068
- const listed = (await store.accounts.accounts()).map((key) => `${option} ${key.provider}:${key.account}`).join("; ");
10069
- throw new CliError("validation_error", `give ${option} \u2014 the stored accounts: ${listed || "none yet"}`);
11242
+ const listed2 = (await store.accounts.accounts()).map((key) => `${option} ${key.provider}:${key.account}`).join("; ");
11243
+ throw new CliError("validation_error", `give ${option} \u2014 the stored accounts: ${listed2 || "none yet"}`);
10070
11244
  } finally {
10071
11245
  await store.close();
10072
11246
  }
@@ -10090,7 +11264,7 @@ var sharedTaskCommands = /* @__PURE__ */ __name((program, tasks, streams, env) =
10090
11264
 
10091
11265
  // dist/tasks/tasks.js
10092
11266
  var personRef = /* @__PURE__ */ __name((person) => person.startsWith("person:") ? person : `person:${person}`, "personRef");
10093
- var fieldsOf2 = /* @__PURE__ */ __name((options) => ({
11267
+ var fieldsOf4 = /* @__PURE__ */ __name((options) => ({
10094
11268
  ...options.title === void 0 ? {} : { title: options.title },
10095
11269
  ...options.priority === void 0 ? {} : { priority: options.priority },
10096
11270
  ...options.parent === void 0 ? {} : { parent: options.parent },
@@ -10114,7 +11288,7 @@ var addToProject = /* @__PURE__ */ __name(async (store, env, options) => {
10114
11288
  project: await canonicalProject(store, options.project),
10115
11289
  title: options.title,
10116
11290
  type,
10117
- ...fieldsOf2(options),
11291
+ ...fieldsOf4(options),
10118
11292
  ...options.due === void 0 || options.due === "none" ? {} : { dueAt: options.due },
10119
11293
  ...options.status === void 0 ? {} : { status: options.status },
10120
11294
  ...options.agent === void 0 ? {} : { agent: options.agent }
@@ -10149,7 +11323,7 @@ var addFromSource = /* @__PURE__ */ __name(async (store, env, source, options) =
10149
11323
  ...options.into === void 0 ? {} : { attach: options.into },
10150
11324
  ...options.new ? { new: true } : {}
10151
11325
  }, author);
10152
- const fields = fieldsOf2(options);
11326
+ const fields = fieldsOf4(options);
10153
11327
  if (Object.keys(fields).length === 0 && !options.assignee?.length)
10154
11328
  return answer;
10155
11329
  await store.tasks.edit(answer.task.id, fields, "owner");
@@ -10178,7 +11352,7 @@ var closeTask = /* @__PURE__ */ __name(async (store, env, id, options) => {
10178
11352
  });
10179
11353
  }, "closeTask");
10180
11354
  var updateTask = /* @__PURE__ */ __name(async (store, env, id, options) => {
10181
- const fields = fieldsOf2(options);
11355
+ const fields = fieldsOf4(options);
10182
11356
  const times = {
10183
11357
  ...options.due === void 0 ? {} : { dueAt: options.due },
10184
11358
  ...options.remindTime === void 0 ? {} : { nextCheckAt: options.remindTime }
@@ -10220,15 +11394,15 @@ var moveTask = /* @__PURE__ */ __name((store, env, id, options) => {
10220
11394
  var commentTask = /* @__PURE__ */ __name((store, env, id, text3) => store.tasks.comment(id, text3, authorOf(env)), "commentTask");
10221
11395
  var taskHistory = /* @__PURE__ */ __name(async (store, id) => {
10222
11396
  const owner = (await store.people.owner())?.uid;
10223
- return (await store.tasks.events(id)).map((event) => ({
10224
- at: event.at,
10225
- kind: event.kind,
10226
- by: event.actor && {
10227
- ref: `${event.actor.type}:${event.actor.id}`,
10228
- name: event.actor.name,
10229
- owner: event.actor.type === "person" && String(event.actor.id) === String(owner)
11397
+ return (await store.tasks.events(id)).map((event2) => ({
11398
+ at: event2.at,
11399
+ kind: event2.kind,
11400
+ by: event2.actor && {
11401
+ ref: `${event2.actor.type}:${event2.actor.id}`,
11402
+ name: event2.actor.name,
11403
+ owner: event2.actor.type === "person" && String(event2.actor.id) === String(owner)
10230
11404
  },
10231
- changes: event.changes
11405
+ changes: event2.changes
10232
11406
  }));
10233
11407
  }, "taskHistory");
10234
11408
 
@@ -10307,11 +11481,11 @@ var tasksCommand2 = /* @__PURE__ */ __name((program, streams, env) => {
10307
11481
  const description = command.options.find((option) => option.long === "--description");
10308
11482
  if (description)
10309
11483
  description.description = "the detail, in Markdown; none clears it";
10310
- command.action(async (id, given) => {
10311
- const raw = given;
11484
+ command.action(async (id, given2) => {
11485
+ const raw = given2;
10312
11486
  const options = {
10313
- ...given,
10314
- ...typeof given.description === "string" && given.description.trim().toLowerCase() === "none" ? { description: null } : {},
11487
+ ...given2,
11488
+ ...typeof given2.description === "string" && given2.description.trim().toLowerCase() === "none" ? { description: null } : {},
10315
11489
  priority: raw.priority === "none" ? null : raw.priority,
10316
11490
  parent: raw.parent === null || raw.parent === "none" ? null : raw.parent,
10317
11491
  due: raw.due === "none" ? null : raw.due,
@@ -10362,10 +11536,10 @@ var VOCABULARY_QUERY = {
10362
11536
  ]
10363
11537
  };
10364
11538
  var vocabularyFilter = /* @__PURE__ */ __name((query, command) => {
10365
- const terms = queryTerms(query, VOCABULARY_QUERY, command);
11539
+ const terms2 = queryTerms(query, VOCABULARY_QUERY, command);
10366
11540
  return {
10367
- ...terms.has("kind") ? { kind: terms.get("kind") } : {},
10368
- ...terms.has("scope") ? { scope: terms.get("scope") } : {}
11541
+ ...terms2.has("kind") ? { kind: terms2.get("kind") } : {},
11542
+ ...terms2.has("scope") ? { scope: terms2.get("scope") } : {}
10369
11543
  };
10370
11544
  }, "vocabularyFilter");
10371
11545
 
@@ -10545,6 +11719,10 @@ var OWN_ENTITIES = entityFields({
10545
11719
  "fulfilled_date",
10546
11720
  "invoice",
10547
11721
  "payment",
11722
+ "direction",
11723
+ "contract",
11724
+ "deal",
11725
+ "lines",
10548
11726
  "review",
10549
11727
  "author",
10550
11728
  "model",
@@ -10599,6 +11777,8 @@ var OWN_ENTITIES = entityFields({
10599
11777
  "reference",
10600
11778
  "allocated",
10601
11779
  "unallocated",
11780
+ "refund_of",
11781
+ "subscription",
10602
11782
  "evidence",
10603
11783
  "review",
10604
11784
  "author",
@@ -10621,7 +11801,9 @@ var OWN_ENTITIES = entityFields({
10621
11801
  "revision",
10622
11802
  "fingerprint",
10623
11803
  "relations",
11804
+ "incoming",
10624
11805
  "entity",
11806
+ "created_entity",
10625
11807
  "flagged",
10626
11808
  "batch_id",
10627
11809
  "created_at",
@@ -10639,8 +11821,162 @@ var OWN_ENTITIES = entityFields({
10639
11821
  "proposed",
10640
11822
  "waiting",
10641
11823
  "flagged",
10642
- "errors"
11824
+ "unmatched",
11825
+ "ignored",
11826
+ "vcard",
11827
+ "errors",
11828
+ "truncated"
11829
+ ],
11830
+ product: [
11831
+ "id",
11832
+ "ref",
11833
+ "title",
11834
+ "kind",
11835
+ "name",
11836
+ "sku",
11837
+ "supplier",
11838
+ "unit",
11839
+ "unit_price",
11840
+ "currency",
11841
+ "description",
11842
+ "archived_date",
11843
+ "author",
11844
+ "model",
11845
+ "source",
11846
+ "created_at",
11847
+ "updated_at"
11848
+ ],
11849
+ contract: [
11850
+ "id",
11851
+ "ref",
11852
+ "title",
11853
+ "name",
11854
+ "number",
11855
+ "kind",
11856
+ "status",
11857
+ "signed_date",
11858
+ "effective_date",
11859
+ "expiration_date",
11860
+ "auto_renew",
11861
+ "renewal",
11862
+ "notice_days",
11863
+ "notice_deadline",
11864
+ "terms",
11865
+ "value",
11866
+ "currency",
11867
+ "deal",
11868
+ "review",
11869
+ "author",
11870
+ "model",
11871
+ "confirmed_by",
11872
+ "source",
11873
+ "reason",
11874
+ "evidence",
11875
+ "project",
11876
+ "project_name",
11877
+ "created_at",
11878
+ "updated_at"
11879
+ ],
11880
+ subscription: [
11881
+ "id",
11882
+ "ref",
11883
+ "title",
11884
+ "name",
11885
+ "direction",
11886
+ "supplier",
11887
+ "customer",
11888
+ "product",
11889
+ "contract",
11890
+ "status",
11891
+ "interval",
11892
+ "start_date",
11893
+ "trial_end_date",
11894
+ "next_renewal_date",
11895
+ "cancelled_date",
11896
+ "end_date",
11897
+ "current_price",
11898
+ "prices",
11899
+ "review",
11900
+ "author",
11901
+ "model",
11902
+ "confirmed_by",
11903
+ "source",
11904
+ "reason",
11905
+ "evidence",
11906
+ "project",
11907
+ "project_name",
11908
+ "created_at",
11909
+ "updated_at"
11910
+ ],
11911
+ subscription_price: [
11912
+ "id",
11913
+ "ref",
11914
+ "title",
11915
+ "subscription",
11916
+ "amount",
11917
+ "currency",
11918
+ "effective_from",
11919
+ "review",
11920
+ "author",
11921
+ "reason",
11922
+ "project",
11923
+ "created_at"
11924
+ ],
11925
+ wallet: [
11926
+ "id",
11927
+ "ref",
11928
+ "title",
11929
+ "name",
11930
+ "kind",
11931
+ "currency",
11932
+ "institution",
11933
+ "number_hint",
11934
+ "holder",
11935
+ "opening_balance",
11936
+ "opening_date",
11937
+ "closed_date",
11938
+ "balance",
11939
+ "until",
11940
+ "pending",
11941
+ "source_says",
11942
+ "author",
11943
+ "model",
11944
+ "source",
11945
+ "created_at",
11946
+ "updated_at"
11947
+ ],
11948
+ transaction: [
11949
+ "id",
11950
+ "ref",
11951
+ "title",
11952
+ "wallet",
11953
+ "wallet_name",
11954
+ "direction",
11955
+ "amount",
11956
+ "currency",
11957
+ "status",
11958
+ "statement_date",
11959
+ "booked_date",
11960
+ "description",
11961
+ "counterparty_name",
11962
+ "counterparty",
11963
+ "reference",
11964
+ "payment",
11965
+ "splits",
11966
+ "uncategorized",
11967
+ "review",
11968
+ "author",
11969
+ "model",
11970
+ "confirmed_by",
11971
+ "source",
11972
+ "reason",
11973
+ "evidence",
11974
+ "project",
11975
+ "project_name",
11976
+ "created_at",
11977
+ "updated_at"
10643
11978
  ],
11979
+ records_match: ["linked", "created", "unmatched", "proposed", "errors", "truncated"],
10644
11980
  payment_allocation: ["payment", "invoice", "amount", "currency", "created_at"]
10645
11981
  });
10646
11982
  var SKILL_TOPICS = [
@@ -10692,6 +12028,11 @@ var createProgram = /* @__PURE__ */ __name(({ streams: raw = processStreams, env
10692
12028
  financeCommands(program, streams, env);
10693
12029
  orderCommands(program, streams, env);
10694
12030
  dealCommands(program, streams, env);
12031
+ productCommands(program, streams, env);
12032
+ contractCommands(program, streams, env);
12033
+ subscriptionCommands(program, streams, env);
12034
+ walletCommands(program, streams, env);
12035
+ transactionCommands(program, streams, env);
10695
12036
  recordsCommand(program, streams, env);
10696
12037
  findingsCommand(program, streams, env);
10697
12038
  actionsCommand(program, streams, env);
@@ -10702,6 +12043,7 @@ var createProgram = /* @__PURE__ */ __name(({ streams: raw = processStreams, env
10702
12043
  searchCommand(program, streams, env);
10703
12044
  meetingReadCommands(program, streams, env);
10704
12045
  meetingPreparationCommand(program, streams, env);
12046
+ eventsCommand(program, streams, env);
10705
12047
  askCommand(program, streams, env);
10706
12048
  syncCommand(program, streams, env, signal, keyring);
10707
12049
  storeCommand(program, streams, env);
@@ -10714,10 +12056,10 @@ var createProgram = /* @__PURE__ */ __name(({ streams: raw = processStreams, env
10714
12056
  const skill2 = customizeSharedCommand(skillCommand2(APP, new URL("../skills/cli-memo/SKILL.md", new URL("../program.js", import.meta.url).href)), "Memo installs its own stored-data instructions through its environment, prints the packaged primary skill without filesystem effects, and takes --json on each skill command because it has no global one.", () => {
10715
12057
  const out = answers(program, streams, env);
10716
12058
  const skill3 = skillCommand(APP, new URL("../skills/cli-memo/SKILL.md", new URL("../program.js", import.meta.url).href), (command) => {
10717
- const json7 = command.opts().json === true;
10718
- const renderer = createRenderer({ format: json7 ? "json" : "pretty", color: false, streams });
12059
+ const json5 = command.opts().json === true;
12060
+ const renderer = createRenderer({ format: json5 ? "json" : "pretty", color: false, streams });
10719
12061
  return {
10720
- renderer: json7 ? { ...renderer, result: /* @__PURE__ */ __name((value) => out.print(true, itemAnswer(value)), "result") } : renderer,
12062
+ renderer: json5 ? { ...renderer, result: /* @__PURE__ */ __name((value) => out.print(true, itemAnswer(value)), "result") } : renderer,
10721
12063
  streams,
10722
12064
  env
10723
12065
  };