@wirecat/cli-core 0.555.0 → 0.556.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/dist/calendar/mcp/index.d.ts +12 -12
  3. package/dist/cli/config-command.js +64 -2
  4. package/dist/cli/config-issues.d.ts +2 -0
  5. package/dist/cli/config-issues.js +11 -3
  6. package/dist/cli/config-repair.d.ts +26 -0
  7. package/dist/cli/config-repair.js +252 -0
  8. package/dist/cli/messenger/store-maintenance-command.d.ts +1 -1
  9. package/dist/cli/messenger/tasks-analysis-command.d.ts +8 -0
  10. package/dist/cli/messenger/tasks-analysis-command.js +184 -0
  11. package/dist/cli/messenger/tasks-command.js +11 -2
  12. package/dist/cli/steps.js +10 -0
  13. package/dist/entities/index.d.ts +64 -2
  14. package/dist/entities/index.js +5 -2
  15. package/dist/entities/task-results.d.ts +72 -0
  16. package/dist/entities/task-results.js +40 -1
  17. package/dist/errors/reasons.d.ts +1 -1
  18. package/dist/errors/reasons.js +9 -0
  19. package/dist/mail/cli/index.d.ts +1 -0
  20. package/dist/mail/cli/index.js +3 -0
  21. package/dist/mail/cli/marks.d.ts +26 -0
  22. package/dist/mail/cli/marks.js +51 -0
  23. package/dist/mail/cli/review.js +70 -0
  24. package/dist/mail/index.d.ts +1 -0
  25. package/dist/mail/index.js +1 -0
  26. package/dist/mail/marks.d.ts +56 -0
  27. package/dist/mail/marks.js +178 -0
  28. package/dist/sends/permissions.js +1 -0
  29. package/dist/services/task-analysis.d.ts +58 -0
  30. package/dist/services/task-analysis.js +125 -0
  31. package/dist/store/exports.d.ts +2 -2
  32. package/dist/store/index.d.ts +1 -1
  33. package/dist/store/sqlite/email-activity.d.ts +31 -0
  34. package/dist/store/sqlite/email-activity.js +38 -0
  35. package/dist/store/sqlite/emails.d.ts +2 -0
  36. package/dist/store/sqlite/emails.js +1 -0
  37. package/dist/store/sqlite/task-analysis-marks.d.ts +7 -0
  38. package/dist/store/sqlite/task-analysis-marks.js +27 -0
  39. package/dist/store/sync.d.ts +5 -1
  40. package/dist/store/sync.js +4 -0
  41. package/dist/store/types.d.ts +25 -0
  42. package/package.json +1 -1
  43. package/parity.json +29 -0
  44. package/skills/follow-ups/SKILL.md +22 -2
