@wirecat/cli-core 0.510.0 → 0.512.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.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,42 @@ shape of this file.
7
7
 
8
8
  ## Unreleased
9
9
 
10
+ ## 0.512.0 — 01.11.2026
11
+
12
+ ### Added
13
+
14
+ - **A project task has two more open states: `todo` and `in_progress`.** `TASK_STATES` is `open`, `todo`,
15
+ `in_progress`, `done`, `dismissed`; `CLOSED_STATES` and `isClosedState` name the closed ones. `tasks.edit` moves a
16
+ project task between any two of them, records each move as a `status` event, sets `started_at` the first time it
17
+ enters `in_progress`, and reopens a closed task: `closed_at`, who closed it and its reason are cleared. Readiness,
18
+ `readyTasks`, claims, a person's open tasks, reminders, duplicate checks and category counts treat both new states as
19
+ open work. A task from a message stays open or closed.
20
+ - **`tasks.board(query, { limit, offset, sort, descending, zone })` and `tasks.boardCounts(query)`** list the owner's
21
+ project tasks across every project (an account's inbox is left out) with a Lucene query over `PROJECT_TASK_FIELDS`:
22
+ `state`, `kind`, `project` (`project:*` for all), `assignee` (`any`, `none`, `"person:12"`), `priority` with
23
+ ranges, `due` and `closed` with ranges, `overdue`, `ready`, and `text`, the words of the title and description
24
+ (prefixes; a task key too). The board sorts by `TASK_SORTS` and returns the total; the counts give how many tasks
25
+ hold each project, assignee, priority and state, each without the query's own terms on that field.
26
+ - **`tasks.taskPeople()`** lists the owner and everyone who holds a role on a live task, with how many tasks.
27
+ - **`tasks.events(id)`** names who acted: `actor.name` is the person's or the bot's name, or null.
28
+ - **`listQuery(text, registry, command, { defaultField })`** reads a bare word as that field instead of refusing it.
29
+ - **`events_list` takes `page`**, as `events list --page` does. Without `account_id` each page is cut from every
30
+ account's events merged in time order, so it reads at most each account's first 1000 events; a page past that is
31
+ refused with `validation_error` and asks for `account_id`.
32
+
33
+ ### Changed — may break callers
34
+
35
+ - **`ClosedState` is `done | dismissed`**, no longer every state but `open`; a check of `state === "open"` for "not
36
+ closed" misses `todo` and `in_progress` — use `isClosedState`.
37
+ - **The calendar MCP tools `event_create` and `event_update` take `operation_id`, not `id`**, as `events create` and
38
+ `events update --following` take `--operation-id` since 0.510.0. The value is the same: the `operation_id` a lost
39
+ write's `outcome_unknown` names, and that error now says "repeat with operation_id". `id` is refused as an unknown
40
+ argument; change agent prompts that pass it.
41
+ - **`events_list` answers the shared list shape**: `page: { mode: "page", limit, has_more, next_page }` and a
42
+ `page.next` step, where it answered `page: 1` and `hasMore`. Read `page.has_more` instead of `hasMore`.
43
+
44
+ ## 0.511.0 — 31.10.2026
45
+
10
46
  ## 0.510.0 — 31.10.2026
11
47
 
12
48
  ### Fixed
@@ -114,6 +150,10 @@ shape of this file.
114
150
  such queries went from 0 meaning hits to 10–17 of 20, with no hit breaking the query.
115
151
  ### Fixed
116
152
 
153
+ - **The parity manifest lists `projects` and `projects evidence`**, with their options and the new `--alias` and
154
+ `--context-query`. Without the rows, `cli-core-parity` failed max and tg once they mounted `projectsCommand` from
155
+ 0.504.0. All three are marked planned, so the check passes with or without the command; a follow-up marks max and
156
+ tg as having it once tg-cli#798 and max-cli#886 are merged.
117
157
  - **Search by meaning inside a filter ranks the filter's own messages.** With fields that hold at most 100,000
118
158
  messages (`RANK_WITHIN_MESSAGES`), `--discover` scores every one of them that has a vector, instead of taking the
119
159
  100 nearest messages overall and dropping those outside the filter. On the owner's store, `chat:<id>` with a chat of
@@ -17,6 +17,7 @@ export declare const calendarTools: ({
17
17
  query?: undefined;
18
18
  timezone?: undefined;
19
19
  limit?: undefined;
20
+ page?: undefined;
20
21
  event?: undefined;
21
22
  } | {
22
23
  account_id: {
@@ -35,12 +36,19 @@ export declare const calendarTools: ({
35
36
  type: string;
36
37
  minimum: number;
37
38
  maximum: number;
39
+ description: string;
40
+ };
41
+ page: {
42
+ type: string;
43
+ minimum: number;
44
+ description: string;
38
45
  };
39
46
  event?: undefined;
40
47
  } | {
41
48
  query?: undefined;
42
49
  timezone?: undefined;
43
50
  limit?: undefined;
51
+ page?: undefined;
44
52
  event: {
45
53
  type: string;
46
54
  minLength: number;
@@ -53,6 +61,7 @@ export declare const calendarTools: ({
53
61
  query?: undefined;
54
62
  timezone?: undefined;
55
63
  limit?: undefined;
64
+ page?: undefined;
56
65
  event?: undefined;
57
66
  account_id?: undefined;
58
67
  };
@@ -78,6 +87,7 @@ export declare const calendarTools: ({
78
87
  query?: undefined;
79
88
  timezone?: undefined;
80
89
  limit?: undefined;
90
+ page?: undefined;
81
91
  event?: undefined;
82
92
  } | {
83
93
  account_id: {
@@ -96,12 +106,19 @@ export declare const calendarTools: ({
96
106
  type: string;
97
107
  minimum: number;
98
108
  maximum: number;
109
+ description: string;
110
+ };
111
+ page: {
112
+ type: string;
113
+ minimum: number;
114
+ description: string;
99
115
  };
100
116
  event?: undefined;
101
117
  } | {
102
118
  query?: undefined;
103
119
  timezone?: undefined;
104
120
  limit?: undefined;
121
+ page?: undefined;
105
122
  event: {
106
123
  type: string;
107
124
  minLength: number;
@@ -114,6 +131,7 @@ export declare const calendarTools: ({
114
131
  query?: undefined;
115
132
  timezone?: undefined;
116
133
  limit?: undefined;
134
+ page?: undefined;
117
135
  event?: undefined;
118
136
  account_id?: undefined;
119
137
  };
@@ -139,6 +157,7 @@ export declare const calendarTools: ({
139
157
  query?: undefined;
140
158
  timezone?: undefined;
141
159
  limit?: undefined;
160
+ page?: undefined;
142
161
  event?: undefined;
143
162
  } | {
144
163
  account_id: {
@@ -157,12 +176,19 @@ export declare const calendarTools: ({
157
176
  type: string;
158
177
  minimum: number;
159
178
  maximum: number;
179
+ description: string;
180
+ };
181
+ page: {
182
+ type: string;
183
+ minimum: number;
184
+ description: string;
160
185
  };
161
186
  event?: undefined;
162
187
  } | {
163
188
  query?: undefined;
164
189
  timezone?: undefined;
165
190
  limit?: undefined;
191
+ page?: undefined;
166
192
  event: {
167
193
  type: string;
168
194
  minLength: number;
@@ -175,6 +201,7 @@ export declare const calendarTools: ({
175
201
  query?: undefined;
176
202
  timezone?: undefined;
177
203
  limit?: undefined;
204
+ page?: undefined;
178
205
  event?: undefined;
179
206
  account_id?: undefined;
180
207
  };
@@ -200,6 +227,7 @@ export declare const calendarTools: ({
200
227
  query?: undefined;
201
228
  timezone?: undefined;
202
229
  limit?: undefined;
230
+ page?: undefined;
203
231
  event?: undefined;
204
232
  } | {
205
233
  account_id: {
@@ -218,12 +246,19 @@ export declare const calendarTools: ({
218
246
  type: string;
219
247
  minimum: number;
220
248
  maximum: number;
249
+ description: string;
250
+ };
251
+ page: {
252
+ type: string;
253
+ minimum: number;
254
+ description: string;
221
255
  };
222
256
  event?: undefined;
223
257
  } | {
224
258
  query?: undefined;
225
259
  timezone?: undefined;
226
260
  limit?: undefined;
261
+ page?: undefined;
227
262
  event: {
228
263
  type: string;
229
264
  minLength: number;
@@ -236,6 +271,7 @@ export declare const calendarTools: ({
236
271
  query?: undefined;
237
272
  timezone?: undefined;
238
273
  limit?: undefined;
274
+ page?: undefined;
239
275
  event?: undefined;
240
276
  account_id?: undefined;
241
277
  };
@@ -320,7 +356,7 @@ export declare const calendarWriteTools: ({
320
356
  type: string;
321
357
  description: string;
322
358
  };
323
- id: {
359
+ operation_id: {
324
360
  type: string;
325
361
  minLength: number;
326
362
  description: string;
@@ -399,7 +435,7 @@ export declare const calendarWriteTools: ({
399
435
  type: string;
400
436
  description: string;
401
437
  };
402
- id: {
438
+ operation_id: {
403
439
  type: string;
404
440
  minLength: number;
405
441
  description: string;
@@ -554,7 +590,7 @@ export declare const calendarWriteTools: ({
554
590
  type: string;
555
591
  description: string;
556
592
  };
557
- id: {
593
+ operation_id: {
558
594
  type: string;
559
595
  minLength: number;
560
596
  description: string;
@@ -633,7 +669,7 @@ export declare const calendarWriteTools: ({
633
669
  type: string;
634
670
  description: string;
635
671
  };
636
- id: {
672
+ operation_id: {
637
673
  type: string;
638
674
  minLength: number;
639
675
  description: string;
@@ -788,7 +824,7 @@ export declare const calendarWriteTools: ({
788
824
  type: string;
789
825
  description: string;
790
826
  };
791
- id: {
827
+ operation_id: {
792
828
  type: string;
793
829
  minLength: number;
794
830
  description: string;
@@ -867,7 +903,7 @@ export declare const calendarWriteTools: ({
867
903
  type: string;
868
904
  description: string;
869
905
  };
870
- id: {
906
+ operation_id: {
871
907
  type: string;
872
908
  minLength: number;
873
909
  description: string;
@@ -1022,7 +1058,7 @@ export declare const calendarWriteTools: ({
1022
1058
  type: string;
1023
1059
  description: string;
1024
1060
  };
1025
- id: {
1061
+ operation_id: {
1026
1062
  type: string;
1027
1063
  minLength: number;
1028
1064
  description: string;
@@ -1101,7 +1137,7 @@ export declare const calendarWriteTools: ({
1101
1137
  type: string;
1102
1138
  description: string;
1103
1139
  };
1104
- id: {
1140
+ operation_id: {
1105
1141
  type: string;
1106
1142
  minLength: number;
1107
1143
  description: string;
@@ -1256,7 +1292,7 @@ export declare const calendarWriteTools: ({
1256
1292
  type: string;
1257
1293
  description: string;
1258
1294
  };
1259
- id: {
1295
+ operation_id: {
1260
1296
  type: string;
1261
1297
  minLength: number;
1262
1298
  description: string;
@@ -1335,7 +1371,7 @@ export declare const calendarWriteTools: ({
1335
1371
  type: string;
1336
1372
  description: string;
1337
1373
  };
1338
- id: {
1374
+ operation_id: {
1339
1375
  type: string;
1340
1376
  minLength: number;
1341
1377
  description: string;
@@ -1,4 +1,5 @@
1
1
  import { CliError, errorObjectOf, mcpErrorResult } from "@wirecat/cli-base";
2
+ import { listOf } from "../../cli/envelope.js";
2
3
  import { isCliFailure } from "../../errors/failures.js";
3
4
  import { listed } from "../../meetings/index.js";
4
5
  import { agentResult, UNTRUSTED_NEUTRAL } from "../../meetings/mcp/index.js";
@@ -30,7 +31,13 @@ export const calendarTools = [
30
31
  description: "stored events, earliest first; `query` takes field terms joined by AND: starts_at (>=, <, or " +
31
32
  "[a TO b}), ends_at>=, changed_at>= (events new, moved or cancelled since, each with change and was), " +
32
33
  "calendar:<id>; a date in the zone given, UTC when absent; without starts_at or ends_at, from today on",
33
- properties: { account_id: integer, query: text, timezone: text, limit: { ...integer, maximum: 1000 } },
34
+ properties: {
35
+ account_id: integer,
36
+ query: text,
37
+ timezone: text,
38
+ limit: { ...integer, maximum: 1000, description: "events per page" },
39
+ page: { ...integer, description: "which page, starting at 1; page.next_page gives the next" },
40
+ },
34
41
  required: [],
35
42
  },
36
43
  {
@@ -63,7 +70,7 @@ const following = {
63
70
  type: "boolean",
64
71
  description: "this occurrence and every later one: the series ends before it, and a new one starts with the change",
65
72
  };
66
- const newId = { ...text, description: "the id an outcome_unknown named: a retry finds that event instead of a new one" };
73
+ const operationId = (description) => ({ ...text, description });
67
74
  const notify = {
68
75
  type: "boolean",
69
76
  description: "whether the provider mails the other attendees; required when there are any",
@@ -98,7 +105,7 @@ export const calendarWriteTools = [
98
105
  calendar: text,
99
106
  ...fields,
100
107
  notify,
101
- id: newId,
108
+ operation_id: operationId("the operation_id a create that ended in outcome_unknown named: a retry finds that event"),
102
109
  },
103
110
  required: ["calendar", "title"],
104
111
  destructive: false,
@@ -107,7 +114,14 @@ export const calendarWriteTools = [
107
114
  name: "event_update",
108
115
  description: "change an event, with series every occurrence of its repeating event and its repeat rule, or with following " +
109
116
  "this occurrence and every later one",
110
- properties: { ...target, ...fields, series: flag, following, notify, id: newId },
117
+ properties: {
118
+ ...target,
119
+ ...fields,
120
+ series: flag,
121
+ following,
122
+ notify,
123
+ operation_id: operationId("with following, the operation_id an outcome_unknown named: a retry finds that new series"),
124
+ },
111
125
  required: ["event"],
112
126
  destructive: true,
113
127
  },
@@ -159,7 +173,7 @@ const argumentsOf = (name, input) => {
159
173
  if (!Object.hasOwn(args, key))
160
174
  throw new CliError("validation_error", `missing argument: ${key}`);
161
175
  for (const [key, value] of Object.entries(args))
162
- if (["account_id", "limit"].includes(key) &&
176
+ if (["account_id", "limit", "page"].includes(key) &&
163
177
  (typeof value !== "number" || !Number.isSafeInteger(value) || value < 1))
164
178
  throw new CliError("validation_error", `${key} must be a positive integer`);
165
179
  else if ([
@@ -172,7 +186,7 @@ const argumentsOf = (name, input) => {
172
186
  "end_time",
173
187
  "start_date",
174
188
  "end_date",
175
- "id",
189
+ "operation_id",
176
190
  "repeat",
177
191
  "to_calendar",
178
192
  ].includes(key) &&
@@ -228,23 +242,9 @@ export const callCalendarTool = async (store, name, input, { accountIds, failure
228
242
  case "store_status":
229
243
  answer = listed((await Promise.all(accounts.map((id) => calendarStatus(store, id, { profile: profileOf(id), now }).then(({ items }) => items)))).flat());
230
244
  break;
231
- case "events_list": {
232
- const limit = args.limit ?? 100;
233
- const lists = await Promise.all(accounts.map(async (accountId) => eventsAnswer(store, await eventsFilter(args.query, {
234
- store,
235
- accountId,
236
- zone: args.timezone ?? "UTC",
237
- now,
238
- }).then((filter) => filter && { ...filter, limit }))));
239
- const items = lists
240
- .flatMap((one) => one.items)
241
- .sort((a, b) => (a.starts_at ?? "").localeCompare(b.starts_at ?? ""));
242
- answer = listed(items.slice(0, limit), {
243
- limit,
244
- hasMore: items.length > limit || lists.some((one) => one.hasMore),
245
- });
245
+ case "events_list":
246
+ answer = await eventsList(store, args, accounts, now);
246
247
  break;
247
- }
248
248
  case "event_show":
249
249
  answer = await eventAnswer((await eventIn()).details);
250
250
  break;
@@ -270,6 +270,41 @@ export const callCalendarTool = async (store, name, input, { accountIds, failure
270
270
  return { content, structuredContent, isError: true };
271
271
  }
272
272
  };
273
+ const EVENTS_READ = 1000;
274
+ /**
275
+ * One page of events across the accounts. Page n of several accounts is not each account's page n, so each one is
276
+ * read from its first event up to the page's end and the merge is cut there.
277
+ */
278
+ const eventsList = async (store, args, accounts, now) => {
279
+ const limit = args.limit ?? 100;
280
+ const page = args.page ?? 1;
281
+ const end = page * limit;
282
+ const merging = accounts.length > 1;
283
+ if (!Number.isSafeInteger(end))
284
+ throw new CliError("validation_error", "page is too far", { param: "page" });
285
+ if (merging && end > EVENTS_READ)
286
+ throw new CliError("validation_error", `page ${page} of ${limit} reads past event ${EVENTS_READ} of each account; name one with account_id`, { param: "account_id" });
287
+ const lists = await Promise.all(accounts.map(async (accountId) => {
288
+ const filter = await eventsFilter(args.query, {
289
+ store,
290
+ accountId,
291
+ zone: args.timezone ?? "UTC",
292
+ now,
293
+ });
294
+ return merging
295
+ ? eventsAnswer(store, filter && { ...filter, limit: end })
296
+ : eventsAnswer(store, filter && { ...filter, limit }, page);
297
+ }));
298
+ const merged = lists.flatMap((one) => one.items).sort((a, b) => (a.starts_at ?? "").localeCompare(b.starts_at ?? ""));
299
+ const items = merging ? merged.slice(end - limit, end) : merged;
300
+ return listOf("events_list", {
301
+ items,
302
+ limit,
303
+ page,
304
+ has_more: (merging && merged.length > end) || lists.some((one) => one.hasMore),
305
+ args: Object.fromEntries(["account_id", "query", "timezone"].filter((key) => args[key] !== undefined).map((key) => [key, args[key]])),
306
+ });
307
+ };
273
308
  const fieldsOf = (args) => ({
274
309
  ...(args.title === undefined ? {} : { title: args.title }),
275
310
  ...(args.start_time === undefined ? {} : { startTime: args.start_time }),
@@ -322,7 +357,7 @@ const writeTool = async (store, name, args, { asked, accounts, now, writes, }) =
322
357
  zone: args.timezone ?? "UTC",
323
358
  names: {
324
359
  notify: "notify: true or false",
325
- id: "id",
360
+ id: "operation_id",
326
361
  calendar: "calendar",
327
362
  series: "series",
328
363
  following: "following",
@@ -338,13 +373,13 @@ const writeTool = async (store, name, args, { asked, accounts, now, writes, }) =
338
373
  const result = name === "event_create"
339
374
  ? await createEvent(context, args.calendar, fieldsOf(args), {
340
375
  ...choice,
341
- ...(args.id === undefined ? {} : { id: args.id }),
376
+ ...(args.operation_id === undefined ? {} : { id: args.operation_id }),
342
377
  })
343
378
  : name === "event_update"
344
379
  ? await updateEvent(context, args.event, fieldsOf(args), {
345
380
  ...on,
346
381
  ...choice,
347
- ...(args.id === undefined ? {} : { id: args.id }),
382
+ ...(args.operation_id === undefined ? {} : { id: args.operation_id }),
348
383
  })
349
384
  : name === "event_delete"
350
385
  ? await deleteEvent(context, args.event, { ...on, ...choice })
@@ -18,9 +18,11 @@ export declare const unfilteredQuery: (entity: string, schema: Parameters<typeof
18
18
  export declare const commandPath: (command: Command) => string;
19
19
  /**
20
20
  * The query as typed, validated against the list's fields, with each default whose field it does not name;
21
- * `undefined` when nothing narrows the list. CLI and MCP read a list's query through this one function.
21
+ * `undefined` when nothing narrows the list. A bare word is refused unless the list names a `defaultField` for it. CLI and MCP read a list's query through this one function.
22
22
  */
23
- export declare const listQuery: (text: string, registry: QueryRegistry, command: string) => QueryAst | undefined;
23
+ export declare const listQuery: (text: string, registry: QueryRegistry, command: string, { defaultField }?: {
24
+ defaultField?: string;
25
+ }) => QueryAst | undefined;
24
26
  /** A list's `[query...]` as typed: the words after its arguments, or one string from MCP. */
25
27
  export type QueryWords = readonly string[] | string | undefined;
26
28
  /** The query a list's action or MCP tool received, as one string for `listQuery`. */
@@ -37,11 +37,11 @@ export const commandPath = (command) => {
37
37
  };
38
38
  /**
39
39
  * The query as typed, validated against the list's fields, with each default whose field it does not name;
40
- * `undefined` when nothing narrows the list. CLI and MCP read a list's query through this one function.
40
+ * `undefined` when nothing narrows the list. A bare word is refused unless the list names a `defaultField` for it. CLI and MCP read a list's query through this one function.
41
41
  */
42
- export const listQuery = (text, registry, command) => {
42
+ export const listQuery = (text, registry, command, { defaultField = "none" } = {}) => {
43
43
  const context = { command, guide: LIST_QUERY_GUIDE };
44
- const typed = text.trim() === "" ? undefined : parseLucene(text, { defaultField: "none", ...context });
44
+ const typed = text.trim() === "" ? undefined : parseLucene(text, { defaultField, ...context });
45
45
  if (typed)
46
46
  validateQuery(typed, registry, context);
47
47
  const named = typed ? fieldsNamed(typed) : new Set();
@@ -4758,7 +4758,7 @@ export declare const ENTITIES: {
4758
4758
  readonly title: v.NullableSchema<v.StringSchema<undefined>, undefined>;
4759
4759
  readonly description: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
4760
4760
  readonly kind: v.PicklistSchema<readonly ["bug", "feature", "chore", "question", "request", "mention", "promise"], undefined>;
4761
- readonly state: v.PicklistSchema<readonly ["open", "done", "dismissed"], undefined>;
4761
+ readonly state: v.PicklistSchema<readonly ["open", "todo", "in_progress", "done", "dismissed"], undefined>;
4762
4762
  readonly origin: v.OptionalSchema<v.PicklistSchema<readonly ["rule", "agent", "owner"], undefined>, undefined>;
4763
4763
  readonly project: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
4764
4764
  readonly account: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
@@ -4820,7 +4820,7 @@ export declare const ENTITIES: {
4820
4820
  readonly title: v.StringSchema<undefined>;
4821
4821
  readonly description: v.NullableSchema<v.StringSchema<undefined>, undefined>;
4822
4822
  readonly type: v.PicklistSchema<readonly ["bug", "feature", "chore", "question", "request", "mention", "promise"], undefined>;
4823
- readonly status: v.PicklistSchema<readonly ["open", "done", "dismissed"], undefined>;
4823
+ readonly status: v.PicklistSchema<readonly ["open", "todo", "in_progress", "done", "dismissed"], undefined>;
4824
4824
  readonly priority: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
4825
4825
  readonly parent: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "a reference such as `note:42`">]>, undefined>;
4826
4826
  readonly source: v.NullableSchema<v.StringSchema<undefined>, undefined>;
@@ -4882,7 +4882,7 @@ export declare const ENTITIES: {
4882
4882
  readonly account: v.StringSchema<undefined>;
4883
4883
  readonly group: v.StringSchema<undefined>;
4884
4884
  readonly kind: v.PicklistSchema<readonly ["question", "request", "mention", "promise"], undefined>;
4885
- readonly state: v.PicklistSchema<readonly ["open", "done", "dismissed"], undefined>;
4885
+ readonly state: v.PicklistSchema<readonly ["open", "todo", "in_progress", "done", "dismissed"], undefined>;
4886
4886
  readonly reason: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
4887
4887
  readonly origin: v.PicklistSchema<readonly ["rule", "agent", "owner"], undefined>;
4888
4888
  readonly created_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`">]>;
@@ -4921,7 +4921,7 @@ export declare const ENTITIES: {
4921
4921
  readonly title: v.StringSchema<undefined>;
4922
4922
  readonly description: v.NullableSchema<v.StringSchema<undefined>, undefined>;
4923
4923
  readonly type: v.PicklistSchema<readonly ["bug", "feature", "chore", "question", "request", "mention", "promise"], undefined>;
4924
- readonly status: v.PicklistSchema<readonly ["open", "done", "dismissed"], undefined>;
4924
+ readonly status: v.PicklistSchema<readonly ["open", "todo", "in_progress", "done", "dismissed"], undefined>;
4925
4925
  readonly priority: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
4926
4926
  readonly parent: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "a reference such as `note:42`">]>, undefined>;
4927
4927
  readonly source: v.NullableSchema<v.StringSchema<undefined>, undefined>;
@@ -4984,7 +4984,7 @@ export declare const ENTITIES: {
4984
4984
  readonly account: v.StringSchema<undefined>;
4985
4985
  readonly group: v.StringSchema<undefined>;
4986
4986
  readonly kind: v.PicklistSchema<readonly ["question", "request", "mention", "promise"], undefined>;
4987
- readonly state: v.PicklistSchema<readonly ["open", "done", "dismissed"], undefined>;
4987
+ readonly state: v.PicklistSchema<readonly ["open", "todo", "in_progress", "done", "dismissed"], undefined>;
4988
4988
  readonly reason: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
4989
4989
  readonly origin: v.PicklistSchema<readonly ["rule", "agent", "owner"], undefined>;
4990
4990
  readonly created_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`">]>;
@@ -5023,7 +5023,7 @@ export declare const ENTITIES: {
5023
5023
  readonly title: v.StringSchema<undefined>;
5024
5024
  readonly description: v.NullableSchema<v.StringSchema<undefined>, undefined>;
5025
5025
  readonly type: v.PicklistSchema<readonly ["bug", "feature", "chore", "question", "request", "mention", "promise"], undefined>;
5026
- readonly status: v.PicklistSchema<readonly ["open", "done", "dismissed"], undefined>;
5026
+ readonly status: v.PicklistSchema<readonly ["open", "todo", "in_progress", "done", "dismissed"], undefined>;
5027
5027
  readonly priority: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
5028
5028
  readonly parent: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "a reference such as `note:42`">]>, undefined>;
5029
5029
  readonly source: v.NullableSchema<v.StringSchema<undefined>, undefined>;
@@ -5153,7 +5153,7 @@ export declare const ENTITIES: {
5153
5153
  readonly title: v.StringSchema<undefined>;
5154
5154
  readonly description: v.NullableSchema<v.StringSchema<undefined>, undefined>;
5155
5155
  readonly type: v.PicklistSchema<readonly ["bug", "feature", "chore", "question", "request", "mention", "promise"], undefined>;
5156
- readonly status: v.PicklistSchema<readonly ["open", "done", "dismissed"], undefined>;
5156
+ readonly status: v.PicklistSchema<readonly ["open", "todo", "in_progress", "done", "dismissed"], undefined>;
5157
5157
  readonly priority: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
5158
5158
  readonly parent: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "a reference such as `note:42`">]>, undefined>;
5159
5159
  readonly source: v.NullableSchema<v.StringSchema<undefined>, undefined>;
@@ -5248,7 +5248,7 @@ export declare const ENTITIES: {
5248
5248
  readonly title: v.StringSchema<undefined>;
5249
5249
  readonly description: v.NullableSchema<v.StringSchema<undefined>, undefined>;
5250
5250
  readonly type: v.PicklistSchema<readonly ["bug", "feature", "chore", "question", "request", "mention", "promise"], undefined>;
5251
- readonly status: v.PicklistSchema<readonly ["open", "done", "dismissed"], undefined>;
5251
+ readonly status: v.PicklistSchema<readonly ["open", "todo", "in_progress", "done", "dismissed"], undefined>;
5252
5252
  readonly priority: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
5253
5253
  readonly parent: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "a reference such as `note:42`">]>, undefined>;
5254
5254
  readonly source: v.NullableSchema<v.StringSchema<undefined>, undefined>;
@@ -7,7 +7,7 @@ export declare const taskCard: v.StrictObjectSchema<{
7
7
  readonly title: v.StringSchema<undefined>;
8
8
  readonly description: v.NullableSchema<v.StringSchema<undefined>, undefined>;
9
9
  readonly type: v.PicklistSchema<readonly ["bug", "feature", "chore", "question", "request", "mention", "promise"], undefined>;
10
- readonly status: v.PicklistSchema<readonly ["open", "done", "dismissed"], undefined>;
10
+ readonly status: v.PicklistSchema<readonly ["open", "todo", "in_progress", "done", "dismissed"], undefined>;
11
11
  readonly priority: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
12
12
  readonly parent: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "a reference such as `note:42`">]>, undefined>;
13
13
  readonly source: v.NullableSchema<v.StringSchema<undefined>, undefined>;
@@ -69,7 +69,7 @@ export declare const taskCreated: v.StrictObjectSchema<{
69
69
  readonly account: v.StringSchema<undefined>;
70
70
  readonly group: v.StringSchema<undefined>;
71
71
  readonly kind: v.PicklistSchema<readonly ["question", "request", "mention", "promise"], undefined>;
72
- readonly state: v.PicklistSchema<readonly ["open", "done", "dismissed"], undefined>;
72
+ readonly state: v.PicklistSchema<readonly ["open", "todo", "in_progress", "done", "dismissed"], undefined>;
73
73
  readonly reason: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
74
74
  readonly origin: v.PicklistSchema<readonly ["rule", "agent", "owner"], undefined>;
75
75
  readonly created_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`">]>;
@@ -108,7 +108,7 @@ export declare const taskCreated: v.StrictObjectSchema<{
108
108
  readonly title: v.StringSchema<undefined>;
109
109
  readonly description: v.NullableSchema<v.StringSchema<undefined>, undefined>;
110
110
  readonly type: v.PicklistSchema<readonly ["bug", "feature", "chore", "question", "request", "mention", "promise"], undefined>;
111
- readonly status: v.PicklistSchema<readonly ["open", "done", "dismissed"], undefined>;
111
+ readonly status: v.PicklistSchema<readonly ["open", "todo", "in_progress", "done", "dismissed"], undefined>;
112
112
  readonly priority: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
113
113
  readonly parent: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "a reference such as `note:42`">]>, undefined>;
114
114
  readonly source: v.NullableSchema<v.StringSchema<undefined>, undefined>;
@@ -171,7 +171,7 @@ export declare const taskClosed: v.StrictObjectSchema<{
171
171
  readonly account: v.StringSchema<undefined>;
172
172
  readonly group: v.StringSchema<undefined>;
173
173
  readonly kind: v.PicklistSchema<readonly ["question", "request", "mention", "promise"], undefined>;
174
- readonly state: v.PicklistSchema<readonly ["open", "done", "dismissed"], undefined>;
174
+ readonly state: v.PicklistSchema<readonly ["open", "todo", "in_progress", "done", "dismissed"], undefined>;
175
175
  readonly reason: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
176
176
  readonly origin: v.PicklistSchema<readonly ["rule", "agent", "owner"], undefined>;
177
177
  readonly created_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`">]>;
@@ -210,7 +210,7 @@ export declare const taskLinks: v.UnionSchema<[v.StrictObjectSchema<{
210
210
  readonly title: v.StringSchema<undefined>;
211
211
  readonly description: v.NullableSchema<v.StringSchema<undefined>, undefined>;
212
212
  readonly type: v.PicklistSchema<readonly ["bug", "feature", "chore", "question", "request", "mention", "promise"], undefined>;
213
- readonly status: v.PicklistSchema<readonly ["open", "done", "dismissed"], undefined>;
213
+ readonly status: v.PicklistSchema<readonly ["open", "todo", "in_progress", "done", "dismissed"], undefined>;
214
214
  readonly priority: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
215
215
  readonly parent: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "a reference such as `note:42`">]>, undefined>;
216
216
  readonly source: v.NullableSchema<v.StringSchema<undefined>, undefined>;
@@ -340,7 +340,7 @@ export declare const taskMerge: v.StrictObjectSchema<{
340
340
  readonly title: v.StringSchema<undefined>;
341
341
  readonly description: v.NullableSchema<v.StringSchema<undefined>, undefined>;
342
342
  readonly type: v.PicklistSchema<readonly ["bug", "feature", "chore", "question", "request", "mention", "promise"], undefined>;
343
- readonly status: v.PicklistSchema<readonly ["open", "done", "dismissed"], undefined>;
343
+ readonly status: v.PicklistSchema<readonly ["open", "todo", "in_progress", "done", "dismissed"], undefined>;
344
344
  readonly priority: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
345
345
  readonly parent: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "a reference such as `note:42`">]>, undefined>;
346
346
  readonly source: v.NullableSchema<v.StringSchema<undefined>, undefined>;
@@ -435,7 +435,7 @@ export declare const taskUnmerge: v.StrictObjectSchema<{
435
435
  readonly title: v.StringSchema<undefined>;
436
436
  readonly description: v.NullableSchema<v.StringSchema<undefined>, undefined>;
437
437
  readonly type: v.PicklistSchema<readonly ["bug", "feature", "chore", "question", "request", "mention", "promise"], undefined>;
438
- readonly status: v.PicklistSchema<readonly ["open", "done", "dismissed"], undefined>;
438
+ readonly status: v.PicklistSchema<readonly ["open", "todo", "in_progress", "done", "dismissed"], undefined>;
439
439
  readonly priority: v.NullableSchema<v.NumberSchema<undefined>, undefined>;
440
440
  readonly parent: v.NullableSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "a reference such as `note:42`">]>, undefined>;
441
441
  readonly source: v.NullableSchema<v.StringSchema<undefined>, undefined>;
@@ -16,7 +16,7 @@ export declare const task: v.StrictObjectSchema<{
16
16
  readonly title: v.NullableSchema<v.StringSchema<undefined>, undefined>;
17
17
  readonly description: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
18
18
  readonly kind: v.PicklistSchema<readonly ["bug", "feature", "chore", "question", "request", "mention", "promise"], undefined>;
19
- readonly state: v.PicklistSchema<readonly ["open", "done", "dismissed"], undefined>;
19
+ readonly state: v.PicklistSchema<readonly ["open", "todo", "in_progress", "done", "dismissed"], undefined>;
20
20
  readonly origin: v.OptionalSchema<v.PicklistSchema<readonly ["rule", "agent", "owner"], undefined>, undefined>;
21
21
  readonly project: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
22
22
  readonly account: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
@@ -1,5 +1,5 @@
1
1
  import { formatLocator } from "../domain/locator.js";
2
- import { createTaskService } from "../tasks/index.js";
2
+ import { createTaskService, isClosedState } from "../tasks/index.js";
3
3
  import { questions } from "./questions.js";
4
4
  import { categorize } from "./task-categories.js";
5
5
  export const taskAccount = ({ provider, account }) => `${provider}:${account}`;
@@ -57,7 +57,7 @@ export const applyTaskRules = async (review, { store, account, now, categories,
57
57
  };
58
58
  const close = async (message, kind, answer) => {
59
59
  for (const task of await store.findBySource(owner, sourceOf(message))) {
60
- if (task.kind !== kind || task.state !== "open")
60
+ if (task.kind !== kind || isClosedState(task.state))
61
61
  continue;
62
62
  result.closed += 1;
63
63
  if (dryRun)
@@ -200,7 +200,7 @@ export interface TasksService {
200
200
  export declare const CLAIM_LEASE_MS: number;
201
201
  export declare const PREVIEW = 200;
202
202
  export declare const taskTypeOf: (typed: string) => "mention" | "promise" | "question" | "request";
203
- export declare const taskStateOf: (typed: string) => "dismissed" | "done" | "open";
203
+ export declare const taskStateOf: (typed: string) => "dismissed" | "done" | "in_progress" | "open" | "todo";
204
204
  export declare const closedStateOf: (typed: string) => "dismissed" | "done";
205
205
  export declare const taskLinkKindOf: (typed: string) => "blocked-by" | "created-from" | "discovered-from" | "duplicate-of" | "evidence" | "follow-up-of" | "related-to";
206
206
  export declare const taskTypesOf: (typed: string) => TaskKind[];