@taskless-app/swarm 0.6.8 → 0.6.9

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/dist/cli.js CHANGED
@@ -110,7 +110,11 @@ var init_types = __esm({
110
110
  // прогона перед самым спавном: «поехал молча» означало бы, что причина запуска исчезла из
111
111
  // истории, и следующий разбор «почему он стартовал поверх незакрытого блокера» упёрся бы в
112
112
  // пустоту. Успешное снятие (блокер смержен) события не порождает — это штатный ход.
113
- "dep_cleared"
113
+ "dep_cleared",
114
+ // TASWM-412: дрон вернул сырую задачу автору (см. RunStatus "returned"). Веха, а не step:
115
+ // прогон на этом кончается, и в истории должно быть видно, что он кончился ВОЗВРАТОМ —
116
+ // иначе возврат читается как брошенная посреди работы задача.
117
+ "returned"
114
118
  ];
115
119
  MILESTONE_KINDS = [
116
120
  "spawned",
@@ -133,8 +137,10 @@ var init_types = __esm({
133
137
  // надзор overmind (TASWM-194) — та же нотификация, что улетела в инбокс, вехой в Истории
134
138
  "note",
135
139
  // заметка дрона «замечено по пути» (TASWM-279) — веха, иначе находка тонет в ленте step'ов
136
- "dep_cleared"
140
+ "dep_cleared",
137
141
  // зависимость снята неуспешным финалом блокера (TASWM-361) — решение роя, веха как conflict
142
+ "returned"
143
+ // дрон вернул сырую задачу автору (TASWM-412) — финал прогона, веха как done/failed
138
144
  ];
139
145
  MILESTONE_KIND_SET = new Set(MILESTONE_KINDS);
140
146
  }
@@ -212,6 +218,14 @@ function buildSegments(created, events, laneEnd) {
212
218
  push(e.at);
213
219
  phase = "superseded";
214
220
  break;
221
+ // TASWM-412: возврат автору — конец прогона, хвост дорожки не должен дорисовываться
222
+ // «работающим» зелёным (та же готча, что чинил TASWM-166 для stopped/superseded).
223
+ // Фаза — ЧУЖАЯ, "stopped": своя фаза значит свой цвет-токен в обеих темах web, то есть
224
+ // правку дизайн-системы; здесь важнее, что полоса перестаёт врать про живую работу.
225
+ case "returned":
226
+ push(e.at);
227
+ phase = "stopped";
228
+ break;
215
229
  }
216
230
  }
217
231
  push(laneEnd);
@@ -249,6 +263,8 @@ function computeBlocker(status, stopReason, lastStep, pr, ci, deps, openQ) {
249
263
  return { icon: "\u23F9", text: stopReason || "\u043E\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D", tone: "stopped" };
250
264
  case "superseded":
251
265
  return { icon: "\u21BA", text: "\u043F\u0435\u0440\u0435\u0438\u0433\u0440\u0430\u043D \u043D\u0430 \u0434\u0440\u0443\u0433\u043E\u0439 \u0432\u0430\u0440\u0438\u0430\u043D\u0442", tone: "superseded" };
266
+ case "returned":
267
+ return { icon: "\u21A9", text: stopReason || "\u0432\u043E\u0437\u0432\u0440\u0430\u0449\u0435\u043D\u0430 \u0430\u0432\u0442\u043E\u0440\u0443 \u043D\u0430 \u0443\u0442\u043E\u0447\u043D\u0435\u043D\u0438\u0435", tone: "stopped" };
252
268
  case "done":
253
269
  return { icon: "\u2705", text: "\u0441\u043C\u0435\u0440\u0436\u0435\u043D\u043E", tone: "done" };
254
270
  default:
@@ -383,7 +399,11 @@ var init_status = __esm({
383
399
  storm_dead: { pill: "storm", label: "\u0448\u0442\u043E\u0440\u043C \u2014 \u0437\u0430\u043C\u043E\u0440\u043E\u0436\u0435\u043D", color: "--warning", terminal: false },
384
400
  // умер в шторм Anthropic, поднимется после отбоя (TASWM-23)
385
401
  stopped: { pill: "stopped", label: "\u043E\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D", color: "--muted-foreground", terminal: true },
386
- superseded: { pill: "superseded", label: "\u043F\u0435\u0440\u0435\u0438\u0433\u0440\u0430\u043D", color: "--muted-foreground", terminal: true }
402
+ superseded: { pill: "superseded", label: "\u043F\u0435\u0440\u0435\u0438\u0433\u0440\u0430\u043D", color: "--muted-foreground", terminal: true },
403
+ // TASWM-412: дрон вернул сырую задачу автору (вопросы комментом, задача назначена на автора
404
+ // и переведена в работу) и освободил слот. Терминальный — работа этого прогона закончена;
405
+ // цвет предупреждающий, а не destructive: смотреть должен АВТОР задачи, чинить нечего.
406
+ returned: { pill: "returned", label: "\u0432\u043E\u0437\u0432\u0440\u0430\u0449\u0435\u043D\u0430 \u0430\u0432\u0442\u043E\u0440\u0443", color: "--warning", terminal: true }
387
407
  };
388
408
  FALLBACK = STATUS_META.queued;
389
409
  TERMINAL_STATUSES = Object.keys(STATUS_META).filter(
@@ -2035,7 +2055,7 @@ var init_package = __esm({
2035
2055
  "package.json"() {
2036
2056
  package_default = {
2037
2057
  name: "@taskless-app/swarm",
2038
- version: "0.6.8",
2058
+ version: "0.6.9",
2039
2059
  type: "module",
2040
2060
  description: "Local control plane for a fleet of AI coding agents (drones), coordinating through Taskless. The overmind runs the swarm.",
2041
2061
  keywords: [
@@ -2085,7 +2105,7 @@ var init_package = __esm({
2085
2105
  execa: "^10.0.0",
2086
2106
  zod: "3.25.76"
2087
2107
  },
2088
- gitHead: "c06a3749a3ef7d0c8fcae83fd79b84ba2318859b"
2108
+ gitHead: "cefe25ffbc0e9791234055c8ba552ff3f8d07a3f"
2089
2109
  };
2090
2110
  }
2091
2111
  });
package/dist/overmind.js CHANGED
@@ -75,7 +75,11 @@ var init_types = __esm({
75
75
  // прогона перед самым спавном: «поехал молча» означало бы, что причина запуска исчезла из
76
76
  // истории, и следующий разбор «почему он стартовал поверх незакрытого блокера» упёрся бы в
77
77
  // пустоту. Успешное снятие (блокер смержен) события не порождает — это штатный ход.
78
- "dep_cleared"
78
+ "dep_cleared",
79
+ // TASWM-412: дрон вернул сырую задачу автору (см. RunStatus "returned"). Веха, а не step:
80
+ // прогон на этом кончается, и в истории должно быть видно, что он кончился ВОЗВРАТОМ —
81
+ // иначе возврат читается как брошенная посреди работы задача.
82
+ "returned"
79
83
  ];
80
84
  MILESTONE_KINDS = [
81
85
  "spawned",
@@ -98,8 +102,10 @@ var init_types = __esm({
98
102
  // надзор overmind (TASWM-194) — та же нотификация, что улетела в инбокс, вехой в Истории
99
103
  "note",
100
104
  // заметка дрона «замечено по пути» (TASWM-279) — веха, иначе находка тонет в ленте step'ов
101
- "dep_cleared"
105
+ "dep_cleared",
102
106
  // зависимость снята неуспешным финалом блокера (TASWM-361) — решение роя, веха как conflict
107
+ "returned"
108
+ // дрон вернул сырую задачу автору (TASWM-412) — финал прогона, веха как done/failed
103
109
  ];
104
110
  MILESTONE_KIND_SET = new Set(MILESTONE_KINDS);
105
111
  }
@@ -177,6 +183,14 @@ function buildSegments(created, events, laneEnd) {
177
183
  push(e.at);
178
184
  phase = "superseded";
179
185
  break;
186
+ // TASWM-412: возврат автору — конец прогона, хвост дорожки не должен дорисовываться
187
+ // «работающим» зелёным (та же готча, что чинил TASWM-166 для stopped/superseded).
188
+ // Фаза — ЧУЖАЯ, "stopped": своя фаза значит свой цвет-токен в обеих темах web, то есть
189
+ // правку дизайн-системы; здесь важнее, что полоса перестаёт врать про живую работу.
190
+ case "returned":
191
+ push(e.at);
192
+ phase = "stopped";
193
+ break;
180
194
  }
181
195
  }
182
196
  push(laneEnd);
@@ -214,6 +228,8 @@ function computeBlocker(status, stopReason, lastStep, pr, ci, deps, openQ) {
214
228
  return { icon: "\u23F9", text: stopReason || "\u043E\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D", tone: "stopped" };
215
229
  case "superseded":
216
230
  return { icon: "\u21BA", text: "\u043F\u0435\u0440\u0435\u0438\u0433\u0440\u0430\u043D \u043D\u0430 \u0434\u0440\u0443\u0433\u043E\u0439 \u0432\u0430\u0440\u0438\u0430\u043D\u0442", tone: "superseded" };
231
+ case "returned":
232
+ return { icon: "\u21A9", text: stopReason || "\u0432\u043E\u0437\u0432\u0440\u0430\u0449\u0435\u043D\u0430 \u0430\u0432\u0442\u043E\u0440\u0443 \u043D\u0430 \u0443\u0442\u043E\u0447\u043D\u0435\u043D\u0438\u0435", tone: "stopped" };
217
233
  case "done":
218
234
  return { icon: "\u2705", text: "\u0441\u043C\u0435\u0440\u0436\u0435\u043D\u043E", tone: "done" };
219
235
  default:
@@ -380,7 +396,11 @@ var init_status = __esm({
380
396
  storm_dead: { pill: "storm", label: "\u0448\u0442\u043E\u0440\u043C \u2014 \u0437\u0430\u043C\u043E\u0440\u043E\u0436\u0435\u043D", color: "--warning", terminal: false },
381
397
  // умер в шторм Anthropic, поднимется после отбоя (TASWM-23)
382
398
  stopped: { pill: "stopped", label: "\u043E\u0441\u0442\u0430\u043D\u043E\u0432\u043B\u0435\u043D", color: "--muted-foreground", terminal: true },
383
- superseded: { pill: "superseded", label: "\u043F\u0435\u0440\u0435\u0438\u0433\u0440\u0430\u043D", color: "--muted-foreground", terminal: true }
399
+ superseded: { pill: "superseded", label: "\u043F\u0435\u0440\u0435\u0438\u0433\u0440\u0430\u043D", color: "--muted-foreground", terminal: true },
400
+ // TASWM-412: дрон вернул сырую задачу автору (вопросы комментом, задача назначена на автора
401
+ // и переведена в работу) и освободил слот. Терминальный — работа этого прогона закончена;
402
+ // цвет предупреждающий, а не destructive: смотреть должен АВТОР задачи, чинить нечего.
403
+ returned: { pill: "returned", label: "\u0432\u043E\u0437\u0432\u0440\u0430\u0449\u0435\u043D\u0430 \u0430\u0432\u0442\u043E\u0440\u0443", color: "--warning", terminal: true }
384
404
  };
385
405
  AWAITING_CI_REASON = "\u0436\u0434\u0451\u0442 \u0433\u043E\u0442\u043E\u0432\u043D\u043E\u0441\u0442\u0438 CI \u2014 \u043F\u0440\u043E\u0432\u0435\u0440\u043A\u0438 PR \u0435\u0449\u0451 \u0438\u0434\u0443\u0442";
386
406
  FALLBACK = STATUS_META.queued;
@@ -4231,13 +4251,17 @@ __export(taskless_exports, {
4231
4251
  requireTaskBody: () => requireTaskBody,
4232
4252
  resetLegacyTokenWarning: () => resetLegacyTokenWarning,
4233
4253
  resolveApiToken: () => resolveApiToken,
4234
- swarmToolArgs: () => swarmToolArgs
4254
+ swarmToolArgs: () => swarmToolArgs,
4255
+ taskAuthor: () => taskAuthor
4235
4256
  });
4236
4257
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
4237
4258
  import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
4238
4259
  function isClosingTaskCategory(category) {
4239
4260
  return category === "completed" || category === "cancelled" || category === "archived";
4240
4261
  }
4262
+ function taskAuthor(u) {
4263
+ return u?.id ? { id: u.id, name: u.displayName || "\u0430\u0432\u0442\u043E\u0440 \u0437\u0430\u0434\u0430\u0447\u0438" } : null;
4264
+ }
4241
4265
  function makeTasklessClient(call, workspaceId, taskUrlBase, fetchFile, fetchImpl = fetch) {
4242
4266
  const ws = workspaceId ? { workspaceId } : {};
4243
4267
  const idCache = /* @__PURE__ */ new Map();
@@ -4277,7 +4301,10 @@ function makeTasklessClient(call, workspaceId, taskUrlBase, fetchFile, fetchImpl
4277
4301
  documents: (task.documents ?? []).filter((d) => !!d.id).map((d) => ({ id: d.id, title: d.title ?? d.id, url: d.url ?? null })),
4278
4302
  // TASWM-283: только ССЫЛКИ (порядок = порядок в задаче). Скачивание — на спавне,
4279
4303
  // в worktree конкретного дрона; getTask зовут и там, где выкладывать некуда.
4280
- attachments: collectTaskAttachments({ description: task.description, comments: task.comments ?? [] })
4304
+ attachments: collectTaskAttachments({ description: task.description, comments: task.comments ?? [] }),
4305
+ // TASWM-412: creator, иначе requester. Прод старее этой правки автора не отдаёт вовсе —
4306
+ // тогда null, и возврат просто обойдётся без переназначения (комментарий важнее).
4307
+ author: taskAuthor(task.creator) ?? taskAuthor(task.requester)
4281
4308
  };
4282
4309
  idCache.set(slug, body.id);
4283
4310
  idCache.set(body.id, body.id);
@@ -4333,6 +4360,17 @@ function makeTasklessClient(call, workspaceId, taskUrlBase, fetchFile, fetchImpl
4333
4360
  startTask: (idOrSlug) => transition("start_task", idOrSlug),
4334
4361
  // TASWM-294: intent — «человек, посмотри», а не «Готово» (см. докблок в TasklessClient).
4335
4362
  finishTask: (idOrSlug) => transition("finish_task", idOrSlug, { intent: "needs_check" }),
4363
+ // TASWM-412: назначение — через общий update_task (тот же путь, что и у UI-роута),
4364
+ // отдельного «assign»-тула у Taskless нет. Успех считаем по факту ответа тула:
4365
+ // safeCall уже отсеял isError и падения, вернув null.
4366
+ assignTask: async (idOrSlug, userId) => {
4367
+ const id = await resolveId(idOrSlug);
4368
+ if (!id) {
4369
+ console.error(`[taskless] update_task(assigneeId) \u043F\u0440\u043E\u043F\u0443\u0449\u0435\u043D: \u0437\u0430\u0434\u0430\u0447\u0430 ${idOrSlug} \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D\u0430`);
4370
+ return false;
4371
+ }
4372
+ return await safeCall("update_task", { id, assigneeId: userId }) != null;
4373
+ },
4336
4374
  uploadShot: (file) => uploadShot(safeCall, file, fetchImpl),
4337
4375
  addComment: async (idOrSlug, body, label, attachments) => {
4338
4376
  const id = await resolveId(idOrSlug);
@@ -9751,6 +9789,7 @@ async function buildDroneServer(store, opts = {}) {
9751
9789
  const server = new McpServer({ name: "overmind-drone", version: "0.1.0" });
9752
9790
  const overmindDead = async () => !await store.alive();
9753
9791
  const slugForInstruction = (fallback) => opts.expectedTaskSlug ?? fallback ?? "<slug>";
9792
+ const iAmReviewer = (run) => run?.reviews_run_id != null || run?.kind === "reviewer" || opts.reviewsRunId != null || opts.runKind === "reviewer";
9754
9793
  const freeze = async (withdraw = false) => {
9755
9794
  let slug;
9756
9795
  let branch;
@@ -9903,6 +9942,120 @@ ${notFoundText}` : notFoundText }],
9903
9942
  return { content: [{ type: "text", text: "\u0437\u0430\u043C\u0435\u0442\u043A\u0430 \u0437\u0430\u043F\u0438\u0441\u0430\u043D\u0430 \u0438 \u0443\u0435\u0434\u0435\u0442 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0443; \u043F\u0440\u043E\u0434\u043E\u043B\u0436\u0430\u0439 \u0440\u0430\u0431\u043E\u0442\u0443 \u2014 \u043E\u0442\u0432\u0435\u0442\u0430 \u043D\u0435 \u0436\u0434\u0438." }] };
9904
9943
  })
9905
9944
  );
9945
+ server.tool(
9946
+ "return_task",
9947
+ "\u0412\u0435\u0440\u043D\u0443\u0442\u044C \u0437\u0430\u0434\u0430\u0447\u0443 \u0410\u0412\u0422\u041E\u0420\u0423 \u043D\u0430 \u0443\u0442\u043E\u0447\u043D\u0435\u043D\u0438\u0435 \u0438 \u0437\u0430\u043A\u0440\u044B\u0442\u044C \u043F\u0440\u043E\u0433\u043E\u043D (\u0441\u043B\u043E\u0442 \u043E\u0441\u0432\u043E\u0431\u043E\u0434\u0438\u0442\u0441\u044F, \u0440\u043E\u0439 \u0432\u043E\u0437\u044C\u043C\u0451\u0442 \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0443\u044E \u0437\u0430\u0434\u0430\u0447\u0443). \u0417\u043E\u0432\u0438, \u0422\u041E\u041B\u042C\u041A\u041E \u0435\u0441\u043B\u0438 \u0437\u0430\u0434\u0430\u0447\u0443 \u043D\u0435\u043B\u044C\u0437\u044F \u0432\u044B\u043F\u043E\u043B\u043D\u0438\u0442\u044C \u043D\u0438 \u0432 \u043E\u0434\u043D\u043E\u043C \u0440\u0430\u0437\u0443\u043C\u043D\u043E\u043C \u0442\u043E\u043B\u043A\u043E\u0432\u0430\u043D\u0438\u0438 \u0418\u041B\u0418 \u043D\u0435\u043F\u043E\u043D\u044F\u0442\u043D\u043E, \u0447\u0435\u043C \u043F\u0440\u043E\u0432\u0435\u0440\u044F\u0442\u044C \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442. \u0414\u0432\u0430 \u043E\u0441\u043C\u044B\u0441\u043B\u0435\u043D\u043D\u044B\u0445 \u0442\u043E\u043B\u043A\u043E\u0432\u0430\u043D\u0438\u044F \u2014 \u041D\u0415 \u043F\u043E\u0432\u043E\u0434: \u0432\u044B\u0431\u0435\u0440\u0438 \u043E\u0447\u0435\u0432\u0438\u0434\u043D\u043E\u0435, \u0441\u0434\u0435\u043B\u0430\u0439 \u0438 \u043D\u0430\u0437\u043E\u0432\u0438 \u0440\u0430\u0437\u0432\u0438\u043B\u043A\u0443 \u0432 \u043E\u043F\u0438\u0441\u0430\u043D\u0438\u0438 PR. \u041F\u043E\u043D\u044F\u0442\u043D\u0430\u044F \u0437\u0430\u0434\u0430\u0447\u0430, \u043A\u043E\u0442\u043E\u0440\u0430\u044F \u0432 \u043E\u0434\u043D\u043E\u043C \u043F\u0443\u043D\u043A\u0442\u0435 \u043F\u0440\u043E\u0442\u0438\u0432\u043E\u0440\u0435\u0447\u0438\u0442 \u043F\u0440\u0430\u0432\u0438\u043B\u0443 \u043F\u0440\u043E\u0435\u043A\u0442\u0430, \u2014 \u0442\u043E\u0436\u0435 \u043D\u0435 \u043F\u043E\u0432\u043E\u0434: \u044D\u0442\u043E ask. \u0417\u0430\u0434\u0430\u0447\u0430 \u0443\u0439\u0434\u0451\u0442 \u0430\u0432\u0442\u043E\u0440\u0443 (\u043D\u0430\u0437\u043D\u0430\u0447\u0438\u043C \u043D\u0430 \u043D\u0435\u0433\u043E \u0438 \u043F\u0435\u0440\u0435\u0432\u0435\u0434\u0451\u043C \u0432 \u0440\u0430\u0431\u043E\u0442\u0443), \u0432\u043E\u043F\u0440\u043E\u0441\u044B \u0443\u0435\u0434\u0443\u0442 \u043A\u043E\u043C\u043C\u0435\u043D\u0442\u043E\u043C \u043E\u0442 \u0442\u0432\u043E\u0435\u0433\u043E \u0438\u043C\u0435\u043D\u0438. \u041F\u043E\u0441\u043B\u0435 \u0432\u044B\u0437\u043E\u0432\u0430 \u0438\u043D\u0441\u0442\u0440\u0443\u043C\u0435\u043D\u0442\u044B \u0431\u043E\u043B\u044C\u0448\u0435 \u043D\u0435 \u0437\u043E\u0432\u0438 \u2014 \u0437\u0430\u0432\u0435\u0440\u0448\u0438 \u0441\u0435\u0441\u0441\u0438\u044E.",
9948
+ {
9949
+ missing: z.string().min(30).describe("\u0447\u0435\u0433\u043E \u0432 \u0437\u0430\u0434\u0430\u0447\u0435 \u043D\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442, \u0447\u0442\u043E\u0431\u044B \u0435\u0451 \u0441\u0434\u0435\u043B\u0430\u0442\u044C \u0438\u043B\u0438 \u043F\u0440\u043E\u0432\u0435\u0440\u0438\u0442\u044C \u2014 \u043A\u043E\u043D\u043A\u0440\u0435\u0442\u043D\u043E, \u0430 \u043D\u0435 \xAB\u043D\u0435\u043F\u043E\u043D\u044F\u0442\u043D\u043E\xBB"),
9950
+ readings: z.array(z.string().min(10)).optional().describe("\u0442\u043E\u043B\u043A\u043E\u0432\u0430\u043D\u0438\u044F \u043F\u043E\u0441\u0442\u0430\u043D\u043E\u0432\u043A\u0438, \u043A\u043E\u0442\u043E\u0440\u044B\u0435 \u0442\u044B \u0440\u0430\u0441\u0441\u043C\u043E\u0442\u0440\u0435\u043B (\u0438 \u0447\u0435\u043C \u043A\u0430\u0436\u0434\u043E\u0435 \u043F\u043B\u043E\u0445\u043E/\u043F\u0440\u043E\u0442\u0438\u0432\u043E\u0440\u0435\u0447\u0438\u0432\u043E)"),
9951
+ assumed: z.string().min(30).describe("\u0447\u0442\u043E \u0442\u044B \u043F\u0440\u0435\u0434\u043F\u043E\u043B\u043E\u0436\u0438\u043B \u0431\u044B \u0441\u0434\u0435\u043B\u0430\u0442\u044C, \u0435\u0441\u043B\u0438 \u0431\u044B \u043F\u0440\u0438\u0448\u043B\u043E\u0441\u044C \u0433\u0430\u0434\u0430\u0442\u044C, \u0438 \u043F\u043E\u0447\u0435\u043C\u0443 \u043D\u0435 \u0441\u0442\u0430\u043B"),
9952
+ questions: z.array(z.string().min(10)).min(1).max(7).describe("\u043A\u043E\u043D\u043A\u0440\u0435\u0442\u043D\u044B\u0435 \u0432\u043E\u043F\u0440\u043E\u0441\u044B \u0430\u0432\u0442\u043E\u0440\u0443 \u2014 \u043E\u0442\u0432\u0435\u0442\u044B \u043D\u0430 \u043D\u0438\u0445 \u0434\u043E\u043B\u0436\u043D\u044B \u0434\u0435\u043B\u0430\u0442\u044C \u0437\u0430\u0434\u0430\u0447\u0443 \u0432\u044B\u043F\u043E\u043B\u043D\u0438\u043C\u043E\u0439")
9953
+ },
9954
+ guard(
9955
+ async ({
9956
+ missing,
9957
+ readings,
9958
+ assumed,
9959
+ questions
9960
+ }) => {
9961
+ if (await overmindDead()) return freeze();
9962
+ const run = await store.myRun();
9963
+ if (iAmReviewer(run) || run?.kind === "hero" || opts.runKind === "hero") {
9964
+ return {
9965
+ content: [
9966
+ {
9967
+ type: "text",
9968
+ text: "return_task \u2014 \u0442\u043E\u043B\u044C\u043A\u043E \u0434\u043B\u044F \u0434\u0440\u043E\u043D\u0430-\u0418\u0421\u041F\u041E\u041B\u041D\u0418\u0422\u0415\u041B\u042F: \u0432\u043E\u0437\u0432\u0440\u0430\u0449\u0430\u044E\u0442 \u0421\u0412\u041E\u042E \u0437\u0430\u0434\u0430\u0447\u0443 \u0430\u0432\u0442\u043E\u0440\u0443. \u0420\u0435\u0432\u044C\u044E\u0435\u0440 \u0437\u0430\u043A\u0440\u044B\u0432\u0430\u0435\u0442 \u043F\u0440\u043E\u0433\u043E\u043D \u0432\u0435\u0440\u0434\u0438\u043A\u0442\u043E\u043C \u0432 done(), \u0413\u0435\u0440\u043E\u0439 \u2014 rest()."
9969
+ }
9970
+ ],
9971
+ isError: true
9972
+ };
9973
+ }
9974
+ const slug = opts.expectedTaskSlug ?? run?.task_slug;
9975
+ if (!opts.taskless || !slug) {
9976
+ return {
9977
+ content: [
9978
+ {
9979
+ type: "text",
9980
+ text: "\u0412\u0435\u0440\u043D\u0443\u0442\u044C \u0437\u0430\u0434\u0430\u0447\u0443 \u043D\u0435\u0447\u0435\u043C: Taskless \u043D\u0435\u0434\u043E\u0441\u0442\u0443\u043F\u0435\u043D (slug-only \u0440\u0435\u0436\u0438\u043C) \u0438\u043B\u0438 \u0437\u0430\u0434\u0430\u0447\u0430 \u043F\u0440\u043E\u0433\u043E\u043D\u0430 \u043D\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043D\u0430 \u2014 \u043D\u0430\u043F\u0438\u0441\u0430\u0442\u044C \u0430\u0432\u0442\u043E\u0440\u0443 \u0438 \u043F\u0435\u0440\u0435\u043D\u0430\u0437\u043D\u0430\u0447\u0438\u0442\u044C \u0437\u0430\u0434\u0430\u0447\u0443 \u043D\u0435\u0432\u043E\u0437\u043C\u043E\u0436\u043D\u043E. \u0421\u043F\u0440\u043E\u0441\u0438 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 \u0447\u0435\u0440\u0435\u0437 ask(), \u0447\u0442\u043E \u0434\u0435\u043B\u0430\u0442\u044C."
9981
+ }
9982
+ ],
9983
+ isError: true
9984
+ };
9985
+ }
9986
+ const droneName = run?.name ?? "(\u0438\u043C\u044F \u043D\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043D\u043E)";
9987
+ const task = await opts.taskless.getTask(slug);
9988
+ const author = task?.author ?? null;
9989
+ const body = [
9990
+ `\u21A9\uFE0F **\u0412\u043E\u0437\u0432\u0440\u0430\u0442 \u0437\u0430\u0434\u0430\u0447\u0438 \u0430\u0432\u0442\u043E\u0440\u0443** \u2014 \u0434\u0440\u043E\u043D ${droneName}${run ? `, \u043F\u0440\u043E\u0433\u043E\u043D #${run.id}` : ""}.`,
9991
+ "",
9992
+ `${author ? `${author.name}, ` : ""}\u044F \u043D\u0435 \u0431\u0435\u0440\u0443\u0441\u044C \u0437\u0430 \u044D\u0442\u0443 \u0437\u0430\u0434\u0430\u0447\u0443: \u0435\u0451 \u043D\u0435\u043B\u044C\u0437\u044F \u0432\u044B\u043F\u043E\u043B\u043D\u0438\u0442\u044C, \u043D\u0435 \u0432\u044B\u0434\u0443\u043C\u0430\u0432 \u043F\u043E\u0441\u0442\u0430\u043D\u043E\u0432\u043A\u0443 \u0437\u0430 \u0442\u0435\u0431\u044F. \u0427\u0442\u043E \u043C\u0435\u0448\u0430\u0435\u0442:`,
9993
+ "",
9994
+ `**\u0427\u0435\u0433\u043E \u043D\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442.** ${missing.trim()}`,
9995
+ ...readings?.length ? ["", "**\u041A\u0430\u043A \u044D\u0442\u043E \u043C\u043E\u0436\u043D\u043E \u043F\u0440\u043E\u0447\u0438\u0442\u0430\u0442\u044C.**", ...readings.map((r) => `- ${r.trim()}`)] : [],
9996
+ "",
9997
+ `**\u0427\u0442\u043E \u044F \u043F\u0440\u0435\u0434\u043F\u043E\u043B\u043E\u0436\u0438\u043B \u0431\u044B \u0438 \u043F\u043E\u0447\u0435\u043C\u0443 \u043D\u0435 \u0441\u0442\u0430\u043B.** ${assumed.trim()}`,
9998
+ "",
9999
+ "**\u0412\u043E\u043F\u0440\u043E\u0441\u044B, \u043F\u043E\u0441\u043B\u0435 \u043E\u0442\u0432\u0435\u0442\u043E\u0432 \u043D\u0430 \u043A\u043E\u0442\u043E\u0440\u044B\u0435 \u0437\u0430\u0434\u0430\u0447\u0443 \u043C\u043E\u0436\u043D\u043E \u0431\u0440\u0430\u0442\u044C:**",
10000
+ ...questions.map((q, i) => `${i + 1}. ${q.trim()}`)
10001
+ ].join("\n");
10002
+ const failures = [];
10003
+ try {
10004
+ await opts.taskless.addComment(slug, body);
10005
+ } catch (e) {
10006
+ failures.push(`\u043A\u043E\u043C\u043C\u0435\u043D\u0442 \u0441 \u0432\u043E\u043F\u0440\u043E\u0441\u0430\u043C\u0438 \u043D\u0435 \u043E\u0442\u043F\u0440\u0430\u0432\u043B\u0435\u043D (${e instanceof Error ? e.message : String(e)})`);
10007
+ }
10008
+ let assignedOk = false;
10009
+ if (author) {
10010
+ assignedOk = await opts.taskless.assignTask(slug, author.id);
10011
+ if (!assignedOk) failures.push("\u0437\u0430\u0434\u0430\u0447\u0430 \u043D\u0435 \u043F\u0435\u0440\u0435\u043D\u0430\u0437\u043D\u0430\u0447\u0435\u043D\u0430 \u043D\u0430 \u0430\u0432\u0442\u043E\u0440\u0430");
10012
+ } else {
10013
+ failures.push("\u0430\u0432\u0442\u043E\u0440 \u0437\u0430\u0434\u0430\u0447\u0438 \u043D\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u0435\u043D (get_task \u0435\u0433\u043E \u043D\u0435 \u043E\u0442\u0434\u0430\u043B) \u2014 \u0437\u0430\u0434\u0430\u0447\u0430 \u043E\u0441\u0442\u0430\u043B\u0430\u0441\u044C \u043D\u0430 \u043F\u0440\u0435\u0436\u043D\u0435\u043C \u0438\u0441\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u0435");
10014
+ }
10015
+ await opts.taskless.startTask(slug).catch((e) => {
10016
+ failures.push(`\u0437\u0430\u0434\u0430\u0447\u0430 \u043D\u0435 \u043F\u0435\u0440\u0435\u0432\u0435\u0434\u0435\u043D\u0430 \u0432 \u0440\u0430\u0431\u043E\u0442\u0443 (${e instanceof Error ? e.message : String(e)})`);
10017
+ });
10018
+ if (!assignedOk) {
10019
+ const after = await opts.taskless.getTask(slug).catch(() => null);
10020
+ if (!after || after.statusCategory === "unstarted") {
10021
+ await store.addEvent(
10022
+ null,
10023
+ "step",
10024
+ `\u0432\u043E\u0437\u0432\u0440\u0430\u0442 \u043D\u0435 \u0437\u0430\u043A\u0440\u044B\u0442: \u0437\u0430\u0434\u0430\u0447\u0430 ${slug} \u043E\u0441\u0442\u0430\u043B\u0430\u0441\u044C claimable (${failures.join("; ")}) \u2014 \u043F\u0440\u043E\u0433\u043E\u043D \u043E\u0441\u0442\u0430\u0432\u043B\u0435\u043D running, \u0447\u0442\u043E\u0431\u044B \u0440\u043E\u0439 \u043D\u0435 \u0432\u0437\u044F\u043B \u0435\u0451 \u043F\u043E \u043A\u0440\u0443\u0433\u0443`
10025
+ );
10026
+ return {
10027
+ content: [
10028
+ {
10029
+ type: "text",
10030
+ text: [
10031
+ `\u0412\u043E\u0437\u0432\u0440\u0430\u0442 \u041D\u0415 \u0437\u0430\u0432\u0435\u0440\u0448\u0451\u043D: ${failures.join("; ")}.`,
10032
+ `\u0417\u0430\u0434\u0430\u0447\u0430 ${slug} \u043E\u0441\u0442\u0430\u043B\u0430\u0441\u044C \u0432 \u0442\u043E\u043C \u0436\u0435 \u0441\u0442\u0430\u0442\u0443\u0441\u0435 \u0438 \u043D\u0430 \u0442\u043E\u043C \u0436\u0435 \u0438\u0441\u043F\u043E\u043B\u043D\u0438\u0442\u0435\u043B\u0435 \u2014 \u0437\u0430\u043A\u0440\u043E\u0439 \u044F \u043F\u0440\u043E\u0433\u043E\u043D \u0441\u0435\u0439\u0447\u0430\u0441, \u0440\u043E\u0439 \u0432\u0437\u044F\u043B \u0431\u044B \u0435\u0451 \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u043C \u0434\u0440\u043E\u043D\u043E\u043C \u043F\u043E \u043A\u0440\u0443\u0433\u0443.`,
10033
+ "\u0412\u043E\u043F\u0440\u043E\u0441\u044B \u0430\u0432\u0442\u043E\u0440\u0443 \u043A\u043E\u043C\u043C\u0435\u043D\u0442\u043E\u043C \u0443\u0436\u0435 \u0443\u0435\u0445\u0430\u043B\u0438. \u041F\u043E\u0432\u0442\u043E\u0440\u0438 return_task \u0447\u0435\u0440\u0435\u0437 \u043C\u0438\u043D\u0443\u0442\u0443 (\u043A\u043E\u043C\u043C\u0435\u043D\u0442 \u0437\u0430\u0434\u0432\u043E\u0438\u0442\u0441\u044F \u2014 \u044D\u0442\u043E \u043C\u0435\u043D\u044C\u0448\u0435\u0435 \u0437\u043B\u043E) \u043B\u0438\u0431\u043E \u0441\u043F\u0440\u043E\u0441\u0438 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 \u0447\u0435\u0440\u0435\u0437 ask()."
10034
+ ].join("\n")
10035
+ }
10036
+ ],
10037
+ isError: true
10038
+ };
10039
+ }
10040
+ }
10041
+ const reason = `\u0432\u043E\u0437\u0432\u0440\u0430\u0449\u0435\u043D\u0430 \u0430\u0432\u0442\u043E\u0440\u0443${author ? ` (${author.name})` : ""}: ${missing.trim()}`;
10042
+ await store.updateRun(null, { status: "returned", stop_reason: reason });
10043
+ await store.addEvent(null, "returned", failures.length ? `${reason} \xB7 \u043D\u0435 \u0434\u043E\u0435\u0445\u0430\u043B\u043E: ${failures.join("; ")}` : reason);
10044
+ return {
10045
+ content: [
10046
+ {
10047
+ type: "text",
10048
+ text: [
10049
+ `\u0417\u0430\u0434\u0430\u0447\u0430 ${slug} \u0432\u043E\u0437\u0432\u0440\u0430\u0449\u0435\u043D\u0430 \u0430\u0432\u0442\u043E\u0440\u0443${author ? ` (${author.name})` : ""}, \u043F\u0440\u043E\u0433\u043E\u043D \u0437\u0430\u043A\u0440\u044B\u0442 \u043A\u0430\u043A \xAB\u0432\u043E\u0437\u0432\u0440\u0430\u0449\u0435\u043D\u0430 \u0430\u0432\u0442\u043E\u0440\u0443\xBB, \u0441\u043B\u043E\u0442 \u043E\u0441\u0432\u043E\u0431\u043E\u0436\u0434\u0451\u043D.`,
10050
+ ...failures.length ? [`\u26A0\uFE0F \u041D\u0435 \u0434\u043E\u0435\u0445\u0430\u043B\u043E: ${failures.join("; ")} \u2014 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440 \u0443\u0432\u0438\u0434\u0438\u0442 \u044D\u0442\u043E \u0432 \u043B\u043E\u0433\u0435 \u043F\u0440\u043E\u0433\u043E\u043D\u0430.`] : [],
10051
+ "\u0411\u043E\u043B\u044C\u0448\u0435 \u0438\u043D\u0441\u0442\u0440\u0443\u043C\u0435\u043D\u0442\u043E\u0432 \u041D\u0415 \u0437\u043E\u0432\u0438 \u0438 \u0437\u0430\u0434\u0430\u0447\u0443 \u0434\u0430\u043B\u044C\u0448\u0435 \u041D\u0415 \u0434\u0435\u043B\u0430\u0439 \u2014 \u043F\u0440\u043E\u0441\u0442\u043E \u0437\u0430\u0432\u0435\u0440\u0448\u0438 \u0441\u0435\u0441\u0441\u0438\u044E."
10052
+ ].join("\n")
10053
+ }
10054
+ ]
10055
+ };
10056
+ }
10057
+ )
10058
+ );
9906
10059
  server.tool(
9907
10060
  "rest",
9908
10061
  "\u0422\u043E\u043B\u044C\u043A\u043E \u0434\u043B\u044F \u0413\u0435\u0440\u043E\u044F-\u043B\u0435\u0439\u0442\u0435\u043D\u0430\u043D\u0442\u0430. \u0417\u0430\u043C\u0435\u0440\u0435\u0442\u044C \u0434\u043E \u0441\u043B\u0435\u0434\u0443\u044E\u0449\u0435\u0433\u043E \u0441\u043E\u0431\u044B\u0442\u0438\u044F \u043E\u0442\u0440\u044F\u0434\u0430: \u0440\u044B\u0432\u043E\u043A \u0441\u0434\u0435\u043B\u0430\u043D (\u043F\u043E\u0434\u0437\u0430\u0434\u0430\u0447\u0438 \u0441\u043E\u0437\u0434\u0430\u043D\u044B / \u0434\u043E\u043A\u043B\u0430\u0434 \u0434\u0430\u043D / \u043E\u0442\u0432\u0435\u0442\u044B \u0440\u043E\u0437\u0434\u0430\u043D\u044B), \u0437\u0432\u0430\u0442\u044C \u0431\u043E\u043B\u044C\u0448\u0435 \u043D\u0435\u0447\u0435\u0433\u043E. \u041F\u0440\u043E\u0433\u043E\u043D \u2192 paused, \u043F\u0440\u043E\u0446\u0435\u0441\u0441 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u0441\u044F; \u0440\u0430\u0437\u0431\u0443\u0434\u0438\u0442 \u043E\u0432\u0435\u0440\u043C\u0430\u0439\u043D\u0434 \u043F\u043E \u0441\u043E\u0431\u044B\u0442\u0438\u044E \u043E\u0442\u0440\u044F\u0434\u0430 \u0438\u043B\u0438 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440 \u0432\u0440\u0443\u0447\u043D\u0443\u044E. \u041E\u0431\u044B\u0447\u043D\u044B\u0439 \u0434\u0440\u043E\u043D \u0441\u0434\u0430\u0451\u0442 \u0440\u0430\u0431\u043E\u0442\u0443 \u0447\u0435\u0440\u0435\u0437 done, \u043D\u0435 rest.",
@@ -9962,9 +10115,7 @@ ${notFoundText}` : notFoundText }],
9962
10115
  isError: true
9963
10116
  };
9964
10117
  }
9965
- const reviewerBySpawn = opts.reviewsRunId != null || opts.runKind === "reviewer";
9966
- const iAmReviewer = run?.reviews_run_id != null || run?.kind === "reviewer" || reviewerBySpawn;
9967
- if (iAmReviewer && run?.reviews_run_id == null) {
10118
+ if (iAmReviewer(run) && run?.reviews_run_id == null) {
9968
10119
  return {
9969
10120
  content: [
9970
10121
  {
@@ -11454,7 +11605,7 @@ async function changedPaths(worktree, opts = {}) {
11454
11605
  // package.json
11455
11606
  var package_default = {
11456
11607
  name: "@taskless-app/swarm",
11457
- version: "0.6.8",
11608
+ version: "0.6.9",
11458
11609
  type: "module",
11459
11610
  description: "Local control plane for a fleet of AI coding agents (drones), coordinating through Taskless. The overmind runs the swarm.",
11460
11611
  keywords: [
@@ -11504,7 +11655,7 @@ var package_default = {
11504
11655
  execa: "^10.0.0",
11505
11656
  zod: "3.25.76"
11506
11657
  },
11507
- gitHead: "c06a3749a3ef7d0c8fcae83fd79b84ba2318859b"
11658
+ gitHead: "cefe25ffbc0e9791234055c8ba552ff3f8d07a3f"
11508
11659
  };
11509
11660
 
11510
11661
  // src/version.ts
@@ -14385,7 +14536,12 @@ ${task.description}` : `\u0417\u0430\u0434\u0430\u0447\u0430 ${run.task_slug} (\
14385
14536
  // вторую ветку мимо PR. Пишем ту, что реально записана на прогоне; пусто (первый спавн —
14386
14537
  // ветку заводит spawnDrone из слага) — прежняя формулировка.
14387
14538
  `\u0422\u044B \u2014 \u0434\u0440\u043E\u043D \u0440\u043E\u044F. \u0420\u0430\u0431\u043E\u0442\u0430\u0435\u0448\u044C \u0432 \u044D\u0442\u043E\u043C git-worktree, \u0432\u0435\u0442\u043A\u0430 \`${run.branch || run.task_slug}\`${run.branch && run.branch !== run.task_slug ? " (\u043E\u043D\u0430 \u041D\u0415 \u0440\u0430\u0432\u043D\u0430 \u0441\u043B\u0430\u0433\u0443 \u0437\u0430\u0434\u0430\u0447\u0438 \u2014 \u044D\u0442\u043E \u043F\u0440\u043E\u0434\u043E\u043B\u0436\u0435\u043D\u0438\u0435 \u0443\u0436\u0435 \u043E\u0442\u043A\u0440\u044B\u0442\u043E\u0433\u043E PR, \u043F\u0443\u0448 \u0442\u043E\u043B\u044C\u043A\u043E \u0432 \u043D\u0435\u0451)" : " \u0441\u043E\u0437\u0434\u0430\u043D\u0430 \u043F\u043E slug \u0437\u0430\u0434\u0430\u0447\u0438"}.`,
14388
- "\u0418\u043D\u0441\u0442\u0440\u0443\u043C\u0435\u043D\u0442\u044B overmind (MCP): report_step(text) \u2014 \u043B\u043E\u0433\u0438\u0440\u0443\u0439 \u0445\u043E\u0434 \u0440\u0430\u0431\u043E\u0442\u044B; read_task() \u2014 \u0441\u0432\u0435\u0436\u0438\u0439 \u0441\u043D\u0430\u043F\u0448\u043E\u0442 \u0437\u0430\u0434\u0430\u0447\u0438 (\u043E\u043F\u0438\u0441\u0430\u043D\u0438\u0435+\u043A\u0440\u0438\u0442\u0435\u0440\u0438\u0438 \u0433\u043E\u0442\u043E\u0432\u043D\u043E\u0441\u0442\u0438+\u043A\u043E\u043C\u043C\u0435\u043D\u0442\u044B+\u0434\u043E\u043A\u0438+\u0438\u0441\u0445\u043E\u0434\u044B \u0441\u043E\u0441\u0435\u0434\u043D\u0438\u0445 \u0437\u0430\u0434\u0430\u0447 \u043F\u043E \u0437\u043E\u043D\u0435 \u043A\u043E\u0434\u0430) \u0431\u0435\u0437 \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u043E\u0432, \u0435\u0441\u043B\u0438 \u0442\u0440\u0435\u0431\u043E\u0432\u0430\u043D\u0438\u044F \u043C\u043E\u0433\u043B\u0438 \u0434\u043E\u043F\u0438\u0441\u0430\u0442\u044C \u043F\u043E\u0441\u043B\u0435 \u0441\u0442\u0430\u0440\u0442\u0430; ask(question, options?) \u2014 \u0435\u0441\u043B\u0438 \u0443\u043F\u0451\u0440\u0441\u044F \u0432 \u0420\u0415\u0428\u0415\u041D\u0418\u0415, \u0441\u043F\u0440\u043E\u0441\u0438 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 (\u0434\u0430\u0439 2\u20134 \u0432\u0430\u0440\u0438\u0430\u043D\u0442\u0430 \u0432 options, \u0435\u0441\u043B\u0438 \u0440\u0430\u0437\u0432\u0438\u043B\u043A\u0430 \u0441\u0442\u0440\u0443\u043A\u0442\u0443\u0440\u043D\u0430\u044F) \u0438 \u0434\u043E\u0436\u0434\u0438\u0441\u044C \u043E\u0442\u0432\u0435\u0442\u0430 (\u041D\u0415 \u0443\u0433\u0430\u0434\u044B\u0432\u0430\u0439); report_acceptance_check(id, state, evidence) \u2014 \u0437\u0430\u043A\u0440\u043E\u0439 \u041A\u0410\u0416\u0414\u042B\u0419 \u043F\u0443\u043D\u043A\u0442 \u043A\u0440\u0438\u0442\u0435\u0440\u0438\u0435\u0432 \u0433\u043E\u0442\u043E\u0432\u043D\u043E\u0441\u0442\u0438 \u0437\u0430\u0434\u0430\u0447\u0438 (id \u0431\u0435\u0440\u0451\u0442\u0441\u044F \u0438\u0437 \u0431\u043B\u043E\u043A\u0430 \xAB\u041A\u0440\u0438\u0442\u0435\u0440\u0438\u0438 \u0433\u043E\u0442\u043E\u0432\u043D\u043E\u0441\u0442\u0438\xBB, state = passed|failed|pending \u043F\u043E \u0444\u0430\u043A\u0442\u0443 \u043F\u0440\u043E\u0433\u043E\u043D\u0430, evidence \u2014 \u0432\u044B\u0432\u043E\u0434 \u043A\u043E\u043C\u0430\u043D\u0434\u044B/\u0441\u0441\u044B\u043B\u043A\u0430/\u0447\u0442\u043E \u043D\u0430\u0431\u043B\u044E\u0434\u0430\u043B); \u043F\u0440\u043E\u0439\u0434\u0438\u0441\u044C \u043F\u043E \u043D\u0438\u043C \u041F\u0415\u0420\u0415\u0414 done(), \u0438\u043D\u0430\u0447\u0435 \u0433\u0430\u043B\u043E\u0447\u043A\u0438 \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0435\u0442 \u0440\u0443\u043A\u0430\u043C\u0438 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440; done(pr_url) \u2014 \u043A\u043E\u0433\u0434\u0430 \u043E\u0442\u043A\u0440\u043E\u0435\u0448\u044C PR; note(text) \u2014 \u0437\u0430\u043C\u0435\u0442\u043A\u0430 \xAB\u0437\u0430\u043C\u0435\u0447\u0435\u043D\u043E \u043F\u043E \u043F\u0443\u0442\u0438\xBB \u0411\u0415\u0417 \u0431\u043B\u043E\u043A\u0438\u0440\u043E\u0432\u043A\u0438: \u043D\u0430\u0442\u043A\u043D\u0443\u043B\u0441\u044F \u043D\u0430 \u043F\u0440\u043E\u0431\u0435\u043B \u0432 \u0434\u0438\u0437\u0430\u0439\u043D-\u0441\u0438\u0441\u0442\u0435\u043C\u0435, \u043F\u0440\u043E\u0442\u0443\u0445\u0448\u0443\u044E \u0438\u043D\u0441\u0442\u0440\u0443\u043A\u0446\u0438\u044E, \u0431\u0430\u0433 \u0440\u044F\u0434\u043E\u043C \u0441\u043E \u0441\u0432\u043E\u0438\u043C \u0434\u0438\u0444\u0444\u043E\u043C \u2014 \u0441\u043A\u0430\u0436\u0438 \u0438 \u0440\u0430\u0431\u043E\u0442\u0430\u0439 \u0434\u0430\u043B\u044C\u0448\u0435, \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440 \u0443\u0432\u0438\u0434\u0438\u0442 \u0438 \u0441\u0430\u043C \u0440\u0435\u0448\u0438\u0442, \u0437\u0430\u0432\u043E\u0434\u0438\u0442\u044C \u043B\u0438 \u0437\u0430\u0434\u0430\u0447\u0443 (\u043D\u0435 \u043F\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0439 \u0442\u0430\u043A\u043E\u0435 \u0432 \u0434\u043E\u0440\u043E\u0433\u043E\u0439 \u0431\u043B\u043E\u043A\u0438\u0440\u0443\u044E\u0449\u0438\u0439 ask \u0438 \u043D\u0435 \u0445\u043E\u0440\u043E\u043D\u0438 \u0432 \u043E\u0442\u0447\u0451\u0442\u0435 \u043E \u0441\u0434\u0430\u0447\u0435).",
14539
+ "\u0418\u043D\u0441\u0442\u0440\u0443\u043C\u0435\u043D\u0442\u044B overmind (MCP): report_step(text) \u2014 \u043B\u043E\u0433\u0438\u0440\u0443\u0439 \u0445\u043E\u0434 \u0440\u0430\u0431\u043E\u0442\u044B; read_task() \u2014 \u0441\u0432\u0435\u0436\u0438\u0439 \u0441\u043D\u0430\u043F\u0448\u043E\u0442 \u0437\u0430\u0434\u0430\u0447\u0438 (\u043E\u043F\u0438\u0441\u0430\u043D\u0438\u0435+\u043A\u0440\u0438\u0442\u0435\u0440\u0438\u0438 \u0433\u043E\u0442\u043E\u0432\u043D\u043E\u0441\u0442\u0438+\u043A\u043E\u043C\u043C\u0435\u043D\u0442\u044B+\u0434\u043E\u043A\u0438+\u0438\u0441\u0445\u043E\u0434\u044B \u0441\u043E\u0441\u0435\u0434\u043D\u0438\u0445 \u0437\u0430\u0434\u0430\u0447 \u043F\u043E \u0437\u043E\u043D\u0435 \u043A\u043E\u0434\u0430) \u0431\u0435\u0437 \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u043E\u0432, \u0435\u0441\u043B\u0438 \u0442\u0440\u0435\u0431\u043E\u0432\u0430\u043D\u0438\u044F \u043C\u043E\u0433\u043B\u0438 \u0434\u043E\u043F\u0438\u0441\u0430\u0442\u044C \u043F\u043E\u0441\u043B\u0435 \u0441\u0442\u0430\u0440\u0442\u0430; ask(question, options?) \u2014 \u0435\u0441\u043B\u0438 \u0443\u043F\u0451\u0440\u0441\u044F \u0432 \u0420\u0415\u0428\u0415\u041D\u0418\u0415, \u0441\u043F\u0440\u043E\u0441\u0438 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440\u0430 (\u0434\u0430\u0439 2\u20134 \u0432\u0430\u0440\u0438\u0430\u043D\u0442\u0430 \u0432 options, \u0435\u0441\u043B\u0438 \u0440\u0430\u0437\u0432\u0438\u043B\u043A\u0430 \u0441\u0442\u0440\u0443\u043A\u0442\u0443\u0440\u043D\u0430\u044F) \u0438 \u0434\u043E\u0436\u0434\u0438\u0441\u044C \u043E\u0442\u0432\u0435\u0442\u0430 (\u041D\u0415 \u0443\u0433\u0430\u0434\u044B\u0432\u0430\u0439); report_acceptance_check(id, state, evidence) \u2014 \u0437\u0430\u043A\u0440\u043E\u0439 \u041A\u0410\u0416\u0414\u042B\u0419 \u043F\u0443\u043D\u043A\u0442 \u043A\u0440\u0438\u0442\u0435\u0440\u0438\u0435\u0432 \u0433\u043E\u0442\u043E\u0432\u043D\u043E\u0441\u0442\u0438 \u0437\u0430\u0434\u0430\u0447\u0438 (id \u0431\u0435\u0440\u0451\u0442\u0441\u044F \u0438\u0437 \u0431\u043B\u043E\u043A\u0430 \xAB\u041A\u0440\u0438\u0442\u0435\u0440\u0438\u0438 \u0433\u043E\u0442\u043E\u0432\u043D\u043E\u0441\u0442\u0438\xBB, state = passed|failed|pending \u043F\u043E \u0444\u0430\u043A\u0442\u0443 \u043F\u0440\u043E\u0433\u043E\u043D\u0430, evidence \u2014 \u0432\u044B\u0432\u043E\u0434 \u043A\u043E\u043C\u0430\u043D\u0434\u044B/\u0441\u0441\u044B\u043B\u043A\u0430/\u0447\u0442\u043E \u043D\u0430\u0431\u043B\u044E\u0434\u0430\u043B); \u043F\u0440\u043E\u0439\u0434\u0438\u0441\u044C \u043F\u043E \u043D\u0438\u043C \u041F\u0415\u0420\u0415\u0414 done(), \u0438\u043D\u0430\u0447\u0435 \u0433\u0430\u043B\u043E\u0447\u043A\u0438 \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0435\u0442 \u0440\u0443\u043A\u0430\u043C\u0438 \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440; done(pr_url) \u2014 \u043A\u043E\u0433\u0434\u0430 \u043E\u0442\u043A\u0440\u043E\u0435\u0448\u044C PR; return_task(missing, readings, assumed, questions) \u2014 \u0432\u0435\u0440\u043D\u0443\u0442\u044C \u0421\u042B\u0420\u0423\u042E \u0437\u0430\u0434\u0430\u0447\u0443 \u0430\u0432\u0442\u043E\u0440\u0443 (\u0441\u043C. \u043F\u0440\u0430\u0432\u0438\u043B\u043E \u043D\u0438\u0436\u0435); note(text) \u2014 \u0437\u0430\u043C\u0435\u0442\u043A\u0430 \xAB\u0437\u0430\u043C\u0435\u0447\u0435\u043D\u043E \u043F\u043E \u043F\u0443\u0442\u0438\xBB \u0411\u0415\u0417 \u0431\u043B\u043E\u043A\u0438\u0440\u043E\u0432\u043A\u0438: \u043D\u0430\u0442\u043A\u043D\u0443\u043B\u0441\u044F \u043D\u0430 \u043F\u0440\u043E\u0431\u0435\u043B \u0432 \u0434\u0438\u0437\u0430\u0439\u043D-\u0441\u0438\u0441\u0442\u0435\u043C\u0435, \u043F\u0440\u043E\u0442\u0443\u0445\u0448\u0443\u044E \u0438\u043D\u0441\u0442\u0440\u0443\u043A\u0446\u0438\u044E, \u0431\u0430\u0433 \u0440\u044F\u0434\u043E\u043C \u0441\u043E \u0441\u0432\u043E\u0438\u043C \u0434\u0438\u0444\u0444\u043E\u043C \u2014 \u0441\u043A\u0430\u0436\u0438 \u0438 \u0440\u0430\u0431\u043E\u0442\u0430\u0439 \u0434\u0430\u043B\u044C\u0448\u0435, \u043E\u043F\u0435\u0440\u0430\u0442\u043E\u0440 \u0443\u0432\u0438\u0434\u0438\u0442 \u0438 \u0441\u0430\u043C \u0440\u0435\u0448\u0438\u0442, \u0437\u0430\u0432\u043E\u0434\u0438\u0442\u044C \u043B\u0438 \u0437\u0430\u0434\u0430\u0447\u0443 (\u043D\u0435 \u043F\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0439 \u0442\u0430\u043A\u043E\u0435 \u0432 \u0434\u043E\u0440\u043E\u0433\u043E\u0439 \u0431\u043B\u043E\u043A\u0438\u0440\u0443\u044E\u0449\u0438\u0439 ask \u0438 \u043D\u0435 \u0445\u043E\u0440\u043E\u043D\u0438 \u0432 \u043E\u0442\u0447\u0451\u0442\u0435 \u043E \u0441\u0434\u0430\u0447\u0435).",
14540
+ // TASWM-412: третий выход из непонятной задачи. Раньше их было два, и оба плохие —
14541
+ // угадать постановку (сделает не то) или ask (слот занят, а ответить может только автор
14542
+ // задачи, не оператор роя). Граница здесь ОБЯЗАТЕЛЬНА: дрон, легко возвращающий задачи,
14543
+ // становится отписочником, а это хуже, чем дрон, который иногда угадывает неверно.
14544
+ "\u0421\u042B\u0420\u0423\u042E \u0417\u0410\u0414\u0410\u0427\u0423 \u041D\u0415 \u0412\u042B\u0414\u0423\u041C\u042B\u0412\u0410\u0419 \u2014 \u0412\u0415\u0420\u041D\u0418 \u0410\u0412\u0422\u041E\u0420\u0423. \u041F\u0440\u043E\u0447\u0438\u0442\u0430\u0432 \u0437\u0430\u0434\u0430\u0447\u0443, \u043E\u0442\u0432\u0435\u0442\u044C \u0441\u0435\u0431\u0435 \u043D\u0430 \u0434\u0432\u0430 \u0432\u043E\u043F\u0440\u043E\u0441\u0430: \u043F\u043E\u043D\u044F\u0442\u043D\u043E \u043B\u0438, \u0427\u0422\u041E \u043D\u0443\u0436\u043D\u043E \u0441\u0434\u0435\u043B\u0430\u0442\u044C, \u0438 \u0435\u0441\u0442\u044C \u043B\u0438 \u0442\u043E, \u041F\u041E \u0427\u0415\u041C\u0423 \u043F\u0440\u043E\u0432\u0435\u0440\u0438\u0442\u044C \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442. \u041E\u0431\u0430 \xAB\u043D\u0435\u0442\xBB \u2192 return_task(missing, readings, assumed, questions): \u0432\u043E\u043F\u0440\u043E\u0441\u044B \u0443\u0435\u0434\u0443\u0442 \u043A\u043E\u043C\u043C\u0435\u043D\u0442\u043E\u043C \u0430\u0432\u0442\u043E\u0440\u0443, \u0437\u0430\u0434\u0430\u0447\u0430 \u0443\u0439\u0434\u0451\u0442 \u043D\u0430 \u043D\u0435\u0433\u043E \u0438 \u0432 \u0440\u0430\u0431\u043E\u0442\u0443, \u043F\u0440\u043E\u0433\u043E\u043D \u0437\u0430\u043A\u0440\u043E\u0435\u0442\u0441\u044F \u043A\u0430\u043A \xAB\u0432\u043E\u0437\u0432\u0440\u0430\u0449\u0435\u043D\u0430 \u0430\u0432\u0442\u043E\u0440\u0443\xBB (\u043D\u0435 \xAB\u043F\u0440\u043E\u0432\u0430\u043B\u0435\u043D\u0430\xBB), \u0441\u043B\u043E\u0442 \u043E\u0441\u0432\u043E\u0431\u043E\u0434\u0438\u0442\u0441\u044F. \u0412\u043E\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044C \u041C\u041E\u0416\u041D\u041E, \u0442\u043E\u043B\u044C\u043A\u043E \u0435\u0441\u043B\u0438 \u0437\u0430\u0434\u0430\u0447\u0443 \u043D\u0435\u043B\u044C\u0437\u044F \u0432\u044B\u043F\u043E\u043B\u043D\u0438\u0442\u044C \u043D\u0438 \u0432 \u043E\u0434\u043D\u043E\u043C \u0440\u0430\u0437\u0443\u043C\u043D\u043E\u043C \u0442\u043E\u043B\u043A\u043E\u0432\u0430\u043D\u0438\u0438 \u0438\u043B\u0438 \u043D\u0435\u0447\u0435\u043C \u043F\u0440\u043E\u0432\u0435\u0440\u0438\u0442\u044C \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442. \u0422\u043E\u043B\u043A\u043E\u0432\u0430\u043D\u0438\u0439 \u0434\u0432\u0430 \u0438 \u043E\u0431\u0430 \u043E\u0441\u043C\u044B\u0441\u043B\u0435\u043D\u043D\u044B \u2014 \u0432\u044B\u0431\u0435\u0440\u0438 \u043E\u0447\u0435\u0432\u0438\u0434\u043D\u043E\u0435, \u0441\u0434\u0435\u043B\u0430\u0439 \u0438 \u043D\u0430\u0437\u043E\u0432\u0438 \u0440\u0430\u0437\u0432\u0438\u043B\u043A\u0443 \u0432 \u043E\u043F\u0438\u0441\u0430\u043D\u0438\u0438 PR. \u0417\u0430\u0434\u0430\u0447\u0430 \u043F\u043E\u043D\u044F\u0442\u043D\u0430, \u043D\u043E \u0432 \u043E\u0434\u043D\u043E\u043C \u043F\u0443\u043D\u043A\u0442\u0435 \u043F\u0440\u043E\u0442\u0438\u0432\u043E\u0440\u0435\u0447\u0438\u0442 \u043F\u0440\u0430\u0432\u0438\u043B\u0443 \u043F\u0440\u043E\u0435\u043A\u0442\u0430 \u2014 \u044D\u0442\u043E ask, \u0430 \u043D\u0435 \u0432\u043E\u0437\u0432\u0440\u0430\u0442.",
14389
14545
  "\u041F\u0440\u0430\u0432\u0438\u043B\u0430: \u0442\u0440\u043E\u0433\u0430\u0435\u0448\u044C UI \u2014 \u0421\u041D\u0410\u0427\u0410\u041B\u0410 \u043F\u043E\u0441\u043C\u043E\u0442\u0440\u0438, \u0435\u0441\u0442\u044C \u043B\u0438 \u0432 \u0440\u0435\u043F\u043E\u0437\u0438\u0442\u043E\u0440\u0438\u0438 \u0441\u043A\u0438\u043B\u043B \u0441 UI-\u043F\u0440\u0430\u0432\u0438\u043B\u0430\u043C\u0438 \u043F\u0440\u043E\u0435\u043A\u0442\u0430, \u0438 \u0441\u043B\u0435\u0434\u0443\u0439 \u0435\u0433\u043E \u0434\u0438\u0437\u0430\u0439\u043D-\u0441\u0438\u0441\u0442\u0435\u043C\u0435 (\u043D\u0435\u0442 \u043D\u0443\u0436\u043D\u043E\u0433\u043E \u043A\u043E\u043D\u0442\u0440\u043E\u043B\u0430 \u2014 \u0437\u0430\u0432\u0435\u0434\u0438 \u043E\u0442\u0434\u0435\u043B\u044C\u043D\u0443\u044E \u0437\u0430\u0434\u0430\u0447\u0443, \u043D\u0435 \u0445\u0430\u0440\u0434\u043A\u043E\u0434\u044C \u043E\u0434\u043D\u043E\u0440\u0430\u0437\u043E\u0432\u043E\u0435); \u043A\u043E\u043C\u043C\u0438\u0442\u044B \u0441\u043E slug \u0437\u0430\u0434\u0430\u0447\u0438 \u0432 \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0438; \u043F\u043E\u0441\u043B\u0435 UI-\u0438\u0437\u043C\u0435\u043D\u0435\u043D\u0438\u0439 \u043F\u0440\u0438\u043B\u043E\u0436\u0438 \u0441\u043A\u0440\u0438\u043D\u044B mobile+desktop \u041A \u0417\u0410\u0414\u0410\u0427\u0415 (\u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440 screenshots \u0443 done); \u043E\u0442\u043A\u0440\u043E\u0439 PR \u0447\u0435\u0440\u0435\u0437 gh \u0438 \u0432\u044B\u0437\u043E\u0432\u0438 done(pr_url).",
14390
14546
  // TASWM-377: у сессии есть ПОТОЛОК ТРАТ, и он режет её без предупреждения, прямо посреди
14391
14547
  // работы. Дрон об этом знать обязан: цена сессии растёт от ЧИСЛА ХОДОВ (каждый ход заново
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@taskless-app/swarm",
3
- "version": "0.6.8",
3
+ "version": "0.6.9",
4
4
  "type": "module",
5
5
  "description": "Local control plane for a fleet of AI coding agents (drones), coordinating through Taskless. The overmind runs the swarm.",
6
6
  "keywords": [
@@ -38,7 +38,7 @@
38
38
  "execa": "^10.0.0",
39
39
  "zod": "3.25.76"
40
40
  },
41
- "gitHead": "c06a3749a3ef7d0c8fcae83fd79b84ba2318859b",
41
+ "gitHead": "cefe25ffbc0e9791234055c8ba552ff3f8d07a3f",
42
42
  "scripts": {
43
43
  "overmind": "NODE_OPTIONS=\"${NODE_OPTIONS:-} --conditions=development\" tsx src/overmind.ts",
44
44
  "swarm": "NODE_OPTIONS=\"${NODE_OPTIONS:-} --conditions=development\" tsx src/cli.ts",