@@ -0,0 +1,184 @@
1
+ import { annotate } from "@wirecat/cli-base/commands";
2
+ import { formatLocator } from "../../domain/locator.js";
3
+ import { storedChatId } from "../../services/message-resolution.js";
4
+ import { momentOf } from "../../services/moment.js";
5
+ import { ANALYSIS_PAGE, ANALYSIS_PAGE_MAX, acknowledgeTaskAnalysis, taskAnalysisList, unanalysedMessages, } from "../../services/task-analysis.js";
6
+ import { TASK_QUERY } from "../../services/tasks.js";
7
+ import { actorOf } from "../author.js";
8
+ import { destroysNothing, LOCAL_READ, LOCAL_WRITE } from "../effects.js";
9
+ import { itemOf, renderAnswer } from "../envelope.js";
10
+ import { listQuery, pagedList, pageOf, typedQuery } from "../list-query.js";
11
+ import { positiveCount } from "../paging.js";
12
+ import { nextStep } from "../steps.js";
13
+ import { messengerContext, refuseLocalWrite } from "./context.js";
14
+ const when = (at) => (at === null ? "—" : at.slice(0, 16).replace("T", " "));
15
+ const sinceOf = (typed) => typed === undefined ? undefined : new Date(momentOf(typed, "--since-time")).toISOString();
16
+ const markItem = (mark) => ({
17
+ chat: mark.chatId,
18
+ from: mark.from,
19
+ through: mark.through,
20
+ through_id: mark.throughId,
21
+ by: mark.by,
22
+ checked_at: mark.checkedAt,
23
+ checked_through: mark.checkedThrough,
24
+ at: mark.at,
25
+ });
26
+ const analysisItem = (chat) => ({
27
+ chat: chat.chatId,
28
+ title: chat.title,
29
+ kind: chat.kind,
30
+ newest_at: chat.newestAt,
31
+ mark: chat.mark === null ? null : markItem(chat.mark),
32
+ waiting: chat.waiting,
33
+ late: chat.late,
34
+ untrusted: ["title"],
35
+ });
36
+ /**
37
+ * Each chat's own point of reading for tasks (`../../services/task-analysis.ts`): how far it was read, what waits, and
38
+ * the step that moves it. Apart from `inbox --new`, `review --new` and the messenger's read state, which other
39
+ * readers move.
40
+ */
41
+ export const analysisCommands = (tasks, messenger) => {
42
+ const tool = messenger.app.command;
43
+ annotate(tasks.command("status"), {
44
+ output: { entity: "task_analysis" },
45
+ effects: LOCAL_READ,
46
+ examples: [`${tool} personal tasks status`],
47
+ })
48
+ .summary("how far each chat was read for tasks, and how much waits")
49
+ .description("every chat that can hold your tasks — not a channel or Saved Messages — with the point its messages were read " +
50
+ "for tasks through, who read them, how many stored messages wait after it, and how many arrived late inside " +
51
+ "the stretch already read (history fetched afterwards). Its own point: reading a chat, marking it read, " +
52
+ "inbox --new and review --new never move it; tasks acknowledge does. Reads only the local store")
53
+ .option("--limit <n>", "how many chats", positiveCount("--limit"))
54
+ .action(async function () {
55
+ const context = messengerContext(this, messenger);
56
+ const { limit, offset } = pageOf(context.settings);
57
+ const chats = await context.withStore((store, account) => taskAnalysisList(store, account), {
58
+ name: "tasks status",
59
+ });
60
+ const shown = chats.slice(offset, offset + limit);
61
+ renderAnswer(this, context, pagedList("tasks status", context.settings, {
62
+ items: shown.map(analysisItem),
63
+ has_more: chats.length > offset + limit,
64
+ }), () => shown.length === 0
65
+ ? ""
66
+ : `${shown
67
+ .map((one) => `${(one.title ?? one.chatId).slice(0, 30).padEnd(30)} read through ${when(one.mark?.through ?? null)}` +
68
+ ` ${one.waiting} waiting${one.late > 0 ? `, ${one.late} late` : ""}`)
69
+ .join("\n")}\n`);
70
+ });
71
+ annotate(tasks.command("review"), {
72
+ output: { entity: "task_review" },
73
+ effects: LOCAL_READ,
74
+ examples: [`${tool} personal tasks review <chat>`, `${tool} personal tasks review <chat> --since-time 30d`],
75
+ })
76
+ .summary("a chat's stored messages not yet read for tasks, with its open tasks")
77
+ .description("the stored messages after the chat's task point, oldest first, and the chat's open tasks, so one read can open " +
78
+ "new tasks and update or close the old ones. A chat never read starts 14 days back. Moves nothing: when done, " +
79
+ "tasks acknowledge <chat> <through> records it. Reads only the local store; messages sync or backfill fetch " +
80
+ "what it lacks")
81
+ .argument("<chat>", messenger.chatArgument)
82
+ .option("--limit <n>", `how many messages (default ${ANALYSIS_PAGE}, ${ANALYSIS_PAGE_MAX} with --since-time; at most ${ANALYSIS_PAGE_MAX})`, positiveCount("--limit"))
83
+ .option("--since-time <time>", "read again from this ISO 8601 time, or 30d ago, whatever the point says; what the point already passed only " +
84
+ "updates and closes tasks, unless tasks add is given --open-new")
85
+ .action(async function (chat) {
86
+ const context = messengerContext(this, messenger);
87
+ const { sinceTime, ...options } = this.opts();
88
+ const since = sinceOf(sinceTime);
89
+ // A read again clears late messages only when one acknowledge covers the whole stretch, so it takes one page.
90
+ const limit = options.limit ?? (since === undefined ? ANALYSIS_PAGE : ANALYSIS_PAGE_MAX);
91
+ const { id, page, sourceOf } = await context.withStore(async (store, account) => {
92
+ const id = await storedChatId(messenger, chat, store, account, { includeLeft: true });
93
+ return {
94
+ id,
95
+ page: await unanalysedMessages(store, account, id, {
96
+ limit: Math.min(limit, ANALYSIS_PAGE_MAX),
97
+ ...(since === undefined ? {} : { since }),
98
+ }),
99
+ sourceOf: (message) => formatLocator({ ...account, chat: id, message }),
100
+ };
101
+ }, { name: "tasks review" });
102
+ const open = await context.withServices((services) => services.tasks.list({
103
+ query: listQuery(typedQuery([`chat:${JSON.stringify(id)}`, "state:open"]), TASK_QUERY, "tasks review"),
104
+ limit: 100,
105
+ offset: 0,
106
+ }));
107
+ const last = page.messages.at(-1);
108
+ renderAnswer(this, context, itemOf({
109
+ chat: id,
110
+ from: page.from,
111
+ mark: page.mark === null ? null : markItem(page.mark),
112
+ late: page.late,
113
+ has_more: page.more,
114
+ through: last ? sourceOf(last.id) : null,
115
+ messages: page.messages.map((one) => ({
116
+ ref: sourceOf(one.id),
117
+ at: one.timestamp,
118
+ sender: one.senderName,
119
+ outgoing: one.outgoing === true,
120
+ reply_to: one.replyTo?.id ?? one.replyToId ?? null,
121
+ text: one.text,
122
+ })),
123
+ open_tasks: open.items.map(({ key = null, kind, title, source_message }) => ({
124
+ key,
125
+ kind,
126
+ title,
127
+ source: source_message,
128
+ })),
129
+ untrusted: ["messages.text", "messages.sender"],
130
+ }, {
131
+ next: last && !(since !== undefined && page.more)
132
+ ? [
133
+ nextStep("tasks.acknowledge", {
134
+ args: { chat: id, message: last.id, since_time: since },
135
+ values: { shown: page.messages.length },
136
+ }),
137
+ ]
138
+ : [],
139
+ }), () => [
140
+ `from ${when(page.from)}: ${page.messages.length} message(s)${page.more ? ", more after them" : ""}` +
141
+ (page.late > 0
142
+ ? `; ${page.late} arrived late inside the stretch read: --since-time ${page.mark?.from} reads it again`
143
+ : ""),
144
+ ...page.messages.map((one) => ` ${when(one.timestamp)} ${one.outgoing ? "you" : (one.senderName ?? "?")}: ${one.text.replace(/\s+/g, " ").slice(0, 100)}`),
145
+ `open tasks (${open.items.length})`,
146
+ ...open.items.map((task) => ` ${task.key} ${task.kind} ${task.title ?? ""}`),
147
+ ...(since !== undefined && page.more
148
+ ? [
149
+ `this read again does not reach the point in one page: acknowledging it moves nothing and late ` +
150
+ "messages stay until a later version pages a read again (tell the owner)",
151
+ ]
152
+ : last
153
+ ? [`done reading: ${tool} tasks acknowledge ${id} ${last.id}`]
154
+ : []),
155
+ "",
156
+ ].join("\n"));
157
+ });
158
+ destroysNothing(annotate(tasks.command("acknowledge"), {
159
+ output: { entity: "task_analysis_mark" },
160
+ effects: LOCAL_WRITE,
161
+ examples: [`${tool} personal tasks acknowledge <chat> <message>`],
162
+ }))
163
+ .summary("record that a chat was read for tasks through a message")
164
+ .description("moves the chat's task point to this message once its tasks are opened, updated or closed; it never moves " +
165
+ "back. With --since-time, the read started there: a read again from the start of the stretch clears what " +
166
+ "arrived late inside it")
167
+ .argument("<chat>", messenger.chatArgument)
168
+ .argument("<message>", "the id of the last message read, as tasks review shows it")
169
+ .option("--since-time <time>", "where the read started, when tasks review was given --since-time")
170
+ .action(async function (chat, message) {
171
+ const context = messengerContext(this, messenger);
172
+ refuseLocalWrite(context, messenger.app.command, "tasks.acknowledge");
173
+ const { sinceTime } = this.opts();
174
+ const since = sinceOf(sinceTime);
175
+ const by = actorOf(this);
176
+ const { mark, moved } = await context.withStore(async (store, account) => {
177
+ const id = await storedChatId(messenger, chat, store, account, { includeLeft: true });
178
+ return acknowledgeTaskAnalysis(store, account, id, message, { by, ...(since === undefined ? {} : { since }) });
179
+ }, { name: "tasks acknowledge" });
180
+ renderAnswer(this, context, itemOf({ ...markItem(mark), moved }), () => moved
181
+ ? `read for tasks from ${when(mark.from)} through ${when(mark.through)}\n`
182
+ : `already read through ${when(mark.through)}; the point stays\n`);
183
+ });
184
+ };
@@ -5,6 +5,7 @@ import { readOnlyLockOf, readOnlyRefusal } from "../../ports/app.js";
5
5
  import { AGENDA_QUERY, agendaItem } from "../../services/agenda.js";
