wildcrane-runner 0.6.0 → 0.6.1

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.
@@ -29,9 +29,9 @@ var __commonJS = (cb, mod) => function __require2() {
29
29
  throw mod = 0, e;
30
30
  }
31
31
  };
32
- var __export = (target, all) => {
33
- for (var name in all)
34
- __defProp(target, name, { get: all[name], enumerable: true });
32
+ var __export = (target, all2) => {
33
+ for (var name in all2)
34
+ __defProp(target, name, { get: all2[name], enumerable: true });
35
35
  };
36
36
  var __copyProps = (to, from, except, desc) => {
37
37
  if (from && typeof from === "object" || typeof from === "function") {
@@ -50,9 +50,9 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
50
50
  mod
51
51
  ));
52
52
 
53
- // ../../../../../cli/node_modules/commander/lib/error.js
53
+ // ../cli/node_modules/commander/lib/error.js
54
54
  var require_error = __commonJS({
55
- "../../../../../cli/node_modules/commander/lib/error.js"(exports) {
55
+ "../cli/node_modules/commander/lib/error.js"(exports) {
56
56
  var CommanderError2 = class extends Error {
57
57
  /**
58
58
  * Constructs the CommanderError class
@@ -85,9 +85,9 @@ var require_error = __commonJS({
85
85
  }
86
86
  });
87
87
 
88
- // ../../../../../cli/node_modules/commander/lib/argument.js
88
+ // ../cli/node_modules/commander/lib/argument.js
89
89
  var require_argument = __commonJS({
90
- "../../../../../cli/node_modules/commander/lib/argument.js"(exports) {
90
+ "../cli/node_modules/commander/lib/argument.js"(exports) {
91
91
  var { InvalidArgumentError: InvalidArgumentError2 } = require_error();
92
92
  var Argument2 = class {
93
93
  /**
@@ -212,9 +212,9 @@ var require_argument = __commonJS({
212
212
  }
213
213
  });
214
214
 
215
- // ../../../../../cli/node_modules/commander/lib/help.js
215
+ // ../cli/node_modules/commander/lib/help.js
216
216
  var require_help = __commonJS({
217
- "../../../../../cli/node_modules/commander/lib/help.js"(exports) {
217
+ "../cli/node_modules/commander/lib/help.js"(exports) {
218
218
  var { humanReadableArgName } = require_argument();
219
219
  var Help2 = class {
220
220
  constructor() {
@@ -781,9 +781,9 @@ ${itemIndentStr}`);
781
781
  }
782
782
  });
783
783
 
784
- // ../../../../../cli/node_modules/commander/lib/option.js
784
+ // ../cli/node_modules/commander/lib/option.js
785
785
  var require_option = __commonJS({
786
- "../../../../../cli/node_modules/commander/lib/option.js"(exports) {
786
+ "../cli/node_modules/commander/lib/option.js"(exports) {
787
787
  var { InvalidArgumentError: InvalidArgumentError2 } = require_error();
788
788
  var Option2 = class {
789
789
  /**
@@ -1082,9 +1082,9 @@ var require_option = __commonJS({
1082
1082
  }
1083
1083
  });
1084
1084
 
1085
- // ../../../../../cli/node_modules/commander/lib/suggestSimilar.js
1085
+ // ../cli/node_modules/commander/lib/suggestSimilar.js
1086
1086
  var require_suggestSimilar = __commonJS({
1087
- "../../../../../cli/node_modules/commander/lib/suggestSimilar.js"(exports) {
1087
+ "../cli/node_modules/commander/lib/suggestSimilar.js"(exports) {
1088
1088
  var maxDistance = 3;
1089
1089
  function editDistance2(a, b) {
1090
1090
  if (Math.abs(a.length - b.length) > maxDistance)
@@ -1162,13 +1162,13 @@ var require_suggestSimilar = __commonJS({
1162
1162
  }
1163
1163
  });
1164
1164
 
1165
- // ../../../../../cli/node_modules/commander/lib/command.js
1165
+ // ../cli/node_modules/commander/lib/command.js
1166
1166
  var require_command = __commonJS({
1167
- "../../../../../cli/node_modules/commander/lib/command.js"(exports) {
1167
+ "../cli/node_modules/commander/lib/command.js"(exports) {
1168
1168
  var EventEmitter = __require("node:events").EventEmitter;
1169
1169
  var childProcess = __require("node:child_process");
1170
- var path80 = __require("node:path");
1171
- var fs86 = __require("node:fs");
1170
+ var path83 = __require("node:path");
1171
+ var fs88 = __require("node:fs");
1172
1172
  var process2 = __require("node:process");
1173
1173
  var { Argument: Argument2, humanReadableArgName } = require_argument();
1174
1174
  var { CommanderError: CommanderError2 } = require_error();
@@ -2149,7 +2149,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2149
2149
  * @param {string} subcommandName
2150
2150
  */
2151
2151
  _checkForMissingExecutable(executableFile, executableDir, subcommandName) {
2152
- if (fs86.existsSync(executableFile)) return;
2152
+ if (fs88.existsSync(executableFile)) return;
2153
2153
  const executableDirMessage = executableDir ? `searched for local subcommand relative to directory '${executableDir}'` : "no directory for search for local subcommand, use .executableDir() to supply a custom directory";
2154
2154
  const executableMissing = `'${executableFile}' does not exist
2155
2155
  - if '${subcommandName}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead
@@ -2167,11 +2167,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
2167
2167
  let launchWithNode = false;
2168
2168
  const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
2169
2169
  function findFile(baseDir, baseName) {
2170
- const localBin = path80.resolve(baseDir, baseName);
2171
- if (fs86.existsSync(localBin)) return localBin;
2172
- if (sourceExt.includes(path80.extname(baseName))) return void 0;
2170
+ const localBin = path83.resolve(baseDir, baseName);
2171
+ if (fs88.existsSync(localBin)) return localBin;
2172
+ if (sourceExt.includes(path83.extname(baseName))) return void 0;
2173
2173
  const foundExt = sourceExt.find(
2174
- (ext) => fs86.existsSync(`${localBin}${ext}`)
2174
+ (ext) => fs88.existsSync(`${localBin}${ext}`)
2175
2175
  );
2176
2176
  if (foundExt) return `${localBin}${foundExt}`;
2177
2177
  return void 0;
@@ -2183,21 +2183,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
2183
2183
  if (this._scriptPath) {
2184
2184
  let resolvedScriptPath;
2185
2185
  try {
2186
- resolvedScriptPath = fs86.realpathSync(this._scriptPath);
2186
+ resolvedScriptPath = fs88.realpathSync(this._scriptPath);
2187
2187
  } catch {
2188
2188
  resolvedScriptPath = this._scriptPath;
2189
2189
  }
2190
- executableDir = path80.resolve(
2191
- path80.dirname(resolvedScriptPath),
2190
+ executableDir = path83.resolve(
2191
+ path83.dirname(resolvedScriptPath),
2192
2192
  executableDir
2193
2193
  );
2194
2194
  }
2195
2195
  if (executableDir) {
2196
2196
  let localFile = findFile(executableDir, executableFile);
2197
2197
  if (!localFile && !subcommand._executableFile && this._scriptPath) {
2198
- const legacyName = path80.basename(
2198
+ const legacyName = path83.basename(
2199
2199
  this._scriptPath,
2200
- path80.extname(this._scriptPath)
2200
+ path83.extname(this._scriptPath)
2201
2201
  );
2202
2202
  if (legacyName !== this._name) {
2203
2203
  localFile = findFile(
@@ -2208,7 +2208,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2208
2208
  }
2209
2209
  executableFile = localFile || executableFile;
2210
2210
  }
2211
- launchWithNode = sourceExt.includes(path80.extname(executableFile));
2211
+ launchWithNode = sourceExt.includes(path83.extname(executableFile));
2212
2212
  let proc;
2213
2213
  if (process2.platform !== "win32") {
2214
2214
  if (launchWithNode) {
@@ -3055,7 +3055,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
3055
3055
  * @return {Command}
3056
3056
  */
3057
3057
  nameFromFilename(filename) {
3058
- this._name = path80.basename(filename, path80.extname(filename));
3058
+ this._name = path83.basename(filename, path83.extname(filename));
3059
3059
  return this;
3060
3060
  }
3061
3061
  /**
@@ -3069,9 +3069,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
3069
3069
  * @param {string} [path]
3070
3070
  * @return {(string|null|Command)}
3071
3071
  */
3072
- executableDir(path81) {
3073
- if (path81 === void 0) return this._executableDir;
3074
- this._executableDir = path81;
3072
+ executableDir(path84) {
3073
+ if (path84 === void 0) return this._executableDir;
3074
+ this._executableDir = path84;
3075
3075
  return this;
3076
3076
  }
3077
3077
  /**
@@ -3321,9 +3321,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
3321
3321
  }
3322
3322
  });
3323
3323
 
3324
- // ../../../../../cli/node_modules/commander/index.js
3324
+ // ../cli/node_modules/commander/index.js
3325
3325
  var require_commander = __commonJS({
3326
- "../../../../../cli/node_modules/commander/index.js"(exports) {
3326
+ "../cli/node_modules/commander/index.js"(exports) {
3327
3327
  var { Argument: Argument2 } = require_argument();
3328
3328
  var { Command: Command2 } = require_command();
3329
3329
  var { CommanderError: CommanderError2, InvalidArgumentError: InvalidArgumentError2 } = require_error();
@@ -3343,10 +3343,10 @@ var require_commander = __commonJS({
3343
3343
  }
3344
3344
  });
3345
3345
 
3346
- // ../../../../../cli/node_modules/commander/esm.mjs
3346
+ // ../cli/node_modules/commander/esm.mjs
3347
3347
  var import_index, program, createCommand, createArgument, createOption, CommanderError, InvalidArgumentError, InvalidOptionArgumentError, Command, Argument, Option, Help;
3348
3348
  var init_esm = __esm({
3349
- "../../../../../cli/node_modules/commander/esm.mjs"() {
3349
+ "../cli/node_modules/commander/esm.mjs"() {
3350
3350
  import_index = __toESM(require_commander(), 1);
3351
3351
  ({
3352
3352
  program,
@@ -3637,11 +3637,11 @@ function boardPath() {
3637
3637
  return rel(KANBAN).split(path3.sep).join("/");
3638
3638
  }
3639
3639
  function boardText(text5) {
3640
- const posix2 = (p) => rel(p).split(path3.sep).join("/");
3640
+ const posix3 = (p) => rel(p).split(path3.sep).join("/");
3641
3641
  const swaps = [
3642
- [ASSETS_PATH_IN_TEXT, posix2(ASSETS)],
3643
- [MOCKUPS_PATH_IN_TEXT, posix2(MOCKUPS)],
3644
- [BOARD_STATE_IN_TEXT, posix2(BOARD_STATE)],
3642
+ [ASSETS_PATH_IN_TEXT, posix3(ASSETS)],
3643
+ [MOCKUPS_PATH_IN_TEXT, posix3(MOCKUPS)],
3644
+ [BOARD_STATE_IN_TEXT, posix3(BOARD_STATE)],
3645
3645
  [BOARD_PATH_IN_TEXT, boardPath()]
3646
3646
  ];
3647
3647
  const swap = (part, i) => i === swaps.length ? part : part.split(swaps[i][0]).map((p) => swap(p, i + 1)).join(swaps[i][1]);
@@ -3850,8 +3850,8 @@ var init_question_block = __esm({
3850
3850
  // ../cli/src/lib/view/rules.ts
3851
3851
  function creationRefusal(id, creation, what, discard = false) {
3852
3852
  if (!creation || creation.state === "unfinished" && discard) return null;
3853
- const run = creation.runId.slice(0, 8);
3854
- return creation.state === "creating" ? `#${id} is still being created by run ${run} \u2014 \`${what}\` is refused until that run finishes.` : `#${id} was never finished being created: run ${run} stopped short. \`${what}\` is refused until that run is picked back up from the board and finishes. Use reject --discard to discard it instead.`;
3853
+ const run2 = creation.runId.slice(0, 8);
3854
+ return creation.state === "creating" ? `#${id} is still being created by run ${run2} \u2014 \`${what}\` is refused until that run finishes.` : `#${id} was never finished being created: run ${run2} stopped short. \`${what}\` is refused until that run is picked back up from the board and finishes. Use reject --discard to discard it instead.`;
3855
3855
  }
3856
3856
  function hasOptions(q) {
3857
3857
  return Array.isArray(q.options) && q.options.length > 0;
@@ -4481,10 +4481,10 @@ function claimBreak(dir) {
4481
4481
  return false;
4482
4482
  }
4483
4483
  }
4484
- function removeClaim(dir, token2) {
4485
- if (token2) {
4484
+ function removeClaim(dir, token3) {
4485
+ if (token3) {
4486
4486
  try {
4487
- fs7.unlinkSync(path8.join(dir, token2));
4487
+ fs7.unlinkSync(path8.join(dir, token3));
4488
4488
  } catch (err) {
4489
4489
  if (err.code !== "ENOENT") throw err;
4490
4490
  }
@@ -4501,15 +4501,15 @@ function removeClaim(dir, token2) {
4501
4501
  }
4502
4502
  function tryLock(dir) {
4503
4503
  fs7.mkdirSync(path8.dirname(dir), { recursive: true });
4504
- const token2 = `${process.pid}-${randomUUID()}`;
4504
+ const token3 = `${process.pid}-${randomUUID()}`;
4505
4505
  const candidate = fs7.mkdtempSync(`${dir}.`);
4506
4506
  try {
4507
- fs7.writeFileSync(path8.join(candidate, token2), "");
4507
+ fs7.writeFileSync(path8.join(candidate, token3), "");
4508
4508
  for (; ; ) {
4509
4509
  try {
4510
4510
  fs7.renameSync(candidate, dir);
4511
4511
  return () => {
4512
- removeClaim(dir, token2);
4512
+ removeClaim(dir, token3);
4513
4513
  };
4514
4514
  } catch (err) {
4515
4515
  const code = err.code;
@@ -5133,16 +5133,12 @@ var init_catalog = __esm({
5133
5133
  function isLanguage(value) {
5134
5134
  return typeof value === "string" && LANGUAGES.includes(value);
5135
5135
  }
5136
- var LANGUAGES, DEFAULT_LANGUAGE, LANGUAGE_NAMES;
5136
+ var LANGUAGES, DEFAULT_LANGUAGE;
5137
5137
  var init_types = __esm({
5138
5138
  "../cli/src/lib/machine/types.ts"() {
5139
5139
  "use strict";
5140
5140
  LANGUAGES = ["en", "zh"];
5141
5141
  DEFAULT_LANGUAGE = "en";
5142
- LANGUAGE_NAMES = {
5143
- en: "English",
5144
- zh: "\u4E2D\u6587"
5145
- };
5146
5142
  }
5147
5143
  });
5148
5144
 
@@ -5483,13 +5479,13 @@ async function attempt(now) {
5483
5479
  }
5484
5480
  function fill(queued, install) {
5485
5481
  const events = [];
5486
- let bytes = Buffer.byteLength(JSON.stringify({ v: VERSION, install, events: [] }));
5482
+ let bytes3 = Buffer.byteLength(JSON.stringify({ v: VERSION, install, events: [] }));
5487
5483
  for (const event2 of queued) {
5488
5484
  if (events.length >= LIMITS.batchEvents) break;
5489
5485
  const piece = Buffer.byteLength(JSON.stringify(event2)) + (events.length ? 1 : 0);
5490
- if (bytes + piece > LIMITS.batchBytes) break;
5486
+ if (bytes3 + piece > LIMITS.batchBytes) break;
5491
5487
  events.push(event2);
5492
- bytes += piece;
5488
+ bytes3 += piece;
5493
5489
  }
5494
5490
  return { events, body: JSON.stringify({ v: VERSION, install, events }) };
5495
5491
  }
@@ -5585,14 +5581,14 @@ function currentTurn() {
5585
5581
  function forgetFileMemos() {
5586
5582
  turn++;
5587
5583
  }
5588
- function memoByFiles(paths, read5) {
5584
+ function memoByFiles(paths, read6) {
5589
5585
  let last = null;
5590
5586
  return () => {
5591
5587
  const now = currentTurn();
5592
5588
  if (last?.turn !== now) {
5593
5589
  const seen = stamp2(paths());
5594
5590
  if (last?.stamp === seen) last.turn = now;
5595
- else last = { stamp: seen, turn: now, value: read5() };
5591
+ else last = { stamp: seen, turn: now, value: read6() };
5596
5592
  }
5597
5593
  return copy(last.value);
5598
5594
  };
@@ -6653,16 +6649,16 @@ function readCatalog() {
6653
6649
  const agents = [];
6654
6650
  const problems = [];
6655
6651
  const refused = [];
6656
- const take = (read5, folder) => {
6657
- if ("problem" in read5) {
6658
- if (!read5.missing) problems.push(read5.problem);
6659
- if (!read5.file) return;
6660
- const { file, name: name2, old } = read5;
6661
- const cause = read5.missing ? "noFile" : old ? "oldKeys" : "file";
6652
+ const take = (read6, folder) => {
6653
+ if ("problem" in read6) {
6654
+ if (!read6.missing) problems.push(read6.problem);
6655
+ if (!read6.file) return;
6656
+ const { file, name: name2, old } = read6;
6657
+ const cause = read6.missing ? "noFile" : old ? "oldKeys" : "file";
6662
6658
  refused.push({ folder, file, cause, ...name2 ? { name: name2 } : {}, ...old ? { keys: old.keys } : {} });
6663
6659
  return;
6664
6660
  }
6665
- const { name, from, builtIn } = read5.agent;
6661
+ const { name, from, builtIn } = read6.agent;
6666
6662
  const refuse3 = (cause, problem) => {
6667
6663
  problems.push(problem);
6668
6664
  if (!builtIn) refused.push({ folder, name, file: from, cause });
@@ -6686,14 +6682,14 @@ function readCatalog() {
6686
6682
  `${from}: its folder is \`${folder}\` but it calls itself \`${name}\`. An agent is asked for by its folder name \u2014 make the two match.`
6687
6683
  );
6688
6684
  }
6689
- agents.push(read5.agent);
6685
+ agents.push(read6.agent);
6690
6686
  };
6691
6687
  for (const folder of bundledFolders()) take(readBundled(folder), folder);
6692
6688
  for (const folder of projectFolders(AGENTS)) {
6693
- const read5 = readProject(AGENTS, folder);
6694
- take(read5, folder);
6695
- if ("agent" in read5 && read5.agent.from.endsWith(LEGACY_AGENT_FILE)) {
6696
- problems.push(`${read5.agent.from}: rename it to ${AGENT_FILE}`);
6689
+ const read6 = readProject(AGENTS, folder);
6690
+ take(read6, folder);
6691
+ if ("agent" in read6 && read6.agent.from.endsWith(LEGACY_AGENT_FILE)) {
6692
+ problems.push(`${read6.agent.from}: rename it to ${AGENT_FILE}`);
6697
6693
  }
6698
6694
  }
6699
6695
  for (const folder of projectFolders(LEGACY_AGENTS)) {
@@ -6795,10 +6791,10 @@ function readProject(root, folder) {
6795
6791
  const missing = rel(path17.join(dir, AGENT_FILE));
6796
6792
  if (!found2) return { problem: `${missing} is missing`, file: missing, missing: true };
6797
6793
  const from = rel(path17.join(dir, found2.name));
6798
- const read5 = parseSpecAgent(found2.text, from, file, false, () => ownFiles(walkFolder(dir, "")));
6799
- if ("problem" in read5) return { ...read5, file: from };
6800
- if ("agent" in read5) Object.assign(read5.agent, { dir, text: found2.text });
6801
- return read5;
6794
+ const read6 = parseSpecAgent(found2.text, from, file, false, () => ownFiles(walkFolder(dir, "")));
6795
+ if ("problem" in read6) return { ...read6, file: from };
6796
+ if ("agent" in read6) Object.assign(read6.agent, { dir, text: found2.text });
6797
+ return read6;
6802
6798
  }
6803
6799
  var specAgentCatalog, bundledFolders, AGENT_FILE, LEGACY_AGENT_FILE, AGENT_FILES, ownFiles;
6804
6800
  var init_catalog2 = __esm({
@@ -7602,10 +7598,10 @@ function findRollout(threadId) {
7602
7598
  }
7603
7599
  for (const name of names5) {
7604
7600
  if (!name.startsWith("rollout-") || !name.endsWith(tail2)) continue;
7605
- const path80 = join(dir, name);
7601
+ const path83 = join(dir, name);
7606
7602
  try {
7607
- const at = statSync(path80).mtimeMs;
7608
- if (!newest || at > newest.at) newest = { path: path80, at };
7603
+ const at = statSync(path83).mtimeMs;
7604
+ if (!newest || at > newest.at) newest = { path: path83, at };
7609
7605
  } catch {
7610
7606
  }
7611
7607
  }
@@ -7613,11 +7609,11 @@ function findRollout(threadId) {
7613
7609
  return newest?.path;
7614
7610
  }
7615
7611
  function readCodexRunFacts(threadId) {
7616
- const path80 = findRollout(threadId);
7617
- if (!path80) return void 0;
7612
+ const path83 = findRollout(threadId);
7613
+ if (!path83) return void 0;
7618
7614
  let raw;
7619
7615
  try {
7620
- raw = readFileSync(path80, "utf8");
7616
+ raw = readFileSync(path83, "utf8");
7621
7617
  } catch {
7622
7618
  return void 0;
7623
7619
  }
@@ -7745,8 +7741,8 @@ function renderCompleted(item) {
7745
7741
  const changes = Array.isArray(item.changes) ? item.changes : [];
7746
7742
  return changes.map((raw) => {
7747
7743
  const change2 = obj(raw);
7748
- const path80 = str2(change2.path);
7749
- return path80 ? `\u23FA ${str2(change2.kind) || "change"}(${path80})
7744
+ const path83 = str2(change2.path);
7745
+ return path83 ? `\u23FA ${str2(change2.kind) || "change"}(${path83})
7750
7746
  ` : "";
7751
7747
  }).join("");
7752
7748
  }
@@ -8005,10 +8001,10 @@ function readKimiRunFacts(sessionId) {
8005
8001
  const total = { input: 0, cacheCreation: 0, cacheRead: 0, output: 0 };
8006
8002
  let model;
8007
8003
  let holding = 0;
8008
- for (const { path: path80, main } of wireFiles(entry.sessionDir)) {
8004
+ for (const { path: path83, main } of wireFiles(entry.sessionDir)) {
8009
8005
  let raw;
8010
8006
  try {
8011
- raw = readFileSync2(path80, "utf8");
8007
+ raw = readFileSync2(path83, "utf8");
8012
8008
  } catch {
8013
8009
  continue;
8014
8010
  }
@@ -8289,8 +8285,8 @@ var init_tail = __esm({
8289
8285
  import fs20 from "node:fs";
8290
8286
  function whereHint(update2, title) {
8291
8287
  const locations = Array.isArray(update2.locations) ? update2.locations : [];
8292
- const path80 = str2(obj(locations[0]).path);
8293
- return path80 && !title.includes(path80) ? hint(path80) : "";
8288
+ const path83 = str2(obj(locations[0]).path);
8289
+ return path83 && !title.includes(path83) ? hint(path83) : "";
8294
8290
  }
8295
8291
  function saidBy(update2) {
8296
8292
  const content = Array.isArray(update2.content) ? update2.content : [];
@@ -8761,8 +8757,8 @@ async function tokensOf(rpc, sessionId) {
8761
8757
  }
8762
8758
  async function contextOf(rpc, sessionId) {
8763
8759
  try {
8764
- const read5 = await rpc.call("session/read", { sessionId, messageLimit: 1 });
8765
- const state = obj(read5.projection);
8760
+ const read6 = await rpc.call("session/read", { sessionId, messageLimit: 1 });
8761
+ const state = obj(read6.projection);
8766
8762
  const used = num(state.contextUsed);
8767
8763
  const limit = num(state.contextWindow);
8768
8764
  return used > 0 ? { used, limit: limit > 0 ? limit : void 0 } : void 0;
@@ -9259,9 +9255,9 @@ function outsideBoardForAdd(cwd = REPO_ROOT) {
9259
9255
  );
9260
9256
  return ["--", ".", ...kept.map((p) => `:(exclude)${p}`)];
9261
9257
  }
9262
- function boardPathsAmong(files) {
9258
+ function boardPathsAmong(files2) {
9263
9259
  const owned = boardManagedPaths();
9264
- return files.filter((file) => {
9260
+ return files2.filter((file) => {
9265
9261
  const p = posix(file);
9266
9262
  return owned.some((dir) => p === dir || p.startsWith(`${dir}/`));
9267
9263
  });
@@ -9375,9 +9371,9 @@ function treeMark(base, cwd = REPO_ROOT) {
9375
9371
  const index = path22.join(ensureAkbDir(), `index-${process.pid}-${Date.now()}`);
9376
9372
  try {
9377
9373
  const env = { ...process.env, GIT_INDEX_FILE: index };
9378
- const run = (args) => spawnSync2("git", args, { cwd, encoding: "utf8", maxBuffer: MAX_OUTPUT, windowsHide: true, env }).status === 0;
9379
- if (!run(["read-tree", base])) return null;
9380
- if (!run(["add", "-A", ...outsideBoardForAdd(cwd)])) return null;
9374
+ const run2 = (args) => spawnSync2("git", args, { cwd, encoding: "utf8", maxBuffer: MAX_OUTPUT, windowsHide: true, env }).status === 0;
9375
+ if (!run2(["read-tree", base])) return null;
9376
+ if (!run2(["add", "-A", ...outsideBoardForAdd(cwd)])) return null;
9381
9377
  const tree = spawnSync2("git", ["write-tree"], {
9382
9378
  cwd,
9383
9379
  encoding: "utf8",
@@ -9467,7 +9463,7 @@ function ignoredInTheWay(commit, cwd) {
9467
9463
  }
9468
9464
  function blockedBy(why) {
9469
9465
  let kind;
9470
- const files = [];
9466
+ const files2 = [];
9471
9467
  for (const line2 of why.split("\n")) {
9472
9468
  if (!kind) {
9473
9469
  kind = headingKind(line2);
@@ -9475,9 +9471,9 @@ function blockedBy(why) {
9475
9471
  }
9476
9472
  if (!/^\s/.test(line2)) break;
9477
9473
  const file = line2.trim();
9478
- if (file) files.push(file);
9474
+ if (file) files2.push(file);
9479
9475
  }
9480
- return kind && files.length ? { kind, files } : void 0;
9476
+ return kind && files2.length ? { kind, files: files2 } : void 0;
9481
9477
  }
9482
9478
  function branchWorktree(branch) {
9483
9479
  const out = git(["worktree", "list", "--porcelain"]);
@@ -9523,7 +9519,7 @@ var init_worktree = __esm({
9523
9519
  return out === null ? null : out.split("\n").filter(Boolean);
9524
9520
  };
9525
9521
  branchPatch = (base, branch, cwd = REPO_ROOT) => gitDiff(["diff", "--binary", base, branch, ...outsideBoard()], cwd);
9526
- lastCommitTouching = (ref, files, cwd = REPO_ROOT) => git(["log", "-1", "--format=%H", ref, "--", ...files], cwd)?.trim() || null;
9522
+ lastCommitTouching = (ref, files2, cwd = REPO_ROOT) => git(["log", "-1", "--format=%H", ref, "--", ...files2], cwd)?.trim() || null;
9527
9523
  continueRebase = (dir) => scripted(["rebase", "--continue"], dir);
9528
9524
  abortRebase = (dir) => void scripted(["rebase", "--abort"], dir);
9529
9525
  conflictedPaths = (dir) => (git(["diff", "--name-only", "--diff-filter=U"], dir) ?? "").split("\n").filter(Boolean);
@@ -9591,8 +9587,8 @@ function modified(file) {
9591
9587
  function byPath(a, b) {
9592
9588
  return a < b ? -1 : a > b ? 1 : 0;
9593
9589
  }
9594
- function byNewest(files) {
9595
- return files.map((file) => ({ file, at: modified(file) })).sort((a, b) => b.at - a.at || byPath(a.file, b.file)).map((one) => one.file);
9590
+ function byNewest(files2) {
9591
+ return files2.map((file) => ({ file, at: modified(file) })).sort((a, b) => b.at - a.at || byPath(a.file, b.file)).map((one) => one.file);
9596
9592
  }
9597
9593
  function versionOf(name) {
9598
9594
  const found2 = /(\d+(?:\.\d+)+)/.exec(name);
@@ -11058,17 +11054,17 @@ function noteRefineTried(store, cardId2) {
11058
11054
  }
11059
11055
  function cardsBeingCreated(runs = readRuns()) {
11060
11056
  const newest = /* @__PURE__ */ new Map();
11061
- for (const run of runs) {
11062
- for (const id of run.createdCardIds ?? []) {
11063
- if (run.cardId === id) continue;
11057
+ for (const run2 of runs) {
11058
+ for (const id of run2.createdCardIds ?? []) {
11059
+ if (run2.cardId === id) continue;
11064
11060
  const best = newest.get(id);
11065
- if (!best || run.startedAt >= best.startedAt) newest.set(id, run);
11061
+ if (!best || run2.startedAt >= best.startedAt) newest.set(id, run2);
11066
11062
  }
11067
11063
  }
11068
11064
  const out = /* @__PURE__ */ new Map();
11069
- for (const [id, run] of newest) {
11070
- if (runIsLive(run)) out.set(id, { state: "creating", runId: run.sessionId });
11071
- else if (run.status !== "done") out.set(id, { state: "unfinished", runId: run.sessionId });
11065
+ for (const [id, run2] of newest) {
11066
+ if (runIsLive(run2)) out.set(id, { state: "creating", runId: run2.sessionId });
11067
+ else if (run2.status !== "done") out.set(id, { state: "unfinished", runId: run2.sessionId });
11072
11068
  }
11073
11069
  return out;
11074
11070
  }
@@ -11156,8 +11152,8 @@ function readTouched(raw) {
11156
11152
  }
11157
11153
  function readPictures(raw) {
11158
11154
  if (!Array.isArray(raw)) return void 0;
11159
- const files = raw.filter((p) => typeof p === "string" && p.length > 0);
11160
- return files.length ? files : void 0;
11155
+ const files2 = raw.filter((p) => typeof p === "string" && p.length > 0);
11156
+ return files2.length ? files2 : void 0;
11161
11157
  }
11162
11158
  function readBlocker(raw) {
11163
11159
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) return void 0;
@@ -11214,18 +11210,18 @@ function readLandingWait(raw) {
11214
11210
  if (!raw || typeof raw !== "object") return void 0;
11215
11211
  const box2 = raw;
11216
11212
  if (box2.kind !== "overwrite" && box2.kind !== "untracked") return void 0;
11217
- const files = Array.isArray(box2.files) ? box2.files.filter((f) => typeof f === "string") : [];
11218
- return files.length ? { kind: box2.kind, files } : void 0;
11213
+ const files2 = Array.isArray(box2.files) ? box2.files.filter((f) => typeof f === "string") : [];
11214
+ return files2.length ? { kind: box2.kind, files: files2 } : void 0;
11219
11215
  }
11220
11216
  function readLandingReason(raw) {
11221
11217
  if (!raw || typeof raw !== "object") return void 0;
11222
11218
  const box2 = raw;
11223
11219
  if (!LANDING_REASONS.has(box2.kind)) return void 0;
11224
- const files = Array.isArray(box2.files) ? box2.files.filter((f) => typeof f === "string") : [];
11220
+ const files2 = Array.isArray(box2.files) ? box2.files.filter((f) => typeof f === "string") : [];
11225
11221
  return {
11226
11222
  kind: box2.kind,
11227
11223
  ...text2(box2.behind) ? { behind: text2(box2.behind) } : {},
11228
- ...files.length ? { files } : {}
11224
+ ...files2.length ? { files: files2 } : {}
11229
11225
  };
11230
11226
  }
11231
11227
  function readAnswers(raw) {
@@ -11249,7 +11245,7 @@ function readReview(raw) {
11249
11245
  if (!raw || typeof raw !== "object") return void 0;
11250
11246
  const box2 = raw;
11251
11247
  const rounds = Array.isArray(box2.rounds) ? box2.rounds : [];
11252
- const stop = box2.stopped;
11248
+ const stop2 = box2.stopped;
11253
11249
  return {
11254
11250
  rounds: rounds.flatMap(
11255
11251
  (r) => r && typeof r.sessionId === "string" && isVerdict(r.verdict) ? [
@@ -11263,11 +11259,11 @@ function readReview(raw) {
11263
11259
  }
11264
11260
  ] : []
11265
11261
  ),
11266
- stopped: stop && typeof stop === "object" && typeof stop.why === "string" ? {
11267
- reason: asStopReason(stop.reason),
11268
- why: stop.why,
11269
- at: typeof stop.at === "number" ? stop.at : 0,
11270
- ...Array.isArray(stop.paths) ? { paths: stop.paths.filter((p) => typeof p === "string") } : {}
11262
+ stopped: stop2 && typeof stop2 === "object" && typeof stop2.why === "string" ? {
11263
+ reason: asStopReason(stop2.reason),
11264
+ why: stop2.why,
11265
+ at: typeof stop2.at === "number" ? stop2.at : 0,
11266
+ ...Array.isArray(stop2.paths) ? { paths: stop2.paths.filter((p) => typeof p === "string") } : {}
11271
11267
  } : void 0
11272
11268
  };
11273
11269
  }
@@ -11330,9 +11326,9 @@ function recordCreatedCards(sessionId, ids) {
11330
11326
  const valid = ids.filter((id) => Number.isInteger(id) && id > 0);
11331
11327
  if (!valid.length) return false;
11332
11328
  return withRuns((runs) => {
11333
- const run = runs.find((entry) => entry.sessionId === sessionId && entry.status === "running");
11334
- if (!run) return false;
11335
- run.createdCardIds = [.../* @__PURE__ */ new Set([...run.createdCardIds ?? [], ...valid])];
11329
+ const run2 = runs.find((entry) => entry.sessionId === sessionId && entry.status === "running");
11330
+ if (!run2) return false;
11331
+ run2.createdCardIds = [.../* @__PURE__ */ new Set([...run2.createdCardIds ?? [], ...valid])];
11336
11332
  return true;
11337
11333
  });
11338
11334
  }
@@ -11382,7 +11378,7 @@ var init_store = __esm({
11382
11378
  stringRecord = (raw) => raw && typeof raw === "object" && !Array.isArray(raw) && Object.values(raw).every((v) => typeof v === "string") ? raw : void 0;
11383
11379
  readRuns = () => readStore().runs;
11384
11380
  PENDING_MS = 3e4;
11385
- runIsLive = (run) => run.status === "running" && (run.pid ? pidAlive(run.pid) : Date.now() - run.startedAt < PENDING_MS);
11381
+ runIsLive = (run2) => run2.status === "running" && (run2.pid ? pidAlive(run2.pid) : Date.now() - run2.startedAt < PENDING_MS);
11386
11382
  creationOf = (runs, cardId2) => cardsBeingCreated(runs).get(cardId2);
11387
11383
  cardCreation = (cardId2, strict = false) => {
11388
11384
  const runs = readRuns();
@@ -11553,24 +11549,28 @@ var init_flows = __esm({
11553
11549
  });
11554
11550
 
11555
11551
  // ../cli/src/lib/agent/language.ts
11556
- function translating(language = readLanguage()) {
11552
+ function runLanguage() {
11553
+ const asked = process.env[RUN_LANGUAGE_ENV];
11554
+ return isLanguage(asked) ? asked : readLanguage();
11555
+ }
11556
+ function translating(language = runLanguage()) {
11557
11557
  return language !== DEFAULT_LANGUAGE;
11558
11558
  }
11559
- function languageNote(language = readLanguage()) {
11560
- if (!translating(language)) return "";
11561
- const name = LANGUAGE_NAMES[language];
11562
- return [
11563
- `Write this board's prose in ${name}: card titles and bodies, open questions and their options, memory notes, and what you say back to me.`,
11564
- `Keep English whatever the language: frontmatter keys and their fixed values, \`##\` and \`###\` section headings, the \`<!-- agent -->\` boundary, todo checkboxes, the \`[user]\` tag, track and module names, and card filenames. Never rename or translate a section title \u2014 the board matches those by literal English text, so a changed one is a card it can no longer read, and a title that is not English needs \`akb raw create --slug\` a short English slug.`,
11565
- `Rewriting a card or a memory file that already exists keeps the language that file is already in; only what you write for me to read personally \u2014 an open question and its options \u2014 follows ${name} on every card, and so does the first note in a memory file still holding nothing but its seeded header.`,
11566
- `This governs the board's prose alone: code, comments, commit messages and the repository's own documents follow the repository, not me. \`akb guide board\` carries the rule in full.`
11567
- ].join(" ");
11559
+ function languageNote(language = runLanguage()) {
11560
+ return LINES[language];
11568
11561
  }
11562
+ var RUN_LANGUAGE_ENV, LINES, inLanguage;
11569
11563
  var init_language = __esm({
11570
11564
  "../cli/src/lib/agent/language.ts"() {
11571
11565
  "use strict";
11572
11566
  init_settings();
11573
11567
  init_types();
11568
+ RUN_LANGUAGE_ENV = "AI4KANBAN_RUN_LANGUAGE";
11569
+ LINES = {
11570
+ en: "",
11571
+ zh: "\u8BF7\u7528\u4E2D\u6587\u56DE\u590D\u548C\u5199\u4F5C\u3002"
11572
+ };
11573
+ inLanguage = (prompt, language = runLanguage()) => [prompt, languageNote(language)].filter(Boolean).join("\n\n");
11574
11574
  }
11575
11575
  });
11576
11576
 
@@ -12497,11 +12497,11 @@ function modelsRun() {
12497
12497
  const ran = /* @__PURE__ */ new Map();
12498
12498
  const { runs } = readStore();
12499
12499
  for (let i = runs.length - 1; i >= 0; i--) {
12500
- const run = runs[i];
12501
- if (!run.harness || !run.model) continue;
12502
- const seen = ran.get(run.harness) ?? [];
12503
- if (!seen.includes(run.model)) seen.push(run.model);
12504
- ran.set(run.harness, seen);
12500
+ const run2 = runs[i];
12501
+ if (!run2.harness || !run2.model) continue;
12502
+ const seen = ran.get(run2.harness) ?? [];
12503
+ if (!seen.includes(run2.model)) seen.push(run2.model);
12504
+ ran.set(run2.harness, seen);
12505
12505
  }
12506
12506
  return ran;
12507
12507
  }
@@ -13346,9 +13346,9 @@ function boardWorkflowDefs() {
13346
13346
  problems.push(`${from} is missing`);
13347
13347
  continue;
13348
13348
  }
13349
- const read5 = parseWorkflowFile(id, source, from);
13350
- if ("problem" in read5) problems.push(read5.problem);
13351
- else defs.push(read5.def);
13349
+ const read6 = parseWorkflowFile(id, source, from);
13350
+ if ("problem" in read6) problems.push(read6.problem);
13351
+ else defs.push(read6.def);
13352
13352
  }
13353
13353
  return { defs, problems };
13354
13354
  }
@@ -13392,9 +13392,9 @@ var init_workflow_file = __esm({
13392
13392
  plain = (agents) => agents.every((h) => !h.extra && !h.off);
13393
13393
  flowList = (agents) => `[${agents.map((h) => scalar(h.agent)).join(", ")}]`;
13394
13394
  BUILTIN_DEFS = BUNDLED.map(([id, source]) => {
13395
- const read5 = parseWorkflowFile(id, source, `the built-in \`${id}\` workflow`);
13396
- if ("problem" in read5) throw new Error(read5.problem);
13397
- return read5.def;
13395
+ const read6 = parseWorkflowFile(id, source, `the built-in \`${id}\` workflow`);
13396
+ if ("problem" in read6) throw new Error(read6.problem);
13397
+ return read6.def;
13398
13398
  });
13399
13399
  fileOf = (id) => path30.join(WORKFLOWS, id, WORKFLOW_FILE);
13400
13400
  }
@@ -13465,8 +13465,8 @@ function foldOldStages(cfg) {
13465
13465
  if (!savedOldStages(cfg)) return false;
13466
13466
  const { ok } = writeConfig((raw) => {
13467
13467
  const block = configBlock(raw.workflows);
13468
- const all = configBlock(block.stages);
13469
- for (const [id, flow] of Object.entries(all)) {
13468
+ const all2 = configBlock(block.stages);
13469
+ for (const [id, flow] of Object.entries(all2)) {
13470
13470
  const mine = { ...configBlock(flow) };
13471
13471
  const plan = readRows(mine.plan);
13472
13472
  const lead = configBlock(mine.execute).lead;
@@ -13476,10 +13476,10 @@ function foldOldStages(cfg) {
13476
13476
  if (typeof lead === "string" && lead.trim() && isBuiltinWorkflow(id) && !BUILTINS.find((w) => w.id === id).land.length) {
13477
13477
  mine[LAND] = { helpers: [{ agent: canonicalSpecAgent(lead), extra: "" }] };
13478
13478
  }
13479
- if (Object.keys(mine).length) all[id] = mine;
13480
- else delete all[id];
13479
+ if (Object.keys(mine).length) all2[id] = mine;
13480
+ else delete all2[id];
13481
13481
  }
13482
- if (Object.keys(all).length) block.stages = all;
13482
+ if (Object.keys(all2).length) block.stages = all2;
13483
13483
  else delete block.stages;
13484
13484
  for (const key of ["added", "agentsOwned", "shipped", "qaScheduled"]) delete block[key];
13485
13485
  if (Object.keys(block).length) raw.workflows = block;
@@ -13753,17 +13753,17 @@ function forgetWorkflowAgent(agent) {
13753
13753
  }
13754
13754
  }
13755
13755
  return save2((block) => {
13756
- const all = configBlock(block.stages);
13757
- for (const [id, flow] of Object.entries(all)) {
13756
+ const all2 = configBlock(block.stages);
13757
+ for (const [id, flow] of Object.entries(all2)) {
13758
13758
  const mine = configBlock(flow);
13759
13759
  for (const [key, value] of Object.entries(mine)) {
13760
13760
  const one = configBlock(value);
13761
13761
  if (Array.isArray(one.helpers)) one.helpers = one.helpers.filter((h) => configBlock(h).agent !== agent);
13762
13762
  mine[key] = one;
13763
13763
  }
13764
- all[id] = mine;
13764
+ all2[id] = mine;
13765
13765
  }
13766
- if (Object.keys(all).length) block.stages = all;
13766
+ if (Object.keys(all2).length) block.stages = all2;
13767
13767
  });
13768
13768
  }
13769
13769
  function scheduledMembers(flow) {
@@ -14042,11 +14042,11 @@ function agentFilesBlock(agent) {
14042
14042
  }
14043
14043
  function agentMemoryBlock(agent) {
14044
14044
  const dir = rel(agentMemoryDir(agent.name));
14045
- const files = readAgentMemory(agent.name);
14046
- if (!files.length) return `Your memory folder is \`${dir}/\`. Nothing is in it yet.`;
14045
+ const files2 = readAgentMemory(agent.name);
14046
+ if (!files2.length) return `Your memory folder is \`${dir}/\`. Nothing is in it yet.`;
14047
14047
  return [
14048
14048
  `Your memory, from \`${dir}/\` \u2014 what you kept on this board in earlier runs. Follow it here:`,
14049
- ...files.map((file) => `### \`${file.name}\`
14049
+ ...files2.map((file) => `### \`${file.name}\`
14050
14050
 
14051
14051
  ${file.text || "_(empty)_"}`)
14052
14052
  ].join("\n\n");
@@ -14145,8 +14145,8 @@ var init_agents = __esm({
14145
14145
  return RETIRED_SETTINGS.filter((r) => r.agent === agent.name && r.key in entry.extra).map((r) => r.note);
14146
14146
  };
14147
14147
  agentsOf = (names5) => {
14148
- const all = specAgents();
14149
- return names5.map((name) => all.find((a) => a.name === name)).filter((a) => !!a);
14148
+ const all2 = specAgents();
14149
+ return names5.map((name) => all2.find((a) => a.name === name)).filter((a) => !!a);
14150
14150
  };
14151
14151
  specAgentAssigned = (name, workflow) => {
14152
14152
  const flow = workflowFor(workflow);
@@ -14558,12 +14558,12 @@ function candidateFileStats(candidate) {
14558
14558
  const change2 = added === "-" || removed === "-" ? "binary" : `+${added} -${removed}`;
14559
14559
  return `${file} (${change2}${fresh ? ", new" : ""})`;
14560
14560
  };
14561
- const files = tracked.split("\n").filter(Boolean).map((line2) => format(line2));
14561
+ const files2 = tracked.split("\n").filter(Boolean).map((line2) => format(line2));
14562
14562
  for (const file of untrackedFiles(candidate)) {
14563
14563
  const stat = gitDiff(["diff", "--no-index", "--numstat", "--", "/dev/null", file], candidate.cwd)?.trim();
14564
- files.push(stat ? format(stat, true) : `${file} (new)`);
14564
+ files2.push(stat ? format(stat, true) : `${file} (new)`);
14565
14565
  }
14566
- return files;
14566
+ return files2;
14567
14567
  }
14568
14568
  function candidateStat(candidate) {
14569
14569
  if (!candidate.base) return null;
@@ -14644,7 +14644,7 @@ var init_outputs = __esm({
14644
14644
  return m ? [{ done: m[1] !== " ", text: m[2].trim() }] : [];
14645
14645
  });
14646
14646
  plannedTodos = (cardId2) => todos(cardId2).map((t) => t.text);
14647
- looksLikePath = (token2) => !/\s/.test(token2) && !token2.includes("://") && !token2.startsWith("-") && token2.includes("/");
14647
+ looksLikePath = (token3) => !/\s/.test(token3) && !token3.includes("://") && !token3.startsWith("-") && token3.includes("/");
14648
14648
  resolveOutput = (file) => {
14649
14649
  if (file.startsWith("~/")) return path35.join(os4.homedir(), file.slice(2));
14650
14650
  if (path35.isAbsolute(file)) return file;
@@ -14681,11 +14681,11 @@ function noWorktreeWhy() {
14681
14681
  if (!currentBranch()) return "this checkout is on a detached HEAD, so a build has nowhere to land";
14682
14682
  return void 0;
14683
14683
  }
14684
- function prepareDelivery(cardId2, wants, files = false) {
14684
+ function prepareDelivery(cardId2, wants, files2 = false) {
14685
14685
  const deliveryId = newDeliveryId();
14686
14686
  const gated = cardId2 !== null;
14687
14687
  const base = inGitRepo() ? headCommit() : null;
14688
- if (files) return { start: { deliveryId, commitMode: "files", base: base ?? void 0 } };
14688
+ if (files2) return { start: { deliveryId, commitMode: "files", base: base ?? void 0 } };
14689
14689
  if (gated && cardWorkflow(cardId2)?.needsArtifact) {
14690
14690
  return {
14691
14691
  start: {
@@ -14805,15 +14805,15 @@ var init_commit_mode = __esm({
14805
14805
  ID_LENGTH2 = 8;
14806
14806
  MAX_NAMED = 5;
14807
14807
  deliveryCwd = (delivery) => delivery.worktree ? worktreeDir(delivery.worktree) : REPO_ROOT;
14808
- dirtyRefusal = (files) => ({
14808
+ dirtyRefusal = (files2) => ({
14809
14809
  error: [
14810
14810
  "Commit or stash your changes before starting.",
14811
14811
  "",
14812
- ...files.slice(0, MAX_NAMED),
14813
- ...files.length > MAX_NAMED ? [`and ${files.length - MAX_NAMED} more`] : []
14812
+ ...files2.slice(0, MAX_NAMED),
14813
+ ...files2.length > MAX_NAMED ? [`and ${files2.length - MAX_NAMED} more`] : []
14814
14814
  ].join("\n"),
14815
14815
  reason: "dirty",
14816
- paths: files.slice(0, MAX_NAMED)
14816
+ paths: files2.slice(0, MAX_NAMED)
14817
14817
  });
14818
14818
  MAX_SUBJECT = 72;
14819
14819
  deliveryName = (delivery) => delivery.cardId === null ? `delivery ${delivery.deliveryId}` : `#${delivery.cardId}`;
@@ -14899,19 +14899,19 @@ function deliveryState(delivery, questions) {
14899
14899
  };
14900
14900
  }
14901
14901
  if (landing?.conflictFiles?.length || landing?.fitAt) {
14902
- const files = landing.conflictFiles ?? [];
14902
+ const files2 = landing.conflictFiles ?? [];
14903
14903
  const attempt2 = (landing.conflictFails ?? 0) + 1;
14904
14904
  const branch2 = `\`${delivery.targetBranch ?? "the target branch"}\``;
14905
- const where2 = files.length ? `${some(files)} against ${branch2}` : `the combined result with ${branch2}`;
14905
+ const where2 = files2.length ? `${some(files2)} against ${branch2}` : `the combined result with ${branch2}`;
14906
14906
  if (landing.status === "waiting" && landing.conflictAt) {
14907
14907
  const left = Math.max(0, Math.round((landing.conflictAt - Date.now()) / 1e3));
14908
14908
  return {
14909
14909
  stage: "retry",
14910
14910
  label: "Waiting to retry",
14911
- line: `Attempt ${attempt2 - 1} left ${where2} ${files.length ? "conflicted" : "unchecked"}. It gave the landing slot up and opens attempt ${attempt2} ${left ? `in ${left}s` : "now"} \u2014 another delivery can land while it waits.`,
14911
+ line: `Attempt ${attempt2 - 1} left ${where2} ${files2.length ? "conflicted" : "unchecked"}. It gave the landing slot up and opens attempt ${attempt2} ${left ? `in ${left}s` : "now"} \u2014 another delivery can land while it waits.`,
14912
14912
  paused: false,
14913
14913
  kind: "conflict-wait",
14914
- files,
14914
+ files: files2,
14915
14915
  branch: delivery.targetBranch,
14916
14916
  attempt: attempt2,
14917
14917
  retryIn: left
@@ -14920,11 +14920,11 @@ function deliveryState(delivery, questions) {
14920
14920
  if (landing.status === "landing") {
14921
14921
  return {
14922
14922
  stage: "conflict",
14923
- label: files.length ? "Resolving a conflict" : "Checking the combined result",
14924
- line: `Attempt ${attempt2}: ${files.length ? "resolving" : "checking"} ${where2}. It lands by itself once ${files.length ? "the conflict is out" : "that is done"} \u2014 nothing is asked of you.`,
14923
+ label: files2.length ? "Resolving a conflict" : "Checking the combined result",
14924
+ line: `Attempt ${attempt2}: ${files2.length ? "resolving" : "checking"} ${where2}. It lands by itself once ${files2.length ? "the conflict is out" : "that is done"} \u2014 nothing is asked of you.`,
14925
14925
  paused: false,
14926
14926
  kind: "conflict",
14927
- files,
14927
+ files: files2,
14928
14928
  branch: delivery.targetBranch,
14929
14929
  attempt: attempt2
14930
14930
  };
@@ -14986,7 +14986,7 @@ var init_pause = __esm({
14986
14986
  HELD_ON_QUESTIONS = "held on an open question";
14987
14987
  IN_LINE = "in line behind";
14988
14988
  count2 = (n) => `${n} open question${n === 1 ? "" : "s"}`;
14989
- some = (files) => files.length === 1 ? `\`${files[0]}\`` : `${files.length} files`;
14989
+ some = (files2) => files2.length === 1 ? `\`${files2[0]}\`` : `${files2.length} files`;
14990
14990
  upper = (text5) => text5 ? text5[0].toUpperCase() + text5.slice(1) : text5;
14991
14991
  end = (text5) => /[.!?)]$/.test(text5) ? text5 : `${text5}.`;
14992
14992
  isHold = (why) => why.startsWith(HELD_ON_QUESTIONS);
@@ -15863,7 +15863,7 @@ var init_stage_end = __esm({
15863
15863
  const flow = flowByAction(action);
15864
15864
  return flow ? stageOfFlow(flow.command) : void 0;
15865
15865
  };
15866
- askedFor = (cardId2, agent) => readStore().runs.some((run) => run.action === "spec" && run.cardId === cardId2 && run.specAgent === agent);
15866
+ askedFor = (cardId2, agent) => readStore().runs.some((run2) => run2.action === "spec" && run2.cardId === cardId2 && run2.specAgent === agent);
15867
15867
  }
15868
15868
  });
15869
15869
 
@@ -15872,10 +15872,10 @@ function reviewOf(delivery) {
15872
15872
  if (!delivery.review) delivery.review = { rounds: [] };
15873
15873
  return delivery.review;
15874
15874
  }
15875
- function nextAfterSession(delivery, run) {
15875
+ function nextAfterSession(delivery, run2) {
15876
15876
  if (delivery.status !== "active") return HOLD;
15877
- if (run.action === "scheduled") return run.status === "done" ? { finish: true } : HOLD;
15878
- if (run.action !== "implement" || run.status !== "done") return HOLD;
15877
+ if (run2.action === "scheduled") return run2.status === "done" ? { finish: true } : HOLD;
15878
+ if (run2.action !== "implement" || run2.status !== "done") return HOLD;
15879
15879
  return stageShortfall("build", delivery) ?? { finish: true };
15880
15880
  }
15881
15881
  function stageShortfall(stage, delivery) {
@@ -15913,23 +15913,23 @@ import path41 from "node:path";
15913
15913
  function writeAudit(delivery, runs) {
15914
15914
  const known = new Map(readAudit(delivery.deliveryId)?.sessions.map((s) => [s.sessionId, s]) ?? []);
15915
15915
  const sessions = delivery.sessions.flatMap((id) => {
15916
- const run = runs.find((r) => r.sessionId === id);
15917
- if (!run) {
15916
+ const run2 = runs.find((r) => r.sessionId === id);
15917
+ if (!run2) {
15918
15918
  const before = known.get(id);
15919
15919
  return before ? [before] : [];
15920
15920
  }
15921
15921
  return [
15922
15922
  {
15923
- sessionId: run.sessionId,
15924
- action: run.action,
15925
- status: run.status,
15926
- startedAt: run.startedAt,
15927
- endedAt: run.endedAt,
15928
- harness: run.harness || void 0,
15929
- model: run.model,
15930
- costUsd: run.costUsd,
15931
- resumedFrom: run.resumedFrom,
15932
- log: rel(run.logPath)
15923
+ sessionId: run2.sessionId,
15924
+ action: run2.action,
15925
+ status: run2.status,
15926
+ startedAt: run2.startedAt,
15927
+ endedAt: run2.endedAt,
15928
+ harness: run2.harness || void 0,
15929
+ model: run2.model,
15930
+ costUsd: run2.costUsd,
15931
+ resumedFrom: run2.resumedFrom,
15932
+ log: rel(run2.logPath)
15933
15933
  }
15934
15934
  ];
15935
15935
  });
@@ -16007,7 +16007,7 @@ function settleOrphanedDeliveries() {
16007
16007
  const recovered = [];
16008
16008
  withStore((store) => {
16009
16009
  const known = new Set(store.deliveries.map((d) => d.deliveryId));
16010
- for (const run of store.runs) if (run.deliveryId) known.add(run.deliveryId);
16010
+ for (const run2 of store.runs) if (run2.deliveryId) known.add(run2.deliveryId);
16011
16011
  for (const audit of audits) {
16012
16012
  if (known.has(audit.deliveryId) || !worktreeExists(audit.worktree)) continue;
16013
16013
  if (lastSessionRunning(audit)) {
@@ -16056,13 +16056,13 @@ function endedDelivery(id) {
16056
16056
  const row = auditRow(audit);
16057
16057
  if (row) rows.set(row.deliveryId, row);
16058
16058
  }
16059
- const all = [...rows.values()].sort((a, b) => a.startedAt - b.startedAt);
16059
+ const all2 = [...rows.values()].sort((a, b) => a.startedAt - b.startedAt);
16060
16060
  if (/^#?\d+$/.test(key)) {
16061
16061
  const cardId2 = Number(key.replace("#", ""));
16062
- const mine = all.filter((d) => d.cardId === cardId2);
16062
+ const mine = all2.filter((d) => d.cardId === cardId2);
16063
16063
  return mine.filter((d) => d.status !== "active").pop() ?? mine.pop();
16064
16064
  }
16065
- return all.find((d) => d.deliveryId === key) ?? all.find((d) => d.deliveryId.startsWith(key));
16065
+ return all2.find((d) => d.deliveryId === key) ?? all2.find((d) => d.deliveryId.startsWith(key));
16066
16066
  }
16067
16067
  function resumeRefusal(delivery, store) {
16068
16068
  const id = delivery.deliveryId;
@@ -16094,11 +16094,11 @@ function resumeRefusal(delivery, store) {
16094
16094
  );
16095
16095
  }
16096
16096
  if (!worktreeExists(delivery.worktree)) {
16097
- const path80 = delivery.worktree ?? "";
16097
+ const path83 = delivery.worktree ?? "";
16098
16098
  return refusal(
16099
16099
  "deliveryWorktreeGone",
16100
- `delivery ${id}'s worktree ${path80} is gone, so there is nothing to carry on. ${rebuild}`,
16101
- { id, task, path: path80, command: discard }
16100
+ `delivery ${id}'s worktree ${path83} is gone, so there is nothing to carry on. ${rebuild}`,
16101
+ { id, task, path: path83, command: discard }
16102
16102
  );
16103
16103
  }
16104
16104
  if (!branchExists(delivery.branch)) {
@@ -16275,8 +16275,8 @@ function activeDelivery(cardId2) {
16275
16275
  function findDelivery(id) {
16276
16276
  const key = id.trim();
16277
16277
  if (!key) return void 0;
16278
- const all = readStore().deliveries;
16279
- return all.find((d) => d.deliveryId === key) ?? all.find((d) => d.deliveryId.startsWith(key));
16278
+ const all2 = readStore().deliveries;
16279
+ return all2.find((d) => d.deliveryId === key) ?? all2.find((d) => d.deliveryId.startsWith(key));
16280
16280
  }
16281
16281
  function namedDelivery(id) {
16282
16282
  const key = id.trim();
@@ -16292,8 +16292,8 @@ function deliveryFor(req) {
16292
16292
  }
16293
16293
  return req.id === void 0 ? void 0 : activeDelivery(req.id);
16294
16294
  }
16295
- function joinDelivery(store, run, title, step, start, direct) {
16296
- const cardId2 = run.cardId;
16295
+ function joinDelivery(store, run2, title, step, start, direct) {
16296
+ const cardId2 = run2.cardId;
16297
16297
  let delivery = cardId2 === null ? void 0 : activeIn(store, cardId2);
16298
16298
  if (!delivery) {
16299
16299
  delivery = {
@@ -16301,7 +16301,7 @@ function joinDelivery(store, run, title, step, start, direct) {
16301
16301
  cardId: cardId2,
16302
16302
  title,
16303
16303
  status: "active",
16304
- startedAt: run.startedAt,
16304
+ startedAt: run2.startedAt,
16305
16305
  sessions: [],
16306
16306
  // The one read of the card this delivery will ever make for its requirements — or,
16307
16307
  // with no card, the sentence or the plan's words it was handed, which can never move
@@ -16346,21 +16346,21 @@ function joinDelivery(store, run, title, step, start, direct) {
16346
16346
  } else if (step === "implement" && delivery.review?.stopped) {
16347
16347
  delivery.review.stopped = void 0;
16348
16348
  }
16349
- delivery.sessions.push(run.sessionId);
16350
- delivery.steps.push({ step, at: run.startedAt });
16351
- joinFlow(run, delivery);
16349
+ delivery.sessions.push(run2.sessionId);
16350
+ delivery.steps.push({ step, at: run2.startedAt });
16351
+ joinFlow(run2, delivery);
16352
16352
  writeAudit(delivery, store.runs);
16353
16353
  return delivery;
16354
16354
  }
16355
16355
  function adoptDirectCard(sessionId, cardId2) {
16356
16356
  return withStore((store) => {
16357
- const run = store.runs.find((r) => r.sessionId === sessionId && r.status === "running");
16358
- if (!run || run.action !== "implement" || run.cardId !== null) return false;
16359
- const delivery = run.deliveryId ? store.deliveries.find((d) => d.deliveryId === run.deliveryId && d.status === "active") : void 0;
16360
- if (run.deliveryId && (!delivery || delivery.cardId !== null)) return false;
16357
+ const run2 = store.runs.find((r) => r.sessionId === sessionId && r.status === "running");
16358
+ if (!run2 || run2.action !== "implement" || run2.cardId !== null) return false;
16359
+ const delivery = run2.deliveryId ? store.deliveries.find((d) => d.deliveryId === run2.deliveryId && d.status === "active") : void 0;
16360
+ if (run2.deliveryId && (!delivery || delivery.cardId !== null)) return false;
16361
16361
  const idle = "ready";
16362
- run.cardId = cardId2;
16363
- run.priorStatus = idle;
16362
+ run2.cardId = cardId2;
16363
+ run2.priorStatus = idle;
16364
16364
  if (!delivery) return true;
16365
16365
  delivery.cardId = cardId2;
16366
16366
  delivery.priorStatus = idle;
@@ -16368,21 +16368,21 @@ function adoptDirectCard(sessionId, cardId2) {
16368
16368
  return true;
16369
16369
  });
16370
16370
  }
16371
- function joinActive(store, run, step, deliveryId) {
16372
- const delivery = deliveryId ? store.deliveries.find((d) => d.status === "active" && d.deliveryId === deliveryId) : run.cardId === null ? void 0 : activeIn(store, run.cardId);
16371
+ function joinActive(store, run2, step, deliveryId) {
16372
+ const delivery = deliveryId ? store.deliveries.find((d) => d.status === "active" && d.deliveryId === deliveryId) : run2.cardId === null ? void 0 : activeIn(store, run2.cardId);
16373
16373
  if (!delivery) return void 0;
16374
- delivery.sessions.push(run.sessionId);
16375
- delivery.steps.push({ step, at: run.startedAt });
16374
+ delivery.sessions.push(run2.sessionId);
16375
+ delivery.steps.push({ step, at: run2.startedAt });
16376
16376
  if (delivery.review?.stopped) delivery.review.stopped = void 0;
16377
16377
  const now = Date.now();
16378
16378
  for (const answer2 of delivery.answers ?? []) if (!answer2.actedAt) answer2.actedAt = now;
16379
- joinFlow(run, delivery);
16379
+ joinFlow(run2, delivery);
16380
16380
  writeAudit(delivery, store.runs);
16381
16381
  return delivery;
16382
16382
  }
16383
- function joinFlow(run, delivery) {
16384
- run.deliveryId = delivery.deliveryId;
16385
- run.flowId = delivery.deliveryId;
16383
+ function joinFlow(run2, delivery) {
16384
+ run2.deliveryId = delivery.deliveryId;
16385
+ run2.flowId = delivery.deliveryId;
16386
16386
  }
16387
16387
  function endDelivery(deliveryId, status) {
16388
16388
  const ended = withStore((store) => {
@@ -16398,18 +16398,18 @@ function endDelivery(deliveryId, status) {
16398
16398
  }
16399
16399
  return ended;
16400
16400
  }
16401
- async function settleDelivery(run) {
16402
- if (!run.deliveryId) return;
16403
- const before = readStore().deliveries.find((d) => d.deliveryId === run.deliveryId);
16401
+ async function settleDelivery(run2) {
16402
+ if (!run2.deliveryId) return;
16403
+ const before = readStore().deliveries.find((d) => d.deliveryId === run2.deliveryId);
16404
16404
  if (!before) return;
16405
- const built = run.status === "done" && run.action === "implement";
16406
- const passed = run.status === "done" && run.action === "scheduled";
16405
+ const built = run2.status === "done" && run2.action === "implement";
16406
+ const passed = run2.status === "done" && run2.action === "scheduled";
16407
16407
  const commit = (built || passed) && before.status === "active" ? commitDeliveryWork(before) : { ok: true };
16408
16408
  const uncommitted = commit.ok ? void 0 : commit.why;
16409
16409
  const reviewed = !uncommitted && before.commitMode === "manual" && before.cardId !== null && (built || passed) ? snapshotReviewed(before) : void 0;
16410
- const files = (built || passed) && before.commitMode === "files" && !before.scheduled ? filesStop(before) : void 0;
16410
+ const files2 = (built || passed) && before.commitMode === "files" && !before.scheduled ? filesStop(before) : void 0;
16411
16411
  const settled = withStore((store) => {
16412
- const delivery = store.deliveries.find((d) => d.deliveryId === run.deliveryId);
16412
+ const delivery = store.deliveries.find((d) => d.deliveryId === run2.deliveryId);
16413
16413
  if (!delivery) return null;
16414
16414
  if (uncommitted && delivery.status === "active") {
16415
16415
  const review = reviewOf(delivery);
@@ -16417,7 +16417,7 @@ async function settleDelivery(run) {
16417
16417
  releaseLanding(delivery);
16418
16418
  return null;
16419
16419
  }
16420
- const next = nextAfterSession(delivery, run);
16420
+ const next = nextAfterSession(delivery, run2);
16421
16421
  if ("hold" in next) return null;
16422
16422
  if ("finish" in next) {
16423
16423
  if (reviewed) {
@@ -16426,12 +16426,12 @@ async function settleDelivery(run) {
16426
16426
  }
16427
16427
  if (delivery.commitMode === "manual" && !delivery.base) return { end: "finished", complete: delivery.cardId !== null };
16428
16428
  if (delivery.commitMode === "files") {
16429
- if (!files) return { end: "finished", complete: delivery.cardId !== null };
16430
- reviewOf(delivery).stopped = { reason: files.reason, why: files.why, at: Date.now(), paths: files.paths };
16429
+ if (!files2) return { end: "finished", complete: delivery.cardId !== null };
16430
+ reviewOf(delivery).stopped = { reason: files2.reason, why: files2.why, at: Date.now(), paths: files2.paths };
16431
16431
  return null;
16432
16432
  }
16433
16433
  if (wantsLanding(delivery)) {
16434
- queueLanding(delivery, run);
16434
+ queueLanding(delivery, run2);
16435
16435
  return null;
16436
16436
  }
16437
16437
  return { end: "finished" };
@@ -16441,15 +16441,15 @@ async function settleDelivery(run) {
16441
16441
  return null;
16442
16442
  });
16443
16443
  if (settled && "end" in settled) {
16444
- endDelivery(run.deliveryId, settled.end);
16445
- if (settled.complete) await completeCard(before.cardId, run.deliveryId);
16444
+ endDelivery(run2.deliveryId, settled.end);
16445
+ if (settled.complete) await completeCard(before.cardId, run2.deliveryId);
16446
16446
  }
16447
- syncAudit(run.deliveryId, run);
16447
+ syncAudit(run2.deliveryId, run2);
16448
16448
  }
16449
16449
  function deliveryAcceptsAnswers(cardId2) {
16450
16450
  return !!deliveryStateOf(cardId2)?.paused;
16451
16451
  }
16452
- function queueLanding(delivery, run) {
16452
+ function queueLanding(delivery, run2) {
16453
16453
  const landing = delivery.landing ?? { status: "waiting", attempts: 0, at: Date.now() };
16454
16454
  delivery.landing = {
16455
16455
  ...landing,
@@ -16458,7 +16458,7 @@ function queueLanding(delivery, run) {
16458
16458
  reason: void 0,
16459
16459
  checks: [
16460
16460
  ...landing.checks ?? [],
16461
- { name: `${run.action} ${run.sessionId.slice(0, 8)}`, ok: true, at: Date.now() }
16461
+ { name: `${run2.action} ${run2.sessionId.slice(0, 8)}`, ok: true, at: Date.now() }
16462
16462
  ],
16463
16463
  at: Date.now()
16464
16464
  };
@@ -16917,20 +16917,20 @@ function waitForTarget(delivery) {
16917
16917
  });
16918
16918
  return { done: true };
16919
16919
  }
16920
- function startConflict(delivery, target, files) {
16920
+ function startConflict(delivery, target, files2) {
16921
16921
  patchLanding(delivery.deliveryId, (landing) => {
16922
16922
  landing.onto = target;
16923
- landing.conflictFiles = files;
16924
- landing.why = `resolving a conflict with ${delivery.targetBranch} in ${names2(files)}`;
16923
+ landing.conflictFiles = files2;
16924
+ landing.why = `resolving a conflict with ${delivery.targetBranch} in ${names2(files2)}`;
16925
16925
  landing.reason = void 0;
16926
16926
  });
16927
16927
  return { start: conflictRun(delivery) };
16928
16928
  }
16929
16929
  function reopenConflict(delivery, dir) {
16930
- const files = conflictedPaths(dir);
16930
+ const files2 = conflictedPaths(dir);
16931
16931
  patchLanding(delivery.deliveryId, (landing) => {
16932
16932
  landing.conflictAt = void 0;
16933
- if (files.length) landing.conflictFiles = files;
16933
+ if (files2.length) landing.conflictFiles = files2;
16934
16934
  if (landing.fitAt) landing.fitAt = Date.now();
16935
16935
  });
16936
16936
  return { start: conflictRun(delivery) };
@@ -17034,9 +17034,9 @@ async function move(delivery, tip, target) {
17034
17034
  return { done: true };
17035
17035
  }
17036
17036
  function landWait(wait, where) {
17037
- const files = wait.files;
17037
+ const files2 = wait.files;
17038
17038
  const at = sameDir(where, REPO_ROOT) ? "your checkout" : `\`${rel(where)}\``;
17039
- return wait.kind === "untracked" ? `${some2(files)} in ${at} ${are(files.length)} not in git, and landing would write over ${them(files.length)} \u2014 move or delete ${them(files.length)}` : `your changes to ${some2(files)} in ${at} would be overwritten by landing \u2014 commit or stash ${them(files.length)}`;
17039
+ return wait.kind === "untracked" ? `${some2(files2)} in ${at} ${are(files2.length)} not in git, and landing would write over ${them(files2.length)} \u2014 move or delete ${them(files2.length)}` : `your changes to ${some2(files2)} in ${at} would be overwritten by landing \u2014 commit or stash ${them(files2.length)}`;
17040
17040
  }
17041
17041
  async function finish(delivery, landed) {
17042
17042
  patchLanding(delivery.deliveryId, (landing) => {
@@ -17059,11 +17059,11 @@ function alreadyOnTarget(delivery) {
17059
17059
  const onto = branchTip(delivery.targetBranch);
17060
17060
  if (!onto) return null;
17061
17061
  const dir = worktreeDir(delivery.worktree);
17062
- const files = changedPaths(delivery.base, delivery.branch, dir);
17063
- if (!files?.length) return null;
17062
+ const files2 = changedPaths(delivery.base, delivery.branch, dir);
17063
+ if (!files2?.length) return null;
17064
17064
  const patch2 = branchPatch(delivery.base, delivery.branch, dir);
17065
17065
  if (!patch2 || !reverseApplies(patch2, onto, dir)) return null;
17066
- return { commit: lastCommitTouching(onto, files, dir) ?? void 0, onto };
17066
+ return { commit: lastCommitTouching(onto, files2, dir) ?? void 0, onto };
17067
17067
  }
17068
17068
  async function settleAlreadyLanded(delivery) {
17069
17069
  const found2 = alreadyOnTarget(delivery);
@@ -17120,8 +17120,8 @@ var init_landing = __esm({
17120
17120
  init_store();
17121
17121
  init_worktree();
17122
17122
  MAX_NAMED2 = 5;
17123
- names2 = (files) => `${files.slice(0, MAX_NAMED2).join(", ")}${files.length > MAX_NAMED2 ? `, and ${files.length - MAX_NAMED2} more` : ""}`;
17124
- some2 = (files) => files.length === 1 ? `\`${files[0]}\`` : `${files.length} files`;
17123
+ names2 = (files2) => `${files2.slice(0, MAX_NAMED2).join(", ")}${files2.length > MAX_NAMED2 ? `, and ${files2.length - MAX_NAMED2} more` : ""}`;
17124
+ some2 = (files2) => files2.length === 1 ? `\`${files2[0]}\`` : `${files2.length} files`;
17125
17125
  are = (n) => n === 1 ? "is" : "are";
17126
17126
  them = (n) => n === 1 ? "it" : "them";
17127
17127
  sayWhy = (deliveryId, why, wait, reason) => patchLanding(deliveryId, (landing) => {
@@ -17181,14 +17181,14 @@ function returnRunPictures(sessionId, box2) {
17181
17181
  } catch {
17182
17182
  }
17183
17183
  }
17184
- function moveRunPictures(from, to, files = []) {
17185
- if (files.length === 0) return [];
17184
+ function moveRunPictures(from, to, files2 = []) {
17185
+ if (files2.length === 0) return [];
17186
17186
  try {
17187
17187
  fs42.renameSync(pictureBox(from), pictureBox(to));
17188
17188
  } catch {
17189
- return files;
17189
+ return files2;
17190
17190
  }
17191
- return files.map((file) => path43.join(pictureBox(to), path43.basename(file)));
17191
+ return files2.map((file) => path43.join(pictureBox(to), path43.basename(file)));
17192
17192
  }
17193
17193
  var pictureName, boxId, freeBox, pictureBox;
17194
17194
  var init_pictures = __esm({
@@ -17248,8 +17248,8 @@ function globalMemories() {
17248
17248
  return out;
17249
17249
  }
17250
17250
  function globalMemoryBlock(agent) {
17251
- const all = globalMemories();
17252
- const kept = agent.memory.map((name) => all.find((m) => m.name === name)).filter((m) => !!m);
17251
+ const all2 = globalMemories();
17252
+ const kept = agent.memory.map((name) => all2.find((m) => m.name === name)).filter((m) => !!m);
17253
17253
  if (!kept.length) return "";
17254
17254
  return [
17255
17255
  "Global memories you share with other agents \u2014 open one only when the work needs it, and",
@@ -17455,7 +17455,7 @@ var init_write_agent = __esm({
17455
17455
  var writing_default;
17456
17456
  var init_writing = __esm({
17457
17457
  "../cli/src/guide/writing.md"() {
17458
- writing_default = '# Write a card\n\nA card has a **human half** for review and a folded **agent half** for implementation.\nEvery flow writes a card in this order:\n\n```text\n<one short paragraph: the observable result and the current behavior or constraint it changes.>\n\n## Worth noting <- answered material decisions; keep empty when none\n- **<question the decision settles>**: <answer>\n\n## Worth noting after implementation\n- **<question the decision settles>**: <answer>\n <- answered material decisions building turned up; written\n by the build, omit when empty. Never approved delivery scope\n\n## By `<name>` agent <- every preview agent\'s section\n\n<!-- agent --> <- boundary\n\n## Today\n## Scope <- requirements, not rationale\n## Todo <- one build step per checkbox\n## Decided by the agent\n- **<question the decision settles>**: <answer>\n### Overruled by the user <- always last\n```\n\n## `Worth noting`\n\n- **Classify first**: follow `akb guide update-questions`; this section contains only answers\n classified as `Worth noting`.\n- **Keep it glanceable**: one entry is one reviewer decision, written as one sentence that\n states the chosen behavior and its main cost. Merge entries governed by one policy. One\n to three independent entries is normal.\n- **Cut the story**: omit chronology, evidence trails, exhaustive consequences, and the\n rejected option unless it is necessary to understand the main cost.\n\n## `Worth noting after implementation`\n\n- **Classify first**: follow `akb guide update-questions`; this section contains only answers\n classified as `Worth noting after implementation`.\n- **Keep it non-blocking**: this section never changes or blocks a delivery already in\n flight.\n- **Use the same compact format**: one reviewer decision and its main cost in one sentence.\n- **Exclude work logs**: never put diagnostics, run history, check results, suggestions,\n or unresolved questions here.\n- **Never approve a deviation here**: work that contradicts the approved requirements must\n be fixed or sent to the user by the build.\n\n## Agent sections\n\n- **Owner\'s rules first**: before rewriting, removing, or overruling content a preview agent\n owns, read that agent\'s rules with `akb raw agent-file <agent> AGENT.md`, and the\n references they point to for the affected part with the same command and their path. When\n they cannot be read, surface the gap before changing that content.\n\n## `Today`\n\n- **Omit by default**: write it, heading included, only when the build depends on findings\n the code does not make obvious; a small change to a few simple files needs none.\n\n## `Todo`\n\n- **Build steps only**: finish planning on the card; never defer it to a todo.\n- **Preserve completed work**: never edit, delete, or untick a checked todo; append a todo to\n reverse it.\n\n## `Decided by the agent`\n\n- **Only what changes the build**: include answered decisions the builder would otherwise\n get wrong and neither `Worth noting` section holds; omit a finding that needs no action.\n- **Preserve superseded calls**: move agent or review decisions the user reverses to\n `Overruled by the user`; delete one the card leaves the builder no room to repeat.\n\n## General writing requirements\n\n- **Keep section titles fixed**: do not rename or translate an existing `##` or `###`\n section title, and leave empty scaffold sections in place.\n- **Edit only the body**: use board commands for every frontmatter field (`akb guide board`).\n- **Name the source in frontmatter**: pass each plan path, card `#id`, or URL the card came\n from as `--source` to `akb raw create`, or `--add-source` to `akb raw update`; never write\n a `## Source` section.\n- **Write for a fresh reader**: use professional, comprehensible language with no assumed\n conversation context.\n- **Keep human half self-contained**: nothing above `<!-- agent -->` may rely on the folded\n agent half.\n- **Keep bullets atomic**: use `- **<short title>**: <one clear sentence>` for one rule per\n bullet.\n- **Specify behavior**: omit planning notes and unnecessary coding details.\n- **Supported embeds**: only valid `<Asset>`, `<Compare>` and `<Storyboard>` markers alone in a\n paragraph embed content; other HTML or JSX is not allowed. Inline or fenced examples remain text.\n- **Compare**: to show two images or two videos against each other, such as a source and its\n clone, write `<Compare a="<src>" b="<src>" label="..." a-label="..." b-label="..." />`;\n never render a side-by-side file for it. For videos, add `shots="<src>"`: a JSON list of\n `{ "id": "S1", "start": 0, "end": 2.25, "name": "..." }` covering video A in order, or a\n storyboard of A. B may be a storyboard instead of a video; it then shows its shot with the\n id A is on, beside that shot of a storyboard `shots`.\n- **Asset label and alt**: `label` is a tag of a few words; an image\'s caption goes in its\n optional `alt="..."`, its shipped alt text, which cannot contain `<`, `>` or its own quote mark.\n- **Asset variants**: versions of the same content, such as languages or devices, are one tag\n with `variants=\'{"<label>": "<src>", ...}\'`, `src` being the one shown first; alternatives the\n user picks between stay separate tags.\n- **Say each fact once**: a section holds only what the card does not already say; leave it\n empty rather than restate the opening paragraph or another section. Cut only the repeated\n part of a line: a name, value or case stated nowhere else stays.\n\n- **Validate after edits**: run `akb raw validate <id>` for every card you wrote. Fix each\n reported file and line before finishing; validation does not rewrite the card for you.\n';
17458
+ writing_default = '# Write a card\n\nA card has a **human half** for review and a folded **agent half** for implementation.\nEvery flow writes a card in this order:\n\n```text\n<one short paragraph: the observable result and the current behavior or constraint it changes.>\n\n## Worth noting <- answered material decisions; keep empty when none\n- **<question the decision settles>**: <answer>\n\n## Worth noting after implementation\n- **<question the decision settles>**: <answer>\n <- answered material decisions building turned up; written\n by the build, omit when empty. Never approved delivery scope\n\n## By `<name>` agent <- every preview agent\'s section\n\n<!-- agent --> <- boundary\n\n## Today\n## Scope <- requirements, not rationale\n## Todo <- one build step per checkbox\n## Decided by the agent\n- **<question the decision settles>**: <answer>\n### Overruled by the user <- always last\n```\n\n## `Worth noting`\n\n- **Classify first**: follow `akb guide update-questions`; this section contains only answers\n classified as `Worth noting`.\n- **Keep it glanceable**: one entry is one reviewer decision, written as one sentence that\n states the chosen behavior and its main cost. Merge entries governed by one policy. One\n to three independent entries is normal.\n- **Cut the story**: omit chronology, evidence trails, exhaustive consequences, and the\n rejected option unless it is necessary to understand the main cost.\n\n## `Worth noting after implementation`\n\n- **Classify first**: follow `akb guide update-questions`; this section contains only answers\n classified as `Worth noting after implementation`.\n- **Keep it non-blocking**: this section never changes or blocks a delivery already in\n flight.\n- **Use the same compact format**: one reviewer decision and its main cost in one sentence.\n- **Exclude work logs**: never put diagnostics, run history, check results, suggestions,\n or unresolved questions here.\n- **Never approve a deviation here**: work that contradicts the approved requirements must\n be fixed or sent to the user by the build.\n\n## Agent sections\n\n- **Owner\'s rules first**: before rewriting, removing, or overruling content a preview agent\n owns, read that agent\'s rules with `akb raw agent-file <agent> AGENT.md`, and the\n references they point to for the affected part with the same command and their path. When\n they cannot be read, surface the gap before changing that content.\n\n## `Today`\n\n- **Omit by default**: write it, heading included, only when the build depends on findings\n the code does not make obvious; a small change to a few simple files needs none.\n\n## `Todo`\n\n- **Build steps only**: finish planning on the card; never defer it to a todo.\n- **Preserve completed work**: never edit, delete, or untick a checked todo; append a todo to\n reverse it.\n\n## `Decided by the agent`\n\n- **Only what changes the build**: include answered decisions the builder would otherwise\n get wrong and neither `Worth noting` section holds; omit a finding that needs no action.\n- **Preserve superseded calls**: move agent or review decisions the user reverses to\n `Overruled by the user`; delete one the card leaves the builder no room to repeat.\n\n## General writing requirements\n\n- **Keep section titles fixed**: write every `##` and `###` section title in English, never\n rename or translate an existing one, and leave empty scaffold sections in place.\n- **Edit only the body**: use board commands for every frontmatter field (`akb guide board`).\n- **Name the source in frontmatter**: pass each plan path, card `#id`, or URL the card came\n from as `--source` to `akb raw create`, or `--add-source` to `akb raw update`; never write\n a `## Source` section.\n- **Write for a fresh reader**: use professional, comprehensible language with no assumed\n conversation context.\n- **Keep human half self-contained**: nothing above `<!-- agent -->` may rely on the folded\n agent half.\n- **Keep bullets atomic**: use `- **<short title>**: <one clear sentence>` for one rule per\n bullet.\n- **Specify behavior**: omit planning notes and unnecessary coding details.\n- **Supported embeds**: only valid `<Asset>`, `<Compare>` and `<Storyboard>` markers alone in a\n paragraph embed content; other HTML or JSX is not allowed. Inline or fenced examples remain text.\n- **Compare**: to show two images or two videos against each other, such as a source and its\n clone, write `<Compare a="<src>" b="<src>" label="..." a-label="..." b-label="..." />`;\n never render a side-by-side file for it. For videos, add `shots="<src>"`: a JSON list of\n `{ "id": "S1", "start": 0, "end": 2.25, "name": "..." }` covering video A in order, or a\n storyboard of A. B may be a storyboard instead of a video; it then shows its shot with the\n id A is on, beside that shot of a storyboard `shots`.\n- **Asset label and alt**: `label` is a tag of a few words; an image\'s caption goes in its\n optional `alt="..."`, its shipped alt text, which cannot contain `<`, `>` or its own quote mark.\n- **Asset variants**: versions of the same content, such as languages or devices, are one tag\n with `variants=\'{"<label>": "<src>", ...}\'`, `src` being the one shown first; alternatives the\n user picks between stay separate tags.\n- **Say each fact once**: a section holds only what the card does not already say; leave it\n empty rather than restate the opening paragraph or another section. Cut only the repeated\n part of a line: a name, value or case stated nowhere else stays.\n\n- **Validate after edits**: run `akb raw validate <id>` for every card you wrote. Fix each\n reported file and line before finishing; validation does not rewrite the card for you.\n';
17459
17459
  }
17460
17460
  });
17461
17461
 
@@ -17633,7 +17633,6 @@ function contractRepairPrompt(req, errors) {
17633
17633
  "The task ended with invalid card formatting. Fix only the errors below in the listed files. Preserve planned behavior and completed work; do not repeat the task or request other agents.",
17634
17634
  errors,
17635
17635
  `Run \`${command} raw validate <id>\` for every affected card and fix every error before finishing.`,
17636
- languageNote(),
17637
17636
  ruleBlock(req, frozenRules(req))
17638
17637
  ].filter(Boolean).join("\n\n"));
17639
17638
  }
@@ -17647,7 +17646,7 @@ function buildAsk(rawReq, notes = []) {
17647
17646
  const req = withWorkflow(rawReq);
17648
17647
  const command = DELIVERY_FLOWS.has(req.action) ? boardCommandFor(req.id) : boardCommand();
17649
17648
  const ask2 = [actionPrompt(req, command, notes), pictureNote(req), commandNote(command)].filter(Boolean).join(" ");
17650
- return realPaths(boardText([ask2, languageNote(), roster(req)].filter(Boolean).join("\n\n")), req);
17649
+ return realPaths(boardText([ask2, roster(req)].filter(Boolean).join("\n\n")), req);
17651
17650
  }
17652
17651
  function cardFileOf(id) {
17653
17652
  const found2 = id === void 0 ? null : locate(id);
@@ -17733,10 +17732,10 @@ function settingsBlock(req) {
17733
17732
  return role ? roleSettingsBlock(role) : "";
17734
17733
  }
17735
17734
  function pictureNote(req) {
17736
- const files = req.pictures ?? [];
17737
- if (!files.length || agentImages(agentForRun(req), req.runtime)?.as !== "message") return "";
17738
- const one = files.length === 1;
17739
- return `${one ? "A picture came" : `${files.length} pictures came`} with this. Read ${one ? "it" : "them"} first: ${files.join(", ")}.`;
17735
+ const files2 = req.pictures ?? [];
17736
+ if (!files2.length || agentImages(agentForRun(req), req.runtime)?.as !== "message") return "";
17737
+ const one = files2.length === 1;
17738
+ return `${one ? "A picture came" : `${files2.length} pictures came`} with this. Read ${one ? "it" : "them"} first: ${files2.join(", ")}.`;
17740
17739
  }
17741
17740
  function frozenRules(req) {
17742
17741
  return deliveryFor(req)?.rules;
@@ -17751,8 +17750,8 @@ function shippedLines(cardId2) {
17751
17750
  const commit = delivery?.landing?.commit;
17752
17751
  if (commit) return [`\`git show ${commit.slice(0, 12)}\` \u2014 the change that landed`];
17753
17752
  if (delivery?.commitMode === "files") {
17754
- const files = recordedOutputs(delivery);
17755
- if (files.length) return ["the files it delivered:", ...files.map((file) => ` ${file}`)];
17753
+ const files2 = recordedOutputs(delivery);
17754
+ if (files2.length) return ["the files it delivered:", ...files2.map((file) => ` ${file}`)];
17756
17755
  }
17757
17756
  return [`nothing on record \u2014 \`git log --grep "(#${cardId2})"\`, or check the card against the project as it stands`];
17758
17757
  }
@@ -18077,7 +18076,6 @@ var init_prompts = __esm({
18077
18076
  init_outputs();
18078
18077
  init_archive();
18079
18078
  init_flows();
18080
- init_language();
18081
18079
  init_resolve();
18082
18080
  init_runner();
18083
18081
  init_workflows();
@@ -18109,7 +18107,7 @@ var init_prompts = __esm({
18109
18107
  `The session you were continuing is gone, and this one holds nothing of it.`,
18110
18108
  `Do the task below from the top, checking each step's precondition before you do it \u2014 work an earlier run already finished is done, so don't repeat it.`
18111
18109
  ].join(" ");
18112
- restartable = (run) => (run.cardId !== null || !!run.deliveryId) && RESTARTABLE.has(run.action);
18110
+ restartable = (run2) => (run2.cardId !== null || !!run2.deliveryId) && RESTARTABLE.has(run2.action);
18113
18111
  NO_IMPLEMENT = `(Unless the request explicitly asks for implementation, don't implement it; revising the card's drafts is not implementing.)`;
18114
18112
  BOARD_FOLDER = "<board folder>";
18115
18113
  CARD_FILE = "<card file>";
@@ -18367,9 +18365,9 @@ function reap(runs, reaped = [], restore = []) {
18367
18365
  }
18368
18366
  return changed;
18369
18367
  }
18370
- function stampDuration(run, endedAt) {
18368
+ function stampDuration(run2, endedAt) {
18371
18369
  try {
18372
- fs46.appendFileSync(run.logPath, durationLine(endedAt - run.startedAt));
18370
+ fs46.appendFileSync(run2.logPath, durationLine(endedAt - run2.startedAt));
18373
18371
  } catch {
18374
18372
  }
18375
18373
  }
@@ -18390,19 +18388,19 @@ function cardNow(cardId2) {
18390
18388
  return null;
18391
18389
  }
18392
18390
  }
18393
- function claimCard(run) {
18394
- const wanted = run.cardId !== null ? RUN_STATUS[run.action] : void 0;
18395
- if (run.cardId === null || !wanted) return void 0;
18396
- const delivery = run.deliveryId ? activeDelivery(run.cardId) : void 0;
18397
- run.priorStatus = (delivery && delivery.deliveryId === run.deliveryId ? delivery.priorStatus : void 0) ?? cardNow(run.cardId)?.status ?? "todo";
18398
- return { cardId: run.cardId, status: wanted };
18391
+ function claimCard(run2) {
18392
+ const wanted = run2.cardId !== null ? RUN_STATUS[run2.action] : void 0;
18393
+ if (run2.cardId === null || !wanted) return void 0;
18394
+ const delivery = run2.deliveryId ? activeDelivery(run2.cardId) : void 0;
18395
+ run2.priorStatus = (delivery && delivery.deliveryId === run2.deliveryId ? delivery.priorStatus : void 0) ?? cardNow(run2.cardId)?.status ?? "todo";
18396
+ return { cardId: run2.cardId, status: wanted };
18399
18397
  }
18400
- async function restoreCardStatus(run) {
18401
- if (run.cardId === null || !RUN_STATUS[run.action]) return;
18402
- if (run.deliveryId && activeDelivery(run.cardId)?.deliveryId === run.deliveryId) return;
18403
- const card = cardNow(run.cardId);
18398
+ async function restoreCardStatus(run2) {
18399
+ if (run2.cardId === null || !RUN_STATUS[run2.action]) return;
18400
+ if (run2.deliveryId && activeDelivery(run2.cardId)?.deliveryId === run2.deliveryId) return;
18401
+ const card = cardNow(run2.cardId);
18404
18402
  if (!card) return;
18405
- await setCardStatus(run.cardId, card.questions > 0 ? "todo" : run.priorStatus ?? "todo");
18403
+ await setCardStatus(run2.cardId, card.questions > 0 ? "todo" : run2.priorStatus ?? "todo");
18406
18404
  }
18407
18405
  async function releaseCard(delivery) {
18408
18406
  if (delivery.cardId === null) return;
@@ -18410,46 +18408,46 @@ async function releaseCard(delivery) {
18410
18408
  if (card?.status !== "implementing") return;
18411
18409
  await setCardStatus(delivery.cardId, card.questions > 0 ? "todo" : delivery.priorStatus ?? "ready");
18412
18410
  }
18413
- function recordPrune(run) {
18414
- if (run.action !== "prune-memory" || run.status !== "done") return;
18411
+ function recordPrune(run2) {
18412
+ if (run2.action !== "prune-memory" || run2.status !== "done") return;
18415
18413
  try {
18416
18414
  stampMemoryPrune();
18417
18415
  } catch {
18418
18416
  }
18419
18417
  }
18420
- function recordMemoryReview(run) {
18421
- if (run.action !== "review-memory" || run.status !== "done") return;
18418
+ function recordMemoryReview(run2) {
18419
+ if (run2.action !== "review-memory" || run2.status !== "done") return;
18422
18420
  try {
18423
- stampMemoryReview(new Date(run.startedAt));
18421
+ stampMemoryReview(new Date(run2.startedAt));
18424
18422
  } catch {
18425
18423
  }
18426
18424
  }
18427
- function recordReflection(run) {
18428
- if (run.action !== "reflect" || run.status !== "done" || !run.cards?.length) return;
18425
+ function recordReflection(run2) {
18426
+ if (run2.action !== "reflect" || run2.status !== "done" || !run2.cards?.length) return;
18429
18427
  try {
18430
- dropReflected(run.cards);
18428
+ dropReflected(run2.cards);
18431
18429
  } catch {
18432
18430
  }
18433
18431
  }
18434
- function recordDismissalReview(run) {
18435
- if (run.action !== "review-dismissals" || run.status !== "done") return;
18432
+ function recordDismissalReview(run2) {
18433
+ if (run2.action !== "review-dismissals" || run2.status !== "done") return;
18436
18434
  try {
18437
- stampDismissalReview(new Date(run.startedAt));
18435
+ stampDismissalReview(new Date(run2.startedAt));
18438
18436
  } catch {
18439
18437
  }
18440
18438
  }
18441
- function recordScheduledRun(run) {
18442
- if (run.action !== "scheduled" || run.status !== "done" || !run.workflow || !run.specAgent) return;
18439
+ function recordScheduledRun(run2) {
18440
+ if (run2.action !== "scheduled" || run2.status !== "done" || !run2.workflow || !run2.specAgent) return;
18443
18441
  try {
18444
- const began = (run.deliveryId ? findDelivery(run.deliveryId)?.startedAt : void 0) ?? run.startedAt;
18445
- stampScheduledRun(run.workflow, run.specAgent, new Date(began));
18442
+ const began = (run2.deliveryId ? findDelivery(run2.deliveryId)?.startedAt : void 0) ?? run2.startedAt;
18443
+ stampScheduledRun(run2.workflow, run2.specAgent, new Date(began));
18446
18444
  } catch {
18447
18445
  }
18448
18446
  }
18449
- function recordProjectDescription(run) {
18450
- if (run.action !== "describe-project" || run.status !== "done") return;
18447
+ function recordProjectDescription(run2) {
18448
+ if (run2.action !== "describe-project" || run2.status !== "done") return;
18451
18449
  try {
18452
- stampProjectDescription(new Date(run.startedAt));
18450
+ stampProjectDescription(new Date(run2.startedAt));
18453
18451
  } catch {
18454
18452
  }
18455
18453
  }
@@ -18457,8 +18455,8 @@ function resumeIdOf(r) {
18457
18455
  if (adoptsSessionId(r.harness) && !carriesSession(r)) return r.sessionId;
18458
18456
  return r.resumeId;
18459
18457
  }
18460
- function resumeSessionId(run) {
18461
- return resumesUnder(run.harness) && !neverStarted(run) ? resumeIdOf(run) : void 0;
18458
+ function resumeSessionId(run2) {
18459
+ return resumesUnder(run2.harness) && !neverStarted(run2) ? resumeIdOf(run2) : void 0;
18462
18460
  }
18463
18461
  function endedDeliveryRefusal(r, refusals) {
18464
18462
  if (!r.deliveryId || !canPickUp(r)) return void 0;
@@ -18532,7 +18530,7 @@ function leftBoardOnLanding(id) {
18532
18530
  }
18533
18531
  function goneCards(runs) {
18534
18532
  const asking = /* @__PURE__ */ new Set();
18535
- for (const run of runs) if (run.cardId !== null && canPickUp(run)) asking.add(run.cardId);
18533
+ for (const run2 of runs) if (run2.cardId !== null && canPickUp(run2)) asking.add(run2.cardId);
18536
18534
  if (asking.size === 0) return asking;
18537
18535
  const onBoard3 = boardCardIds();
18538
18536
  const gone = /* @__PURE__ */ new Set();
@@ -18542,12 +18540,12 @@ function goneCards(runs) {
18542
18540
  async function listRuns() {
18543
18541
  const reaped = [];
18544
18542
  const restore = [];
18545
- const runs = withRuns((all) => {
18546
- reap(all, reaped, restore);
18547
- return all.map((r) => ({ ...r }));
18543
+ const runs = withRuns((all2) => {
18544
+ reap(all2, reaped, restore);
18545
+ return all2.map((r) => ({ ...r }));
18548
18546
  });
18549
- for (const run of restore) await restoreCardStatus(run);
18550
- for (const run of reaped) await settleDelivery(run);
18547
+ for (const run2 of restore) await restoreCardStatus(run2);
18548
+ for (const run2 of reaped) await settleDelivery(run2);
18551
18549
  for (const sub of runs) {
18552
18550
  if (sub.action !== "sub" || sub.status !== "running" || !sub.parentId) continue;
18553
18551
  if (!runs.some((r) => r.sessionId === sub.parentId && r.status === "running")) await stopRun(sub.sessionId);
@@ -18584,17 +18582,17 @@ function findRun(runs, id) {
18584
18582
  if (hits.length === 1) return hits[0];
18585
18583
  return hits.length > 1 ? null : void 0;
18586
18584
  }
18587
- async function getRun(id, bytes) {
18585
+ async function getRun(id, bytes3) {
18588
18586
  const restore = [];
18589
- const runs = withRuns((all) => {
18590
- reap(all, [], restore);
18591
- return all.map((r) => ({ ...r }));
18587
+ const runs = withRuns((all2) => {
18588
+ reap(all2, [], restore);
18589
+ return all2.map((r) => ({ ...r }));
18592
18590
  });
18593
- for (const run of restore) await restoreCardStatus(run);
18591
+ for (const run2 of restore) await restoreCardStatus(run2);
18594
18592
  const found2 = findRun(runs, id);
18595
18593
  if (!found2) return null;
18596
18594
  const view = toView(found2, goneCards([found2]));
18597
- const raw = readLogTail(found2.logPath, bytes) ?? "";
18595
+ const raw = readLogTail(found2.logPath, bytes3) ?? "";
18598
18596
  const { tail: tail2, result, durationMs, costUsd, model, usage: usage3 } = splitLog(raw);
18599
18597
  view.tail = tail2;
18600
18598
  if (result && found2.status !== "running" && !view.result) view.result = result;
@@ -18689,8 +18687,8 @@ function openRun(req, prompt, notes = [], sessionId = randomUUID6(), said3) {
18689
18687
  const cardless = !!direct;
18690
18688
  let start;
18691
18689
  if (pass || req.action === "implement" && (cardless || cardId2 !== null && !activeDelivery(cardId2))) {
18692
- const files = direct?.scheduled ? !!workflowById(direct.scheduled.workflow)?.needsArtifact : false;
18693
- const prepared = prepareDelivery(cardId2, req.commitMode, files);
18690
+ const files2 = direct?.scheduled ? !!workflowById(direct.scheduled.workflow)?.needsArtifact : false;
18691
+ const prepared = prepareDelivery(cardId2, req.commitMode, files2);
18694
18692
  if ("error" in prepared) return prepared;
18695
18693
  start = prepared.start;
18696
18694
  }
@@ -18783,15 +18781,15 @@ function openRun(req, prompt, notes = [], sessionId = randomUUID6(), said3) {
18783
18781
  function planningSession(cardId2, cwd = REPO_ROOT) {
18784
18782
  const here = (dir) => !dir || path48.resolve(dir) === cwd;
18785
18783
  const ended = readRuns().filter((r) => r.status === "done").sort((a, b) => b.startedAt - a.startedAt);
18786
- const of = (run2, fork) => {
18787
- if (!here(run2.cwd)) return { none: "elsewhere" };
18788
- const resumeId = resumeSessionId(run2);
18789
- return resumeId ? { session: { harness: run2.harness, resumeId }, fork } : { none: "unrecorded" };
18784
+ const of = (run3, fork) => {
18785
+ if (!here(run3.cwd)) return { none: "elsewhere" };
18786
+ const resumeId = resumeSessionId(run3);
18787
+ return resumeId ? { session: { harness: run3.harness, resumeId }, fork } : { none: "unrecorded" };
18790
18788
  };
18791
18789
  const planned = ended.find((r) => r.cardId === cardId2 && PLANNING.has(r.action));
18792
18790
  if (planned) return of(planned, false);
18793
- const run = ended.find((r) => (r.action === "create" || r.action === "setup") && r.createdCardIds?.includes(cardId2));
18794
- const created = run ? of(run, true) : void 0;
18791
+ const run2 = ended.find((r) => (r.action === "create" || r.action === "setup") && r.createdCardIds?.includes(cardId2));
18792
+ const created = run2 ? of(run2, true) : void 0;
18795
18793
  return created ?? { none: "unrecorded" };
18796
18794
  }
18797
18795
  function carriedSession(req) {
@@ -18822,8 +18820,8 @@ function carriedSession(req) {
18822
18820
  };
18823
18821
  }
18824
18822
  function planningRun(sessionId) {
18825
- const run = peekRun(sessionId);
18826
- return run?.status === "running" && PLANNING.has(run.action) ? run : void 0;
18823
+ const run2 = peekRun(sessionId);
18824
+ return run2?.status === "running" && PLANNING.has(run2.action) ? run2 : void 0;
18827
18825
  }
18828
18826
  function requestOf(record) {
18829
18827
  const id = record.cardId ?? void 0;
@@ -18849,11 +18847,11 @@ function requestOf(record) {
18849
18847
  }
18850
18848
  async function openResume(id) {
18851
18849
  const restore = [];
18852
- const runs = withRuns((all) => {
18853
- reap(all, [], restore);
18854
- return all.map((r) => ({ ...r }));
18850
+ const runs = withRuns((all2) => {
18851
+ reap(all2, [], restore);
18852
+ return all2.map((r) => ({ ...r }));
18855
18853
  });
18856
- for (const run of restore) await restoreCardStatus(run);
18854
+ for (const run2 of restore) await restoreCardStatus(run2);
18857
18855
  const prev = findRun(runs, id);
18858
18856
  if (prev === null) return ambiguousRun(id);
18859
18857
  if (!prev) return unknownRun(id);
@@ -18952,8 +18950,8 @@ async function resumeHeld(prev, plan, sessionId, resuming, fresh) {
18952
18950
  flowId: prev.flowId
18953
18951
  };
18954
18952
  const out = withCreationLock(() => withStore((store) => {
18955
- const all = store.runs;
18956
- const latest = all.find((r) => r.sessionId === prev.sessionId);
18953
+ const all2 = store.runs;
18954
+ const latest = all2.find((r) => r.sessionId === prev.sessionId);
18957
18955
  if (!latest) return refusal("runContinued", "that run has already been continued");
18958
18956
  if (latest.discardedCards?.some((c) => c.pending || locate(c.id))) {
18959
18957
  return refusal("discardUnfinished", "A card discard did not finish. Retry discarding it before resuming creation.");
@@ -18968,11 +18966,11 @@ async function resumeHeld(prev, plan, sessionId, resuming, fresh) {
18968
18966
  repair.errors = repair.errors.split("\n").filter((line2) => !record.discardedCards.some((c) => line2.includes(c.path) || new RegExp(`Task #${c.id}(?![0-9])`).test(line2))).join("\n");
18969
18967
  if (!repair.cardIds.length) record.formatRepair = void 0;
18970
18968
  }
18971
- const heldCreation = all.find((r) => runIsLive(r) && (r.cardId !== null && (latest.createdCardIds ?? []).includes(r.cardId) || (r.createdCardIds ?? []).some((id) => (latest.createdCardIds ?? []).includes(id))));
18969
+ const heldCreation = all2.find((r) => runIsLive(r) && (r.cardId !== null && (latest.createdCardIds ?? []).includes(r.cardId) || (r.createdCardIds ?? []).some((id) => (latest.createdCardIds ?? []).includes(id))));
18972
18970
  if (heldCreation) return refusal("creationHeld", "A card from this creation is already being worked on. Wait for that run to finish.");
18973
- const locked = lockedBy(all, prev.action, prev.cardId, prev.discard);
18971
+ const locked = lockedBy(all2, prev.action, prev.cardId, prev.discard);
18974
18972
  if (locked) return locked;
18975
- all.push(record);
18973
+ all2.push(record);
18976
18974
  const delivery = store.deliveries.find((d) => d.deliveryId === prev.deliveryId && d.status === "active");
18977
18975
  if (delivery) {
18978
18976
  delivery.sessions.push(record.sessionId);
@@ -18980,8 +18978,8 @@ async function resumeHeld(prev, plan, sessionId, resuming, fresh) {
18980
18978
  record.deliveryId = delivery.deliveryId;
18981
18979
  record.flowId = delivery.deliveryId;
18982
18980
  }
18983
- const at = all.findIndex((r) => r.sessionId === prev.sessionId);
18984
- if (at >= 0) all.splice(at, 1);
18981
+ const at = all2.findIndex((r) => r.sessionId === prev.sessionId);
18982
+ if (at >= 0) all2.splice(at, 1);
18985
18983
  return { run: record };
18986
18984
  }));
18987
18985
  if ("error" in out) return out;
@@ -19020,8 +19018,8 @@ function forgetRun(sessionId) {
19020
19018
  }
19021
19019
  }
19022
19020
  function askForSpec(sessionId, ask2) {
19023
- const run = peekRun(sessionId);
19024
- if (!run) return "no-run";
19021
+ const run2 = peekRun(sessionId);
19022
+ if (!run2) return "no-run";
19025
19023
  const file = readAsks(sessionId);
19026
19024
  if (file.asks.some((a) => a.specAgent === ask2.specAgent && a.cardId === ask2.cardId)) return "already";
19027
19025
  file.asks.push(ask2);
@@ -19090,9 +19088,9 @@ function markSpawned(sessionId, pid) {
19090
19088
  }
19091
19089
  function patch(sessionId, change2) {
19092
19090
  return withRuns((runs) => {
19093
- const run = runs.find((r) => r.sessionId === sessionId);
19094
- if (run) change2(run);
19095
- return run ? { ...run } : void 0;
19091
+ const run2 = runs.find((r) => r.sessionId === sessionId);
19092
+ if (run2) change2(run2);
19093
+ return run2 ? { ...run2 } : void 0;
19096
19094
  });
19097
19095
  }
19098
19096
  function peekRun(sessionId) {
@@ -19100,19 +19098,19 @@ function peekRun(sessionId) {
19100
19098
  }
19101
19099
  async function closeRun(sessionId, res) {
19102
19100
  const closed = withRuns((runs) => {
19103
- const run = runs.find((r) => r.sessionId === sessionId);
19104
- if (!run || run.status !== "running") return void 0;
19105
- run.status = res.status;
19106
- if (res.ok !== void 0) run.ok = res.ok;
19107
- run.code = res.code ?? null;
19108
- if (res.error) run.error = res.error;
19109
- if (res.note) run.note = res.note;
19110
- if (res.errorWhy?.length) run.errorWhy = res.errorWhy;
19111
- if (res.noteWhy?.length) run.noteWhy = res.noteWhy;
19112
- if (res.tickedNothing) run.tickedNothing = true;
19113
- run.endedAt = res.endedAt ?? Date.now();
19114
- run.pid = void 0;
19115
- return { ...run };
19101
+ const run2 = runs.find((r) => r.sessionId === sessionId);
19102
+ if (!run2 || run2.status !== "running") return void 0;
19103
+ run2.status = res.status;
19104
+ if (res.ok !== void 0) run2.ok = res.ok;
19105
+ run2.code = res.code ?? null;
19106
+ if (res.error) run2.error = res.error;
19107
+ if (res.note) run2.note = res.note;
19108
+ if (res.errorWhy?.length) run2.errorWhy = res.errorWhy;
19109
+ if (res.noteWhy?.length) run2.noteWhy = res.noteWhy;
19110
+ if (res.tickedNothing) run2.tickedNothing = true;
19111
+ run2.endedAt = res.endedAt ?? Date.now();
19112
+ run2.pid = void 0;
19113
+ return { ...run2 };
19116
19114
  });
19117
19115
  if (!closed) return;
19118
19116
  if (closed.status === "done" || closed.status === "error") {
@@ -19138,14 +19136,14 @@ async function stopRun(id) {
19138
19136
  const restore = [];
19139
19137
  const out = withRuns((runs) => {
19140
19138
  reap(runs, [], restore);
19141
- const run = findRun(runs, id);
19142
- if (run === null) return { ok: false, ...ambiguousRun(id) };
19143
- if (!run) return { ok: false, ...unknownRun(id) };
19144
- if (run.status !== "running") return { ok: true, sessionId: run.sessionId };
19145
- run.stopping = true;
19146
- return { ok: true, sessionId: run.sessionId, pid: run.pid, live: true };
19139
+ const run2 = findRun(runs, id);
19140
+ if (run2 === null) return { ok: false, ...ambiguousRun(id) };
19141
+ if (!run2) return { ok: false, ...unknownRun(id) };
19142
+ if (run2.status !== "running") return { ok: true, sessionId: run2.sessionId };
19143
+ run2.stopping = true;
19144
+ return { ok: true, sessionId: run2.sessionId, pid: run2.pid, live: true };
19147
19145
  });
19148
- for (const run of restore) await restoreCardStatus(run);
19146
+ for (const run2 of restore) await restoreCardStatus(run2);
19149
19147
  const live = out;
19150
19148
  if (!live.ok || !live.live) {
19151
19149
  return { ok: live.ok, sessionId: live.sessionId, error: live.error, reason: live.reason, args: live.args };
@@ -19179,13 +19177,13 @@ async function cancelDelivery(id) {
19179
19177
  }
19180
19178
  async function stopSubRuns(parentId) {
19181
19179
  const live = liveSubRuns(parentId);
19182
- for (const run of live) await stopRun(run.sessionId);
19183
- await Promise.all(live.map((run) => runIsDown(run.sessionId)));
19180
+ for (const run2 of live) await stopRun(run2.sessionId);
19181
+ await Promise.all(live.map((run2) => runIsDown(run2.sessionId)));
19184
19182
  }
19185
19183
  async function runIsDown(sessionId) {
19186
19184
  for (const until = Date.now() + STOP_WAIT_MS; Date.now() < until; ) {
19187
- const run = readRuns().find((r) => r.sessionId === sessionId);
19188
- if (!run || !runIsLive(run)) return;
19185
+ const run2 = readRuns().find((r) => r.sessionId === sessionId);
19186
+ if (!run2 || !runIsLive(run2)) return;
19189
19187
  await sleep2(STOP_POLL_MS);
19190
19188
  }
19191
19189
  }
@@ -19529,13 +19527,13 @@ import path49 from "node:path";
19529
19527
  function cardsOnWorkflow(id) {
19530
19528
  const wanted = id || DEFAULT_WORKFLOW;
19531
19529
  const ids = [];
19532
- let files;
19530
+ let files2;
19533
19531
  try {
19534
- files = walkMd(TODO);
19532
+ files2 = walkMd(TODO);
19535
19533
  } catch {
19536
19534
  return [];
19537
19535
  }
19538
- for (const file of files) {
19536
+ for (const file of files2) {
19539
19537
  const base = path49.basename(file);
19540
19538
  const card = base === "root.md" ? idPrefix(path49.basename(path49.dirname(file))) : idPrefix(base);
19541
19539
  if (card === null) continue;
@@ -20116,8 +20114,8 @@ function settleDelivery2(id, skipped, unskipped) {
20116
20114
  function specRunAgent() {
20117
20115
  const id = insideRun();
20118
20116
  if (!id) return void 0;
20119
- const run = readStore().runs.find((r) => r.sessionId === id);
20120
- return run?.action === "spec" ? run.specAgent : void 0;
20117
+ const run2 = readStore().runs.find((r) => r.sessionId === id);
20118
+ return run2?.action === "spec" ? run2.specAgent : void 0;
20121
20119
  }
20122
20120
  function cmdTag(id, positions, tagRaw) {
20123
20121
  const ns = positions.split(",").map((s) => s.trim()).filter((s) => s.length > 0).map(Number);
@@ -20442,16 +20440,16 @@ function addToInbox(drop) {
20442
20440
  if (file && file.data.length > MAX_BYTES) {
20443
20441
  return { ok: false, error: `${path55.basename(file.name)} is over ${MAX_BYTES / 1024 / 1024} MB \u2014 too big for the board.` };
20444
20442
  }
20445
- const read5 = describe(typed, file);
20446
- const keep = read5.keep;
20443
+ const read6 = describe(typed, file);
20444
+ const keep = read6.keep;
20447
20445
  const said3 = drop.source?.trim() ?? "";
20448
20446
  const hit = said3 ? matchSourceType(said3) : "";
20449
20447
  const kept = said3 && !hit ? metaPair("source", said3) : null;
20450
20448
  const incoming = {
20451
- ...read5.incoming,
20449
+ ...read6.incoming,
20452
20450
  ...drop.title?.trim() ? { title: oneLine(drop.title) } : {},
20453
20451
  ...hit ? { sourceType: hit } : {},
20454
- ...kept ? { meta: [kept, ...read5.incoming.meta] } : {},
20452
+ ...kept ? { meta: [kept, ...read6.incoming.meta] } : {},
20455
20453
  ...drop.agent ? { agent: drop.agent } : {},
20456
20454
  ...drop.workflow ? { workflow: drop.workflow } : {}
20457
20455
  };
@@ -21080,21 +21078,21 @@ function scheduledNext(workflow, one) {
21080
21078
  }
21081
21079
  function insideScheduledPass() {
21082
21080
  const sessionId = insideRun();
21083
- const run = sessionId ? readStore().runs.find((r) => r.sessionId === sessionId) : void 0;
21084
- return run?.action === "scheduled" && run.workflow && run.specAgent ? { workflow: run.workflow, agent: run.specAgent } : null;
21081
+ const run2 = sessionId ? readStore().runs.find((r) => r.sessionId === sessionId) : void 0;
21082
+ return run2?.action === "scheduled" && run2.workflow && run2.specAgent ? { workflow: run2.workflow, agent: run2.specAgent } : null;
21085
21083
  }
21086
21084
  function runAgent() {
21087
21085
  const sessionId = insideRun();
21088
21086
  const runs = sessionId ? readStore().runs : [];
21089
- const run = runs.find((r) => r.sessionId === sessionId);
21090
- if (!run) return null;
21091
- if (run.action !== "sub") return agentOf(run);
21092
- const parent = runs.find((r) => r.sessionId === run.parentId);
21093
- return parent ? agentOf(parent) : run.specAgent ?? null;
21087
+ const run2 = runs.find((r) => r.sessionId === sessionId);
21088
+ if (!run2) return null;
21089
+ if (run2.action !== "sub") return agentOf(run2);
21090
+ const parent = runs.find((r) => r.sessionId === run2.parentId);
21091
+ return parent ? agentOf(parent) : run2.specAgent ?? null;
21094
21092
  }
21095
- function agentOf(run) {
21096
- if (run.action === "scheduled") return run.specAgent ?? null;
21097
- return flowNodes().find((n) => n.flow === run.action)?.agent ?? null;
21093
+ function agentOf(run2) {
21094
+ if (run2.action === "scheduled") return run2.specAgent ?? null;
21095
+ return flowNodes().find((n) => n.flow === run2.action)?.agent ?? null;
21098
21096
  }
21099
21097
  var scheduledRequest, isPass, openPasses, stalePasses;
21100
21098
  var init_scheduled = __esm({
@@ -21112,7 +21110,7 @@ var init_scheduled = __esm({
21112
21110
  workflow: pass.workflow,
21113
21111
  specAgent: pass.agent
21114
21112
  });
21115
- isPass = (run, pass) => run.action === "scheduled" && run.workflow === pass.workflow && run.specAgent === pass.agent;
21113
+ isPass = (run2, pass) => run2.action === "scheduled" && run2.workflow === pass.workflow && run2.specAgent === pass.agent;
21116
21114
  openPasses = (deliveries, pass) => deliveries.filter(
21117
21115
  (d) => d.status === "active" && d.scheduled?.workflow === pass.workflow && d.scheduled.agent === pass.agent
21118
21116
  );
@@ -21263,14 +21261,14 @@ function openRows() {
21263
21261
  }
21264
21262
  return rows.sort((a, b) => a.id - b.id);
21265
21263
  }
21266
- function cmdStale(rows, all, scope, mod) {
21264
+ function cmdStale(rows, all2, scope, mod) {
21267
21265
  const days = staleAfter();
21268
21266
  const ages = cardAges();
21269
21267
  if (ages === null) {
21270
21268
  say(`not a git repository \u2014 a card's age is the date git last saw its file, so there is nothing to list.`);
21271
21269
  return { cards: [], module: mod, staleAfter: days };
21272
21270
  }
21273
- const open3 = new Set(all.map((r) => r.id));
21271
+ const open3 = new Set(all2.map((r) => r.id));
21274
21272
  const stale3 = rows.filter(canGoStale).map((r) => ({ row: r, age: ages.get(r.file) })).filter((r) => r.age !== void 0 && r.age.days >= days).sort((a, b) => b.age.days - a.age.days || a.row.id - b.row.id);
21275
21273
  const cards = stale3.map(({ row, age }) => ({ ...row, file: rel(row.file), ...age }));
21276
21274
  if (!stale3.length) {
@@ -21288,18 +21286,18 @@ function cmdStale(rows, all, scope, mod) {
21288
21286
  return { cards, module: mod, staleAfter: days };
21289
21287
  }
21290
21288
  function archivedFiles() {
21291
- const files = /* @__PURE__ */ new Map();
21292
- if (!fs59.existsSync(ARCHIVE)) return files;
21289
+ const files2 = /* @__PURE__ */ new Map();
21290
+ if (!fs59.existsSync(ARCHIVE)) return files2;
21293
21291
  for (const file of walkMd(ARCHIVE)) {
21294
21292
  const id = idPrefix(path58.basename(file));
21295
- if (id !== null) files.set(id, file);
21293
+ if (id !== null) files2.set(id, file);
21296
21294
  }
21297
21295
  for (const dir of walkDirs(ARCHIVE)) {
21298
21296
  const id = idPrefix(path58.basename(dir));
21299
21297
  const root = path58.join(dir, "root.md");
21300
- if (id !== null && fs59.existsSync(root)) files.set(id, root);
21298
+ if (id !== null && fs59.existsSync(root)) files2.set(id, root);
21301
21299
  }
21302
- return files;
21300
+ return files2;
21303
21301
  }
21304
21302
  function cmdArchived(opts) {
21305
21303
  let since = null;
@@ -21319,14 +21317,14 @@ function cmdArchived(opts) {
21319
21317
  }
21320
21318
  const workflow = opts.workflow === void 0 ? null : knownWorkflow(opts.workflow);
21321
21319
  const open3 = boardCardIds();
21322
- const files = archivedFiles();
21320
+ const files2 = archivedFiles();
21323
21321
  const cards = landedDeliveries({ since: since?.getTime(), workflow: workflow ?? void 0 }).filter((d) => !open3.has(d.cardId)).map((d) => ({
21324
21322
  id: d.cardId,
21325
21323
  title: d.title,
21326
21324
  workflow: d.workflow,
21327
21325
  landedAt: formatStamp(new Date(d.at)),
21328
21326
  commit: d.commit,
21329
- file: files.has(d.cardId) ? rel(files.get(d.cardId)) : ""
21327
+ file: files2.has(d.cardId) ? rel(files2.get(d.cardId)) : ""
21330
21328
  }));
21331
21329
  const result = { cards, since: since ? formatStamp(since) : null, workflow };
21332
21330
  const scope = [workflow ? `on workflow \`${workflow}\`` : "", since ? `since ${formatStamp(since)}` : ""].filter(Boolean).join(" ");
@@ -21350,8 +21348,8 @@ function cmdList(opts) {
21350
21348
  }
21351
21349
  if (opts.since !== void 0) die("--since only applies to --archived.");
21352
21350
  if (opts.workflow !== void 0) die("--workflow only applies to --archived.");
21353
- const all = openRows();
21354
- let rows = all;
21351
+ const all2 = openRows();
21352
+ let rows = all2;
21355
21353
  let scope = "on the board";
21356
21354
  const mod = opts.module;
21357
21355
  if (mod !== void 0) {
@@ -21363,7 +21361,7 @@ function cmdList(opts) {
21363
21361
  rows = rows.filter((r) => r.modules.includes(mod));
21364
21362
  scope = `tagged \`${mod}\``;
21365
21363
  }
21366
- if (opts.stale) return cmdStale(rows, all, scope, mod === void 0 ? null : mod);
21364
+ if (opts.stale) return cmdStale(rows, all2, scope, mod === void 0 ? null : mod);
21367
21365
  const cards = rows.map((r) => ({ ...r, file: rel(r.file) }));
21368
21366
  if (!rows.length) {
21369
21367
  say(`no open cards ${scope}.`);
@@ -21443,10 +21441,10 @@ function stripOldHeader(text5) {
21443
21441
  }
21444
21442
  function cmdMigrate(opts) {
21445
21443
  const dry = opts.dryRun === true;
21446
- const files = walkMd(TODO).filter((f) => path59.basename(f) !== "README.md");
21444
+ const files2 = walkMd(TODO).filter((f) => path59.basename(f) !== "README.md");
21447
21445
  let changed = 0;
21448
21446
  let skipped = 0;
21449
- for (const file of files) {
21447
+ for (const file of files2) {
21450
21448
  const text5 = fs60.readFileSync(file, "utf8");
21451
21449
  if (text5.trimStart().startsWith("---")) {
21452
21450
  skipped++;
@@ -21646,16 +21644,16 @@ function removeCard2(id, metric, options) {
21646
21644
  }
21647
21645
  }
21648
21646
  withStore((store) => {
21649
- for (const run of store.runs) {
21650
- if (!leaving.some((c) => run.createdCardIds?.includes(c.id))) continue;
21651
- const marks = new Map((run.discardedCards ?? []).map((c) => [c.id, c]));
21647
+ for (const run2 of store.runs) {
21648
+ if (!leaving.some((c) => run2.createdCardIds?.includes(c.id))) continue;
21649
+ const marks = new Map((run2.discardedCards ?? []).map((c) => [c.id, c]));
21652
21650
  for (const c of leaving) marks.set(c.id, { id: c.id, path: rel(c.file), pending: true });
21653
- run.discardedCards = [...marks.values()];
21651
+ run2.discardedCards = [...marks.values()];
21654
21652
  }
21655
21653
  });
21656
21654
  }
21657
21655
  if (options.discard) withStore((store) => {
21658
- for (const run of store.runs) for (const card of run.discardedCards ?? []) {
21656
+ for (const run2 of store.runs) for (const card of run2.discardedCards ?? []) {
21659
21657
  if (leftIds.includes(card.id)) delete card.pending;
21660
21658
  }
21661
21659
  });
@@ -21856,10 +21854,10 @@ var init_agent_file = __esm({
21856
21854
  // ../cli/src/commands/memory-file.ts
21857
21855
  function cmdMemoryFile(askedName) {
21858
21856
  const name = askedName.trim();
21859
- const all = globalMemories();
21860
- const memory = all.find((m) => m.name === name);
21857
+ const all2 = globalMemories();
21858
+ const memory = all2.find((m) => m.name === name);
21861
21859
  if (!memory) {
21862
- const has = all.length ? `It has: ${all.map((m) => m.name).join(", ")}.` : "It has none.";
21860
+ const has = all2.length ? `It has: ${all2.map((m) => m.name).join(", ")}.` : "It has none.";
21863
21861
  die(`"${name}" is not a global memory on this board. ${has}`, { kind: "no-such-memory", memory: name });
21864
21862
  }
21865
21863
  say(memory.text);
@@ -22295,12 +22293,12 @@ function variantsProblem(raw, src, id) {
22295
22293
  return `variants is not valid JSON. ${shape}`;
22296
22294
  }
22297
22295
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return `variants is not a JSON object. ${shape}`;
22298
- const files = Object.values(parsed);
22299
- if (files.length < 2 || !files.every((f) => typeof f === "string" && f)) return `variants needs at least two labels, each naming a file. ${shape}`;
22300
- if (!files.includes(src)) return `src="${src}" is not one of the variants. Set src to the version shown first.`;
22296
+ const files2 = Object.values(parsed);
22297
+ if (files2.length < 2 || !files2.every((f) => typeof f === "string" && f)) return `variants needs at least two labels, each naming a file. ${shape}`;
22298
+ if (!files2.includes(src)) return `src="${src}" is not one of the variants. Set src to the version shown first.`;
22301
22299
  if (id === void 0) return null;
22302
22300
  const dir = path62.join(ASSETS, String(id));
22303
- for (const f of files) {
22301
+ for (const f of files2) {
22304
22302
  const parts = f.split("/");
22305
22303
  if (parts.length !== 3 || parts[0] !== ".assets" || parts[1] !== String(id) || !inside(dir, parts[2])) {
22306
22304
  return `Variant ${f} names no file in this card's asset folder .assets/${id}/. Write the file there or fix the path.`;
@@ -22323,7 +22321,7 @@ function compareProblem(attrs, id) {
22323
22321
  if (!script && kind !== compareKind(attrs.b)) return src("Compare a and b must both be images or both be videos.");
22324
22322
  if (attrs.shots === void 0) return script ? shots('shots is required when b is a storyboard. Add shots="..." naming a storyboard or shots list of video a.') : null;
22325
22323
  if (kind !== "video") return shots("shots is for videos only. Remove it from this Compare tag.");
22326
- const read5 = (at) => {
22324
+ const read6 = (at) => {
22327
22325
  const named2 = assetName(at, id, ["json"]);
22328
22326
  if (!("name" in named2)) return { message: `Compare shots is ${named2.actual}; expected ${named2.expected}.` };
22329
22327
  const file = inside(dir, named2.name);
@@ -22334,12 +22332,12 @@ function compareProblem(attrs, id) {
22334
22332
  return { message: `${at} is not valid JSON.` };
22335
22333
  }
22336
22334
  };
22337
- const list = read5(attrs.shots);
22335
+ const list = read6(attrs.shots);
22338
22336
  if ("message" in list) return shots(list.message);
22339
22337
  const why = Array.isArray(list.data) ? shotsProblem(list.data) : storyboardProblem(list.data);
22340
22338
  if (why) return shots(`${attrs.shots}: ${why}`);
22341
22339
  if (!script) return null;
22342
- const b = read5(attrs.b);
22340
+ const b = read6(attrs.b);
22343
22341
  if ("message" in b) return src(b.message);
22344
22342
  const bad = storyboardProblem(b.data);
22345
22343
  if (bad) return src(`${attrs.b}: ${bad}`);
@@ -22586,11 +22584,11 @@ function newOpId() {
22586
22584
  opCounter += 1;
22587
22585
  return `${process.pid.toString(36)}-${Date.now().toString(36)}-${opCounter.toString(36)}`;
22588
22586
  }
22589
- async function leaseAnd(provider, target, run) {
22587
+ async function leaseAnd(provider, target, run2) {
22590
22588
  const got = await provider.lease(target);
22591
22589
  if (!got.ok) return { ok: false, kind: "refused", error: got.error };
22592
22590
  try {
22593
- return await run(envelope(got.lease.revision, got.lease.id));
22591
+ return await run2(envelope(got.lease.revision, got.lease.id));
22594
22592
  } finally {
22595
22593
  await provider.releaseLease(got.lease.id);
22596
22594
  }
@@ -22732,14 +22730,14 @@ function localBoard() {
22732
22730
  },
22733
22731
  // ---- the named `akb raw` moves ----------------------------------------
22734
22732
  async runMove(move2, input, env) {
22735
- const run = MOVES[move2];
22736
- if (!run) return Promise.resolve(opRefused(new Error(`unknown command "${move2}".`)));
22733
+ const run2 = MOVES[move2];
22734
+ if (!run2) return Promise.resolve(opRefused(new Error(`unknown command "${move2}".`)));
22737
22735
  const target = moveTarget(move2, input.args);
22738
22736
  try {
22739
22737
  return await withBoardLock(() => {
22740
22738
  const no = checkWrite(target, env, revisionAt(target));
22741
22739
  if (no) return no;
22742
- const data = run(input);
22740
+ const data = run2(input);
22743
22741
  if (data instanceof Promise) return data.then((data2) => opOk(revisionAt(target), { data: data2 }));
22744
22742
  return opOk(revisionAt(target), { data: data || {} });
22745
22743
  });
@@ -22748,10 +22746,10 @@ function localBoard() {
22748
22746
  }
22749
22747
  },
22750
22748
  readMove(move2, input) {
22751
- const run = MOVES[move2];
22752
- if (!run) return Promise.reject(new Error(`unknown command "${move2}".`));
22749
+ const run2 = MOVES[move2];
22750
+ if (!run2) return Promise.reject(new Error(`unknown command "${move2}".`));
22753
22751
  try {
22754
- return Promise.resolve(run(input) || {});
22752
+ return Promise.resolve(run2(input) || {});
22755
22753
  } catch (e) {
22756
22754
  return Promise.reject(e);
22757
22755
  }
@@ -22813,8 +22811,8 @@ function board() {
22813
22811
  if (!active) active = localBoard();
22814
22812
  return active;
22815
22813
  }
22816
- function withLease(target, run) {
22817
- return leaseAnd(board(), target, run);
22814
+ function withLease(target, run2) {
22815
+ return leaseAnd(board(), target, run2);
22818
22816
  }
22819
22817
  var active, setCardStatusOn, archiveCard, finishSetupStep, cancelBoardDelivery, resumeBoardDelivery, discardBoardDelivery;
22820
22818
  var init_board2 = __esm({
@@ -23093,18 +23091,18 @@ async function refresh() {
23093
23091
  }
23094
23092
  }
23095
23093
  function sessionFrom(body, previous) {
23096
- const token2 = body;
23097
- const subject2 = token2.user?.id ?? previous?.subject;
23098
- if (!token2.access_token || !token2.refresh_token || !subject2) return null;
23099
- const expiresAt = token2.expires_at ? token2.expires_at * 1e3 : Date.now() + (token2.expires_in ?? 3600) * 1e3;
23094
+ const token3 = body;
23095
+ const subject2 = token3.user?.id ?? previous?.subject;
23096
+ if (!token3.access_token || !token3.refresh_token || !subject2) return null;
23097
+ const expiresAt = token3.expires_at ? token3.expires_at * 1e3 : Date.now() + (token3.expires_in ?? 3600) * 1e3;
23100
23098
  return {
23101
23099
  version: 1,
23102
23100
  supabaseUrl: cloudEndpoints().supabaseUrl,
23103
- accessToken: token2.access_token,
23104
- refreshToken: token2.refresh_token,
23101
+ accessToken: token3.access_token,
23102
+ refreshToken: token3.refresh_token,
23105
23103
  expiresAt,
23106
23104
  subject: subject2,
23107
- email: token2.user?.email ?? previous?.email,
23105
+ email: token3.user?.email ?? previous?.email,
23108
23106
  handle: previous?.handle,
23109
23107
  name: previous?.name,
23110
23108
  avatarUrl: previous?.avatarUrl,
@@ -23193,16 +23191,16 @@ function cloudWorkflow(name) {
23193
23191
  }
23194
23192
  async function call(method, route2, body, key) {
23195
23193
  if (!cloudConfigured()) return { ok: false, error: NOT_CONFIGURED, code: "bad_request" };
23196
- const token2 = await accessToken();
23197
- if (!token2.ok) {
23198
- return token2.reason === "unreachable" ? { ok: false, error: `Cloud could not be reached: ${token2.error}` } : { ok: false, error: "This machine is not signed in to Cloud.", code: "unauthenticated" };
23194
+ const token3 = await accessToken();
23195
+ if (!token3.ok) {
23196
+ return token3.reason === "unreachable" ? { ok: false, error: `Cloud could not be reached: ${token3.error}` } : { ok: false, error: "This machine is not signed in to Cloud.", code: "unauthenticated" };
23199
23197
  }
23200
23198
  let response;
23201
23199
  try {
23202
23200
  response = await fetch(`${cloudEndpoints().api}${route2}`, {
23203
23201
  method,
23204
23202
  headers: {
23205
- authorization: `Bearer ${token2.token}`,
23203
+ authorization: `Bearer ${token3.token}`,
23206
23204
  ...body ? { "content-type": "application/json" } : {},
23207
23205
  ...key ? { "idempotency-key": key } : {}
23208
23206
  },
@@ -23228,7 +23226,8 @@ async function createTask(from, said3) {
23228
23226
  source: "api",
23229
23227
  source_context: { task: from },
23230
23228
  ...said3.run ? { run: true } : {},
23231
- ...said3.metadata && Object.keys(said3.metadata).length ? { metadata: said3.metadata } : {}
23229
+ ...said3.metadata && Object.keys(said3.metadata).length ? { metadata: said3.metadata } : {},
23230
+ ...said3.triage ? { triage: `tri_${source.value.project.replace(/^prj_/, "")}_${said3.triage}` } : {}
23232
23231
  };
23233
23232
  const key = `akb-${crypto2.createHash("sha256").update(`${from}
23234
23233
  ${said3.slug?.trim() || said3.title}`).digest("hex").slice(0, 40)}`;
@@ -23358,6 +23357,7 @@ __export(board_exports, {
23358
23357
  buildBoardProgram: () => buildBoardProgram
23359
23358
  });
23360
23359
  import fs68 from "node:fs";
23360
+ import path65 from "node:path";
23361
23361
  async function dispatch(move2, cmd, args, opts, cli) {
23362
23362
  const ctx = ctxOf(cmd, cli.program);
23363
23363
  const data = await runAction(ctx, {}, async () => {
@@ -23391,24 +23391,30 @@ async function cloudCard(task, opts) {
23391
23391
  } catch {
23392
23392
  }
23393
23393
  }
23394
- const run = opts.schedule !== void 0;
23394
+ const run2 = opts.schedule !== void 0;
23395
23395
  const made = await createTask(task, {
23396
23396
  title: String(opts.title ?? "").trim(),
23397
23397
  request,
23398
23398
  workflow: typeof opts.workflow === "string" && opts.workflow.trim() ? opts.workflow.trim() : void 0,
23399
- run,
23399
+ run: run2,
23400
23400
  slug: typeof opts.slug === "string" ? opts.slug : void 0,
23401
- metadata: run ? cardFields(opts) : void 0
23401
+ metadata: run2 ? cardFields(opts) : void 0,
23402
+ triage: typeof opts.triage === "string" ? triageFile(opts.triage) : void 0
23402
23403
  });
23403
23404
  if (!made.ok) throw new BoardError(`Cloud did not make the task: ${made.error}`, { kind: "refused" });
23404
23405
  const { task: created, number, from } = made.value;
23405
- if (run) {
23406
+ if (run2) {
23406
23407
  say(number);
23407
23408
  say(` made ${created.key} in Cloud${made.value.replayed ? " (already made)" : ""} \u2014 it is planned there, from ${from.key}`);
23408
23409
  return { done: { board: KANBAN, id: number, ids: [], key: created.key, task: created.id, replayed: made.value.replayed } };
23409
23410
  }
23410
23411
  return { opts: { ...opts, id: number, fromTask: from.key, schedule: void 0 } };
23411
23412
  }
23413
+ function triageFile(sourceId) {
23414
+ const found2 = [...readInbox(), ...readAllDismissed(), ...readArchived()].find((s) => s.sourceId === sourceId.trim());
23415
+ if (!found2) throw new BoardError(`nothing in triage is ${sourceId}`, { kind: "refused" });
23416
+ return path65.basename(found2.relPath, ".md");
23417
+ }
23412
23418
  function cardFields(opts) {
23413
23419
  const list = (v) => Array.isArray(v) && v.length ? v.map((x) => String(x).replace(/^#/, "")) : void 0;
23414
23420
  return Object.fromEntries(Object.entries({
@@ -23568,6 +23574,7 @@ var init_board3 = __esm({
23568
23574
  init_rules();
23569
23575
  init_shared();
23570
23576
  init_esm();
23577
+ init_inbox();
23571
23578
  init_tasks();
23572
23579
  init_idea();
23573
23580
  CREATE_SCHEDULES = SCHEDULED_ACTIONS.filter((a) => a !== "revise");
@@ -23577,15 +23584,15 @@ var init_board3 = __esm({
23577
23584
 
23578
23585
  // ../cli/src/lib/board-cli.ts
23579
23586
  import fs69 from "node:fs";
23580
- import path65 from "node:path";
23587
+ import path66 from "node:path";
23581
23588
  function useBoard(found2, dirNamed) {
23582
- if (!found2.named && found2.board === path65.join(found2.root, "docs", "kanban")) setBoardRoot(found2.root, dirNamed);
23589
+ if (!found2.named && found2.board === path66.join(found2.root, "docs", "kanban")) setBoardRoot(found2.root, dirNamed);
23583
23590
  else setBoardDir(found2.board, found2.root);
23584
23591
  useProjectState();
23585
23592
  }
23586
23593
  function whole(found2, move2) {
23587
23594
  if (move2 === MAKES_A_BOARD) return found2;
23588
- if (!fs69.existsSync(path65.join(found2.board, "todo"))) {
23595
+ if (!fs69.existsSync(path66.join(found2.board, "todo"))) {
23589
23596
  die(`the board in ${found2.board} has no todo/ \u2014 run \`init\` to add what is missing.`, {
23590
23597
  kind: "board-incomplete",
23591
23598
  dir: found2.root
@@ -23594,11 +23601,11 @@ function whole(found2, move2) {
23594
23601
  return found2;
23595
23602
  }
23596
23603
  function findBoardUpward(from) {
23597
- let dir = path65.resolve(from);
23604
+ let dir = path66.resolve(from);
23598
23605
  for (; ; ) {
23599
- if (hasBoard(dir)) return { root: dir, board: path65.join(dir, "docs", "kanban") };
23606
+ if (hasBoard(dir)) return { root: dir, board: path66.join(dir, "docs", "kanban") };
23600
23607
  if (isBoardDir(dir)) return { root: projectRootOf(dir), board: dir };
23601
- const up = path65.dirname(dir);
23608
+ const up = path66.dirname(dir);
23602
23609
  if (up === dir) return null;
23603
23610
  dir = up;
23604
23611
  }
@@ -23606,7 +23613,7 @@ function findBoardUpward(from) {
23606
23613
  function resolveBoard(move2, { board: board2, dir, cwd, installHint }) {
23607
23614
  const named2 = board2 ?? boardFromEnv();
23608
23615
  if (named2) {
23609
- const folder = path65.resolve(cwd, named2);
23616
+ const folder = path66.resolve(cwd, named2);
23610
23617
  if (!fs69.existsSync(folder) && move2 !== MAKES_A_BOARD) {
23611
23618
  die(`no such folder: ${folder}`, { kind: "no-such-folder", dir: folder });
23612
23619
  }
@@ -23619,7 +23626,7 @@ function resolveBoard(move2, { board: board2, dir, cwd, installHint }) {
23619
23626
  return { root: projectRootOf(folder), board: folder, named: true };
23620
23627
  }
23621
23628
  if (dir !== null) {
23622
- const root = path65.resolve(dir);
23629
+ const root = path66.resolve(dir);
23623
23630
  if (!fs69.existsSync(root)) die(`no such folder: ${root}`, { kind: "no-such-folder", dir: root });
23624
23631
  if (!hasBoard(root) && move2 !== MAKES_A_BOARD) {
23625
23632
  die(`no board in ${root} \u2014 it has no docs/kanban/. Run ${installHint} there to make one.`, {
@@ -23627,14 +23634,14 @@ function resolveBoard(move2, { board: board2, dir, cwd, installHint }) {
23627
23634
  dir: root
23628
23635
  });
23629
23636
  }
23630
- return whole({ root, board: path65.join(root, "docs", "kanban") }, move2);
23637
+ return whole({ root, board: path66.join(root, "docs", "kanban") }, move2);
23631
23638
  }
23632
23639
  const found2 = findBoardUpward(cwd);
23633
23640
  if (found2) return whole(found2, move2);
23634
- if (move2 === MAKES_A_BOARD) return { root: path65.resolve(cwd), board: path65.join(path65.resolve(cwd), "docs", "kanban") };
23641
+ if (move2 === MAKES_A_BOARD) return { root: path66.resolve(cwd), board: path66.join(path66.resolve(cwd), "docs", "kanban") };
23635
23642
  die(
23636
- `no board here. Looked in ${path65.resolve(cwd)} and every folder above it for docs/kanban/. Run ${installHint} to make one, or name the board with --board.`,
23637
- { kind: "no-board", dir: path65.resolve(cwd) }
23643
+ `no board here. Looked in ${path66.resolve(cwd)} and every folder above it for docs/kanban/. Run ${installHint} to make one, or name the board with --board.`,
23644
+ { kind: "no-board", dir: path66.resolve(cwd) }
23638
23645
  );
23639
23646
  }
23640
23647
  function editDistance(a, b) {
@@ -23716,8 +23723,8 @@ var init_board_cli = __esm({
23716
23723
  init_io();
23717
23724
  init_pointer();
23718
23725
  MAKES_A_BOARD = "init";
23719
- hasBoard = (dir) => fs69.existsSync(path65.join(dir, "docs", "kanban"));
23720
- isBoardDir = (dir) => fs69.existsSync(path65.join(dir, "todo")) && fs69.existsSync(path65.join(dir, "config.md"));
23726
+ hasBoard = (dir) => fs69.existsSync(path66.join(dir, "docs", "kanban"));
23727
+ isBoardDir = (dir) => fs69.existsSync(path66.join(dir, "todo")) && fs69.existsSync(path66.join(dir, "config.md"));
23721
23728
  boardFromEnv = () => {
23722
23729
  const named2 = process.env.AI4KANBAN_BOARD?.trim();
23723
23730
  return named2 ? named2 : null;
@@ -23726,8 +23733,8 @@ var init_board_cli = __esm({
23726
23733
  });
23727
23734
 
23728
23735
  // ../cli/src/lib/agent/approve.ts
23729
- import fs73 from "node:fs";
23730
- import path69 from "node:path";
23736
+ import fs75 from "node:fs";
23737
+ import path72 from "node:path";
23731
23738
  function approvalRequest(req) {
23732
23739
  const id = req.id;
23733
23740
  const card = id === void 0 ? null : findCard(id);
@@ -23745,12 +23752,12 @@ function advancePhase(id) {
23745
23752
  const card = findCard(id);
23746
23753
  const found2 = locate(id);
23747
23754
  if (!card || !found2 || !awaitingApproval(card)) return { error: `#${id} is no longer waiting on approval.` };
23748
- const file = found2.kind === "group" ? path69.join(found2.target, "root.md") : found2.target;
23749
- const { meta, body } = parseFrontmatter(fs73.readFileSync(file, "utf8"));
23755
+ const file = found2.kind === "group" ? path72.join(found2.target, "root.md") : found2.target;
23756
+ const { meta, body } = parseFrontmatter(fs75.readFileSync(file, "utf8"));
23750
23757
  if (!meta) return { error: `#${id} has no frontmatter` };
23751
23758
  meta.phase = card.stage + 1;
23752
23759
  meta.status = "todo";
23753
- fs73.writeFileSync(file, serializeFrontmatter(meta) + "\n" + body);
23760
+ fs75.writeFileSync(file, serializeFrontmatter(meta) + "\n" + body);
23754
23761
  return null;
23755
23762
  }
23756
23763
  var init_approve = __esm({
@@ -23840,10 +23847,10 @@ function open2(req, sessionId) {
23840
23847
  returnRunPictures(sessionId, req.box);
23841
23848
  return opened;
23842
23849
  }
23843
- const { run } = opened;
23844
- const pid = spawnWatcher(run.sessionId);
23845
- markSpawned(run.sessionId, pid);
23846
- return { run, spawned: pid !== void 0 };
23850
+ const { run: run2 } = opened;
23851
+ const pid = spawnWatcher(run2.sessionId);
23852
+ markSpawned(run2.sessionId, pid);
23853
+ return { run: run2, spawned: pid !== void 0 };
23847
23854
  }
23848
23855
  async function startResume(id) {
23849
23856
  const opened = await openResume(id);
@@ -23870,16 +23877,16 @@ var init_start = __esm({
23870
23877
  });
23871
23878
 
23872
23879
  // ../cli/src/lib/agent/task-chats.ts
23873
- import fs74 from "node:fs";
23874
- import path70 from "node:path";
23880
+ import fs76 from "node:fs";
23881
+ import path73 from "node:path";
23875
23882
  function taskChatFile(task, home3) {
23876
23883
  if (!TASK.test(task)) throw new Error(`${task} is not a task id.`);
23877
- return path70.join(taskChatsDir(home3), `${task}.jsonl`);
23884
+ return path73.join(taskChatsDir(home3), `${task}.jsonl`);
23878
23885
  }
23879
23886
  function readTaskChat(task, home3) {
23880
23887
  let text5;
23881
23888
  try {
23882
- text5 = fs74.readFileSync(taskChatFile(task, home3), "utf8");
23889
+ text5 = fs76.readFileSync(taskChatFile(task, home3), "utf8");
23883
23890
  } catch {
23884
23891
  return [];
23885
23892
  }
@@ -23900,20 +23907,20 @@ var init_task_chats = __esm({
23900
23907
  "use strict";
23901
23908
  init_home();
23902
23909
  TASK = /^[\w-]{1,100}$/;
23903
- taskChatsDir = (home3 = machineHome()) => path70.join(home3, "chats");
23910
+ taskChatsDir = (home3 = machineHome()) => path73.join(home3, "chats");
23904
23911
  }
23905
23912
  });
23906
23913
 
23907
23914
  // ../cli/src/lib/agent/memory-review.ts
23908
- import fs75 from "node:fs";
23909
- import path71 from "node:path";
23915
+ import fs77 from "node:fs";
23916
+ import path74 from "node:path";
23910
23917
  function taskChatsToReview(tasks) {
23911
- const cards = fs75.existsSync(ARCHIVE) ? walkMd(ARCHIVE) : [];
23918
+ const cards = fs77.existsSync(ARCHIVE) ? walkMd(ARCHIVE) : [];
23912
23919
  const out = [];
23913
23920
  for (const task of [...new Set(tasks)]) {
23914
23921
  const slug2 = task.toLowerCase().replace(/_/g, "-");
23915
- const file = cards.find((f) => /^\d+-/.test(path71.basename(f)) && path71.basename(f).endsWith(`-${slug2}.md`));
23916
- const id = file ? idPrefix(path71.basename(file)) : null;
23922
+ const file = cards.find((f) => /^\d+-/.test(path74.basename(f)) && path74.basename(f).endsWith(`-${slug2}.md`));
23923
+ const id = file ? idPrefix(path74.basename(file)) : null;
23917
23924
  const card = file && id !== null ? readArchived2(id, file) : null;
23918
23925
  let lines = [];
23919
23926
  try {
@@ -23929,7 +23936,7 @@ function taskChatsToReview(tasks) {
23929
23936
  }
23930
23937
  function readArchived2(id, file) {
23931
23938
  try {
23932
- const { meta, body } = parseFrontmatter(fs75.readFileSync(file, "utf8"));
23939
+ const { meta, body } = parseFrontmatter(fs77.readFileSync(file, "utf8"));
23933
23940
  if (!meta) return null;
23934
23941
  return { id, title: meta.title, modules: meta.modules ?? [], rejected: meta.rejected, body };
23935
23942
  } catch {
@@ -23975,8 +23982,8 @@ var init_memory_review = __esm({
23975
23982
  });
23976
23983
 
23977
23984
  // ../cli/src/lib/agent/flow.ts
23978
- import fs76 from "node:fs";
23979
- import path72 from "node:path";
23985
+ import fs78 from "node:fs";
23986
+ import path75 from "node:path";
23980
23987
  function readCard2(id, home3 = "board") {
23981
23988
  const found2 = home3 === "archive" ? locateArchived(id) : locate(id);
23982
23989
  if (!found2) {
@@ -23985,10 +23992,10 @@ function readCard2(id, home3 = "board") {
23985
23992
  { kind: "card-not-found", id }
23986
23993
  );
23987
23994
  }
23988
- const file = found2.kind === "group" ? path72.join(found2.target, "root.md") : found2.target;
23995
+ const file = found2.kind === "group" ? path75.join(found2.target, "root.md") : found2.target;
23989
23996
  let text5;
23990
23997
  try {
23991
- text5 = fs76.readFileSync(file, "utf8");
23998
+ text5 = fs78.readFileSync(file, "utf8");
23992
23999
  } catch {
23993
24000
  die(`#${id} is on the board but ${rel(file)} can't be read.`, { kind: "card-unreadable", id });
23994
24001
  }
@@ -24046,7 +24053,7 @@ function memoryLines(modules, name) {
24046
24053
  }
24047
24054
  function configText() {
24048
24055
  try {
24049
- return fs76.readFileSync(CONFIG, "utf8").trim() || null;
24056
+ return fs78.readFileSync(CONFIG, "utf8").trim() || null;
24050
24057
  } catch {
24051
24058
  return null;
24052
24059
  }
@@ -24092,10 +24099,10 @@ function candidateField(delivery) {
24092
24099
  }
24093
24100
  const candidate = candidateOf(delivery);
24094
24101
  const stat = candidateStat(candidate);
24095
- const files = candidateFileStats(candidate);
24102
+ const files2 = candidateFileStats(candidate);
24096
24103
  const patch2 = candidatePatch(candidate);
24097
24104
  const command = delivery.worktree && delivery.branch ? `git diff ${delivery.base.slice(0, 12)} ${delivery.branch}` : `git diff ${delivery.base.slice(0, 12)}`;
24098
- const shown2 = files?.length ? ["changed files:", ...files.map((file) => ` ${file}`)] : ["no file changed"];
24105
+ const shown2 = files2?.length ? ["changed files:", ...files2.map((file) => ` ${file}`)] : ["no file changed"];
24099
24106
  let diff = [];
24100
24107
  if (patch2 === null) diff = ["", "the diff could not be read"];
24101
24108
  else if (patch2.length > MAX_DIFF) {
@@ -24119,7 +24126,7 @@ function workspaceField(delivery) {
24119
24126
  if (!delivery?.worktree) return [];
24120
24127
  return field("workspace", [
24121
24128
  `write code in ${delivery.worktree} \u2014 this delivery's own worktree, on branch ${delivery.branch}.`,
24122
- path72.resolve(process.cwd()).startsWith(worktreeDir(delivery.worktree)) ? `it is your working folder already; the board's own files are NOT in it and never go on that branch.` : `cd into it first \u2014 you are in the project checkout, and code written here is not part of this build. The board's own files are NOT in it and never go on that branch.`,
24129
+ path75.resolve(process.cwd()).startsWith(worktreeDir(delivery.worktree)) ? `it is your working folder already; the board's own files are NOT in it and never go on that branch.` : `cd into it first \u2014 you are in the project checkout, and code written here is not part of this build. The board's own files are NOT in it and never go on that branch.`,
24123
24130
  `every board command names the project's own copy: \`${boardCommandFor()} <command>\`.`,
24124
24131
  `${rel(REPO_ROOT)} is the project \u2014 the card, the memory files and the docs are changed there, not here.`
24125
24132
  ]);
@@ -24127,7 +24134,7 @@ function workspaceField(delivery) {
24127
24134
  function conflictField(delivery) {
24128
24135
  if (!delivery?.worktree) return field("conflict", "no delivery with a worktree is landing right now");
24129
24136
  const dir = worktreeDir(delivery.worktree);
24130
- const files = conflictedPaths(dir);
24137
+ const files2 = conflictedPaths(dir);
24131
24138
  const target = delivery.targetBranch ?? "the target branch";
24132
24139
  const since = delivery.landing?.originalBase ?? delivery.base;
24133
24140
  const onto = delivery.landing?.onto ?? delivery.targetBranch;
@@ -24138,7 +24145,7 @@ function conflictField(delivery) {
24138
24145
  return field("conflict", [
24139
24146
  ...delivery.landing?.why ? [`landing: ${delivery.landing.why}`] : [],
24140
24147
  `worktree: ${delivery.worktree}`,
24141
- ...files.length ? [`conflicted files (${files.length}):`, ...listed(files)] : ["conflicted files: none"],
24148
+ ...files2.length ? [`conflicted files (${files2.length}):`, ...listed(files2)] : ["conflicted files: none"],
24142
24149
  ...since && onto ? [
24143
24150
  `original base: ${short2(since)} \u2014 \`git diff ${short2(since)} ${short2(onto)}\` is what ${target} brought in since this delivery started`,
24144
24151
  `${target} changed since then (${theirs.length}):`,
@@ -24500,7 +24507,7 @@ function printFlow(rawReq, program2 = "akb") {
24500
24507
  say("");
24501
24508
  say(`there is no \`akb\` on this machine \u2014 every \`akb\` below, in the flows too, is \`${program2}\` here.`);
24502
24509
  }
24503
- if (req.action !== "setup" && fs76.existsSync(SETUP_CHECKLIST)) {
24510
+ if (req.action !== "setup" && fs78.existsSync(SETUP_CHECKLIST)) {
24504
24511
  say("");
24505
24512
  say(`this board is not set up yet \u2014 ${rel(SETUP_CHECKLIST)} is still there.`);
24506
24513
  say(`finish it first: ${setupInstruction()}`);
@@ -24540,6 +24547,11 @@ function printFlow(rawReq, program2 = "akb") {
24540
24547
  say("");
24541
24548
  say(rule);
24542
24549
  }
24550
+ const language = languageNote();
24551
+ if (language) {
24552
+ say("");
24553
+ say(language);
24554
+ }
24543
24555
  return {
24544
24556
  mode: "print",
24545
24557
  action: req.action,
@@ -24589,9 +24601,9 @@ var init_flow = __esm({
24589
24601
  EDITABLE_FIELDS = "--title|--priority|--roi|--modules|--blocked-by|--related";
24590
24602
  bodyScaffoldClose = (lead = "fill the existing") => [`${lead} body scaffold; do not rename or translate its section titles, and leave empty scaffold sections in place`];
24591
24603
  MAX_LISTED = 50;
24592
- listed = (files) => [
24593
- ...files.slice(0, MAX_LISTED).map((f) => ` ${f}`),
24594
- ...files.length > MAX_LISTED ? [` \u2026and ${files.length - MAX_LISTED} more`] : []
24604
+ listed = (files2) => [
24605
+ ...files2.slice(0, MAX_LISTED).map((f) => ` ${f}`),
24606
+ ...files2.length > MAX_LISTED ? [` \u2026and ${files2.length - MAX_LISTED} more`] : []
24595
24607
  ];
24596
24608
  answeredClose = (delivery, self) => `${self} delivery answered ${delivery.deliveryId} --changed|--unchanged "<why>" \u2014 before you drop the questions; dropping the last one with nothing said carries the build on as --unchanged`;
24597
24609
  stageClose = (meta) => {
@@ -24715,30 +24727,30 @@ function stalledLine(cardId2, next) {
24715
24727
  if (!card || card.schedule || refinementStep(card) === "done") return null;
24716
24728
  return next === "incomplete" ? `QA left untagged questions on #${card.id}, so it did not finish. #${card.id} is still at todo and nothing else will pick it up \u2014 refine it again, or mark it ready yourself.` : `#${card.id} is still in To do after planning, and the board won't plan it again on its own \u2014 refine it again, or mark it ready yourself.`;
24717
24729
  }
24718
- function planStageEnd(run) {
24719
- if (run.cardId === null || stageOfAction(run.action) !== "plan") return null;
24720
- const card = currentCard(run.cardId);
24730
+ function planStageEnd(run2) {
24731
+ if (run2.cardId === null || stageOfAction(run2.action) !== "plan") return null;
24732
+ const card = currentCard(run2.cardId);
24721
24733
  if (!card || card.openBlockers.length > 0 || openOf(card.questions).length > 0 || card.schedule) return null;
24722
24734
  if (refinementStep(card) !== "done") return null;
24723
24735
  return endOfStage(stageContract("plan"), card);
24724
24736
  }
24725
- function refinementRunsAfter(run, changed, before, waitingForSpec = false, refused = []) {
24726
- for (const id of /* @__PURE__ */ new Set([...changed, ...run.cardId === null ? [] : [run.cardId]])) {
24737
+ function refinementRunsAfter(run2, changed, before, waitingForSpec = false, refused = []) {
24738
+ for (const id of /* @__PURE__ */ new Set([...changed, ...run2.cardId === null ? [] : [run2.cardId]])) {
24727
24739
  scheduleRefineOnBlock(id);
24728
24740
  }
24729
- const next = waitingForSpec || run.cardId === null || !["clarify", "resolve", "edit", "approve"].includes(run.action) ? null : refinementAfter(run.action, run.cardId, run.flowId);
24730
- const starts2 = refinesAfter(run.action, changed, before).filter(
24731
- (req) => req.id !== run.cardId || run.refineRound === void 0 && run.action !== "spec"
24741
+ const next = waitingForSpec || run2.cardId === null || !["clarify", "resolve", "edit", "approve"].includes(run2.action) ? null : refinementAfter(run2.action, run2.cardId, run2.flowId);
24742
+ const starts2 = refinesAfter(run2.action, changed, before).filter(
24743
+ (req) => req.id !== run2.cardId || run2.refineRound === void 0 && run2.action !== "spec"
24732
24744
  );
24733
24745
  const refusedNote = waitingForSpec || !refused.length ? "" : `Spec agents not started: ${refused.map((r) => r.error).join(" ")}`;
24734
24746
  const plain2 = typeof next === "object" && next ? next : null;
24735
24747
  const carryOn = plain2 && refusedNote ? { ...plain2, notes: [plain2.notes, refusedNote].filter(Boolean).join("\n\n") } : plain2;
24736
- const end2 = waitingForSpec || carryOn || starts2.length ? null : planStageEnd(run);
24748
+ const end2 = waitingForSpec || carryOn || starts2.length ? null : planStageEnd(run2);
24737
24749
  const short2 = end2 && "missing" in end2 ? end2 : null;
24738
- const stalled = (short2 ? shortLine(short2, run.cardId) : void 0) ?? (waitingForSpec ? void 0 : (run.refineRound !== void 0 || next === "incomplete") && stalledLine(run.cardId, next) || void 0);
24750
+ const stalled = (short2 ? shortLine(short2, run2.cardId) : void 0) ?? (waitingForSpec ? void 0 : (run2.refineRound !== void 0 || next === "incomplete") && stalledLine(run2.cardId, next) || void 0);
24739
24751
  const stalledWhy = [
24740
24752
  ...refusedNote ? [{ kind: "specRefused", refusals: refused }] : [],
24741
- ...!stalled ? [] : short2 ? [{ kind: "stageShort", args: { stage: short2.stage, card: String(run.cardId), agents: short2.missing.join(", ") } }] : next === "incomplete" ? [{ kind: "qaUnfinished", args: { card: String(run.cardId) } }] : [{ kind: "refineStalled", args: { card: String(run.cardId) } }]
24753
+ ...!stalled ? [] : short2 ? [{ kind: "stageShort", args: { stage: short2.stage, card: String(run2.cardId), agents: short2.missing.join(", ") } }] : next === "incomplete" ? [{ kind: "qaUnfinished", args: { card: String(run2.cardId) } }] : [{ kind: "refineStalled", args: { card: String(run2.cardId) } }]
24742
24754
  ];
24743
24755
  return {
24744
24756
  runs: [...starts2, ...carryOn ? [carryOn] : [], ...end2 && "ask" in end2 ? [end2.ask] : []],
@@ -24921,21 +24933,21 @@ __export(watch_exports, {
24921
24933
  watchRun: () => watchRun
24922
24934
  });
24923
24935
  import { spawn as spawn3 } from "node:child_process";
24924
- import fs77 from "node:fs";
24936
+ import fs79 from "node:fs";
24925
24937
  async function watchRun(sessionId, resume = startResume) {
24926
24938
  const spec = readSpec(sessionId);
24927
- const run = peekRun(sessionId);
24928
- if (!run || !spec) {
24929
- if (run?.status === "running") await closeRun(sessionId, { status: "interrupted", code: null });
24939
+ const run2 = peekRun(sessionId);
24940
+ if (!run2 || !spec) {
24941
+ if (run2?.status === "running") await closeRun(sessionId, { status: "interrupted", code: null });
24930
24942
  return 1;
24931
24943
  }
24932
- if (run.stopping) {
24944
+ if (run2.stopping) {
24933
24945
  await closeRun(sessionId, { status: "stopped", code: null });
24934
24946
  return 1;
24935
24947
  }
24936
24948
  const stopping = () => peekRun(sessionId)?.status !== "running";
24937
24949
  let releaseIndex = null;
24938
- if (needsIndexLock(run.action)) {
24950
+ if (needsIndexLock(run2.action)) {
24939
24951
  releaseIndex = await acquireIndexLock(stopping);
24940
24952
  if (!releaseIndex) {
24941
24953
  if (!stopping()) await closeRun(sessionId, { status: "interrupted", code: null });
@@ -24954,14 +24966,14 @@ async function watchRun(sessionId, resume = startResume) {
24954
24966
  const claimed = patch(sessionId, (r) => {
24955
24967
  claim = claimCard(r);
24956
24968
  });
24957
- const record = claimed ?? run;
24969
+ const record = claimed ?? run2;
24958
24970
  const sub = record.action === "sub";
24959
24971
  if (claim) await setCardStatus(claim.cardId, claim.status);
24960
- fs77.mkdirSync(SESSIONS_DIR, { recursive: true });
24961
- const logFile = fs77.createWriteStream(record.logPath, { flags: "a" });
24972
+ fs79.mkdirSync(SESSIONS_DIR, { recursive: true });
24973
+ const logFile = fs79.createWriteStream(record.logPath, { flags: "a" });
24962
24974
  logFile.on("error", () => {
24963
24975
  });
24964
- const eventsFile = fs77.createWriteStream(eventsPathOf(sessionId), { flags: "a" });
24976
+ const eventsFile = fs79.createWriteStream(eventsPathOf(sessionId), { flags: "a" });
24965
24977
  eventsFile.on("error", () => {
24966
24978
  });
24967
24979
  const event2 = (e) => eventsFile.write(`${JSON.stringify(e)}
@@ -24982,7 +24994,7 @@ async function watchRun(sessionId, resume = startResume) {
24982
24994
  if (active2.startNote) log.write(`[board] ${active2.startNote}
24983
24995
  `);
24984
24996
  const basePrompt = record.formatRepair ? contractRepairPrompt(requestOf(record), record.formatRepair.errors) : record.resumedFrom ? spec.prompt || resumePrompt(record.deliveryId, record.cardId, record.action) : spec.prompt;
24985
- const prompt = [basePrompt, discardedCardsPrompt(record.discardedCards)].filter(Boolean).join("\n\n");
24997
+ const prompt = inLanguage([basePrompt, discardedCardsPrompt(record.discardedCards)].filter(Boolean).join("\n\n"));
24986
24998
  const before = markBoard();
24987
24999
  const sources = snapshotSpecs();
24988
25000
  const wasBroken = new Set(boardComplaints());
@@ -24995,7 +25007,7 @@ async function watchRun(sessionId, resume = startResume) {
24995
25007
  void refreshCatalog();
24996
25008
  const client = active2.client;
24997
25009
  const restartBase = !client || record.formatRepair ? void 0 : record.resumedFrom ? restartPrompt(requestOf(record), record.deliveryId) : record.continues && !record.continues.fork ? spec.prompt : void 0;
24998
- const restart = restartBase ? [restartBase, discardedCardsPrompt(record.discardedCards)].filter(Boolean).join("\n\n") : void 0;
25010
+ const restart = restartBase ? inLanguage([restartBase, discardedCardsPrompt(record.discardedCards)].filter(Boolean).join("\n\n")) : void 0;
24999
25011
  const stdinPrompt = client ? void 0 : active2.stdinPrompt;
25000
25012
  const stdio = [client || stdinPrompt ? "pipe" : "ignore", "pipe", "pipe"];
25001
25013
  let child;
@@ -25444,11 +25456,11 @@ function tickedNoSetupStep(record) {
25444
25456
  const now = tickedSetupSteps();
25445
25457
  return now !== void 0 && now <= record.setupTicked;
25446
25458
  }
25447
- function settleBoard(run, changed, before) {
25459
+ function settleBoard(run2, changed, before) {
25448
25460
  try {
25449
- const helpers = specRunsAfter(readSpecAsks(run.sessionId));
25450
- const waitingForSpec = helpers.some((req) => req.id === run.cardId);
25451
- return refinementRunsAfter(run, changed, before, waitingForSpec, readSpecRefusals(run.sessionId));
25461
+ const helpers = specRunsAfter(readSpecAsks(run2.sessionId));
25462
+ const waitingForSpec = helpers.some((req) => req.id === run2.cardId);
25463
+ return refinementRunsAfter(run2, changed, before, waitingForSpec, readSpecRefusals(run2.sessionId));
25452
25464
  } catch {
25453
25465
  return null;
25454
25466
  }
@@ -25530,6 +25542,7 @@ var init_watch = __esm({
25530
25542
  init_log();
25531
25543
  init_wire();
25532
25544
  init_prompts();
25545
+ init_language();
25533
25546
  init_resolve();
25534
25547
  init_runner();
25535
25548
  init_retry();
@@ -25549,7 +25562,7 @@ var init_watch = __esm({
25549
25562
  });
25550
25563
 
25551
25564
  // ../cli/src/kanban.ts
25552
- import fs85 from "node:fs";
25565
+ import fs87 from "node:fs";
25553
25566
  import { fileURLToPath as fileURLToPath3 } from "node:url";
25554
25567
 
25555
25568
  // ../cli/src/lib/cli/agent.ts
@@ -25646,11 +25659,11 @@ ${final}` : lines;
25646
25659
  }
25647
25660
  function testConnection(pin) {
25648
25661
  const ask2 = !pin ? {} : runtimeById(pin) ? { pin } : { pin, harness: pin };
25649
- const run = openPlan(planRun(randomUUID7(), REPO_ROOT, void 0, ask2));
25662
+ const run2 = openPlan(planRun(randomUUID7(), REPO_ROOT, void 0, ask2));
25650
25663
  const startedAt = Date.now();
25651
- const [cmd, ...args] = run.argv;
25652
- const client = run.client;
25653
- const stdinPrompt = client ? void 0 : run.stdinPrompt;
25664
+ const [cmd, ...args] = run2.argv;
25665
+ const client = run2.client;
25666
+ const stdinPrompt = client ? void 0 : run2.stdinPrompt;
25654
25667
  const stdio = [client || stdinPrompt ? "pipe" : "ignore", "pipe", "pipe"];
25655
25668
  return new Promise((resolve2) => {
25656
25669
  let events = "";
@@ -25662,16 +25675,16 @@ function testConnection(pin) {
25662
25675
  if (settled) return;
25663
25676
  settled = true;
25664
25677
  stopTimer();
25665
- const output = run.startNote && res.output ? `${run.startNote}
25678
+ const output = run2.startNote && res.output ? `${run2.startNote}
25666
25679
  ${res.output}` : res.output;
25667
- resolve2({ ...res, output, harness: run.harness, ms: Date.now() - startedAt });
25680
+ resolve2({ ...res, output, harness: run2.harness, ms: Date.now() - startedAt });
25668
25681
  };
25669
25682
  const spawnFailed = (e) => {
25670
25683
  if (e?.code === "ENOENT") {
25671
- done2({ ok: false, missing: cmd, install: run.install });
25684
+ done2({ ok: false, missing: cmd, install: run2.install });
25672
25685
  return;
25673
25686
  }
25674
- done2({ ok: false, output: said2(events, run.renderer?.result(), `${stderr}
25687
+ done2({ ok: false, output: said2(events, run2.renderer?.result(), `${stderr}
25675
25688
  ${String(e)}`) });
25676
25689
  };
25677
25690
  const mark = stopMark();
@@ -25683,7 +25696,7 @@ ${String(e)}`) });
25683
25696
  // folder — an agent started there is outside the repo, and codex refuses to run at
25684
25697
  // all ("Not inside a trusted directory").
25685
25698
  cwd: REPO_ROOT,
25686
- env: markEnv(run.env, mark),
25699
+ env: markEnv(run2.env, mark),
25687
25700
  shell: false,
25688
25701
  // Same as a run: a piped stdin makes `claude -p` wait and then warn, which would
25689
25702
  // land in the output as if it were the failure — and it is a pipe, and stays open,
@@ -25705,18 +25718,18 @@ ${String(e)}`) });
25705
25718
  done2({
25706
25719
  ok: false,
25707
25720
  timedOut: true,
25708
- output: said2(events + (run.renderer?.flush() ?? ""), run.renderer?.result(), stderr + errs.flush())
25721
+ output: said2(events + (run2.renderer?.flush() ?? ""), run2.renderer?.result(), stderr + errs.flush())
25709
25722
  });
25710
25723
  }, TIMEOUT_MS);
25711
25724
  if (typeof timer.unref === "function") timer.unref();
25712
25725
  stopTimer = () => clearTimeout(timer);
25713
- const renderer = run.renderer;
25726
+ const renderer = run2.renderer;
25714
25727
  if (renderer) {
25715
25728
  child.stdout.on("data", (d) => {
25716
25729
  events += renderer.push(d.toString());
25717
25730
  });
25718
25731
  }
25719
- const errs = createStderrFilter(run.quietStderr);
25732
+ const errs = createStderrFilter(run2.quietStderr);
25720
25733
  child.stderr.on("data", (d) => {
25721
25734
  stderr += errs.push(d.toString());
25722
25735
  });
@@ -26053,7 +26066,7 @@ async function testAgent(args) {
26053
26066
 
26054
26067
  // ../cli/src/commands/cloud.ts
26055
26068
  import fs71 from "node:fs";
26056
- import path67 from "node:path";
26069
+ import path68 from "node:path";
26057
26070
 
26058
26071
  // ../cli/src/lib/cloud/avatar.ts
26059
26072
  init_session();
@@ -26077,9 +26090,9 @@ async function download(url) {
26077
26090
  if (!response.ok) return null;
26078
26091
  const type = response.headers.get("content-type")?.split(";")[0]?.trim() ?? "";
26079
26092
  if (!type.startsWith("image/")) return null;
26080
- const bytes = Buffer.from(await response.arrayBuffer());
26081
- if (bytes.byteLength === 0 || bytes.byteLength > MAX_BYTES2) return null;
26082
- return `data:${type};base64,${bytes.toString("base64")}`;
26093
+ const bytes3 = Buffer.from(await response.arrayBuffer());
26094
+ if (bytes3.byteLength === 0 || bytes3.byteLength > MAX_BYTES2) return null;
26095
+ return `data:${type};base64,${bytes3.toString("base64")}`;
26083
26096
  } catch {
26084
26097
  return null;
26085
26098
  }
@@ -26102,10 +26115,10 @@ init_home();
26102
26115
  init_config2();
26103
26116
  init_session();
26104
26117
  import fs70 from "node:fs";
26105
- import path66 from "node:path";
26118
+ import path67 from "node:path";
26106
26119
  var FRESH_MS = 10 * 6e4;
26107
26120
  var GRACE_MS = 7 * 24 * 60 * 6e4;
26108
- var heldFile = () => path66.join(machineHome(), "pro.json");
26121
+ var heldFile = () => path67.join(machineHome(), "pro.json");
26109
26122
  function forgetPro() {
26110
26123
  fs70.rmSync(heldFile(), { force: true });
26111
26124
  }
@@ -26126,18 +26139,18 @@ async function readCloudAccount() {
26126
26139
  configured: cloudConfigured()
26127
26140
  };
26128
26141
  if (!blank.configured) return { ...blank, message: NOT_CONFIGURED };
26129
- const token2 = await accessToken();
26130
- if (!token2.ok) {
26131
- if (token2.reason === "signed-out") return blank;
26132
- if (token2.reason === "unreachable") {
26133
- return { ...blank, ...held3(), state: "signed-in", error: token2.error };
26142
+ const token3 = await accessToken();
26143
+ if (!token3.ok) {
26144
+ if (token3.reason === "signed-out") return blank;
26145
+ if (token3.reason === "unreachable") {
26146
+ return { ...blank, ...held3(), state: "signed-in", error: token3.error };
26134
26147
  }
26135
26148
  return { ...blank, ...held3(), state: "expired" };
26136
26149
  }
26137
26150
  let response;
26138
26151
  try {
26139
26152
  response = await fetch(`${cloudEndpoints().api}/v1/session`, {
26140
- headers: { authorization: `Bearer ${token2.token}` }
26153
+ headers: { authorization: `Bearer ${token3.token}` }
26141
26154
  });
26142
26155
  } catch (e) {
26143
26156
  return {
@@ -26280,7 +26293,7 @@ async function cloudImage(opts, program2) {
26280
26293
  const prompt = opts.prompt.trim();
26281
26294
  if (!prompt) usage("Missing the prompt.", line2);
26282
26295
  const references = opts.refs.map((file) => {
26283
- const type = REF_TYPES[path67.extname(file).toLowerCase()];
26296
+ const type = REF_TYPES[path68.extname(file).toLowerCase()];
26284
26297
  if (!type) usage(`--ref ${file}: use a PNG, JPEG or WebP file.`, line2);
26285
26298
  try {
26286
26299
  return `data:${type};base64,${fs71.readFileSync(file).toString("base64")}`;
@@ -26361,13 +26374,13 @@ function refuse(m, fallback) {
26361
26374
  die([m.zh, m.en, fallback.zh, fallback.en].join("\n"), { kind: "cloud-refused", bare: true });
26362
26375
  }
26363
26376
  async function generate(g) {
26364
- const token2 = await accessToken();
26365
- if (!token2.ok) refuse(SAID[token2.reason], g.fallback);
26377
+ const token3 = await accessToken();
26378
+ if (!token3.ok) refuse(SAID[token3.reason], g.fallback);
26366
26379
  let res;
26367
26380
  try {
26368
26381
  res = await fetch(`${cloudEndpoints().api}${g.endpoint}`, {
26369
26382
  method: "POST",
26370
- headers: { authorization: `Bearer ${token2.token}`, "content-type": "application/json" },
26383
+ headers: { authorization: `Bearer ${token3.token}`, "content-type": "application/json" },
26371
26384
  body: JSON.stringify(g.body)
26372
26385
  });
26373
26386
  } catch {
@@ -26383,20 +26396,602 @@ async function generate(g) {
26383
26396
  if (res.status === 400) usage(error?.message ?? "The request was refused.", g.usage);
26384
26397
  refuse(g.failed, g.fallback);
26385
26398
  }
26386
- fs71.mkdirSync(path67.dirname(path67.resolve(g.out)), { recursive: true });
26399
+ fs71.mkdirSync(path68.dirname(path68.resolve(g.out)), { recursive: true });
26387
26400
  fs71.writeFileSync(g.out, Buffer.from(await res.arrayBuffer()));
26388
26401
  say(`${g.out} (${g.label(res)})`);
26389
26402
  return { out: g.out };
26390
26403
  }
26391
26404
 
26405
+ // ../cli/src/commands/cloud-import.ts
26406
+ import crypto3 from "node:crypto";
26407
+ import fs73 from "node:fs";
26408
+ import path70 from "node:path";
26409
+
26410
+ // ../cloud/src/board-files.ts
26411
+ var ROOTS = ["todo/", ".archive/", "memory/", "workflows/", "triage/", "assets/", "rules/"];
26412
+ var SETTINGS = ["modules.md", "config.md"];
26413
+ var isSettingsPath = (path83) => SETTINGS.includes(path83) || /^rules\/(?:workflows\/)?[^/]+\.md$/.test(path83);
26414
+ var BOARD_FILE_LIMIT = 256 * 1024;
26415
+ function isBoardPath(path83) {
26416
+ if (!path83 || path83.length > 500 || path83.startsWith("/") || path83.includes("\\") || path83.includes("\0")) return false;
26417
+ if (path83.split("/").some((part) => !part || part === "." || part === "..")) return false;
26418
+ if (path83 === "todo/README.md" || path83.split("/").includes(".sync")) return false;
26419
+ if (path83.startsWith("workflows/")) return true;
26420
+ if (SETTINGS.includes(path83)) return true;
26421
+ if (path83.startsWith("rules/")) return isSettingsPath(path83);
26422
+ if (path83.startsWith("assets/")) return path83.endsWith(".json");
26423
+ return ROOTS.some((root) => path83.startsWith(root)) && path83.endsWith(".md");
26424
+ }
26425
+ var workflowFolder = (id) => id.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
26426
+
26427
+ // ../cloud/src/v1/workflow-files.ts
26428
+ init_workflow_def();
26429
+ init_parse();
26430
+ var WORKFLOW_FILE2 = "WORKFLOW.md";
26431
+ var MCP_FILE = "mcp.json";
26432
+ var KB = 1024;
26433
+ var FILE_LIMITS = { file: 256 * KB, total: 2 * KB * KB, count: 500, path: 512 };
26434
+ var LAND_ROLES2 = ["builder"];
26435
+ var SEGMENT2 = /^[\w.-]+$/;
26436
+ var bytes = (text5) => new TextEncoder().encode(text5).length;
26437
+ function folderPath(file, top) {
26438
+ const parts = file.split("/");
26439
+ if (parts.length < 3 || parts[0] !== top || !AGENT_NAME.test(parts[1])) return null;
26440
+ if (parts.slice(2).some((p) => !SEGMENT2.test(p) || p === "." || p === "..")) return null;
26441
+ return [parts[1], parts.slice(2).join("/")];
26442
+ }
26443
+ function mcpProblem(text5) {
26444
+ let read6;
26445
+ try {
26446
+ read6 = JSON.parse(text5);
26447
+ } catch {
26448
+ return "is not JSON";
26449
+ }
26450
+ const servers = read6?.mcpServers;
26451
+ if (!servers || typeof servers !== "object" || Array.isArray(servers)) return "must hold `mcpServers`, an object of name \u2192 server";
26452
+ for (const [name, server] of Object.entries(servers)) {
26453
+ const { command, args, ...rest } = server ?? {};
26454
+ if (!AGENT_NAME.test(name)) return `names a server \`${name}\`; use lowercase letters, digits and dashes`;
26455
+ if (typeof command !== "string" || !command) return `server \`${name}\` needs a \`command\``;
26456
+ if (args !== void 0 && !(Array.isArray(args) && args.every((a) => typeof a === "string"))) return `server \`${name}\`: \`args\` must be a list of strings`;
26457
+ if (Object.keys(rest).length) return `server \`${name}\` takes only \`command\` and \`args\``;
26458
+ }
26459
+ return null;
26460
+ }
26461
+ function checkWorkflowFiles(value, official = false) {
26462
+ const fail = (file, reason, tooLarge = false) => ({ ok: false, file, reason, ...tooLarge ? { tooLarge } : {} });
26463
+ if (!value || typeof value !== "object" || Array.isArray(value)) return fail("files", "must be an object of path \u2192 text");
26464
+ const entries = Object.entries(value);
26465
+ if (entries.length > FILE_LIMITS.count) return fail("files", `holds at most ${FILE_LIMITS.count} files`, true);
26466
+ let total = 0;
26467
+ const folders2 = /* @__PURE__ */ new Map();
26468
+ const skills = /* @__PURE__ */ new Set();
26469
+ for (const [file, text5] of entries) {
26470
+ if (typeof text5 !== "string" || text5.includes("\0")) return fail(file, "is not a text file");
26471
+ if (file.length > FILE_LIMITS.path) return fail(file, `the path is longer than ${FILE_LIMITS.path} characters`);
26472
+ const size = bytes(text5);
26473
+ if (size > FILE_LIMITS.file) return fail(file, `is larger than ${FILE_LIMITS.file / KB} KB`, true);
26474
+ total += size;
26475
+ if (total > FILE_LIMITS.total) return fail("files", `are larger than ${FILE_LIMITS.total / KB / KB} MB together`, true);
26476
+ if (file === WORKFLOW_FILE2) continue;
26477
+ if (official && file === MCP_FILE) {
26478
+ const problem = mcpProblem(text5);
26479
+ if (problem) return fail(file, problem);
26480
+ continue;
26481
+ }
26482
+ if (official && file.startsWith("skills/")) {
26483
+ if (!folderPath(file, "skills")) return fail(file, "is not inside skills/<name>/");
26484
+ skills.add(file.split("/")[1]);
26485
+ continue;
26486
+ }
26487
+ const at = folderPath(file, "agents");
26488
+ if (!at) return fail(file, `is neither ${WORKFLOW_FILE2} nor inside agents/<name>/`);
26489
+ if (!folders2.has(at[0])) folders2.set(at[0], /* @__PURE__ */ new Map());
26490
+ folders2.get(at[0]).set(at[1], text5);
26491
+ }
26492
+ for (const name of skills) {
26493
+ if (value[`skills/${name}/SKILL.md`] === void 0) return fail(`skills/${name}/SKILL.md`, "is missing");
26494
+ }
26495
+ const source = value[WORKFLOW_FILE2];
26496
+ if (source === void 0) return fail(WORKFLOW_FILE2, "is missing");
26497
+ const read6 = parseWorkflowFile("workflow", source, WORKFLOW_FILE2);
26498
+ if ("problem" in read6) return fail(WORKFLOW_FILE2, read6.problem.replace(`${WORKFLOW_FILE2}: `, ""));
26499
+ const def = read6.def;
26500
+ const agents = /* @__PURE__ */ new Map();
26501
+ for (const [name, own] of folders2) {
26502
+ const from = `agents/${name}/AGENT.md`;
26503
+ const text5 = own.get("AGENT.md");
26504
+ if (text5 === void 0) return fail(from, "is missing");
26505
+ const parsed = parseSpecAgent(text5, from, (p) => own.get(p) ?? null, false, () => [...own.keys()].filter((p) => p !== "AGENT.md"));
26506
+ if ("problem" in parsed) return fail(from, parsed.problem.replace(`${from}: `, ""));
26507
+ if (parsed.agent.name !== name) return fail(from, `calls itself \`${parsed.agent.name}\`; it must match its folder`);
26508
+ agents.set(name, parsed.agent);
26509
+ }
26510
+ const named2 = [
26511
+ ...def.previews.map((h) => [h.agent, "it previews with"]),
26512
+ ...def.land.filter((h) => !LAND_ROLES2.includes(h.agent)).map((h) => [h.agent, "it lands with"]),
26513
+ ...def.scheduled.map((s) => [s.agent, "it schedules"])
26514
+ ];
26515
+ for (const [name, why] of named2) {
26516
+ if (!agents.has(name)) return fail(WORKFLOW_FILE2, `${why} \`${name}\`, which has no agents/${name}/AGENT.md`);
26517
+ }
26518
+ return { ok: true, def, files: value };
26519
+ }
26520
+
26521
+ // ../cli/src/commands/cloud-import.ts
26522
+ init_bundled();
26523
+
26524
+ // ../cli/src/lib/agents/shared-memory.ts
26525
+ init_bundled();
26526
+ init_parse();
26527
+ import fs72 from "node:fs";
26528
+ import path69 from "node:path";
26529
+ function sharedMemory(board2) {
26530
+ const declared = /* @__PURE__ */ new Map();
26531
+ const take = (folder, text5, builtIn) => {
26532
+ if (text5 === null || declared.has(folder)) return;
26533
+ const read6 = parseSpecAgent(text5, folder, () => null, builtIn);
26534
+ if ("agent" in read6 && read6.agent.name === folder) declared.set(folder, read6.agent.memoryFiles.workspace);
26535
+ };
26536
+ for (const [key, text5] of Object.entries(BUNDLED_AGENT_FILES)) {
26537
+ const at = /^([^/]+)\/AGENT\.md$/.exec(key);
26538
+ if (at) take(at[1], text5, true);
26539
+ }
26540
+ const root = path69.join(board2, "agents");
26541
+ let folders2 = [];
26542
+ try {
26543
+ folders2 = fs72.readdirSync(root, { withFileTypes: true }).filter((e) => e.isDirectory() && !e.name.startsWith(".")).map((e) => e.name);
26544
+ } catch {
26545
+ }
26546
+ for (const folder of folders2.sort()) {
26547
+ let text5 = null;
26548
+ try {
26549
+ text5 = fs72.readFileSync(path69.join(root, folder, "AGENT.md"), "utf8");
26550
+ } catch {
26551
+ }
26552
+ take(folder, text5, false);
26553
+ }
26554
+ const matches = [...declared].flatMap(([agent, paths]) => paths.map((p) => matcher(`agents/${agent}/${p}`)));
26555
+ return (name) => matches.some((m) => m(name));
26556
+ }
26557
+ function matcher(entry) {
26558
+ if (entry.endsWith("/")) return (name) => name.startsWith(entry);
26559
+ const re = new RegExp(`^${entry.split("*").map((part) => part.replace(/[.+?^${}()|[\]\\]/g, "\\$&")).join("[^/]*")}$`);
26560
+ return (name) => re.test(name);
26561
+ }
26562
+
26563
+ // ../cli/src/commands/cloud-import.ts
26564
+ init_workflows();
26565
+ init_cards();
26566
+ init_config2();
26567
+ init_tasks();
26568
+ init_session();
26569
+ init_frontmatter();
26570
+ init_io();
26571
+ init_paths();
26572
+ init_questions();
26573
+ var BATCH = 50;
26574
+ var TITLE_LIMIT = 200;
26575
+ var APP_URL = "https://app.wildcrane.ai";
26576
+ var BOUNDARY = "<!-- agent -->";
26577
+ var Refused = class extends Error {
26578
+ constructor(message, code) {
26579
+ super(message);
26580
+ this.code = code;
26581
+ }
26582
+ code;
26583
+ };
26584
+ var token2 = "";
26585
+ async function api(method, route2, body, raw) {
26586
+ let res;
26587
+ try {
26588
+ res = await fetch(`${cloudEndpoints().api}${route2}`, {
26589
+ method,
26590
+ headers: {
26591
+ authorization: `Bearer ${token2}`,
26592
+ ...raw ? { "content-type": raw.type } : body !== void 0 ? { "content-type": "application/json" } : {}
26593
+ },
26594
+ ...raw ? { body: raw.bytes } : body !== void 0 ? { body: JSON.stringify(body) } : {},
26595
+ signal: AbortSignal.timeout(12e4)
26596
+ });
26597
+ } catch (e) {
26598
+ throw new Refused(`Cloud could not be reached: ${e instanceof Error ? e.message : String(e)}`);
26599
+ }
26600
+ const parsed = await res.json().catch(() => ({}));
26601
+ if (!res.ok) throw new Refused(parsed.error?.message ?? `Cloud answered ${res.status}.`, parsed.error?.code);
26602
+ return parsed;
26603
+ }
26604
+ async function all(route2) {
26605
+ const out = [];
26606
+ let after2 = null;
26607
+ do {
26608
+ const sep = route2.includes("?") ? "&" : "?";
26609
+ const page = await api("GET", `${route2}${sep}limit=100${after2 ? `&after=${encodeURIComponent(after2)}` : ""}`);
26610
+ out.push(...page.data);
26611
+ after2 = page.next;
26612
+ } while (after2);
26613
+ return out;
26614
+ }
26615
+ async function findProject(asked) {
26616
+ if (/^prj_/.test(asked)) return api("GET", `/v1/projects/${encodeURIComponent(asked)}`);
26617
+ const workspaces = await all("/v1/workspaces");
26618
+ for (const ws of workspaces) {
26619
+ const found2 = (await all(`/v1/projects?workspace=${encodeURIComponent(ws.id)}`)).find((p) => p.prefix.toLowerCase() === asked.toLowerCase());
26620
+ if (found2) return found2;
26621
+ }
26622
+ throw new Refused(`No project of yours has the id or prefix "${asked}".`, "not_found");
26623
+ }
26624
+ var read = (file) => fs73.readFileSync(file, "utf8");
26625
+ var bytes2 = (text5) => Buffer.byteLength(text5, "utf8");
26626
+ function files(dir) {
26627
+ if (!fs73.existsSync(dir)) return [];
26628
+ const out = [];
26629
+ for (const entry of fs73.readdirSync(dir, { withFileTypes: true })) {
26630
+ if (entry.name.startsWith(".")) continue;
26631
+ const full = path70.join(dir, entry.name);
26632
+ if (entry.isDirectory()) out.push(...files(full));
26633
+ else if (entry.isFile()) out.push(full);
26634
+ }
26635
+ return out;
26636
+ }
26637
+ var posix2 = (p) => p.split(path70.sep).join("/");
26638
+ function openCards() {
26639
+ const out = [];
26640
+ for (const file of walkMd(TODO)) {
26641
+ const rel2 = posix2(path70.relative(TODO, file));
26642
+ if (rel2 === "README.md") continue;
26643
+ const parts = rel2.split("/");
26644
+ const text5 = read(file);
26645
+ const meta = parseFrontmatter(text5).meta;
26646
+ if (!meta) continue;
26647
+ const name = parts[parts.length - 1];
26648
+ const root = name === "root.md" && parts.length === 2;
26649
+ const id = root ? idPrefix(parts[0]) : idPrefix(name);
26650
+ if (id === null) continue;
26651
+ const group = !root && parts.length === 2 ? idPrefix(parts[0]) : null;
26652
+ const slug2 = (root ? parts[0] : name.replace(/\.md$/, "")).replace(/^\d+-?/, "");
26653
+ out.push({ id, rel: rel2, text: text5, meta, group, root, slug: slug2 });
26654
+ }
26655
+ return out.sort((a, b) => a.id - b.id);
26656
+ }
26657
+ function bodyProblems(text5) {
26658
+ const out = [];
26659
+ if (bytes2(text5) > BOARD_FILE_LIMIT) out.push({ zh: "\u8D85\u8FC7 256 KB", en: "over 256 KB" });
26660
+ let fence = null;
26661
+ let boundaries = 0;
26662
+ for (const line2 of text5.split("\n")) {
26663
+ const mark = /^ {0,3}(`{3,}|~{3,})(.*)$/.exec(line2);
26664
+ const run2 = mark?.[1] ?? "";
26665
+ if (fence) {
26666
+ if (run2[0] === fence.char && run2.length >= fence.size && !mark?.[2]?.trim()) fence = null;
26667
+ } else if (run2) fence = { char: run2[0], size: run2.length };
26668
+ else if (line2.trim() === BOUNDARY) boundaries++;
26669
+ }
26670
+ if (fence) out.push({ zh: "\u4EE3\u7801\u5757\u672A\u95ED\u5408", en: "a code fence is never closed" });
26671
+ if (boundaries > 1) out.push({ zh: `\`${BOUNDARY}\` \u51FA\u73B0\u591A\u4E8E\u4E00\u6B21`, en: `holds \`${BOUNDARY}\` more than once` });
26672
+ return out;
26673
+ }
26674
+ function packWorkflow(flow) {
26675
+ const own = path70.join(WORKFLOWS, flow.id);
26676
+ const out = {};
26677
+ for (const file of files(own)) out[posix2(path70.relative(own, file))] = read(file);
26678
+ const named2 = [...flow.previews, ...flow.land, ...flow.scheduled].map((h) => h.agent).filter((a) => !LAND_ROLES.includes(a));
26679
+ for (const agent of new Set(named2)) {
26680
+ const dir = path70.join(AGENTS, agent);
26681
+ if (fs73.existsSync(path70.join(dir, "AGENT.md"))) {
26682
+ for (const file of files(dir)) out[`agents/${agent}/${posix2(path70.relative(dir, file))}`] = read(file);
26683
+ continue;
26684
+ }
26685
+ for (const [key, text5] of Object.entries(BUNDLED_AGENT_FILES)) {
26686
+ if (key.startsWith(`${agent}/`)) out[`agents/${key}`] = text5;
26687
+ }
26688
+ }
26689
+ return out;
26690
+ }
26691
+ var builtinId = (id) => `wf_builtin_${id.replace(/-/g, "_")}`;
26692
+ function rewriteRefs(text5, numbers) {
26693
+ const swap = (s) => s.replace(/(^|[^\w#&/])#(\d+)\b/g, (_, lead, n) => {
26694
+ const to = numbers.get(Number(n));
26695
+ return to === void 0 ? `${lead}old#${n}` : `${lead}#${to}`;
26696
+ });
26697
+ let fence = null;
26698
+ return text5.split("\n").map((line2) => {
26699
+ const mark = /^ {0,3}(`{3,}|~{3,})(.*)$/.exec(line2);
26700
+ const run2 = mark?.[1] ?? "";
26701
+ if (fence) {
26702
+ if (run2[0] === fence.char && run2.length >= fence.size && !mark?.[2]?.trim()) fence = null;
26703
+ return line2;
26704
+ }
26705
+ if (run2) {
26706
+ fence = { char: run2[0], size: run2.length };
26707
+ return line2;
26708
+ }
26709
+ return line2.split(/(`+[^`]*`+)/).map((part, i) => i % 2 ? part : swap(part)).join("");
26710
+ }).join("\n");
26711
+ }
26712
+ function cardForCloud(text5, numbers, workflow) {
26713
+ const end2 = /^---\r?\n[\s\S]*?\r?\n---(?:\r?\n|$)/.exec(text5)?.[0].length ?? 0;
26714
+ const front = end2 ? text5.slice(0, end2) : "";
26715
+ const lines = rewriteRefs(front, numbers).split("\n").map((line2) => {
26716
+ const list = /^(blocked_by|related):\s*\[(.*)\]\s*$/.exec(line2);
26717
+ if (list) {
26718
+ const kept = list[2].split(",").map((s) => numbers.get(Number(s.trim()))).filter((n) => n !== void 0);
26719
+ return `${list[1]}: [${kept.join(", ")}]`;
26720
+ }
26721
+ if (/^status:\s*implementing\s*$/.test(line2)) return "status: ready";
26722
+ if (workflow && /^workflow:/.test(line2)) return `workflow: ${workflow}`;
26723
+ return line2;
26724
+ });
26725
+ return lines.join("\n") + rewriteRefs(text5.slice(end2), numbers);
26726
+ }
26727
+ function reviewOf2(meta) {
26728
+ const questions = meta.questions ?? [];
26729
+ let open3 = false;
26730
+ for (const [i, q] of questions.entries()) {
26731
+ const { tag, text: text5 } = parseQuestion(q.text);
26732
+ if (tag !== "user" || !openOf([q]).length) continue;
26733
+ open3 = true;
26734
+ if (q.options?.length) return { question: text5, options: q.options.slice(0, 8), position: i + 1 };
26735
+ }
26736
+ return open3 || meta.status === "ready" || meta.status === "implementing" ? true : null;
26737
+ }
26738
+ function draftsOf(text5) {
26739
+ const out = /* @__PURE__ */ new Map();
26740
+ for (const m of text5.matchAll(/\]\(\s*<?([^)\s>]+)>?(?:\s+"[^"]*")?\s*\)|\bsrc=["']([^"']+)["']/g)) {
26741
+ const name = m[1] ?? m[2];
26742
+ const at = /^\.(assets|mockups)\/(.+)$/.exec(name);
26743
+ if (!at) continue;
26744
+ const base = at[1] === "assets" ? ASSETS : MOCKUPS;
26745
+ const file = path70.resolve(base, at[2]);
26746
+ if (file.startsWith(base + path70.sep) && fs73.statSync(file, { throwIfNoEntry: false })?.isFile()) out.set(name, file);
26747
+ }
26748
+ return [...out].map(([name, file]) => ({ name, file }));
26749
+ }
26750
+ var TYPES = {
26751
+ ".png": "image/png",
26752
+ ".jpg": "image/jpeg",
26753
+ ".jpeg": "image/jpeg",
26754
+ ".gif": "image/gif",
26755
+ ".webp": "image/webp",
26756
+ ".svg": "image/svg+xml",
26757
+ ".mp4": "video/mp4",
26758
+ ".webm": "video/webm",
26759
+ ".mp3": "audio/mpeg",
26760
+ ".pdf": "application/pdf",
26761
+ ".html": "text/html",
26762
+ ".md": "text/markdown",
26763
+ ".mov": "video/quicktime",
26764
+ ".wav": "audio/wav",
26765
+ ".json": "application/json"
26766
+ };
26767
+ function kindOf(ext) {
26768
+ if (ext === ".html") return "html";
26769
+ if (ext === ".md" || ext === ".mdx") return "markdown";
26770
+ const type = TYPES[ext] ?? "";
26771
+ if (type.startsWith("image/")) return "image";
26772
+ return type.startsWith("video/") || type.startsWith("audio/") ? "video" : "asset";
26773
+ }
26774
+ async function uploadDrafts(task, drafts) {
26775
+ const card = await api("GET", `/v1/tasks/${task}/card`);
26776
+ if (Object.keys(card.assets ?? {}).length) return 0;
26777
+ const assets = {};
26778
+ for (const { name, file } of drafts) {
26779
+ if (!card.body.includes(name)) continue;
26780
+ const ext = path70.extname(file).toLowerCase();
26781
+ const type = TYPES[ext] ?? "application/octet-stream";
26782
+ const data = fs73.readFileSync(file);
26783
+ const artifact = await api("POST", `/v1/tasks/${task}/artifacts`, { type: kindOf(ext), name: name.slice(0, 200) });
26784
+ const upload = await api("POST", `/v1/artifacts/${artifact.id}/uploads`, { content_type: type, size: Math.max(data.length, 1) });
26785
+ await api("PUT", `/v1/uploads/${upload.id}`, void 0, { bytes: data, type });
26786
+ const version = await api("POST", `/v1/artifacts/${artifact.id}/versions`, { upload: upload.id });
26787
+ assets[name] = { artifact: artifact.id, version: version.version };
26788
+ }
26789
+ if (!Object.keys(assets).length) return 0;
26790
+ await api("PUT", `/v1/tasks/${task}/card`, { body: card.body, base_version: card.version, assets });
26791
+ return Object.keys(assets).length;
26792
+ }
26793
+ function stop(lines) {
26794
+ die(lines.join("\n"), { kind: "cloud-refused", bare: true });
26795
+ }
26796
+ async function cloudImport(opts, program2) {
26797
+ if (!opts.project) {
26798
+ die(`Missing --project.
26799
+ usage: ${program2} cloud import --project <id or prefix> [--dry-run]`, { kind: "bad-args", bare: true, exitCode: 2 });
26800
+ }
26801
+ const held4 = await accessToken();
26802
+ if (!held4.ok) {
26803
+ stop(held4.reason === "unreachable" ? ["\u65E0\u6CD5\u8FDE\u63A5 WildCrane Cloud\u3002\u8BF7\u68C0\u67E5\u7F51\u7EDC\u540E\u91CD\u8BD5\u3002", "Could not reach WildCrane Cloud. Check your connection and try again."] : [
26804
+ "\u672A\u767B\u5F55 WildCrane Cloud\u3002\u8BF7\u5728 WildCrane \u5E94\u7528\u7684\u201C\u914D\u7F6E \u2192 Cloud\u201D\u4E2D\u767B\u5F55\u540E\u91CD\u8BD5\u3002",
26805
+ "Not signed in to WildCrane Cloud. Sign in from Configuration \u2192 Cloud in the WildCrane app, then try again."
26806
+ ]);
26807
+ }
26808
+ token2 = held4.token;
26809
+ try {
26810
+ return await run(opts.project, !!opts.dryRun);
26811
+ } catch (e) {
26812
+ if (!(e instanceof Refused)) throw e;
26813
+ stop([
26814
+ "\u5BFC\u5165\u5DF2\u505C\u6B62\uFF0CCloud \u62D2\u7EDD\u4E86\u8BF7\u6C42\uFF1A",
26815
+ "The import stopped; Cloud refused it:",
26816
+ ` ${e.message}`,
26817
+ "\u4FEE\u6B63\u540E\u91CD\u65B0\u8FD0\u884C\uFF0C\u5DF2\u5BFC\u5165\u7684\u5185\u5BB9\u4E0D\u4F1A\u91CD\u590D\u3002",
26818
+ "Fix it and run again; what was imported is not imported twice."
26819
+ ]);
26820
+ }
26821
+ }
26822
+ async function run(asked, dryRun) {
26823
+ const project = await findProject(asked);
26824
+ const cloudFlows = await all(`/v1/workflows?workspace=${encodeURIComponent(project.workspace)}`);
26825
+ const board2 = crypto3.createHash("sha256").update(fs73.realpathSync(KANBAN)).digest("hex").slice(0, 16);
26826
+ const cards = openCards();
26827
+ const problems = [];
26828
+ const where = (file) => posix2(path70.relative(KANBAN, file));
26829
+ const own = workflows().filter((w) => !w.builtIn);
26830
+ const packed = /* @__PURE__ */ new Map();
26831
+ for (const flow of own) {
26832
+ const files2 = packWorkflow(flow);
26833
+ const checked = checkWorkflowFiles(files2);
26834
+ if (!checked.ok) problems.push({ file: `workflows/${flow.id}`, reason: { zh: `${checked.file} ${checked.reason}`, en: `${checked.file} ${checked.reason}` } });
26835
+ else packed.set(flow.id, files2);
26836
+ }
26837
+ for (const card of cards) {
26838
+ const file = `todo/${card.rel}`;
26839
+ for (const reason of bodyProblems(card.text)) problems.push({ file, reason });
26840
+ if (!card.meta.title.trim()) problems.push({ file, reason: { zh: "\u6CA1\u6709\u6807\u9898", en: "has no title" } });
26841
+ if (bytes2(card.meta.title.trim()) > TITLE_LIMIT) problems.push({ file, reason: { zh: `\u6807\u9898\u8D85\u8FC7 ${TITLE_LIMIT} \u5B57\u8282`, en: `the title is over ${TITLE_LIMIT} bytes` } });
26842
+ const wf = card.meta.workflow || "coding";
26843
+ if (isBuiltinWorkflow(wf)) {
26844
+ if (!cloudFlows.some((w) => w.id === builtinId(wf))) {
26845
+ problems.push({ file, reason: { zh: `workflow \`${wf}\` \u672A\u5728\u8BE5 workspace \u5B89\u88C5\uFF0C\u8BF7\u5148\u5728 Cloud \u7684 Workflows \u9875\u5B89\u88C5`, en: `workflow \`${wf}\` is not installed in this workspace; install it from Workflows in Cloud first` } });
26846
+ }
26847
+ } else if (!workflowById(wf)) {
26848
+ problems.push({ file, reason: { zh: `\u672A\u77E5\u7684 workflow \`${wf}\``, en: `unknown workflow \`${wf}\`` } });
26849
+ }
26850
+ }
26851
+ const shared = sharedMemory(KANBAN);
26852
+ const root = `projects/${project.id}/`;
26853
+ const boardFiles = [];
26854
+ for (const file of [...files(MEMORY), ...files(RULES), CONFIG, MODULES_MD]) {
26855
+ if (!fs73.existsSync(file)) continue;
26856
+ const rel2 = where(file);
26857
+ if (!isBoardPath(rel2)) continue;
26858
+ const content = read(file);
26859
+ if (bytes2(content) > BOARD_FILE_LIMIT) {
26860
+ problems.push({ file: rel2, reason: { zh: "\u8D85\u8FC7 256 KB", en: "over 256 KB" } });
26861
+ continue;
26862
+ }
26863
+ const isShared = rel2.startsWith("memory/") && shared(rel2.slice("memory/".length));
26864
+ boardFiles.push({ local: rel2, path: isShared ? rel2 : root + rel2, content });
26865
+ }
26866
+ const listed2 = await all(
26867
+ `/v1/tasks?project=${project.id}&workspace=${encodeURIComponent(project.workspace)}`
26868
+ );
26869
+ if (listed2.some((t) => t.source_context?.import?.board !== board2)) {
26870
+ problems.push({ file: `${project.name} (${project.prefix})`, reason: { zh: "\u8BE5\u9879\u76EE\u5DF2\u6709\u81EA\u5DF1\u7684\u4EFB\u52A1\uFF0C\u8BF7\u5BFC\u5165\u4E00\u4E2A\u7A7A\u9879\u76EE", en: "this project already has tasks of its own; import into an empty project" } });
26871
+ }
26872
+ const left = leftLocal(own);
26873
+ if (problems.length) {
26874
+ stop([
26875
+ "\u5BFC\u5165\u524D\u68C0\u67E5\u53D1\u73B0\u95EE\u9898\uFF0C\u4EC0\u4E48\u90FD\u6CA1\u6709\u5199\u5165\uFF1A",
26876
+ "The check before importing found problems; nothing was written:",
26877
+ ...problems.map((p) => ` ${p.file}: ${p.reason.zh} / ${p.reason.en}`)
26878
+ ]);
26879
+ }
26880
+ const reviews = cards.filter((c) => reviewOf2(c.meta));
26881
+ if (dryRun) {
26882
+ const wouldShare = boardFiles.filter((f) => !f.path.startsWith(root)).length;
26883
+ say(`\u9884\u68C0\u901A\u8FC7 \xB7 Check passed \u2014 ${project.name} (${project.prefix})`);
26884
+ say(` \u5361\u7247 Cards: ${cards.length}\uFF08\u5F85\u5BA1 on review: ${reviews.length}\uFF09`);
26885
+ say(` \u81EA\u5EFA workflow Own workflows: ${own.length}`);
26886
+ say(` \u9879\u76EE\u6587\u4EF6 Project files: ${boardFiles.length - wouldShare} \xB7 workspace \u8BB0\u5FC6 Workspace memory: ${wouldShare}`);
26887
+ cards.forEach((c, i) => say(` #${c.id} \u2192 ${project.prefix}-${i + 1} ${c.meta.title}${reviewOf2(c.meta) ? " [\u5F85\u5BA1 review]" : ""}`));
26888
+ sayLeft(left);
26889
+ return { dryRun: true, cards: cards.length, reviews: reviews.length, workflows: own.length, files: boardFiles.length, left };
26890
+ }
26891
+ const cloudOf = /* @__PURE__ */ new Map();
26892
+ for (const flow of own) {
26893
+ const found2 = cloudFlows.find((w) => !w.builtin && w.name === flow.name);
26894
+ const id = found2?.id ?? (await api("POST", "/v1/workflows", { files: packed.get(flow.id), workspace: project.workspace })).id;
26895
+ cloudOf.set(flow.id, id);
26896
+ }
26897
+ const { next } = await api("POST", `/v1/projects/${project.id}/import`, { board: board2, cards: [] });
26898
+ const numbers = /* @__PURE__ */ new Map();
26899
+ for (const t of listed2) {
26900
+ const at = t.source_context?.import;
26901
+ if (at?.board === board2 && typeof at.number === "number") numbers.set(at.number, numberOf(t.key));
26902
+ }
26903
+ let n = next;
26904
+ for (const c of cards) if (!numbers.has(c.id)) numbers.set(c.id, n++);
26905
+ const ruleFile2 = (rel2) => {
26906
+ const at = /^rules\/workflows\/([^/]+)\.md$/.exec(rel2);
26907
+ const id = at && cloudOf.get(at[1]);
26908
+ return id ? `rules/workflows/${workflowFolder(id)}.md` : rel2;
26909
+ };
26910
+ const sent = boardFiles.map((f) => ({ path: f.path.startsWith(root) ? root + ruleFile2(f.local) : f.path, content: f.content }));
26911
+ const pathOf = (c) => {
26912
+ const at = numbers.get(c.id);
26913
+ if (c.root) return `todo/${at}-${c.slug || "group"}/root.md`;
26914
+ const group = c.group === null ? null : cards.find((x) => x.root && x.id === c.group);
26915
+ const name = `${at}-${c.slug || "task"}.md`;
26916
+ return group ? `todo/${numbers.get(group.id)}-${group.slug || "group"}/${name}` : `todo/${name}`;
26917
+ };
26918
+ const made = [];
26919
+ const kept = [];
26920
+ for (let i = 0; i < Math.max(cards.length, 1); i += BATCH) {
26921
+ const batch = cards.slice(i, i + BATCH).map((c) => {
26922
+ const wf = c.meta.workflow || "coding";
26923
+ const cloud = cloudOf.get(wf);
26924
+ const review = reviewOf2(c.meta);
26925
+ return {
26926
+ ref: c.id,
26927
+ number: numbers.get(c.id),
26928
+ title: c.meta.title.trim(),
26929
+ workflow: cloud ?? builtinId(wf),
26930
+ path: pathOf(c),
26931
+ body: cardForCloud(c.text, numbers, cloud ? workflowFolder(cloud) : null),
26932
+ ...review ? { review } : {}
26933
+ };
26934
+ });
26935
+ const done2 = await api(
26936
+ "POST",
26937
+ `/v1/projects/${project.id}/import`,
26938
+ { board: board2, cards: batch, ...i === 0 ? { files: sent } : {} }
26939
+ );
26940
+ made.push(...done2.cards);
26941
+ kept.push(...done2.kept);
26942
+ }
26943
+ let drafts = 0;
26944
+ for (const c of reviews) {
26945
+ const task = made.find((m) => m.ref === c.id)?.task;
26946
+ const named2 = draftsOf(c.text);
26947
+ if (task && named2.length) drafts += await uploadDrafts(task, named2);
26948
+ }
26949
+ const memory = sent.filter((f) => /(^|\/)memory\//.test(f.path)).length - kept.length;
26950
+ say(`\u5DF2\u5BFC\u5165\u5230 ${project.name} \xB7 Imported into ${project.name} (${project.prefix})`);
26951
+ say(` \u5361\u7247 Cards: ${made.length}\uFF08\u5F85\u5BA1 on review: ${reviews.length}\uFF09`);
26952
+ say(` \u81EA\u5EFA workflow Own workflows: ${cloudOf.size}`);
26953
+ say(` \u8BB0\u5FC6 Memory files: ${memory}${drafts ? ` \xB7 \u8349\u7A3F Drafts: ${drafts}` : ""}`);
26954
+ if (kept.length) {
26955
+ say(" \u8FD9\u4E9B workspace \u8BB0\u5FC6 Cloud \u5DF2\u6709\uFF0C\u4FDD\u7559\u4E86 Cloud \u7684\u7248\u672C \xB7 Kept Cloud\u2019s copy of these workspace memory files:");
26956
+ for (const k of kept) say(` ${k}`);
26957
+ }
26958
+ say(` ${APP_URL}/projects/${project.id}`);
26959
+ sayLeft(left);
26960
+ say("\u672C\u5730\u770B\u677F\u5DF2\u4E0D\u518D\u751F\u6548\uFF0C\u6838\u5BF9\u65E0\u8BEF\u540E\u8BF7\u81EA\u884C\u5220\u9664 `docs/kanban/`\u3002");
26961
+ say("This local board is no longer used. Once you have checked Cloud, delete `docs/kanban/` yourself.");
26962
+ return { project: project.id, cards: made, workflows: [...cloudOf.values()], memory, drafts, kept, left };
26963
+ }
26964
+ function leftLocal(own) {
26965
+ const out = [];
26966
+ const count4 = (dir) => fs73.existsSync(dir) ? walkMd(dir).length : 0;
26967
+ const archived = count4(ARCHIVE);
26968
+ if (archived) out.push(`.archive/ (${archived})`);
26969
+ const triage = count4(TRIAGE);
26970
+ if (triage) out.push(`triage/ (${triage})`);
26971
+ if (fs73.existsSync(DELIVERIES)) out.push("deliveries/");
26972
+ if (fs73.existsSync(path70.join(KANBAN, "metrics.csv"))) out.push("metrics.csv");
26973
+ const named2 = new Set(own.flatMap((w) => [...w.previews, ...w.land, ...w.scheduled].map((h) => h.agent)));
26974
+ if (fs73.existsSync(AGENTS)) {
26975
+ for (const e of fs73.readdirSync(AGENTS, { withFileTypes: true })) {
26976
+ if (e.isDirectory() && !e.name.startsWith(".") && !named2.has(e.name)) out.push(`agents/${e.name}/`);
26977
+ }
26978
+ }
26979
+ return out;
26980
+ }
26981
+ function sayLeft(left) {
26982
+ if (!left.length) return;
26983
+ say(" \u7559\u5728\u672C\u5730\u3001\u672A\u5BFC\u5165 \xB7 Left on this computer, not imported:");
26984
+ for (const l of left) say(` ${l}`);
26985
+ }
26986
+
26392
26987
  // ../cli/src/commands/cloud-template.ts
26393
26988
  init_config2();
26394
26989
  init_session();
26395
26990
  init_io();
26396
26991
  init_paths();
26397
26992
  import { createHash as createHash4 } from "node:crypto";
26398
- import fs72 from "node:fs";
26399
- import path68 from "node:path";
26993
+ import fs74 from "node:fs";
26994
+ import path71 from "node:path";
26400
26995
  var SLUG = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
26401
26996
  var CAPTURED = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?(?:Z|[+-]\d{2}:\d{2})$/;
26402
26997
  var MAX_BYTES3 = 50 * 1024 * 1024;
@@ -26429,13 +27024,13 @@ function invalid(zh, en) {
26429
27024
  refuse2({ zh: `\u6A21\u677F\u672A\u901A\u8FC7\u6821\u9A8C\uFF1A${zh}`, en: `The template is not valid: ${en}` });
26430
27025
  }
26431
27026
  async function ask(route2, init = {}, fallback) {
26432
- const token2 = await accessToken();
26433
- if (!token2.ok) refuse2(SAID[token2.reason], fallback);
27027
+ const token3 = await accessToken();
27028
+ if (!token3.ok) refuse2(SAID[token3.reason], fallback);
26434
27029
  let res;
26435
27030
  try {
26436
27031
  res = await fetch(`${cloudEndpoints().api}/v1/templates${route2}`, {
26437
27032
  ...init,
26438
- headers: { authorization: `Bearer ${token2.token}` }
27033
+ headers: { authorization: `Bearer ${token3.token}` }
26439
27034
  });
26440
27035
  } catch {
26441
27036
  refuse2(SAID.unreachable, fallback);
@@ -26494,11 +27089,11 @@ async function templatePreview(name, opts, program2) {
26494
27089
  This template has no preview.`);
26495
27090
  const written = [];
26496
27091
  for (const p of previews) {
26497
- const bytes = Buffer.from(await (await ask(`/${at}/previews/${route(p.path)}`, {}, WITHOUT)).arrayBuffer());
26498
- const file = path68.basename(p.path);
26499
- const out = path68.join(opts.to, file.startsWith(`${name}-`) ? file : `${name}-${file}`);
26500
- fs72.mkdirSync(opts.to, { recursive: true });
26501
- fs72.writeFileSync(out, bytes);
27092
+ const bytes3 = Buffer.from(await (await ask(`/${at}/previews/${route(p.path)}`, {}, WITHOUT)).arrayBuffer());
27093
+ const file = path71.basename(p.path);
27094
+ const out = path71.join(opts.to, file.startsWith(`${name}-`) ? file : `${name}-${file}`);
27095
+ fs74.mkdirSync(opts.to, { recursive: true });
27096
+ fs74.writeFileSync(out, bytes3);
26502
27097
  written.push(out);
26503
27098
  say(out);
26504
27099
  }
@@ -26511,15 +27106,15 @@ async function templateGet(name, opts, program2) {
26511
27106
  const { template } = await asJson(await ask(`/${at}`, {}, WITHOUT));
26512
27107
  const fetched = [];
26513
27108
  for (const f of template.files) {
26514
- const out = path68.resolve(to, f.path);
26515
- if (!out.startsWith(path68.resolve(to) + path68.sep)) refuse2(T.corrupt, WITHOUT);
26516
- const bytes = Buffer.from(await (await ask(`/${at}/files/${route(f.path)}`, {}, WITHOUT)).arrayBuffer());
26517
- if (bytes.byteLength !== f.size || createHash4("sha256").update(bytes).digest("hex") !== f.sha256) {
27109
+ const out = path71.resolve(to, f.path);
27110
+ if (!out.startsWith(path71.resolve(to) + path71.sep)) refuse2(T.corrupt, WITHOUT);
27111
+ const bytes3 = Buffer.from(await (await ask(`/${at}/files/${route(f.path)}`, {}, WITHOUT)).arrayBuffer());
27112
+ if (bytes3.byteLength !== f.size || createHash4("sha256").update(bytes3).digest("hex") !== f.sha256) {
26518
27113
  refuse2(T.corrupt, WITHOUT);
26519
27114
  }
26520
- fetched.push({ out, bytes });
27115
+ fetched.push({ out, bytes: bytes3 });
26521
27116
  }
26522
- const taken = fetched.filter((f) => fs72.existsSync(f.out)).map((f) => path68.relative(to, f.out));
27117
+ const taken = fetched.filter((f) => fs74.existsSync(f.out)).map((f) => path71.relative(to, f.out));
26523
27118
  if (taken.length > 0) {
26524
27119
  refuse2({
26525
27120
  zh: `\u76EE\u6807\u6587\u4EF6\u5939\u5DF2\u6709\u540C\u540D\u6587\u4EF6\uFF1A${taken.join("\u3001")}\u3002\u8BF7\u6362\u4E00\u4E2A\u6587\u4EF6\u5939\uFF0C\u6216\u5148\u79FB\u8D70\u8FD9\u4E9B\u6587\u4EF6\u3002`,
@@ -26527,8 +27122,8 @@ async function templateGet(name, opts, program2) {
26527
27122
  });
26528
27123
  }
26529
27124
  for (const f of fetched) {
26530
- fs72.mkdirSync(path68.dirname(f.out), { recursive: true });
26531
- fs72.writeFileSync(f.out, f.bytes);
27125
+ fs74.mkdirSync(path71.dirname(f.out), { recursive: true });
27126
+ fs74.writeFileSync(f.out, f.bytes);
26532
27127
  }
26533
27128
  say(`\u5DF2\u53D6\u56DE ${name}\uFF1A${fetched.length} \u4E2A\u6587\u4EF6\uFF0C\u4F4D\u4E8E ${to}
26534
27129
  Fetched ${name}: ${fetched.length} files into ${to}`);
@@ -26546,25 +27141,25 @@ async function templateSource(name, opts) {
26546
27141
  say(`evidence: ${e.path}`);
26547
27142
  continue;
26548
27143
  }
26549
- const out = path68.join(opts.to, `${name}-${path68.basename(e.path)}`);
26550
- fs72.mkdirSync(opts.to, { recursive: true });
26551
- fs72.writeFileSync(out, Buffer.from(await (await ask(`/${at}/evidence/${route(e.path)}`)).arrayBuffer()));
27144
+ const out = path71.join(opts.to, `${name}-${path71.basename(e.path)}`);
27145
+ fs74.mkdirSync(opts.to, { recursive: true });
27146
+ fs74.writeFileSync(out, Buffer.from(await (await ask(`/${at}/evidence/${route(e.path)}`)).arrayBuffer()));
26552
27147
  written.push(out);
26553
27148
  say(out);
26554
27149
  }
26555
27150
  return { name, source, evidence: written.length > 0 ? written : evidence.map((e) => e.path) };
26556
27151
  }
26557
27152
  async function templatePublish(dir, opts) {
26558
- const root = path68.resolve(dir);
26559
- const manifest = path68.join(root, "template.md");
26560
- if (!fs72.existsSync(manifest)) invalid("\u6587\u4EF6\u5939\u9876\u5C42\u7F3A\u5C11 template.md\u3002", "template.md is missing from the folder\u2019s top level.");
26561
- const meta = readTemplateMeta(fs72.readFileSync(manifest, "utf8"));
26562
- const files = walk2(root);
26563
- const total = files.reduce((sum, f) => sum + fs72.statSync(path68.join(root, f)).size, 0);
27153
+ const root = path71.resolve(dir);
27154
+ const manifest = path71.join(root, "template.md");
27155
+ if (!fs74.existsSync(manifest)) invalid("\u6587\u4EF6\u5939\u9876\u5C42\u7F3A\u5C11 template.md\u3002", "template.md is missing from the folder\u2019s top level.");
27156
+ const meta = readTemplateMeta(fs74.readFileSync(manifest, "utf8"));
27157
+ const files2 = walk2(root);
27158
+ const total = files2.reduce((sum, f) => sum + fs74.statSync(path71.join(root, f)).size, 0);
26564
27159
  if (total > MAX_BYTES3) invalid("\u6A21\u677F\u6587\u4EF6\u5408\u8BA1\u8D85\u8FC7 50 MB\u3002", "the template\u2019s files exceed 50 MB.");
26565
27160
  for (const extra of [...opts.preview, ...opts.evidence]) {
26566
- if (!fs72.existsSync(extra)) invalid(`\u627E\u4E0D\u5230\u6587\u4EF6 ${extra}\u3002`, `${extra} does not exist.`);
26567
- if (path68.resolve(extra).startsWith(root + path68.sep)) {
27161
+ if (!fs74.existsSync(extra)) invalid(`\u627E\u4E0D\u5230\u6587\u4EF6 ${extra}\u3002`, `${extra} does not exist.`);
27162
+ if (path71.resolve(extra).startsWith(root + path71.sep)) {
26568
27163
  invalid(
26569
27164
  `${extra} \u5728\u6A21\u677F\u6587\u4EF6\u5939\u5185\uFF1B\u9884\u89C8\u56FE\u4E0E\u6765\u6E90\u51ED\u8BC1\u9700\u653E\u5728\u6A21\u677F\u6587\u4EF6\u5939\u4E4B\u5916\u3002`,
26570
27165
  `${extra} is inside the template folder; keep previews and evidence outside it.`
@@ -26576,17 +27171,17 @@ async function templatePublish(dir, opts) {
26576
27171
  }
26577
27172
  const form = new FormData();
26578
27173
  form.set("meta", JSON.stringify({ ...meta, replace: !!opts.replace }));
26579
- const add = (kind, name, file) => form.append(`${kind}:${name}`, new Blob([fs72.readFileSync(file)]), path68.basename(name));
26580
- for (const f of files) add("files", f, path68.join(root, f));
26581
- for (const f of opts.preview) add("previews", path68.basename(f), f);
26582
- for (const f of opts.evidence) add("evidence", path68.basename(f), f);
27174
+ const add = (kind, name, file) => form.append(`${kind}:${name}`, new Blob([fs74.readFileSync(file)]), path71.basename(name));
27175
+ for (const f of files2) add("files", f, path71.join(root, f));
27176
+ for (const f of opts.preview) add("previews", path71.basename(f), f);
27177
+ for (const f of opts.evidence) add("evidence", path71.basename(f), f);
26583
27178
  const done2 = await asJson(await ask("", { method: "POST", body: form }));
26584
27179
  say(
26585
- done2.replaced ? `\u5DF2\u66FF\u6362 ${done2.name}\uFF1A${files.length} \u4E2A\u6587\u4EF6\u3002
26586
- Replaced ${done2.name}: ${files.length} files.` : `\u5DF2\u53D1\u5E03 ${done2.name}\uFF1A${files.length} \u4E2A\u6587\u4EF6\u3002
26587
- Published ${done2.name}: ${files.length} files.`
27180
+ done2.replaced ? `\u5DF2\u66FF\u6362 ${done2.name}\uFF1A${files2.length} \u4E2A\u6587\u4EF6\u3002
27181
+ Replaced ${done2.name}: ${files2.length} files.` : `\u5DF2\u53D1\u5E03 ${done2.name}\uFF1A${files2.length} \u4E2A\u6587\u4EF6\u3002
27182
+ Published ${done2.name}: ${files2.length} files.`
26588
27183
  );
26589
- return { name: done2.name, replaced: done2.replaced, files };
27184
+ return { name: done2.name, replaced: done2.replaced, files: files2 };
26590
27185
  }
26591
27186
  async function templateDelete(name) {
26592
27187
  await ask(`/${encodeURIComponent(name)}`, { method: "DELETE" });
@@ -26595,11 +27190,11 @@ Deleted ${name} from the catalog.`);
26595
27190
  return { name, deleted: true };
26596
27191
  }
26597
27192
  async function templateShowcase(name, dir) {
26598
- const file = path68.join(dir, "showcase.json");
26599
- if (!fs72.existsSync(file)) invalid(`${dir} \u4E2D\u7F3A\u5C11 showcase.json\u3002`, `showcase.json is missing from ${dir}.`);
27193
+ const file = path71.join(dir, "showcase.json");
27194
+ if (!fs74.existsSync(file)) invalid(`${dir} \u4E2D\u7F3A\u5C11 showcase.json\u3002`, `showcase.json is missing from ${dir}.`);
26600
27195
  let meta;
26601
27196
  try {
26602
- meta = JSON.parse(fs72.readFileSync(file, "utf8"));
27197
+ meta = JSON.parse(fs74.readFileSync(file, "utf8"));
26603
27198
  } catch {
26604
27199
  return invalid("showcase.json \u4E0D\u662F\u6709\u6548\u7684 JSON\u3002", "showcase.json is not valid JSON.");
26605
27200
  }
@@ -26611,9 +27206,9 @@ async function templateShowcase(name, dir) {
26611
27206
  const form = new FormData();
26612
27207
  form.set("meta", JSON.stringify(meta));
26613
27208
  for (const p of new Set(named2)) {
26614
- const at = path68.join(dir, p);
26615
- if (!fs72.existsSync(at)) invalid(`\u627E\u4E0D\u5230\u6587\u4EF6 ${at}\u3002`, `${at} does not exist.`);
26616
- form.append(`media:${p}`, new Blob([fs72.readFileSync(at)]), p);
27209
+ const at = path71.join(dir, p);
27210
+ if (!fs74.existsSync(at)) invalid(`\u627E\u4E0D\u5230\u6587\u4EF6 ${at}\u3002`, `${at} does not exist.`);
27211
+ form.append(`media:${p}`, new Blob([fs74.readFileSync(at)]), p);
26617
27212
  }
26618
27213
  const done2 = await asJson(await ask(`/${encodeURIComponent(name)}/showcase`, { method: "PUT", body: form }));
26619
27214
  say(`\u5DF2\u66F4\u65B0 ${name} \u7684\u5C55\u793A\u8D44\u6599\uFF1A${done2.files} \u4E2A\u6587\u4EF6\u3002
@@ -26622,7 +27217,7 @@ Updated ${name}'s showcase: ${done2.files} files.`);
26622
27217
  }
26623
27218
  function walk2(root, sub = "") {
26624
27219
  const out = [];
26625
- for (const entry of fs72.readdirSync(path68.join(root, sub), { withFileTypes: true })) {
27220
+ for (const entry of fs74.readdirSync(path71.join(root, sub), { withFileTypes: true })) {
26626
27221
  if (entry.name.startsWith(".") || entry.name === "node_modules") continue;
26627
27222
  const rel2 = sub ? `${sub}/${entry.name}` : entry.name;
26628
27223
  if (entry.isDirectory()) out.push(...walk2(root, rel2));
@@ -26956,7 +27551,7 @@ init_sessions();
26956
27551
  init_env();
26957
27552
  init_store();
26958
27553
  import { spawnSync as spawnSync5 } from "node:child_process";
26959
- import path73 from "node:path";
27554
+ import path76 from "node:path";
26960
27555
  var AGENTS2 = {
26961
27556
  claude: "claude-code",
26962
27557
  codex: "codex",
@@ -26971,10 +27566,10 @@ var AGENTS2 = {
26971
27566
  var RUNTIMES = /* @__PURE__ */ new Set(["node", "bun", "deno"]);
26972
27567
  function agentOf2(args) {
26973
27568
  const words = args.trim().split(/\s+/);
26974
- const first = path73.basename(words[0] ?? "");
27569
+ const first = path76.basename(words[0] ?? "");
26975
27570
  const script = RUNTIMES.has(first) ? words[1] ?? "" : words[0] ?? "";
26976
27571
  if (script.includes("/@anthropic-ai/claude-code/")) return "claude-code";
26977
- return AGENTS2[path73.basename(script).replace(/\.(m?js|cjs|exe)$/, "")];
27572
+ return AGENTS2[path76.basename(script).replace(/\.(m?js|cjs|exe)$/, "")];
26978
27573
  }
26979
27574
  function processChain() {
26980
27575
  if (process.platform === "win32") return [];
@@ -27018,8 +27613,8 @@ function terminalSession(chain, env, opencode, cwd = process.cwd()) {
27018
27613
  return resumeId ? { harness, resumeId, cwd } : void 0;
27019
27614
  }
27020
27615
  function currentSession() {
27021
- const run = insideRun();
27022
- if (run) return readStore().runs.find((r) => r.sessionId === run)?.origin;
27616
+ const run2 = insideRun();
27617
+ if (run2) return readStore().runs.find((r) => r.sessionId === run2)?.origin;
27023
27618
  return terminalSession(probes.chain(), process.env, probes.opencode);
27024
27619
  }
27025
27620
 
@@ -27035,8 +27630,8 @@ init_tasks();
27035
27630
  init_read();
27036
27631
  init_rules();
27037
27632
  init_board2();
27038
- import fs78 from "node:fs";
27039
- import path74 from "node:path";
27633
+ import fs80 from "node:fs";
27634
+ import path77 from "node:path";
27040
27635
  var FOLLOW_MS = 400;
27041
27636
  async function cmdStartRun(action, args, opts, program2 = "akb") {
27042
27637
  const { req, follow, print } = readRequest(action, args, opts);
@@ -27076,13 +27671,13 @@ async function cmdStartRun(action, args, opts, program2 = "akb") {
27076
27671
  sayIfHeld(req, program2);
27077
27672
  const started = action === "refine" ? await startRefinement(req) : await startRun(runnable);
27078
27673
  if ("error" in started) die(started.error, { kind: "run-refused", action });
27079
- const { run, spawned } = started;
27080
- if (!spawned) die(`couldn't start a process for run ${run.sessionId}`, { kind: "spawn-failed" });
27081
- say(`${action} \u2014 run ${run.sessionId}${run.deliveryId ? ` in delivery ${run.deliveryId}` : ""}`);
27082
- say(` follow it: ${program2} run log ${short(run.sessionId)} --follow${BOARD_FLAG}`);
27083
- say(` stop it: ${program2} run stop ${short(run.sessionId)}${BOARD_FLAG}`);
27084
- if (follow) return await followStarted(run.sessionId, program2, opts.events === true);
27085
- return { sessionId: run.sessionId, action, cardId: run.cardId };
27674
+ const { run: run2, spawned } = started;
27675
+ if (!spawned) die(`couldn't start a process for run ${run2.sessionId}`, { kind: "spawn-failed" });
27676
+ say(`${action} \u2014 run ${run2.sessionId}${run2.deliveryId ? ` in delivery ${run2.deliveryId}` : ""}`);
27677
+ say(` follow it: ${program2} run log ${short(run2.sessionId)} --follow${BOARD_FLAG}`);
27678
+ say(` stop it: ${program2} run stop ${short(run2.sessionId)}${BOARD_FLAG}`);
27679
+ if (follow) return await followStarted(run2.sessionId, program2, opts.events === true);
27680
+ return { sessionId: run2.sessionId, action, cardId: run2.cardId };
27086
27681
  }
27087
27682
  async function cmdRunScheduled(workflow, agent, opts, program2 = "akb") {
27088
27683
  const id = knownWorkflow(workflow);
@@ -27092,12 +27687,12 @@ async function cmdRunScheduled(workflow, agent, opts, program2 = "akb") {
27092
27687
  if (insideRun() || opts.print) return printFlow(req, program2);
27093
27688
  const started = await startRun(req);
27094
27689
  if ("error" in started) die(started.error, { kind: "run-refused", action: "scheduled" });
27095
- const { run, spawned } = started;
27096
- if (!spawned) die(`couldn't start a process for run ${run.sessionId}`, { kind: "spawn-failed" });
27097
- say(`${one.agent} \u2014 run ${run.sessionId}${run.deliveryId ? ` in delivery ${run.deliveryId}` : ""}`);
27098
- say(` follow it: ${program2} run log ${short(run.sessionId)} --follow${BOARD_FLAG}`);
27099
- if (opts.follow) return await followStarted(run.sessionId, program2, opts.events === true);
27100
- return { sessionId: run.sessionId, action: "scheduled" };
27690
+ const { run: run2, spawned } = started;
27691
+ if (!spawned) die(`couldn't start a process for run ${run2.sessionId}`, { kind: "spawn-failed" });
27692
+ say(`${one.agent} \u2014 run ${run2.sessionId}${run2.deliveryId ? ` in delivery ${run2.deliveryId}` : ""}`);
27693
+ say(` follow it: ${program2} run log ${short(run2.sessionId)} --follow${BOARD_FLAG}`);
27694
+ if (opts.follow) return await followStarted(run2.sessionId, program2, opts.events === true);
27695
+ return { sessionId: run2.sessionId, action: "scheduled" };
27101
27696
  }
27102
27697
  async function createInCloud(task, description, workflow) {
27103
27698
  const title = description.split("\n")[0].trim().slice(0, 120);
@@ -27215,12 +27810,12 @@ function readRequest(action, args, opts) {
27215
27810
  async function cmdResume(id, opts) {
27216
27811
  const opened = await startResume(id ?? "last");
27217
27812
  if ("error" in opened) die(opened.error, { kind: "run-refused" });
27218
- const { run } = opened;
27219
- if (!opened.spawned) die(`couldn't start a process for run ${run.sessionId}`, { kind: "spawn-failed" });
27220
- const within = run.deliveryId ? ` in delivery ${run.deliveryId}` : "";
27221
- say(run.resumedFrom ? `continuing ${short(run.resumedFrom)} \u2014 run ${run.sessionId}${within}` : `trying again \u2014 run ${run.sessionId}${within}`);
27222
- if (opts.follow === true) return await followStarted(run.sessionId, "akb");
27223
- return { sessionId: run.sessionId, resumedFrom: run.resumedFrom };
27813
+ const { run: run2 } = opened;
27814
+ if (!opened.spawned) die(`couldn't start a process for run ${run2.sessionId}`, { kind: "spawn-failed" });
27815
+ const within = run2.deliveryId ? ` in delivery ${run2.deliveryId}` : "";
27816
+ say(run2.resumedFrom ? `continuing ${short(run2.resumedFrom)} \u2014 run ${run2.sessionId}${within}` : `trying again \u2014 run ${run2.sessionId}${within}`);
27817
+ if (opts.follow === true) return await followStarted(run2.sessionId, "akb");
27818
+ return { sessionId: run2.sessionId, resumedFrom: run2.resumedFrom };
27224
27819
  }
27225
27820
  async function cmdCancel(named2) {
27226
27821
  const res = await cancelBoardDelivery(named2);
@@ -27310,7 +27905,7 @@ async function cmdSubStart(words, opts) {
27310
27905
  let prompt = words.join(" ");
27311
27906
  if (opts.file) {
27312
27907
  try {
27313
- prompt = fs78.readFileSync(path74.resolve(opts.file), "utf8");
27908
+ prompt = fs80.readFileSync(path77.resolve(opts.file), "utf8");
27314
27909
  } catch {
27315
27910
  die(`--file: cannot read ${opts.file}`, { kind: "run-refused" });
27316
27911
  }
@@ -27576,7 +28171,7 @@ async function cmdWatch(sessionId) {
27576
28171
  // ../cli/src/commands/triage.ts
27577
28172
  init_scheduled();
27578
28173
  init_workflows();
27579
- import fs80 from "node:fs";
28174
+ import fs82 from "node:fs";
27580
28175
 
27581
28176
  // ../cli/src/lib/signals/index.ts
27582
28177
  init_cards();
@@ -27586,16 +28181,16 @@ init_yaml();
27586
28181
  // ../cli/src/lib/signals/config.ts
27587
28182
  init_settings2();
27588
28183
  init_paths();
27589
- import fs79 from "node:fs";
27590
- import path75 from "node:path";
28184
+ import fs81 from "node:fs";
28185
+ import path78 from "node:path";
27591
28186
  var TOKEN_KEY = "TRIAGE_ENDPOINT_TOKEN";
27592
28187
  var ENDPOINT_SETTING = "Triage endpoint";
27593
28188
  var LINE2 = /^- \*\*Triage endpoint\*\*\s*[—-]\s*(.+)$/m;
27594
- var boardRel3 = (file) => rel(file).split(path75.sep).join("/");
28189
+ var boardRel3 = (file) => rel(file).split(path78.sep).join("/");
27595
28190
  function signalEndpoint() {
27596
28191
  let text5;
27597
28192
  try {
27598
- text5 = fs79.readFileSync(CONFIG, "utf8");
28193
+ text5 = fs81.readFileSync(CONFIG, "utf8");
27599
28194
  } catch {
27600
28195
  return "";
27601
28196
  }
@@ -27639,7 +28234,7 @@ function readMeta(sent) {
27639
28234
  }
27640
28235
  return pairs;
27641
28236
  }
27642
- function read(raw) {
28237
+ function read2(raw) {
27643
28238
  const missing = REQUIRED.filter((field2) => !text4(raw[field2]));
27644
28239
  if (missing.length > 0) return { ok: false, why: `missing ${missing.join(", ")}` };
27645
28240
  const sent = text4(raw.collected_at);
@@ -27715,7 +28310,7 @@ async function fetchSignals() {
27715
28310
  report3.failed.push({ which: `item ${at + 1}`, why: "not an object" });
27716
28311
  return;
27717
28312
  }
27718
- const found2 = read(raw);
28313
+ const found2 = read2(raw);
27719
28314
  if (!found2.ok) {
27720
28315
  report3.failed.push({ which: text4(raw.source_id) || `item ${at + 1}`, why: found2.why });
27721
28316
  return;
@@ -27771,7 +28366,7 @@ async function cmdTriageAdd(opts) {
27771
28366
  let body = opts.text;
27772
28367
  if (opts.file !== void 0) {
27773
28368
  try {
27774
- body = fs80.readFileSync(opts.file, "utf8");
28369
+ body = fs82.readFileSync(opts.file, "utf8");
27775
28370
  } catch {
27776
28371
  die(`can't read ${opts.file} \u2014 write the item to a file, then pass its path`, { kind: "needs-input" });
27777
28372
  }
@@ -27895,16 +28490,16 @@ async function cmdSpec(opts, program2 = "akb") {
27895
28490
  }
27896
28491
  const started = await startRun(req);
27897
28492
  if ("error" in started) die(started.error, { kind: "run-refused", action: "spec" });
27898
- const { run, spawned } = started;
27899
- if (!spawned) die(`couldn't start a process to run ${run.sessionId}`, { kind: "spawn-failed" });
28493
+ const { run: run2, spawned } = started;
28494
+ if (!spawned) die(`couldn't start a process to run ${run2.sessionId}`, { kind: "spawn-failed" });
27900
28495
  if (ownRuntime || ownSession) {
27901
28496
  say(`${name} runs in ${ownRuntime ? "its own runtime" : "a session of its own"}, so it started as a separate run \u2014 don't write its section yourself.`);
27902
28497
  }
27903
- say(`spec ${name} #${id} \u2014 run ${run.sessionId}`);
27904
- say(` follow it: ${program2} run log ${short(run.sessionId)} --follow${BOARD_FLAG}`);
27905
- say(` stop it: ${program2} run stop ${short(run.sessionId)}${BOARD_FLAG}`);
27906
- if (opts.follow === true) return await followStarted(run.sessionId, program2);
27907
- return { sessionId: run.sessionId, action: "spec", specAgent: name, cardId: id };
28498
+ say(`spec ${name} #${id} \u2014 run ${run2.sessionId}`);
28499
+ say(` follow it: ${program2} run log ${short(run2.sessionId)} --follow${BOARD_FLAG}`);
28500
+ say(` stop it: ${program2} run stop ${short(run2.sessionId)}${BOARD_FLAG}`);
28501
+ if (opts.follow === true) return await followStarted(run2.sessionId, program2);
28502
+ return { sessionId: run2.sessionId, action: "spec", specAgent: name, cardId: id };
27908
28503
  }
27909
28504
  function noteOf(words, flag) {
27910
28505
  const typed = words.join(" ").trim();
@@ -28055,7 +28650,13 @@ function declareRuns(program2, cli) {
28055
28650
  withShared(cloud.command("sign-out")).summary("forget it: this machine stops reaching Cloud, and nothing on any board changes").action(async function() {
28056
28651
  await boardless(this, cli, (p) => cmdCloud(["sign-out"], p));
28057
28652
  });
28058
- withShared(cloud.command("image")).argument("[prompt...]", "what to draw").summary("generate an image through Cloud, spending Pro credits").option("--aspect <ratio>", "the aspect ratio, e.g. 16:9").option("--ref <file>", "a PNG, JPEG or WebP to draw from; repeat for more", (v, all) => [...all, v], []).option("--out <file>", "where to write the image").action(async function(prompt) {
28653
+ withShared(cloud.command("import")).summary("import this board into an empty Cloud project").description(
28654
+ "Imports the open cards, memory, rules and own workflows of this board into an empty Cloud project, numbered from 1 in the order of their ids. Checks everything first and writes nothing on a problem; changes nothing on this computer. Run again to finish an import that stopped."
28655
+ ).option("--project <id-or-prefix>", "the Cloud project, by id or by its prefix").option("--dry-run", "only check, and list what would be imported and what stays here").action(async function() {
28656
+ const o = this.opts();
28657
+ await onBoard2(this, cli, (p) => cloudImport({ project: o.project, dryRun: o.dryRun }, p));
28658
+ });
28659
+ withShared(cloud.command("image")).argument("[prompt...]", "what to draw").summary("generate an image through Cloud, spending Pro credits").option("--aspect <ratio>", "the aspect ratio, e.g. 16:9").option("--ref <file>", "a PNG, JPEG or WebP to draw from; repeat for more", (v, all2) => [...all2, v], []).option("--out <file>", "where to write the image").action(async function(prompt) {
28059
28660
  const o = this.opts();
28060
28661
  await boardless(
28061
28662
  this,
@@ -28094,7 +28695,7 @@ function declareRuns(program2, cli) {
28094
28695
  withShared(template.command("source")).argument("<name>", "the template").summary("where a template came from, and the evidence captured at the time").option("--to <dir>", "download the evidence into this folder").action(async function(name) {
28095
28696
  await boardless(this, cli, () => templateSource(name, this.opts()));
28096
28697
  });
28097
- withShared(template.command("publish")).argument("<dir>", "the template's folder, holding template.md").summary("publish a template (maintainers only)").option("--preview <file>", "a catalog preview image, kept outside the folder; repeat for more", (v, all) => [...all, v], []).option("--evidence <file>", "a capture of the reference, kept outside the folder; repeat for more", (v, all) => [...all, v], []).option("--replace", "replace the template already published under this name").action(async function(dir) {
28698
+ withShared(template.command("publish")).argument("<dir>", "the template's folder, holding template.md").summary("publish a template (maintainers only)").option("--preview <file>", "a catalog preview image, kept outside the folder; repeat for more", (v, all2) => [...all2, v], []).option("--evidence <file>", "a capture of the reference, kept outside the folder; repeat for more", (v, all2) => [...all2, v], []).option("--replace", "replace the template already published under this name").action(async function(dir) {
28098
28699
  const o = this.opts();
28099
28700
  await boardless(this, cli, () => templatePublish(dir, o));
28100
28701
  });
@@ -28177,8 +28778,8 @@ function declareRuns(program2, cli) {
28177
28778
  }
28178
28779
  var RUN_ID = "a run's id, any prefix of one that names only one run, or `last`. Left out, it means the newest run";
28179
28780
  var DELIVERY = "the delivery, or the card it is on";
28180
- function declareRunning(run, cli) {
28181
- const verb = (name) => withShared(run.command(name));
28781
+ function declareRunning(run2, cli) {
28782
+ const verb = (name) => withShared(run2.command(name));
28182
28783
  verb("list").summary("what is running, and what ran lately").option("-c, --card <id>", "only the runs on that card", cardId).option("-a, --all", "every run this board has kept, not just the last ten").action(async function() {
28183
28784
  await onBoard2(this, cli, (p) => cmdRuns(this.opts(), p));
28184
28785
  });
@@ -28334,8 +28935,8 @@ function declareAgent(program2, cli) {
28334
28935
  }
28335
28936
 
28336
28937
  // ../cli/src/lib/cli/setup.ts
28337
- import fs84 from "node:fs";
28338
- import path79 from "node:path";
28938
+ import fs86 from "node:fs";
28939
+ import path82 from "node:path";
28339
28940
 
28340
28941
  // ../cli/src/commands/install.ts
28341
28942
  init_local();
@@ -28347,14 +28948,14 @@ init_io();
28347
28948
  init_paths();
28348
28949
  init_memory();
28349
28950
  init_yaml2();
28350
- import fs83 from "node:fs";
28351
- import path78 from "node:path";
28951
+ import fs85 from "node:fs";
28952
+ import path81 from "node:path";
28352
28953
  import { spawnSync as spawnSync8 } from "node:child_process";
28353
28954
 
28354
28955
  // ../cli/src/lib/skill/install.ts
28355
28956
  import { spawnSync as spawnSync7 } from "node:child_process";
28356
- import fs82 from "node:fs";
28357
- import path77 from "node:path";
28957
+ import fs84 from "node:fs";
28958
+ import path80 from "node:path";
28358
28959
  import { fileURLToPath as fileURLToPath2 } from "node:url";
28359
28960
 
28360
28961
  // ../skill/SKILL.md
@@ -28369,8 +28970,8 @@ init_version();
28369
28970
  init_version();
28370
28971
  init_project();
28371
28972
  import { spawnSync as spawnSync6 } from "node:child_process";
28372
- import fs81 from "node:fs";
28373
- import path76 from "node:path";
28973
+ import fs83 from "node:fs";
28974
+ import path79 from "node:path";
28374
28975
  var MARKER3 = "# ai4kanban commit guard";
28375
28976
  var MARKER_LINE = new RegExp(`^${MARKER3}\\b`, "m");
28376
28977
  var CHECK = [
@@ -28402,9 +29003,9 @@ function hookScript(sessions) {
28402
29003
  ""
28403
29004
  ].join("\n");
28404
29005
  }
28405
- var read2 = (file) => {
29006
+ var read3 = (file) => {
28406
29007
  try {
28407
- return fs81.readFileSync(file, "utf8");
29008
+ return fs83.readFileSync(file, "utf8");
28408
29009
  } catch {
28409
29010
  return null;
28410
29011
  }
@@ -28416,7 +29017,7 @@ function hooksDir(root) {
28416
29017
  windowsHide: true
28417
29018
  });
28418
29019
  if (out.error || out.status !== 0 || !out.stdout.trim()) return null;
28419
- return path76.resolve(root, out.stdout.trim());
29020
+ return path79.resolve(root, out.stdout.trim());
28420
29021
  }
28421
29022
  function hasOwnHooksPath(root) {
28422
29023
  const out = spawnSync6("git", ["config", "--get", "core.hooksPath"], {
@@ -28426,18 +29027,18 @@ function hasOwnHooksPath(root) {
28426
29027
  });
28427
29028
  return !out.error && out.status === 0 && !!out.stdout.trim();
28428
29029
  }
28429
- var sessionsPath = (root) => path76.join(projectStateDir(path76.join(root, "docs", "kanban"), root), SESSIONS_FILE);
29030
+ var sessionsPath = (root) => path79.join(projectStateDir(path79.join(root, "docs", "kanban"), root), SESSIONS_FILE);
28430
29031
  function readCommitHook(root) {
28431
29032
  const dir = hooksDir(root);
28432
29033
  if (!dir) return { state: "no-git" };
28433
- const where = shown(root, path76.join(dir, "pre-commit"));
29034
+ const where = shown(root, path79.join(dir, "pre-commit"));
28434
29035
  const line2 = guardLine(sessionsPath(root));
28435
29036
  if (hasOwnHooksPath(root)) return { state: "hooks-path", path: where, line: line2 };
28436
- const text5 = read2(path76.join(dir, "pre-commit"));
29037
+ const text5 = read3(path79.join(dir, "pre-commit"));
28437
29038
  if (text5 === null) return { state: "absent", path: where };
28438
29039
  return MARKER_LINE.test(text5) ? { state: "ours", path: where } : { state: "foreign", path: where, line: line2 };
28439
29040
  }
28440
- var shown = (root, p) => (path76.relative(root, p) || p).split(path76.sep).join("/");
29041
+ var shown = (root, p) => (path79.relative(root, p) || p).split(path79.sep).join("/");
28441
29042
  function installCommitHook(root) {
28442
29043
  const hook = readCommitHook(root);
28443
29044
  if (hook.state === "no-git") return {};
@@ -28448,11 +29049,11 @@ function installCommitHook(root) {
28448
29049
  ${hook.line}`
28449
29050
  };
28450
29051
  }
28451
- const file = path76.join(root, hook.path);
29052
+ const file = path79.join(root, hook.path);
28452
29053
  try {
28453
- fs81.mkdirSync(path76.dirname(file), { recursive: true });
28454
- fs81.writeFileSync(file, hookScript(sessionsPath(root)), { mode: 493 });
28455
- fs81.chmodSync(file, 493);
29054
+ fs83.mkdirSync(path79.dirname(file), { recursive: true });
29055
+ fs83.writeFileSync(file, hookScript(sessionsPath(root)), { mode: 493 });
29056
+ fs83.chmodSync(file, 493);
28456
29057
  } catch (e) {
28457
29058
  return { note: `${hook.path} could not be written \u2014 ${e instanceof Error ? e.message : String(e)}` };
28458
29059
  }
@@ -28468,9 +29069,9 @@ function sayCommitHook(state) {
28468
29069
 
28469
29070
  // ../cli/src/lib/skill/install.ts
28470
29071
  var TARGETS = [
28471
- { rel: path77.join(".claude", "skills", "kanban"), agent: "Claude Code" },
29072
+ { rel: path80.join(".claude", "skills", "kanban"), agent: "Claude Code" },
28472
29073
  {
28473
- rel: path77.join(".agents", "skills", "kanban"),
29074
+ rel: path80.join(".agents", "skills", "kanban"),
28474
29075
  agent: "Codex, Cursor, OpenCode, Kimi Code, DeepSeek Harness, ZCode, Grok Build"
28475
29076
  }
28476
29077
  ];
@@ -28482,25 +29083,25 @@ var SELF2 = fileURLToPath2(import.meta.url);
28482
29083
  function rulesPath() {
28483
29084
  return SELF2;
28484
29085
  }
28485
- function read3(file) {
29086
+ function read4(file) {
28486
29087
  try {
28487
- return fs82.readFileSync(file, "utf8");
29088
+ return fs84.readFileSync(file, "utf8");
28488
29089
  } catch {
28489
29090
  return null;
28490
29091
  }
28491
29092
  }
28492
29093
  function statOf(p) {
28493
29094
  try {
28494
- return fs82.lstatSync(p);
29095
+ return fs84.lstatSync(p);
28495
29096
  } catch {
28496
29097
  return null;
28497
29098
  }
28498
29099
  }
28499
29100
  function versionIn(dir) {
28500
- const note = read3(path77.join(dir, "SKILL.md"));
29101
+ const note = read4(path80.join(dir, "SKILL.md"));
28501
29102
  const stampedNote = note?.match(NOTE_STAMP);
28502
29103
  if (stampedNote) return stampedNote[1];
28503
- const src = read3(path77.join(dir, "kanban.mjs"));
29104
+ const src = read4(path80.join(dir, "kanban.mjs"));
28504
29105
  if (!src) return null;
28505
29106
  const stamped = src.slice(0, 400).match(BUILT_STAMP);
28506
29107
  if (stamped) return stamped[1];
@@ -28524,7 +29125,7 @@ function folderState(dir) {
28524
29125
  const st = statOf(dir);
28525
29126
  if (!st) return { state: "absent", version: null };
28526
29127
  if (st.isSymbolicLink()) return { state: "linked", version: versionIn(dir) };
28527
- if (!fs82.existsSync(path77.join(dir, "SKILL.md"))) return { state: "absent", version: null };
29128
+ if (!fs84.existsSync(path80.join(dir, "SKILL.md"))) return { state: "absent", version: null };
28528
29129
  const version = versionIn(dir);
28529
29130
  if (!version) return { state: "unknown", version: null };
28530
29131
  return { state: isOlder(version, SKILL_VERSION) ? "stale" : "current", version };
@@ -28532,9 +29133,9 @@ function folderState(dir) {
28532
29133
  function readSkillState(root) {
28533
29134
  const dir = rootOr(root);
28534
29135
  const folders2 = TARGETS.map((target) => ({
28535
- path: target.rel.split(path77.sep).join("/"),
29136
+ path: target.rel.split(path80.sep).join("/"),
28536
29137
  agent: target.agent,
28537
- ...folderState(path77.join(dir, target.rel))
29138
+ ...folderState(path80.join(dir, target.rel))
28538
29139
  }));
28539
29140
  return {
28540
29141
  version: SKILL_VERSION,
@@ -28571,10 +29172,10 @@ function commandParagraph(command) {
28571
29172
  ].join("\n");
28572
29173
  }
28573
29174
  function writeFolder(dir, command) {
28574
- fs82.rmSync(dir, { recursive: true, force: true });
28575
- fs82.mkdirSync(dir, { recursive: true });
29175
+ fs84.rmSync(dir, { recursive: true, force: true });
29176
+ fs84.mkdirSync(dir, { recursive: true });
28576
29177
  const filled = SKILL_default.replace(COMMAND_BLOCK, commandParagraph(command));
28577
- fs82.writeFileSync(path77.join(dir, "SKILL.md"), `${filled.trimEnd()}
29178
+ fs84.writeFileSync(path80.join(dir, "SKILL.md"), `${filled.trimEnd()}
28578
29179
 
28579
29180
  <!-- ai4kanban ${SKILL_VERSION} -->
28580
29181
  `);
@@ -28590,8 +29191,8 @@ function installSkill(root, only, invoked) {
28590
29191
  const wrote = [];
28591
29192
  const skipped = [];
28592
29193
  for (const target of TARGETS) {
28593
- const dest = path77.join(dir, target.rel);
28594
- const shown2 = target.rel.split(path77.sep).join("/");
29194
+ const dest = path80.join(dir, target.rel);
29195
+ const shown2 = target.rel.split(path80.sep).join("/");
28595
29196
  const { state: state2 } = folderState(dest);
28596
29197
  if (state2 === "linked") {
28597
29198
  skipped.push({ path: shown2, agent: target.agent, why: "a symlink into a source checkout \u2014 left untouched" });
@@ -28661,10 +29262,10 @@ var Report = class {
28661
29262
  for (const line2 of this.notes) say(` ! ${line2}`);
28662
29263
  }
28663
29264
  };
28664
- var read4 = (file) => fs83.existsSync(file) ? fs83.readFileSync(file, "utf8") : null;
29265
+ var read5 = (file) => fs85.existsSync(file) ? fs85.readFileSync(file, "utf8") : null;
28665
29266
  function statOf2(p) {
28666
29267
  try {
28667
- return fs83.lstatSync(p);
29268
+ return fs85.lstatSync(p);
28668
29269
  } catch {
28669
29270
  return null;
28670
29271
  }
@@ -28675,10 +29276,10 @@ async function boardMove(root, args, board2) {
28675
29276
  if (code !== 0) throw new BoardError(`\`board ${args.join(" ")}\` failed \u2014 nothing else was changed`, { kind: "board-move-failed" });
28676
29277
  }
28677
29278
  function boardAbove(root) {
28678
- let at = path78.dirname(path78.resolve(root));
29279
+ let at = path81.dirname(path81.resolve(root));
28679
29280
  for (; ; ) {
28680
- if (fs83.existsSync(path78.join(at, "docs", "kanban"))) return at;
28681
- const up = path78.dirname(at);
29281
+ if (fs85.existsSync(path81.join(at, "docs", "kanban"))) return at;
29282
+ const up = path81.dirname(at);
28682
29283
  if (up === at) return null;
28683
29284
  at = up;
28684
29285
  }
@@ -28686,10 +29287,10 @@ function boardAbove(root) {
28686
29287
  async function cmdInstall(ctx) {
28687
29288
  const report3 = new Report();
28688
29289
  const board2 = ctx.board ?? null;
28689
- const where = board2 ? path78.relative(ctx.dir, board2) || board2 : "docs/kanban";
29290
+ const where = board2 ? path81.relative(ctx.dir, board2) || board2 : "docs/kanban";
28690
29291
  say(`wildcrane ${SKILL_VERSION} \u2014 installing into ${ctx.dir}`);
28691
29292
  say("");
28692
- const above = board2 || fs83.existsSync(path78.join(ctx.dir, "docs", "kanban")) ? null : boardAbove(ctx.dir);
29293
+ const above = board2 || fs85.existsSync(path81.join(ctx.dir, "docs", "kanban")) ? null : boardAbove(ctx.dir);
28693
29294
  if (above) {
28694
29295
  report3.notes.push(`there is already a board at ${above} \u2014 this makes a second one, and commands run here will find this one`);
28695
29296
  }
@@ -28711,7 +29312,7 @@ async function cmdInstall(ctx) {
28711
29312
  say("board UI (Configuration \u2192 Agent setup), or here:");
28712
29313
  say("");
28713
29314
  say(` ${ctx.program} skill`);
28714
- return { installed: ctx.dir, board: board2 ?? path78.join(ctx.dir, "docs", "kanban") };
29315
+ return { installed: ctx.dir, board: board2 ?? path81.join(ctx.dir, "docs", "kanban") };
28715
29316
  }
28716
29317
  async function cmdSkill(ctx, mode) {
28717
29318
  const report3 = new Report();
@@ -28756,7 +29357,7 @@ function placeSkill(ctx, mode, report3) {
28756
29357
  const before = readSkillState(ctx.dir).folders;
28757
29358
  for (const folder of before) {
28758
29359
  if (folder.state !== "absent" && folder.state !== "linked") {
28759
- rescueSkillConfig(ctx.dir, path78.join(ctx.dir, folder.path), report3);
29360
+ rescueSkillConfig(ctx.dir, path81.join(ctx.dir, folder.path), report3);
28760
29361
  }
28761
29362
  }
28762
29363
  const result = installSkill(ctx.dir, mode === "update" ? "present" : void 0, ctx.program);
@@ -28779,20 +29380,20 @@ function placeSkill(ctx, mode, report3) {
28779
29380
  return { result, from: before.map((f) => f.version).find(Boolean) || null };
28780
29381
  }
28781
29382
  function rescueSkillConfig(root, skillDir, report3) {
28782
- const old = read4(path78.join(skillDir, "config.md"));
29383
+ const old = read5(path81.join(skillDir, "config.md"));
28783
29384
  if (!old || old.includes("{{")) return;
28784
- const boardConfig = path78.join(root, "docs", "kanban", "config.md");
28785
- const current = read4(boardConfig);
29385
+ const boardConfig = path81.join(root, "docs", "kanban", "config.md");
29386
+ const current = read5(boardConfig);
28786
29387
  if (current === null) {
28787
- fs83.mkdirSync(path78.dirname(boardConfig), { recursive: true });
28788
- fs83.writeFileSync(boardConfig, old);
29388
+ fs85.mkdirSync(path81.dirname(boardConfig), { recursive: true });
29389
+ fs85.writeFileSync(boardConfig, old);
28789
29390
  report3.did.push("moved your filled-in config.md out of the skill folder to docs/kanban/config.md");
28790
29391
  return;
28791
29392
  }
28792
29393
  if (current === old) return;
28793
- const aside = path78.join(root, "docs", "kanban", "config.from-skill.md");
28794
- if (fs83.existsSync(aside)) return;
28795
- fs83.writeFileSync(aside, old);
29394
+ const aside = path81.join(root, "docs", "kanban", "config.from-skill.md");
29395
+ if (fs85.existsSync(aside)) return;
29396
+ fs85.writeFileSync(aside, old);
28796
29397
  report3.notes.push(
28797
29398
  "the old skill folder held a different filled-in config.md \u2014 saved as docs/kanban/config.from-skill.md; fold anything worth keeping into docs/kanban/config.md and delete it"
28798
29399
  );
@@ -28846,8 +29447,8 @@ async function cmdUpdate2(ctx) {
28846
29447
  return { updated: ctx.dir, from, to: SKILL_VERSION };
28847
29448
  }
28848
29449
  async function repairBoard(root, report3) {
28849
- const board2 = path78.join(root, "docs", "kanban");
28850
- if (!fs83.existsSync(board2)) {
29450
+ const board2 = path81.join(root, "docs", "kanban");
29451
+ if (!fs85.existsSync(board2)) {
28851
29452
  report3.notes.push("no docs/kanban/ here \u2014 run `akb install` to scaffold the board");
28852
29453
  return;
28853
29454
  }
@@ -28877,20 +29478,20 @@ function moveRuntimes(root, board2, report3) {
28877
29478
  }
28878
29479
  }
28879
29480
  function moveLegacyMemory(board2, report3) {
28880
- const memory = path78.join(board2, "memory");
29481
+ const memory = path81.join(board2, "memory");
28881
29482
  const moved = [];
28882
29483
  for (const name of MEMORY_FILES) {
28883
- const from = path78.join(board2, name);
29484
+ const from = path81.join(board2, name);
28884
29485
  const st = statOf2(from);
28885
29486
  if (!st || !st.isFile()) continue;
28886
- fs83.mkdirSync(memory, { recursive: true });
28887
- const to = path78.join(memory, name);
28888
- const there = read4(to);
29487
+ fs85.mkdirSync(memory, { recursive: true });
29488
+ const to = path81.join(memory, name);
29489
+ const there = read5(to);
28889
29490
  if (there === null) {
28890
- fs83.renameSync(from, to);
29491
+ fs85.renameSync(from, to);
28891
29492
  moved.push(name);
28892
- } else if (there === read4(from)) {
28893
- fs83.rmSync(from);
29493
+ } else if (there === read5(from)) {
29494
+ fs85.rmSync(from);
28894
29495
  moved.push(name);
28895
29496
  } else {
28896
29497
  report3.notes.push(`both docs/kanban/${name} and docs/kanban/memory/${name} exist and differ \u2014 merge them by hand`);
@@ -28899,23 +29500,23 @@ function moveLegacyMemory(board2, report3) {
28899
29500
  if (moved.length) report3.did.push(`moved the memory set into docs/kanban/memory/: ${moved.join(", ")}`);
28900
29501
  }
28901
29502
  function dropRecordFile(board2) {
28902
- const file = path78.join(board2, "record.csv");
28903
- if (!fs83.existsSync(file)) return null;
28904
- fs83.rmSync(file);
29503
+ const file = path81.join(board2, "record.csv");
29504
+ if (!fs85.existsSync(file)) return null;
29505
+ fs85.rmSync(file);
28905
29506
  return "removed docs/kanban/record.csv (the planning scores it fed are gone)";
28906
29507
  }
28907
29508
  function dropModuleGoals(board2, report3) {
28908
- const memory = path78.join(board2, "memory");
28909
- if (!fs83.existsSync(memory)) return;
28910
- const root = read4(path78.join(memory, "goal.md"));
29509
+ const memory = path81.join(board2, "memory");
29510
+ if (!fs85.existsSync(memory)) return;
29511
+ const root = read5(path81.join(memory, "goal.md"));
28911
29512
  let dropped = 0;
28912
- for (const entry of fs83.readdirSync(memory, { withFileTypes: true })) {
29513
+ for (const entry of fs85.readdirSync(memory, { withFileTypes: true })) {
28913
29514
  if (!entry.isDirectory()) continue;
28914
- const file = path78.join(memory, entry.name, "goal.md");
28915
- const text5 = read4(file);
29515
+ const file = path81.join(memory, entry.name, "goal.md");
29516
+ const text5 = read5(file);
28916
29517
  if (text5 === null) continue;
28917
29518
  if (text5 === root || text5.includes(UNFILLED) || !goalWords(text5)) {
28918
- fs83.rmSync(file);
29519
+ fs85.rmSync(file);
28919
29520
  dropped++;
28920
29521
  } else {
28921
29522
  report3.notes.push(
@@ -28937,10 +29538,10 @@ var PLAN_LEADS = {
28937
29538
  var GONE_LEADS = ["software-planner", "planner"];
28938
29539
  function planLeads(board2) {
28939
29540
  const leads = { ...PLAN_LEADS };
28940
- const root = path78.join(board2, "workflows");
28941
- for (const entry of fs83.existsSync(root) ? fs83.readdirSync(root, { withFileTypes: true }) : []) {
29541
+ const root = path81.join(board2, "workflows");
29542
+ for (const entry of fs85.existsSync(root) ? fs85.readdirSync(root, { withFileTypes: true }) : []) {
28942
29543
  if (!entry.isDirectory()) continue;
28943
- const meta = splitFrontmatter(read4(path78.join(root, entry.name, "WORKFLOW.md")) ?? "").meta;
29544
+ const meta = splitFrontmatter(read5(path81.join(root, entry.name, "WORKFLOW.md")) ?? "").meta;
28944
29545
  const stages = meta === null ? void 0 : parseYamlBlock(meta).stages;
28945
29546
  const plan = stages && typeof stages === "object" && !Array.isArray(stages) ? stages.plan : void 0;
28946
29547
  const lead = plan && typeof plan === "object" && !Array.isArray(plan) && typeof plan.lead === "string" ? plan.lead.trim() : "";
@@ -28949,40 +29550,40 @@ function planLeads(board2) {
28949
29550
  return leads;
28950
29551
  }
28951
29552
  function movePlanRules(board2, report3) {
28952
- const rules = path78.join(board2, "rules");
29553
+ const rules = path81.join(board2, "rules");
28953
29554
  const moved = [];
28954
29555
  for (const [id, leads] of Object.entries(planLeads(board2))) {
28955
29556
  for (const lead of leads) {
28956
- const from = path78.join(rules, `${lead}.md`);
28957
- const rule = read4(from)?.trim();
29557
+ const from = path81.join(rules, `${lead}.md`);
29558
+ const rule = read5(from)?.trim();
28958
29559
  if (!rule) continue;
28959
- const to = path78.join(rules, "workflows", `${id}.md`);
28960
- const there = read4(to)?.trim() ?? "";
29560
+ const to = path81.join(rules, "workflows", `${id}.md`);
29561
+ const there = read5(to)?.trim() ?? "";
28961
29562
  if (!there.includes(rule)) {
28962
- fs83.mkdirSync(path78.dirname(to), { recursive: true });
28963
- fs83.writeFileSync(to, `${[there, rule].filter(Boolean).join("\n\n")}
29563
+ fs85.mkdirSync(path81.dirname(to), { recursive: true });
29564
+ fs85.writeFileSync(to, `${[there, rule].filter(Boolean).join("\n\n")}
28964
29565
  `);
28965
29566
  moved.push(`${lead} \u2192 ${id}`);
28966
29567
  }
28967
29568
  }
28968
29569
  }
28969
- for (const lead of GONE_LEADS) fs83.rmSync(path78.join(rules, `${lead}.md`), { force: true });
29570
+ for (const lead of GONE_LEADS) fs85.rmSync(path81.join(rules, `${lead}.md`), { force: true });
28970
29571
  if (moved.length) report3.did.push(`made each plan agent's rule its workflow's card rule (docs/kanban/rules/workflows/): ${moved.join(", ")}`);
28971
29572
  }
28972
29573
  function noteOldWorkflows(board2, report3) {
28973
29574
  const old = (dir, file, keys) => {
28974
- const root = path78.join(board2, dir);
28975
- return (fs83.existsSync(root) ? fs83.readdirSync(root, { withFileTypes: true }) : []).filter((e) => e.isDirectory() && keys.test(splitFrontmatter(read4(path78.join(root, e.name, file)) ?? "").meta ?? "")).map((e) => `docs/kanban/${dir}/${e.name}/${file}`);
29575
+ const root = path81.join(board2, dir);
29576
+ return (fs85.existsSync(root) ? fs85.readdirSync(root, { withFileTypes: true }) : []).filter((e) => e.isDirectory() && keys.test(splitFrontmatter(read5(path81.join(root, e.name, file)) ?? "").meta ?? "")).map((e) => `docs/kanban/${dir}/${e.name}/${file}`);
28976
29577
  };
28977
- const files = [...old("workflows", "WORKFLOW.md", /^(stages|delivers):/m), ...old("agents", "AGENT.md", /^\s+(hook|lead):/m)];
28978
- if (files.length) {
29578
+ const files2 = [...old("workflows", "WORKFLOW.md", /^(stages|delivers):/m), ...old("agents", "AGENT.md", /^\s+(hook|lead):/m)];
29579
+ if (files2.length) {
28979
29580
  report3.notes.push(
28980
- `written in the old form, so not read until rewritten \u2014 list a workflow's agents under \`previews\`, \`land\` and \`scheduled\`, and drop \`hook\`/\`lead\` from each agent (or ask the Workflow builder): ${files.join(", ")}`
29581
+ `written in the old form, so not read until rewritten \u2014 list a workflow's agents under \`previews\`, \`land\` and \`scheduled\`, and drop \`hook\`/\`lead\` from each agent (or ask the Workflow builder): ${files2.join(", ")}`
28981
29582
  );
28982
29583
  }
28983
29584
  }
28984
29585
  function checkConfig(board2, report3) {
28985
- const current = read4(path78.join(board2, "config.md"));
29586
+ const current = read5(path81.join(board2, "config.md"));
28986
29587
  if (!current) return;
28987
29588
  const added = missingConfigKeys(current);
28988
29589
  if (added.length) {
@@ -28992,7 +29593,7 @@ function checkConfig(board2, report3) {
28992
29593
  }
28993
29594
  }
28994
29595
  function checkModules(board2, report3) {
28995
- const map2 = read4(path78.join(board2, "modules.md"));
29596
+ const map2 = read5(path81.join(board2, "modules.md"));
28996
29597
  if (map2 && map2.includes(UNFILLED)) {
28997
29598
  report3.notes.push(
28998
29599
  "docs/kanban/modules.md is still blank \u2014 write it from the repo (`akb guide module-map`)"
@@ -29046,13 +29647,13 @@ function declareSetup(program2, cli) {
29046
29647
  program2.version(SKILL_VERSION, "-v, --version", "print this version").addHelpText("beforeAll", spelled(cli.program));
29047
29648
  const dirOption = (cmd) => cmd.option("--dir <path>", "the project to work on (default: the current folder)").option("--json", "answer as one JSON object instead of prose");
29048
29649
  const where = (cmd) => {
29049
- const dir = path79.resolve(String(cmd.optsWithGlobals().dir ?? cli.cwd));
29050
- if (!fs84.existsSync(dir)) throw new BoardError(`no such folder: ${dir}`, { kind: "no-such-folder", dir });
29650
+ const dir = path82.resolve(String(cmd.optsWithGlobals().dir ?? cli.cwd));
29651
+ if (!fs86.existsSync(dir)) throw new BoardError(`no such folder: ${dir}`, { kind: "no-such-folder", dir });
29051
29652
  return dir;
29052
29653
  };
29053
29654
  const boardOf = (cmd) => {
29054
29655
  const named2 = cmd.optsWithGlobals().board;
29055
- return named2 ? path79.resolve(cli.cwd, named2) : null;
29656
+ return named2 ? path82.resolve(cli.cwd, named2) : null;
29056
29657
  };
29057
29658
  dirOption(program2.command("install")).option("--board <dir>", "put the board here instead of docs/kanban/ (relative to this folder)").summary("scaffold docs/kanban/ \u2014 the board, and nothing else").description(
29058
29659
  "Installing writes the board and nothing outside docs/kanban/. Driving that board from a coding agent is a later extra \u2014 `akb skill install`, or the button in the board UI under Configuration \u2192 Agent setup. Safe to run twice."
@@ -29125,7 +29726,7 @@ function invokedDirectly() {
29125
29726
  const entry = process.argv[1];
29126
29727
  if (!entry) return false;
29127
29728
  try {
29128
- return fs85.realpathSync(entry) === fs85.realpathSync(SELF3);
29729
+ return fs87.realpathSync(entry) === fs87.realpathSync(SELF3);
29129
29730
  } catch {
29130
29731
  return false;
29131
29732
  }