6
6
  import { storedChatId } from "../../services/message-resolution.js";
7
7
  import { aheadOf, momentOf } from "../../services/moment.js";
8
+ import { refuseAlreadyRead } from "../../services/task-analysis.js";
8
9
  import { unlistedNote } from "../../services/task-categories.js";
9
10
  import { ARRIVAL_WINDOW, applyTaskRulesToChats } from "../../services/task-rules.js";
10
11
  import { CLAIM_LEASE_MS, closedStateOf, TASK_PAIR_QUERY, TASK_QUERY, taskLinkKindOf, taskTypeOf, } from "../../services/tasks.js";
@@ -18,6 +19,7 @@ import { positiveCount } from "../paging.js";
18
19
  import { messengerContext, refuseLocalWrite } from "./context.js";
19
20
  import { coverageGaps } from "./search-answers.js";
20
21
  import { refuseJsonl, taskStatsAnswer } from "./stats-answers.js";
22
+ import { analysisCommands } from "./tasks-analysis-command.js";
21
23
  const line = ({ id, key, state, kind, group, createdAt, message, note }) => [
22
24
  key ?? id.slice(0, 8),
23
25
  state.padEnd(9),
@@ -175,11 +177,17 @@ export const tasksCommand = (messenger) => {
175
177
  .requiredOption("--type <type>", "the task's type: question, request, mention or promise", taskTypeOf)
176
178
  .requiredOption("--category <name>", categoryHelp)
177
179
  .option("--into <id>", "when tasks add listed tasks that may be the same job: link the message to this one instead of opening a task")
178
- .option("--new", "when tasks add listed tasks that may be the same job: open the task anyway"), "send Alex the API token").action(async function (message) {
180
+ .option("--new", "when tasks add listed tasks that may be the same job: open the task anyway")
181
+ .option("--open-new", "open a task from a message the chat's task point already passed (a read again with tasks review " +
182
+ "--since-time); without it such a read only updates and closes tasks"), "send Alex the API token").action(async function (message) {
179
183
  const context = messengerContext(this, messenger);
180
184
  refuseLocalWrite(context, messenger.app.command, "tasks.add");
181
185
  const options = this.opts();
182
- const { into, new: anyway, ...rest } = options;
186
+ const { into, new: anyway, openNew, ...rest } = options;
187
+ if (!openNew)
188
+ await context.withStore((store, account) => refuseAlreadyRead(store, account, message), {
189
+ name: "tasks add",
190
+ });
183
191
  const plan = planFrom(rest);
184
192
  const { task, created, attached, review, followUpOf, card: planned, } = await context.withServices((services) => services.tasks.add(message, options.type, writerOf(this), plan, {
185
193
  ...(into === undefined ? {} : { attach: into }),
@@ -440,6 +448,7 @@ export const tasksCommand = (messenger) => {
440
448
  }, { name: "tasks scan" });
441
449
  renderAnswer(this, context, listOf("tasks scan", { items: passes.map(snakeKeys), limit: passes.length, has_more: false }), () => `${passes.map((pass) => applyText(pass, yes, tool)).join("\n")}\n`);
442
450
  });
451
+ analysisCommands(tasks, messenger);
443
452
  destroysNothing(annotate(tasks.command("claim"), {
444
453
  output: { entity: "task_card" },
445
454
  effects: LOCAL_WRITE,
package/dist/cli/steps.js CHANGED
@@ -209,6 +209,16 @@ export const STEPS = defineSteps([
209
209
  args: [],
210
210
  why: "serve still runs an older version; a restart runs the one installed now",
211
211
  },
212
+ {
213
+ id: "tasks.acknowledge",
214
+ command: "tasks acknowledge",
215
+ args: [
216
+ { name: "chat", required: true },
217
+ { name: "message", required: true },
218
+ { name: "since_time", required: false },
219
+ ],
220
+ why: "once the tasks these {shown} messages hold are opened, updated or closed, so the next review starts after them",
221
+ },
212
222
  {
213
223
  id: "search.meetings",
214
224
  command: "*",
@@ -81,14 +81,14 @@ import { automaticTags, tagChange } from "./tag-change.js";
81
81
  import { tagging } from "./tagging.js";
82
82
  import { task } from "./task.js";
83
83
  import { taskPair } from "./task-pair.js";
84
- import { taskCard, taskCategories, taskClosed, taskCreated, taskLinks, taskMerge, taskScan, taskSimilar, taskUnmerge } from "./task-results.js";
84
+ import { taskAnalysis, taskAnalysisMark, taskCard, taskCategories, taskClosed, taskCreated, taskLinks, taskMerge, taskScan, taskSimilar, taskUnmerge } from "./task-results.js";
85
85
  import { topic } from "./topic.js";
86
86
  /**
87
87
  * One schema per thing a command can answer with. A command returns an entity or one of its views — a
88
88
  * subset of its fields, never a renamed one. Commands move onto these one by one; until then, a schema
89
89
  * is the target, not a description of today's output.
90
90
  */
91
- export { account, accountChange, accountPrivacy, accountPrivacyChange, accountProfile, accountSession, adminReport, agenda, analysisConsent, analysisConsentRevocation, attachment, attachmentBytes, attachmentExtraction, attachmentTextChange, automaticTags, botAdmin, botMenuEntry, botProfile, botSeenChat, botTemplate, botWebhook, cachedChatMetadata, callRecord, chart, chat, chatAdminChange, chatArchive, chatEvent, chatFolderChange, chatFolderOrder, chatFolderRemoval, chatGroupChange, chatInspection, chatInvite, chatInviteChange, chatMembersChange, chatMembersFetch, chatMetadata, chatMetadataRefresh, chatModeration, chatMuting, chatPin, chatRead, chatRemoval, chatRequestChange, chatRules, chatSender, chatStats, chatTracking, chatUnread, contact, contactActivity, contactAlias, contactCheck, contactContext, contactImport, contactLookup, contactNote, contactNoteRemoval, contactPreparation, contactStateChange, contactSync, contactUpdate, conversation, conversationBatch, conversationBatchStatus, conversationBuildResult, conversationChange, conversationDetails, conversationEmbedding, conversationEmbeddingStatus, conversationHit, conversationPreparation, conversationReadiness, counterRefresh, counters, document, documentLink, endedAccountSessions, evidence, evidencePacket, fact, folder, hit, identity, imageEmbedding, inviteLink, job, joinRequest, linkedPerson, mediaArchive, mediaArchiveCheck, mediaArchiveMove, mediaArchiveTimer, meeting, meetingProjectCandidates, meetingSeriesInventory, member, memory, mention, mentionDecision, mentionDetails, mentionDomain, mentionRebuild, message, messageContext, messageCounts, messageDeletion, messageDownload, messageEvent, messageLink, messageLinks, messagePin, messageStar, messageSync, messageTranscript, messageWrite, model, modelKey, note, officialStats, organization, person, place, poll, pollChange, pollVote, project, ranking, reaction, reactionChange, recipient, recipientAdded, recipientChange, recipientOff, recipientRemoved, recordedRun, reference, relationship, reminder, removedModelKey, retention, runDetails, runHit, runLocation, savedSearch, scheduledJob, searchHistoryClear, sendAttempt, serveSummary, stickerInventory, storeBackup, storeChatStatus, storeCheck, storeClear, storeCopyRemoval, storeDecrypt, storedModelKey, storeExport, storeGapPlan, storeGapRepair, storeInfo, storeJobCancel, storeJobClear, storeJobDetails, storeJobRetry, storeMigration, storeReindex, storeRepair, storeReset, storeRestore, storeTable, tagChange, tagging, task, taskCard, taskCategories, taskClosed, taskCreated, taskLinks, taskMerge, taskPair, taskScan, taskSimilar, taskStats, taskUnmerge, topic, topicIcon, trackedChat, trackedChatHistory, watchedMessage, watchItem, };
91
+ export { account, accountChange, accountPrivacy, accountPrivacyChange, accountProfile, accountSession, adminReport, agenda, analysisConsent, analysisConsentRevocation, attachment, attachmentBytes, attachmentExtraction, attachmentTextChange, automaticTags, botAdmin, botMenuEntry, botProfile, botSeenChat, botTemplate, botWebhook, cachedChatMetadata, callRecord, chart, chat, chatAdminChange, chatArchive, chatEvent, chatFolderChange, chatFolderOrder, chatFolderRemoval, chatGroupChange, chatInspection, chatInvite, chatInviteChange, chatMembersChange, chatMembersFetch, chatMetadata, chatMetadataRefresh, chatModeration, chatMuting, chatPin, chatRead, chatRemoval, chatRequestChange, chatRules, chatSender, chatStats, chatTracking, chatUnread, contact, contactActivity, contactAlias, contactCheck, contactContext, contactImport, contactLookup, contactNote, contactNoteRemoval, contactPreparation, contactStateChange, contactSync, contactUpdate, conversation, conversationBatch, conversationBatchStatus, conversationBuildResult, conversationChange, conversationDetails, conversationEmbedding, conversationEmbeddingStatus, conversationHit, conversationPreparation, conversationReadiness, counterRefresh, counters, document, documentLink, endedAccountSessions, evidence, evidencePacket, fact, folder, hit, identity, imageEmbedding, inviteLink, job, joinRequest, linkedPerson, mediaArchive, mediaArchiveCheck, mediaArchiveMove, mediaArchiveTimer, meeting, meetingProjectCandidates, meetingSeriesInventory, member, memory, mention, mentionDecision, mentionDetails, mentionDomain, mentionRebuild, message, messageContext, messageCounts, messageDeletion, messageDownload, messageEvent, messageLink, messageLinks, messagePin, messageStar, messageSync, messageTranscript, messageWrite, model, modelKey, note, officialStats, organization, person, place, poll, pollChange, pollVote, project, ranking, reaction, reactionChange, recipient, recipientAdded, recipientChange, recipientOff, recipientRemoved, recordedRun, reference, relationship, reminder, removedModelKey, retention, runDetails, runHit, runLocation, savedSearch, scheduledJob, searchHistoryClear, sendAttempt, serveSummary, stickerInventory, storeBackup, storeChatStatus, storeCheck, storeClear, storeCopyRemoval, storeDecrypt, storedModelKey, storeExport, storeGapPlan, storeGapRepair, storeInfo, storeJobCancel, storeJobClear, storeJobDetails, storeJobRetry, storeMigration, storeReindex, storeRepair, storeReset, storeRestore, storeTable, tagChange, tagging, task, taskAnalysis, taskAnalysisMark, taskCard, taskCategories, taskClosed, taskCreated, taskLinks, taskMerge, taskPair, taskScan, taskSimilar, taskStats, taskUnmerge, topic, topicIcon, trackedChat, trackedChatHistory, watchedMessage, watchItem, };
92
92
  export declare const ENTITIES: {
93
93
  readonly meeting_ingestion: v.StrictObjectSchema<{
94
94
  readonly meetings: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
@@ -5696,6 +5696,68 @@ export declare const ENTITIES: {
5696
5696
  readonly category: v.NullableSchema<v.StringSchema<undefined>, undefined>;
5697
5697
  }, undefined>, undefined>;
5698
5698
  }, undefined>;
5699
+ readonly task_analysis: v.StrictObjectSchema<{
5700
+ readonly chat: v.StringSchema<undefined>;
5701
+ readonly title: v.NullableSchema<v.StringSchema<undefined>, undefined>;
5702
+ readonly kind: v.StringSchema<undefined>;
5703
+ readonly newest_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
5704
+ readonly mark: v.NullableSchema<v.StrictObjectSchema<{
5705
+ readonly chat: v.StringSchema<undefined>;
5706
+ readonly from: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
5707
+ readonly through: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
5708
+ readonly through_id: v.StringSchema<undefined>;
5709
+ readonly by: v.StringSchema<undefined>;
5710
+ readonly checked_at: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
5711
+ readonly checked_through: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
5712
+ readonly at: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
5713
+ }, undefined>, undefined>;
5714
+ readonly waiting: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
5715
+ readonly late: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
5716
+ readonly untrusted: v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, undefined>;
5717
+ }, undefined>;
5718
+ readonly task_analysis_mark: v.StrictObjectSchema<{
5719
+ readonly chat: v.StringSchema<undefined>;
5720
+ readonly from: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
5721
+ readonly through: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
5722
+ readonly through_id: v.StringSchema<undefined>;
5723
+ readonly by: v.StringSchema<undefined>;
5724
+ readonly checked_at: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
5725
+ readonly checked_through: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
5726
+ readonly at: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
5727
+ readonly moved: v.BooleanSchema<undefined>;
5728
+ }, undefined>;
5729
+ readonly task_review: v.StrictObjectSchema<{
5730
+ readonly chat: v.StringSchema<undefined>;
5731
+ readonly from: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
5732
+ readonly mark: v.NullableSchema<v.StrictObjectSchema<{
5733
+ readonly chat: v.StringSchema<undefined>;
5734
+ readonly from: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
5735
+ readonly through: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
5736
+ readonly through_id: v.StringSchema<undefined>;
5737
+ readonly by: v.StringSchema<undefined>;
5738
+ readonly checked_at: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
5739
+ readonly checked_through: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
5740
+ readonly at: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
5741
+ }, undefined>, undefined>;
5742
+ readonly late: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
5743
+ readonly has_more: v.BooleanSchema<undefined>;
5744
+ readonly through: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "a reference such as `note:42`">]>, undefined>;
5745
+ readonly messages: v.ArraySchema<v.StrictObjectSchema<{
5746
+ readonly ref: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "a reference such as `note:42`">]>;
5747
+ readonly at: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
5748
+ readonly sender: v.NullableSchema<v.StringSchema<undefined>, undefined>;
5749
+ readonly outgoing: v.BooleanSchema<undefined>;
5750
+ readonly reply_to: v.NullableSchema<v.StringSchema<undefined>, undefined>;
5751
+ readonly text: v.StringSchema<undefined>;
5752
+ }, undefined>, undefined>;
5753
+ readonly open_tasks: v.ArraySchema<v.StrictObjectSchema<{
5754
+ readonly key: v.NullableSchema<v.StringSchema<undefined>, undefined>;
5755
+ readonly kind: v.StringSchema<undefined>;
5756
+ readonly title: v.NullableSchema<v.StringSchema<undefined>, undefined>;
5757
+ readonly source: v.NullableSchema<v.StringSchema<undefined>, undefined>;
5758
+ }, undefined>, undefined>;
5759
+ readonly untrusted: v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, undefined>;
5760
+ }, undefined>;
5699
5761
  readonly fact: v.StrictObjectSchema<{
5700
5762
  readonly ref: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "a reference such as `note:42`">]>;
5701
5763
  readonly id: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
@@ -87,14 +87,14 @@ import { automaticTags, tagChange } from "./tag-change.js";
87
87
  import { tagging } from "./tagging.js";
88
88
  import { task } from "./task.js";
89
89
  import { taskPair } from "./task-pair.js";
90
- import { taskCard, taskCategories, taskClosed, taskCreated, taskLinks, taskMerge, taskScan, taskSimilar, taskUnmerge, } from "./task-results.js";
90
+ import { taskAnalysis, taskAnalysisMark, taskAnalysisMarkMoved, taskCard, taskCategories, taskClosed, taskCreated, taskLinks, taskMerge, taskReview, taskScan, taskSimilar, taskUnmerge, } from "./task-results.js";
91
91
  import { topic } from "./topic.js";
92
92
  /**
93
93
  * One schema per thing a command can answer with. A command returns an entity or one of its views — a
94
94
  * subset of its fields, never a renamed one. Commands move onto these one by one; until then, a schema
95
95
  * is the target, not a description of today's output.
96
96
  */
97
- export { account, accountChange, accountPrivacy, accountPrivacyChange, accountProfile, accountSession, adminReport, agenda, analysisConsent, analysisConsentRevocation, attachment, attachmentBytes, attachmentExtraction, attachmentTextChange, automaticTags, botAdmin, botMenuEntry, botProfile, botSeenChat, botTemplate, botWebhook, cachedChatMetadata, callRecord, chart, chat, chatAdminChange, chatArchive, chatEvent, chatFolderChange, chatFolderOrder, chatFolderRemoval, chatGroupChange, chatInspection, chatInvite, chatInviteChange, chatMembersChange, chatMembersFetch, chatMetadata, chatMetadataRefresh, chatModeration, chatMuting, chatPin, chatRead, chatRemoval, chatRequestChange, chatRules, chatSender, chatStats, chatTracking, chatUnread, contact, contactActivity, contactAlias, contactCheck, contactContext, contactImport, contactLookup, contactNote, contactNoteRemoval, contactPreparation, contactStateChange, contactSync, contactUpdate, conversation, conversationBatch, conversationBatchStatus, conversationBuildResult, conversationChange, conversationDetails, conversationEmbedding, conversationEmbeddingStatus, conversationHit, conversationPreparation, conversationReadiness, counterRefresh, counters, document, documentLink, endedAccountSessions, evidence, evidencePacket, fact, folder, hit, identity, imageEmbedding, inviteLink, job, joinRequest, linkedPerson, mediaArchive, mediaArchiveCheck, mediaArchiveMove, mediaArchiveTimer, meeting, meetingProjectCandidates, meetingSeriesInventory, member, memory, mention, mentionDecision, mentionDetails, mentionDomain, mentionRebuild, message, messageContext, messageCounts, messageDeletion, messageDownload, messageEvent, messageLink, messageLinks, messagePin, messageStar, messageSync, messageTranscript, messageWrite, model, modelKey, note, officialStats, organization, person, place, poll, pollChange, pollVote, project, ranking, reaction, reactionChange, recipient, recipientAdded, recipientChange, recipientOff, recipientRemoved, recordedRun, reference, relationship, reminder, removedModelKey, retention, runDetails, runHit, runLocation, savedSearch, scheduledJob, searchHistoryClear, sendAttempt, serveSummary, stickerInventory, storeBackup, storeChatStatus, storeCheck, storeClear, storeCopyRemoval, storeDecrypt, storedModelKey, storeExport, storeGapPlan, storeGapRepair, storeInfo, storeJobCancel, storeJobClear, storeJobDetails, storeJobRetry, storeMigration, storeReindex, storeRepair, storeReset, storeRestore, storeTable, tagChange, tagging, task, taskCard, taskCategories, taskClosed, taskCreated, taskLinks, taskMerge, taskPair, taskScan, taskSimilar, taskStats, taskUnmerge, topic, topicIcon, trackedChat, trackedChatHistory, watchedMessage, watchItem, };
97
+ export { account, accountChange, accountPrivacy, accountPrivacyChange, accountProfile, accountSession, adminReport, agenda, analysisConsent, analysisConsentRevocation, attachment, attachmentBytes, attachmentExtraction, attachmentTextChange, automaticTags, botAdmin, botMenuEntry, botProfile, botSeenChat, botTemplate, botWebhook, cachedChatMetadata, callRecord, chart, chat, chatAdminChange, chatArchive, chatEvent, chatFolderChange, chatFolderOrder, chatFolderRemoval, chatGroupChange, chatInspection, chatInvite, chatInviteChange, chatMembersChange, chatMembersFetch, chatMetadata, chatMetadataRefresh, chatModeration, chatMuting, chatPin, chatRead, chatRemoval, chatRequestChange, chatRules, chatSender, chatStats, chatTracking, chatUnread, contact, contactActivity, contactAlias, contactCheck, contactContext, contactImport, contactLookup, contactNote, contactNoteRemoval, contactPreparation, contactStateChange, contactSync, contactUpdate, conversation, conversationBatch, conversationBatchStatus, conversationBuildResult, conversationChange, conversationDetails, conversationEmbedding, conversationEmbeddingStatus, conversationHit, conversationPreparation, conversationReadiness, counterRefresh, counters, document, documentLink, endedAccountSessions, evidence, evidencePacket, fact, folder, hit, identity, imageEmbedding, inviteLink, job, joinRequest, linkedPerson, mediaArchive, mediaArchiveCheck, mediaArchiveMove, mediaArchiveTimer, meeting, meetingProjectCandidates, meetingSeriesInventory, member, memory, mention, mentionDecision, mentionDetails, mentionDomain, mentionRebuild, message, messageContext, messageCounts, messageDeletion, messageDownload, messageEvent, messageLink, messageLinks, messagePin, messageStar, messageSync, messageTranscript, messageWrite, model, modelKey, note, officialStats, organization, person, place, poll, pollChange, pollVote, project, ranking, reaction, reactionChange, recipient, recipientAdded, recipientChange, recipientOff, recipientRemoved, recordedRun, reference, relationship, reminder, removedModelKey, retention, runDetails, runHit, runLocation, savedSearch, scheduledJob, searchHistoryClear, sendAttempt, serveSummary, stickerInventory, storeBackup, storeChatStatus, storeCheck, storeClear, storeCopyRemoval, storeDecrypt, storedModelKey, storeExport, storeGapPlan, storeGapRepair, storeInfo, storeJobCancel, storeJobClear, storeJobDetails, storeJobRetry, storeMigration, storeReindex, storeRepair, storeReset, storeRestore, storeTable, tagChange, tagging, task, taskAnalysis, taskAnalysisMark, taskCard, taskCategories, taskClosed, taskCreated, taskLinks, taskMerge, taskPair, taskScan, taskSimilar, taskStats, taskUnmerge, topic, topicIcon, trackedChat, trackedChatHistory, watchedMessage, watchItem, };
98
98
  export const ENTITIES = {
99
99
  sync_progress: syncProgress,
100
100
  ...MEETING_RESULT_ENTITIES,
@@ -233,6 +233,9 @@ export const ENTITIES = {
233
233
  task_unmerge: taskUnmerge,
234
234
  task_categories: taskCategories,
235
235
  task_scan: taskScan,
236
+ task_analysis: taskAnalysis,
237
+ task_analysis_mark: taskAnalysisMarkMoved,
238
+ task_review: taskReview,
236
239
  fact,
237
240
  memory,
238
241
  meeting,
@@ -587,3 +587,75 @@ export declare const taskScan: v.StrictObjectSchema<{
587
587
  readonly category: v.NullableSchema<v.StringSchema<undefined>, undefined>;
588
588
  }, undefined>, undefined>;
589
589
  }, undefined>;
590
+ export declare const taskAnalysisMark: v.StrictObjectSchema<{
591
+ readonly chat: v.StringSchema<undefined>;
592
+ readonly from: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
593
+ readonly through: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
594
+ readonly through_id: v.StringSchema<undefined>;
595
+ readonly by: v.StringSchema<undefined>;
596
+ readonly checked_at: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
597
+ readonly checked_through: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
598
+ readonly at: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
599
+ }, undefined>;
600
+ export declare const taskAnalysisMarkMoved: v.StrictObjectSchema<{
601
+ readonly chat: v.StringSchema<undefined>;
602
+ readonly from: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
603
+ readonly through: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
604
+ readonly through_id: v.StringSchema<undefined>;
605
+ readonly by: v.StringSchema<undefined>;
606
+ readonly checked_at: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
607
+ readonly checked_through: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
608
+ readonly at: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
609
+ readonly moved: v.BooleanSchema<undefined>;
610
+ }, undefined>;
611
+ export declare const taskAnalysis: v.StrictObjectSchema<{
612
+ readonly chat: v.StringSchema<undefined>;
613
+ readonly title: v.NullableSchema<v.StringSchema<undefined>, undefined>;
614
+ readonly kind: v.StringSchema<undefined>;
615
+ readonly newest_at: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>, undefined>;
616
+ readonly mark: v.NullableSchema<v.StrictObjectSchema<{
617
+ readonly chat: v.StringSchema<undefined>;
618
+ readonly from: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
619
+ readonly through: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
620
+ readonly through_id: v.StringSchema<undefined>;
621
+ readonly by: v.StringSchema<undefined>;
622
+ readonly checked_at: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
623
+ readonly checked_through: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
624
+ readonly at: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
625
+ }, undefined>, undefined>;
626
+ readonly waiting: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
627
+ readonly late: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
628
+ readonly untrusted: v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, undefined>;
629
+ }, undefined>;
630
+ export declare const taskReview: v.StrictObjectSchema<{
631
+ readonly chat: v.StringSchema<undefined>;
632
+ readonly from: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
633
+ readonly mark: v.NullableSchema<v.StrictObjectSchema<{
634
+ readonly chat: v.StringSchema<undefined>;
635
+ readonly from: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
636
+ readonly through: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
637
+ readonly through_id: v.StringSchema<undefined>;
638
+ readonly by: v.StringSchema<undefined>;
639
+ readonly checked_at: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
640
+ readonly checked_through: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
641
+ readonly at: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
642
+ }, undefined>, undefined>;
643
+ readonly late: v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 0, undefined>]>;
644
+ readonly has_more: v.BooleanSchema<undefined>;
645
+ readonly through: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "a reference such as `note:42`">]>, undefined>;
646
+ readonly messages: v.ArraySchema<v.StrictObjectSchema<{
647
+ readonly ref: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "a reference such as `note:42`">]>;
648
+ readonly at: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, "an ISO 8601 time in UTC">, v.EndsWithAction<string, "Z", "an ISO 8601 time in UTC, ending in `Z`">]>;
649
+ readonly sender: v.NullableSchema<v.StringSchema<undefined>, undefined>;
650
+ readonly outgoing: v.BooleanSchema<undefined>;
651
+ readonly reply_to: v.NullableSchema<v.StringSchema<undefined>, undefined>;
652
+ readonly text: v.StringSchema<undefined>;
653
+ }, undefined>, undefined>;
654
+ readonly open_tasks: v.ArraySchema<v.StrictObjectSchema<{
655
+ readonly key: v.NullableSchema<v.StringSchema<undefined>, undefined>;
656
+ readonly kind: v.StringSchema<undefined>;
657
+ readonly title: v.NullableSchema<v.StringSchema<undefined>, undefined>;
658
+ readonly source: v.NullableSchema<v.StringSchema<undefined>, undefined>;
659
+ }, undefined>, undefined>;
660
+ readonly untrusted: v.OptionalSchema<v.ArraySchema<v.StringSchema<undefined>, undefined>, undefined>;
661
+ }, undefined>;
@@ -2,7 +2,7 @@ import * as v from "valibot";
2
2
  import { TASK_TYPES } from "../domain/knowledge.js";
3
3
  import { LINK_KINDS, LINK_SOURCES } from "../store/sqlite/link-kinds.js";
4
4
  import { PRIORITY_LABELS, TASK_KINDS, TASK_ORIGINS, TASK_STATES, TASK_VERDICTS } from "../tasks/index.js";
5
- import { count, id, reference, text, time } from "./fields.js";
5
+ import { count, id, reference, text, time, untrusted } from "./fields.js";
6
6
  import { closeSuggestion } from "./task.js";
7
7
  import { taskPair } from "./task-pair.js";
8
8
  const nullableTime = v.nullable(time);
@@ -135,3 +135,42 @@ export const taskScan = v.strictObject({
135
135
  held_chats: v.optional(count),
136
136
  tasks: v.array(v.strictObject({ source: text, kind: v.picklist(TASK_KINDS), category: v.nullable(text) })),
137
137
  });
138
+ export const taskAnalysisMark = v.strictObject({
139
+ chat: text,
140
+ from: time,
141
+ through: time,
142
+ through_id: text,
143
+ by: text,
144
+ checked_at: time,
145
+ checked_through: time,
146
+ at: time,
147
+ });
148
+ export const taskAnalysisMarkMoved = v.strictObject({ ...taskAnalysisMark.entries, moved: v.boolean() });
149
+ export const taskAnalysis = v.strictObject({
150
+ chat: text,
151
+ title: v.nullable(text),
152
+ kind: text,
153
+ newest_at: nullableTime,
154
+ mark: v.nullable(taskAnalysisMark),
155
+ waiting: count,
156
+ late: count,
157
+ untrusted,
158
+ });
159
+ export const taskReview = v.strictObject({
160
+ chat: text,
161
+ from: time,
162
+ mark: v.nullable(taskAnalysisMark),
163
+ late: count,
164
+ has_more: v.boolean(),
165
+ through: v.nullable(reference),
166
+ messages: v.array(v.strictObject({
167
+ ref: reference,
168
+ at: time,
169
+ sender: v.nullable(text),
170
+ outgoing: v.boolean(),
171
+ reply_to: v.nullable(text),
172
+ text,
173
+ })),
174
+ open_tasks: v.array(v.strictObject({ key: v.nullable(text), kind: text, title: v.nullable(text), source: v.nullable(text) })),
175
+ untrusted,
176
+ });
@@ -7,7 +7,7 @@ export declare const REASONS: ErrorReason[];
7
7
  * Detail keys an error from this package may carry, until each is registered on its own reason. Not `cause`:
8
8
  * that can hold a provider's or SQLite's raw text.
9
9
  */
10
- export declare const DETAILS: readonly ["contracts", "calendars", "allowed", "alternative", "arguments", "at", "available", "batch", "budget", "built", "candidates", "chat", "chat_id", "cli", "complete", "emitted_bytes", "exact", "forum", "guide", "hint", "id", "index", "kind", "limit", "limit_source", "max_bytes", "model", "name", "operation_id", "operation_ids", "text_limit", "store_refused_in", "subtasks", "partial_output", "parent", "path", "permission", "person_ids", "previous_chat_id", "profiles", "provider_error", "provider", "recovery", "reference", "remembered", "retry_at", "retry_after_ms", "runtime", "saved", "scheduled_for", "script", "sent", "sent_count", "settlement_failed", "span", "sqlite", "stage", "standing", "state", "stderr", "term", "total", "upgraded", "wanted"];
10
+ export declare const DETAILS: readonly ["contracts", "calendars", "allowed", "alternative", "arguments", "at", "available", "batch", "budget", "built", "candidates", "chat", "chat_id", "cli", "column", "complete", "emitted_bytes", "exact", "file", "forum", "guide", "hint", "id", "index", "kind", "limit", "limit_source", "line", "max_bytes", "model", "name", "operation_id", "operation_ids", "text_limit", "store_refused_in", "subtasks", "partial_output", "parent", "path", "permission", "person_ids", "previous_chat_id", "profiles", "provider_error", "provider", "recovery", "reference", "remembered", "retry_at", "retry_after_ms", "runtime", "saved", "scheduled_for", "script", "sent", "sent_count", "settlement_failed", "span", "sqlite", "stage", "standing", "state", "stderr", "term", "total", "upgraded", "wanted"];
11
11
  /** What a CLI adds to the shared registry: its own reasons, and the detail keys its adapters raise. */
12
12
  export interface AppErrors {
13
13
  reasons?: readonly ErrorReason[];
@@ -57,6 +57,11 @@ const OTHERS = [
57
57
  validation("push.too-many-files", "the folder holds more files than one push takes"),
58
58
  validation("push.unreadable", "the folder to push could not be read"),
59
59
  validation("spreadsheet.unreadable", "the workbook could not be read"),
60
+ [
61
+ "config.unrepairable",
62
+ "configuration_error",
63
+ "the settings file's damage has more than one reading; nothing was changed, so it is fixed by hand",
64
+ ],
60
65
  ["state.invalid", "configuration_error", "the saved sync state is unreadable or invalid; it is kept, not reset"],
61
66
  ["sync.partial", "provider_error", "some calendars did not sync; the next sync retries them"],
62
67
  validation("event.conflict", "the event changed at the provider since the last sync; sync and try again"),
@@ -188,6 +193,7 @@ const OTHERS = [
188
193
  validation("task.has-subtasks", "the task has subtasks; move or detach them before it moves to another project"),
189
194
  validation("task.is-subtask", "a subtask moves to another project only when it is detached from its parent in the same write"),
190
195
  validation("task.duplicate-candidates", "open tasks may be the same job: attach to one, or add it as new"),
196
+ validation("task.already-read", "the message was already read for tasks: a read again only updates and closes tasks unless --open-new"),
191
197
  validation("task.certainty-required", "an agent closes a task with its certainty, 0 to 1"),
192
198
  ["task.pair-decided", "permission_error", "the owner already decided the pair; an agent does not change it"],
193
199
  validation("task.no-close-suggestion", "the task has no agent's close waiting on the owner"),
@@ -245,9 +251,11 @@ export const DETAILS = [
245
251
  "chat",
246
252
  "chat_id",
247
253
  "cli",
254
+ "column",
248
255
  "complete",
249
256
  "emitted_bytes",
250
257
  "exact",
258
+ "file",
251
259
  "forum",
252
260
  "guide",
253
261
  "hint",
@@ -256,6 +264,7 @@ export const DETAILS = [
256
264
  "kind",
257
265
  "limit",
258
266
  "limit_source",
267
+ "line",
259
268
  "max_bytes",
260
269
  "model",
261
270
  "name",
@@ -2,6 +2,7 @@ import { Command } from "commander";
2
2
  import { type MailServerAccess } from "../../mail/server-search.js";
3
3
  import type { AppIdentity } from "../../ports/app.js";
4
4
  import { type AccountKey, type MessageStore } from "../../store/store.js";
5
+ export { mailMark, markItem, markText } from "./marks.js";
5
6
  export { MAIL_REVIEW_QUERY, MAIL_REVIEW_STEPS } from "./review.js";
6
7
  /** What a mail CLI hands the shared commands: how to open the store for one run, and whose mail it reads. */
7
8
  export interface MailReads {
@@ -18,7 +18,9 @@ import { searchMailServer } from "../../mail/server-search.js";
18
18
  import { atDetail } from "../../output-detail.js";
19
19
  import { sourceKey } from "../../services/server-search.js";
20
20
  import { queryFilter, THREAD_COLUMNS } from "../../store/store.js";
21
+ import { acknowledgeCommand } from "./marks.js";
21
22
  import { mailReviewCommand } from "./review.js";
23
+ export { mailMark, markItem, markText } from "./marks.js";
22
24
  export { MAIL_REVIEW_QUERY, MAIL_REVIEW_STEPS } from "./review.js";
23
25
  /** A locked or broken store must fail the command, not read as "nothing stored yet". */
24
26
  const absentAccount = (error) => {
@@ -226,6 +228,7 @@ const messagesCommand = (mail) => {
226
228
  ? listOf("messages show", { items: shown, limit: Math.max(1, shown.length), has_more: false })
227
229
  : itemOf(shown.find((_, at) => emails[at]?.anchor) ?? shown[0]), () => shownText(emails));
228
230
  });
231
+ messages.addCommand(acknowledgeCommand(mail));
229
232
  return messages;
230
233
  };
231
234
  const mailThread = v.strictObject({
@@ -0,0 +1,26 @@
1
+ import { Command } from "commander";
2
+ import * as v from "valibot";
3
+ import { type MailMark } from "../marks.js";
4
+ import type { MailReads } from "./index.js";
5
+ /** A holder's mark as `--json`, `mail status` and MCP show it. */
6
+ export declare const mailMark: v.StrictObjectSchema<{
7
+ readonly holder: v.StringSchema<undefined>;
8
+ readonly through_id: v.NumberSchema<undefined>;
9
+ readonly through_received_at: v.NullableSchema<v.StringSchema<undefined>, undefined>;
10
+ readonly held: v.NumberSchema<undefined>;
11
+ readonly read: v.NumberSchema<undefined>;
12
+ readonly skipped: v.StrictObjectSchema<{
13
+ readonly bulk: v.NumberSchema<undefined>;
14
+ readonly envelope: v.NumberSchema<undefined>;
15
+ readonly partial: v.NumberSchema<undefined>;
16
+ readonly draft: v.NumberSchema<undefined>;
17
+ }, undefined>;
18
+ readonly updated_at: v.StringSchema<undefined>;
19
+ }, undefined>;
20
+ export declare const markItem: (mark: MailMark) => v.InferOutput<typeof mailMark>;
21
+ export declare const markText: (mark: MailMark) => string;
22
+ /**
23
+ * `messages acknowledge`: a holder says it is done with what `review --holder` gave it, and its mark moves there. It
24
+ * only moves the holder's own bookkeeping forward, so a read-only scheduled run may do it.
25
+ */
26
+ export declare const acknowledgeCommand: (mail: MailReads) => Command;