wildcrane-runner 0.6.4 → 0.6.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/runner.mjs CHANGED
@@ -1,4 +1,4 @@
1
- // wildcrane-runner 0.6.4 — built by runner/scripts/build.mjs. Do not edit.
1
+ // wildcrane-runner 0.6.5 — built by runner/scripts/build.mjs. Do not edit.
2
2
  import { createRequire as __ai4kanbanRequire } from 'node:module'
3
3
  const require = __ai4kanbanRequire(import.meta.url)
4
4
  var __create = Object.create;
@@ -4382,15 +4382,15 @@ var require_react_dom_server_legacy_node_production = __commonJS({
4382
4382
  childState.suspenseyImages && (parentState.suspenseyImages = true);
4383
4383
  }
4384
4384
  function createRenderState(resumableState, generateStaticMarkup) {
4385
- var idPrefix2 = resumableState.idPrefix, bootstrapChunks = [], bootstrapScriptContent = resumableState.bootstrapScriptContent, bootstrapScripts = resumableState.bootstrapScripts, bootstrapModules = resumableState.bootstrapModules;
4385
+ var idPrefix = resumableState.idPrefix, bootstrapChunks = [], bootstrapScriptContent = resumableState.bootstrapScriptContent, bootstrapScripts = resumableState.bootstrapScripts, bootstrapModules = resumableState.bootstrapModules;
4386
4386
  void 0 !== bootstrapScriptContent && (bootstrapChunks.push("<script"), pushCompletedShellIdAttribute(bootstrapChunks, resumableState), bootstrapChunks.push(
4387
4387
  ">",
4388
4388
  ("" + bootstrapScriptContent).replace(scriptRegex, scriptReplacer),
4389
4389
  "</script>"
4390
4390
  ));
4391
- bootstrapScriptContent = idPrefix2 + "P:";
4392
- var JSCompiler_object_inline_segmentPrefix_1724 = idPrefix2 + "S:";
4393
- idPrefix2 += "B:";
4391
+ bootstrapScriptContent = idPrefix + "P:";
4392
+ var JSCompiler_object_inline_segmentPrefix_1724 = idPrefix + "S:";
4393
+ idPrefix += "B:";
4394
4394
  var JSCompiler_object_inline_preconnects_1738 = /* @__PURE__ */ new Set(), JSCompiler_object_inline_fontPreloads_1739 = /* @__PURE__ */ new Set(), JSCompiler_object_inline_highImagePreloads_1740 = /* @__PURE__ */ new Set(), JSCompiler_object_inline_styles_1741 = /* @__PURE__ */ new Map(), JSCompiler_object_inline_bootstrapScripts_1742 = /* @__PURE__ */ new Set(), JSCompiler_object_inline_scripts_1743 = /* @__PURE__ */ new Set(), JSCompiler_object_inline_bulkPreloads_1744 = /* @__PURE__ */ new Set(), JSCompiler_object_inline_preloads_1745 = {
4395
4395
  images: /* @__PURE__ */ new Map(),
4396
4396
  stylesheets: /* @__PURE__ */ new Map(),
@@ -4449,7 +4449,7 @@ var require_react_dom_server_legacy_node_production = __commonJS({
4449
4449
  return {
4450
4450
  placeholderPrefix: bootstrapScriptContent,
4451
4451
  segmentPrefix: JSCompiler_object_inline_segmentPrefix_1724,
4452
- boundaryPrefix: idPrefix2,
4452
+ boundaryPrefix: idPrefix,
4453
4453
  startInlineScript: "<script",
4454
4454
  startInlineStyle: "<style",
4455
4455
  preamble: { htmlChunks: null, headChunks: null, bodyChunks: null },
@@ -7804,7 +7804,7 @@ var require_react_dom_server_node_production = __commonJS({
7804
7804
  '<script nonce="' + escapeTextForBrowser(externalRuntimeConfig) + '"'
7805
7805
  ), nonceStyle = "string" === typeof nonce ? void 0 : nonce && nonce.style, inlineStyleWithNonce = void 0 === nonceStyle ? startInlineStyle : stringToPrecomputedChunk(
7806
7806
  '<style nonce="' + escapeTextForBrowser(nonceStyle) + '"'
7807
- ), idPrefix2 = resumableState.idPrefix, bootstrapChunks = [], bootstrapScriptContent = resumableState.bootstrapScriptContent, bootstrapScripts = resumableState.bootstrapScripts, bootstrapModules = resumableState.bootstrapModules;
7807
+ ), idPrefix = resumableState.idPrefix, bootstrapChunks = [], bootstrapScriptContent = resumableState.bootstrapScriptContent, bootstrapScripts = resumableState.bootstrapScripts, bootstrapModules = resumableState.bootstrapModules;
7808
7808
  void 0 !== bootstrapScriptContent && (bootstrapChunks.push(inlineScriptWithNonce), pushCompletedShellIdAttribute(bootstrapChunks, resumableState), bootstrapChunks.push(
7809
7809
  endOfStartTag,
7810
7810
  ("" + bootstrapScriptContent).replace(scriptRegex, scriptReplacer),
@@ -7825,9 +7825,9 @@ var require_react_dom_server_node_production = __commonJS({
7825
7825
  remainingCapacity: 2 + ("number" === typeof maxHeadersLength ? maxHeadersLength : 2e3)
7826
7826
  } : null;
7827
7827
  onHeaders = {
7828
- placeholderPrefix: stringToPrecomputedChunk(idPrefix2 + "P:"),
7829
- segmentPrefix: stringToPrecomputedChunk(idPrefix2 + "S:"),
7830
- boundaryPrefix: stringToPrecomputedChunk(idPrefix2 + "B:"),
7828
+ placeholderPrefix: stringToPrecomputedChunk(idPrefix + "P:"),
7829
+ segmentPrefix: stringToPrecomputedChunk(idPrefix + "S:"),
7830
+ boundaryPrefix: stringToPrecomputedChunk(idPrefix + "B:"),
7831
7831
  startInlineScript: inlineScriptWithNonce,
7832
7832
  startInlineStyle: inlineStyleWithNonce,
7833
7833
  preamble: createPreambleState(),
@@ -7865,12 +7865,12 @@ var require_react_dom_server_node_production = __commonJS({
7865
7865
  };
7866
7866
  if (void 0 !== bootstrapScripts)
7867
7867
  for (importMap = 0; importMap < bootstrapScripts.length; importMap++)
7868
- idPrefix2 = bootstrapScripts[importMap], nonceStyle = inlineScriptWithNonce = void 0, inlineStyleWithNonce = {
7868
+ idPrefix = bootstrapScripts[importMap], nonceStyle = inlineScriptWithNonce = void 0, inlineStyleWithNonce = {
7869
7869
  rel: "preload",
7870
7870
  as: "script",
7871
7871
  fetchPriority: "low",
7872
7872
  nonce
7873
- }, "string" === typeof idPrefix2 ? inlineStyleWithNonce.href = maxHeadersLength = idPrefix2 : (inlineStyleWithNonce.href = maxHeadersLength = idPrefix2.src, inlineStyleWithNonce.integrity = nonceStyle = "string" === typeof idPrefix2.integrity ? idPrefix2.integrity : void 0, inlineStyleWithNonce.crossOrigin = inlineScriptWithNonce = "string" === typeof idPrefix2 || null == idPrefix2.crossOrigin ? void 0 : "use-credentials" === idPrefix2.crossOrigin ? "use-credentials" : ""), idPrefix2 = resumableState, bootstrapScriptContent = maxHeadersLength, idPrefix2.scriptResources[bootstrapScriptContent] = null, idPrefix2.moduleScriptResources[bootstrapScriptContent] = null, idPrefix2 = [], pushLinkImpl(idPrefix2, inlineStyleWithNonce), onHeaders.bootstrapScripts.add(idPrefix2), bootstrapChunks.push(
7873
+ }, "string" === typeof idPrefix ? inlineStyleWithNonce.href = maxHeadersLength = idPrefix : (inlineStyleWithNonce.href = maxHeadersLength = idPrefix.src, inlineStyleWithNonce.integrity = nonceStyle = "string" === typeof idPrefix.integrity ? idPrefix.integrity : void 0, inlineStyleWithNonce.crossOrigin = inlineScriptWithNonce = "string" === typeof idPrefix || null == idPrefix.crossOrigin ? void 0 : "use-credentials" === idPrefix.crossOrigin ? "use-credentials" : ""), idPrefix = resumableState, bootstrapScriptContent = maxHeadersLength, idPrefix.scriptResources[bootstrapScriptContent] = null, idPrefix.moduleScriptResources[bootstrapScriptContent] = null, idPrefix = [], pushLinkImpl(idPrefix, inlineStyleWithNonce), onHeaders.bootstrapScripts.add(idPrefix), bootstrapChunks.push(
7874
7874
  startScriptSrc,
7875
7875
  escapeTextForBrowser(maxHeadersLength),
7876
7876
  attributeEnd
@@ -16247,16 +16247,16 @@ var require_react_dom_server_legacy_node_development = __commonJS({
16247
16247
  childState.suspenseyImages && (parentState.suspenseyImages = true);
16248
16248
  }
16249
16249
  function createRenderState(resumableState, generateStaticMarkup) {
16250
- var idPrefix2 = resumableState.idPrefix, bootstrapChunks = [], bootstrapScriptContent = resumableState.bootstrapScriptContent, bootstrapScripts = resumableState.bootstrapScripts, bootstrapModules = resumableState.bootstrapModules;
16250
+ var idPrefix = resumableState.idPrefix, bootstrapChunks = [], bootstrapScriptContent = resumableState.bootstrapScriptContent, bootstrapScripts = resumableState.bootstrapScripts, bootstrapModules = resumableState.bootstrapModules;
16251
16251
  void 0 !== bootstrapScriptContent && (bootstrapChunks.push("<script"), pushCompletedShellIdAttribute(bootstrapChunks, resumableState), bootstrapChunks.push(
16252
16252
  endOfStartTag,
16253
16253
  escapeEntireInlineScriptContent(bootstrapScriptContent),
16254
16254
  endInlineScript
16255
16255
  ));
16256
- idPrefix2 = {
16257
- placeholderPrefix: idPrefix2 + "P:",
16258
- segmentPrefix: idPrefix2 + "S:",
16259
- boundaryPrefix: idPrefix2 + "B:",
16256
+ idPrefix = {
16257
+ placeholderPrefix: idPrefix + "P:",
16258
+ segmentPrefix: idPrefix + "S:",
16259
+ boundaryPrefix: idPrefix + "B:",
16260
16260
  startInlineScript: "<script",
16261
16261
  startInlineStyle: "<style",
16262
16262
  preamble: { htmlChunks: null, headChunks: null, bodyChunks: null },
@@ -16301,7 +16301,7 @@ var require_react_dom_server_legacy_node_development = __commonJS({
16301
16301
  nonce: void 0
16302
16302
  };
16303
16303
  "string" === typeof scriptConfig ? props.href = src = scriptConfig : (props.href = src = scriptConfig.src, props.integrity = integrity = "string" === typeof scriptConfig.integrity ? scriptConfig.integrity : void 0, props.crossOrigin = crossOrigin = "string" === typeof scriptConfig || null == scriptConfig.crossOrigin ? void 0 : "use-credentials" === scriptConfig.crossOrigin ? "use-credentials" : "");
16304
- preloadBootstrapScriptOrModule(resumableState, idPrefix2, src, props);
16304
+ preloadBootstrapScriptOrModule(resumableState, idPrefix, src, props);
16305
16305
  bootstrapChunks.push(
16306
16306
  '<script src="',
16307
16307
  escapeTextForBrowser(src),
@@ -16328,7 +16328,7 @@ var require_react_dom_server_legacy_node_development = __commonJS({
16328
16328
  nonce: void 0
16329
16329
  }, "string" === typeof bootstrapScriptContent ? integrity.href = scriptConfig = bootstrapScriptContent : (integrity.href = scriptConfig = bootstrapScriptContent.src, integrity.integrity = crossOrigin = "string" === typeof bootstrapScriptContent.integrity ? bootstrapScriptContent.integrity : void 0, integrity.crossOrigin = src = "string" === typeof bootstrapScriptContent || null == bootstrapScriptContent.crossOrigin ? void 0 : "use-credentials" === bootstrapScriptContent.crossOrigin ? "use-credentials" : ""), preloadBootstrapScriptOrModule(
16330
16330
  resumableState,
16331
- idPrefix2,
16331
+ idPrefix,
16332
16332
  scriptConfig,
16333
16333
  integrity
16334
16334
  ), bootstrapChunks.push(
@@ -16345,31 +16345,31 @@ var require_react_dom_server_legacy_node_development = __commonJS({
16345
16345
  attributeEnd
16346
16346
  ), pushCompletedShellIdAttribute(bootstrapChunks, resumableState), bootstrapChunks.push(' async=""></script>');
16347
16347
  return {
16348
- placeholderPrefix: idPrefix2.placeholderPrefix,
16349
- segmentPrefix: idPrefix2.segmentPrefix,
16350
- boundaryPrefix: idPrefix2.boundaryPrefix,
16351
- startInlineScript: idPrefix2.startInlineScript,
16352
- startInlineStyle: idPrefix2.startInlineStyle,
16353
- preamble: idPrefix2.preamble,
16354
- externalRuntimeScript: idPrefix2.externalRuntimeScript,
16355
- bootstrapChunks: idPrefix2.bootstrapChunks,
16356
- importMapChunks: idPrefix2.importMapChunks,
16357
- onHeaders: idPrefix2.onHeaders,
16358
- headers: idPrefix2.headers,
16359
- resets: idPrefix2.resets,
16360
- charsetChunks: idPrefix2.charsetChunks,
16361
- viewportChunks: idPrefix2.viewportChunks,
16362
- hoistableChunks: idPrefix2.hoistableChunks,
16363
- preconnects: idPrefix2.preconnects,
16364
- fontPreloads: idPrefix2.fontPreloads,
16365
- highImagePreloads: idPrefix2.highImagePreloads,
16366
- styles: idPrefix2.styles,
16367
- bootstrapScripts: idPrefix2.bootstrapScripts,
16368
- scripts: idPrefix2.scripts,
16369
- bulkPreloads: idPrefix2.bulkPreloads,
16370
- preloads: idPrefix2.preloads,
16371
- nonce: idPrefix2.nonce,
16372
- stylesToHoist: idPrefix2.stylesToHoist,
16348
+ placeholderPrefix: idPrefix.placeholderPrefix,
16349
+ segmentPrefix: idPrefix.segmentPrefix,
16350
+ boundaryPrefix: idPrefix.boundaryPrefix,
16351
+ startInlineScript: idPrefix.startInlineScript,
16352
+ startInlineStyle: idPrefix.startInlineStyle,
16353
+ preamble: idPrefix.preamble,
16354
+ externalRuntimeScript: idPrefix.externalRuntimeScript,
16355
+ bootstrapChunks: idPrefix.bootstrapChunks,
16356
+ importMapChunks: idPrefix.importMapChunks,
16357
+ onHeaders: idPrefix.onHeaders,
16358
+ headers: idPrefix.headers,
16359
+ resets: idPrefix.resets,
16360
+ charsetChunks: idPrefix.charsetChunks,
16361
+ viewportChunks: idPrefix.viewportChunks,
16362
+ hoistableChunks: idPrefix.hoistableChunks,
16363
+ preconnects: idPrefix.preconnects,
16364
+ fontPreloads: idPrefix.fontPreloads,
16365
+ highImagePreloads: idPrefix.highImagePreloads,
16366
+ styles: idPrefix.styles,
16367
+ bootstrapScripts: idPrefix.bootstrapScripts,
16368
+ scripts: idPrefix.scripts,
16369
+ bulkPreloads: idPrefix.bulkPreloads,
16370
+ preloads: idPrefix.preloads,
16371
+ nonce: idPrefix.nonce,
16372
+ stylesToHoist: idPrefix.stylesToHoist,
16373
16373
  generateStaticMarkup
16374
16374
  };
16375
16375
  }
@@ -21749,7 +21749,7 @@ var require_react_dom_server_node_development = __commonJS({
21749
21749
  '<script nonce="' + escapeTextForBrowser(externalRuntimeConfig) + '"'
21750
21750
  ), nonceStyle = "string" === typeof nonce ? void 0 : nonce && nonce.style, inlineStyleWithNonce = void 0 === nonceStyle ? startInlineStyle : stringToPrecomputedChunk(
21751
21751
  '<style nonce="' + escapeTextForBrowser(nonceStyle) + '"'
21752
- ), idPrefix2 = resumableState.idPrefix, bootstrapChunks = [], bootstrapScriptContent = resumableState.bootstrapScriptContent, bootstrapScripts = resumableState.bootstrapScripts, bootstrapModules = resumableState.bootstrapModules;
21752
+ ), idPrefix = resumableState.idPrefix, bootstrapChunks = [], bootstrapScriptContent = resumableState.bootstrapScriptContent, bootstrapScripts = resumableState.bootstrapScripts, bootstrapModules = resumableState.bootstrapModules;
21753
21753
  void 0 !== bootstrapScriptContent && (bootstrapChunks.push(inlineScriptWithNonce), pushCompletedShellIdAttribute(bootstrapChunks, resumableState), bootstrapChunks.push(
21754
21754
  endOfStartTag,
21755
21755
  escapeEntireInlineScriptContent(bootstrapScriptContent),
@@ -21774,9 +21774,9 @@ var require_react_dom_server_node_development = __commonJS({
21774
21774
  remainingCapacity: 2 + ("number" === typeof maxHeadersLength ? maxHeadersLength : 2e3)
21775
21775
  } : null;
21776
21776
  onHeaders = {
21777
- placeholderPrefix: stringToPrecomputedChunk(idPrefix2 + "P:"),
21778
- segmentPrefix: stringToPrecomputedChunk(idPrefix2 + "S:"),
21779
- boundaryPrefix: stringToPrecomputedChunk(idPrefix2 + "B:"),
21777
+ placeholderPrefix: stringToPrecomputedChunk(idPrefix + "P:"),
21778
+ segmentPrefix: stringToPrecomputedChunk(idPrefix + "S:"),
21779
+ boundaryPrefix: stringToPrecomputedChunk(idPrefix + "B:"),
21780
21780
  startInlineScript: inlineScriptWithNonce,
21781
21781
  startInlineStyle: inlineStyleWithNonce,
21782
21782
  preamble: createPreambleState(),
@@ -21814,16 +21814,16 @@ var require_react_dom_server_node_development = __commonJS({
21814
21814
  };
21815
21815
  if (void 0 !== bootstrapScripts)
21816
21816
  for (importMap = 0; importMap < bootstrapScripts.length; importMap++)
21817
- maxHeadersLength = bootstrapScripts[importMap], inlineStyleWithNonce = nonceStyle = void 0, idPrefix2 = {
21817
+ maxHeadersLength = bootstrapScripts[importMap], inlineStyleWithNonce = nonceStyle = void 0, idPrefix = {
21818
21818
  rel: "preload",
21819
21819
  as: "script",
21820
21820
  fetchPriority: "low",
21821
21821
  nonce
21822
- }, "string" === typeof maxHeadersLength ? idPrefix2.href = inlineScriptWithNonce = maxHeadersLength : (idPrefix2.href = inlineScriptWithNonce = maxHeadersLength.src, idPrefix2.integrity = inlineStyleWithNonce = "string" === typeof maxHeadersLength.integrity ? maxHeadersLength.integrity : void 0, idPrefix2.crossOrigin = nonceStyle = "string" === typeof maxHeadersLength || null == maxHeadersLength.crossOrigin ? void 0 : "use-credentials" === maxHeadersLength.crossOrigin ? "use-credentials" : ""), preloadBootstrapScriptOrModule(
21822
+ }, "string" === typeof maxHeadersLength ? idPrefix.href = inlineScriptWithNonce = maxHeadersLength : (idPrefix.href = inlineScriptWithNonce = maxHeadersLength.src, idPrefix.integrity = inlineStyleWithNonce = "string" === typeof maxHeadersLength.integrity ? maxHeadersLength.integrity : void 0, idPrefix.crossOrigin = nonceStyle = "string" === typeof maxHeadersLength || null == maxHeadersLength.crossOrigin ? void 0 : "use-credentials" === maxHeadersLength.crossOrigin ? "use-credentials" : ""), preloadBootstrapScriptOrModule(
21823
21823
  resumableState,
21824
21824
  onHeaders,
21825
21825
  inlineScriptWithNonce,
21826
- idPrefix2
21826
+ idPrefix
21827
21827
  ), bootstrapChunks.push(
21828
21828
  startScriptSrc,
21829
21829
  escapeTextForBrowser(inlineScriptWithNonce),
@@ -84355,7 +84355,7 @@ function alive(pid) {
84355
84355
  return e2.code === "EPERM";
84356
84356
  }
84357
84357
  }
84358
- var sleep = (ms2) => new Promise((resolve2) => setTimeout(resolve2, ms2));
84358
+ var sleep = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
84359
84359
 
84360
84360
  // src/home.ts
84361
84361
  import crypto from "node:crypto";
@@ -84453,9 +84453,9 @@ function status(line) {
84453
84453
  }
84454
84454
 
84455
84455
  // src/protocol.ts
84456
- var VERSION = true ? "0.6.4" : "0.0.0";
84457
- var AKB_VERSION = true ? "0.11.3" : "0.0.0";
84458
- var AKB_CONTRACT = true ? 1 : 0;
84456
+ var VERSION = true ? "0.6.5" : "0.0.0";
84457
+ var AKB_VERSION = true ? "0.11.4" : "0.0.0";
84458
+ var AKB_CONTRACT = true ? 2 : 0;
84459
84459
  var EXIT_REFUSED = 10;
84460
84460
  var EXIT_OUTDATED = 11;
84461
84461
 
@@ -85940,8 +85940,8 @@ function createTail(log) {
85940
85940
  // ../cli/package.json
85941
85941
  var package_default = {
85942
85942
  name: "wildcrane",
85943
- version: "0.11.3",
85944
- akbContract: 1,
85943
+ version: "0.11.4",
85944
+ akbContract: 2,
85945
85945
  description: "WildCrane's `akb` command \u2014 scaffold the Markdown board under docs/kanban/, put an agent on a card, and carry the flows the agent works by.",
85946
85946
  keywords: [
85947
85947
  "kanban",
@@ -86936,6 +86936,7 @@ var REPO_ROOT = "";
86936
86936
  var KANBAN = "";
86937
86937
  var TODO = "";
86938
86938
  var ARCHIVE = "";
86939
+ var REJECTIONS_TO_REVIEW = ".sync";
86939
86940
  var ARCHIVE_MD = "";
86940
86941
  var README = "";
86941
86942
  var MODULES_MD = "";
@@ -88041,6 +88042,7 @@ var DEFAULT_HARNESS = HARNESSES[0];
88041
88042
  checkHarnesses(HARNESSES);
88042
88043
 
88043
88044
  // ../cli/src/lib/agent/env.ts
88045
+ var SCHEDULED_AGENTS_ENV = "AI4KANBAN_SCHEDULED_AGENTS";
88044
88046
  var SESSION_VARS = {
88045
88047
  "claude-code": "CLAUDE_CODE_SESSION_ID",
88046
88048
  codex: "CODEX_THREAD_ID"
@@ -88253,7 +88255,7 @@ var secretsSet = () => Object.fromEntries(Object.entries(readAll()).map(([id, ke
88253
88255
  var RUNTIMES = ["claude-code", "codex", "cursor", "opencode", "kimi", "dsh", "zcode", "grok"];
88254
88256
  var PROTOCOL = 11;
88255
88257
  var TIMEOUT_MS = 2e4;
88256
- async function send(method, route, body, signedIn, ms2, type) {
88258
+ async function send(method, route, body, signedIn, ms, type) {
88257
88259
  const headers = { accept: "application/json" };
88258
88260
  if (signedIn) {
88259
88261
  const token = await accessToken();
@@ -88269,7 +88271,7 @@ async function send(method, route, body, signedIn, ms2, type) {
88269
88271
  method,
88270
88272
  headers,
88271
88273
  body: body === void 0 ? void 0 : raw ? body : JSON.stringify(body),
88272
- signal: AbortSignal.timeout(ms2)
88274
+ signal: AbortSignal.timeout(ms)
88273
88275
  });
88274
88276
  return { ok: true, value: response };
88275
88277
  } catch (e2) {
@@ -88808,239 +88810,6 @@ function nextDue(lastRun, cadence) {
88808
88810
  return new Date(last2.getFullYear(), last2.getMonth(), last2.getDate() + c2.n, hour, minute, 0, 0);
88809
88811
  }
88810
88812
 
88811
- // ../cli/src/lib/yaml.ts
88812
- function yamlScalar(s) {
88813
- const text3 = String(s);
88814
- if (text3 === "") return '""';
88815
- if (/^[-?:,[\]{}#&*!|>'"%@`]/.test(text3) || /:\s/.test(text3) || /[\n"]/.test(text3) || /^\s|\s$/.test(text3)) {
88816
- return JSON.stringify(text3);
88817
- }
88818
- return text3;
88819
- }
88820
- function unquote(v2) {
88821
- const text3 = String(v2).trim();
88822
- if (text3.startsWith('"') && text3.endsWith('"')) {
88823
- try {
88824
- return JSON.parse(text3);
88825
- } catch {
88826
- return text3.slice(1, -1);
88827
- }
88828
- }
88829
- if (text3.startsWith("'") && text3.endsWith("'")) return text3.slice(1, -1);
88830
- return text3;
88831
- }
88832
-
88833
- // ../cli/src/lib/question-block.ts
88834
- var MODES = ["single", "multi"];
88835
- var withoutTag = (text3) => text3.replace(/^\[user\]\s+/, "");
88836
- function normalizeQuestion(raw) {
88837
- if (raw && typeof raw === "object" && !Array.isArray(raw)) {
88838
- const source = raw;
88839
- const text3 = withoutTag(String(source.question ?? source.text ?? ""));
88840
- const extra = {
88841
- ...typeof source.agent === "string" && source.agent.trim() ? { agent: source.agent.trim() } : {},
88842
- ...source.skipped === true || source.skipped === "true" ? { skipped: true } : {}
88843
- };
88844
- const options = (Array.isArray(source.options) ? source.options : []).map((o2) => String(o2).trim()).filter(Boolean);
88845
- if (options.length === 0) return { text: text3, ...extra };
88846
- const mode = MODES.includes(String(source.mode)) ? String(source.mode) : "single";
88847
- const recommend = (Array.isArray(source.recommend) ? source.recommend : []).map(Number).filter((n) => Number.isInteger(n) && n >= 1 && n <= options.length);
88848
- return { text: text3, mode, options, recommend: mode === "single" ? recommend.slice(0, 1) : recommend, ...extra };
88849
- }
88850
- return { text: withoutTag(String(raw)) };
88851
- }
88852
- function parseQuestionsBlock(lines) {
88853
- const out = [];
88854
- for (let i = 0; i < lines.length; i++) {
88855
- const m = lines[i].match(/^\s*-\s+([\s\S]*)$/);
88856
- if (!m) continue;
88857
- const head2 = m[1];
88858
- const opened = head2.match(/^question:\s*(.*)$/);
88859
- if (!opened) {
88860
- out.push(normalizeQuestion(unquote(head2)));
88861
- continue;
88862
- }
88863
- const q3 = {
88864
- question: unquote(opened[1]),
88865
- options: [],
88866
- recommend: []
88867
- };
88868
- while (i + 1 < lines.length && !/^\s*-\s/.test(lines[i + 1])) {
88869
- const field = lines[i + 1].match(/^\s*([A-Za-z_]+):\s*(.*)$/);
88870
- i++;
88871
- if (!field) continue;
88872
- const [, key, val] = field;
88873
- if (key === "options") {
88874
- while (i + 1 < lines.length && /^\s*-\s+/.test(lines[i + 1])) {
88875
- q3.options.push(unquote(lines[i + 1].replace(/^\s*-\s+/, "")));
88876
- i++;
88877
- }
88878
- } else if (key === "recommend") {
88879
- q3.recommend = val.replace(/^\[|\]$/g, "").split(",").map((s) => Number(s.trim())).filter((n) => Number.isInteger(n));
88880
- } else if (key === "mode") {
88881
- q3.mode = unquote(val);
88882
- } else if (key === "agent") {
88883
- q3.agent = unquote(val);
88884
- } else if (key === "skipped") {
88885
- q3.skipped = unquote(val) === "true";
88886
- }
88887
- }
88888
- out.push(normalizeQuestion(q3));
88889
- }
88890
- return out;
88891
- }
88892
-
88893
- // ../cli/src/lib/view/rules.ts
88894
- var openOf = (questions) => questions.filter((q3) => !q3.skipped);
88895
-
88896
- // ../cli/src/lib/frontmatter.ts
88897
- function parseFrontmatter(text3) {
88898
- const lines = text3.split("\n");
88899
- if (lines[0].trim() !== "---") return { meta: null, body: text3 };
88900
- let i = 1;
88901
- const fm = [];
88902
- while (i < lines.length && lines[i].trim() !== "---") {
88903
- fm.push(lines[i]);
88904
- i++;
88905
- }
88906
- if (i >= lines.length) return { meta: null, body: text3 };
88907
- const meta = {};
88908
- for (let j2 = 0; j2 < fm.length; j2++) {
88909
- const m = fm[j2].match(/^([A-Za-z_]+):\s*(.*)$/);
88910
- if (!m) continue;
88911
- const key = m[1];
88912
- const val = m[2];
88913
- if (key === "questions") {
88914
- if (val === "") {
88915
- const block = [];
88916
- while (j2 + 1 < fm.length && /^\s/.test(fm[j2 + 1]) && fm[j2 + 1].trim() !== "") {
88917
- block.push(fm[j2 + 1]);
88918
- j2++;
88919
- }
88920
- meta.questions = parseQuestionsBlock(block);
88921
- } else {
88922
- meta.questions = val.trim() === "[]" ? [] : [normalizeQuestion(unquote(val))];
88923
- }
88924
- continue;
88925
- }
88926
- if (val === "") {
88927
- const items = [];
88928
- while (j2 + 1 < fm.length && /^\s*-\s+/.test(fm[j2 + 1])) {
88929
- items.push(unquote(fm[j2 + 1].replace(/^\s*-\s+/, "")));
88930
- j2++;
88931
- }
88932
- meta[key] = items;
88933
- } else if (val.startsWith("[")) {
88934
- const inner = val.slice(1, val.lastIndexOf("]"));
88935
- meta[key] = inner.split(",").map((s) => s.trim()).filter(Boolean).map(unquote);
88936
- } else {
88937
- meta[key] = unquote(val);
88938
- }
88939
- }
88940
- for (const k of ["blocked_by", "related"]) {
88941
- const value = meta[k];
88942
- if (Array.isArray(value)) {
88943
- meta[k] = value.map((x2) => Number(String(x2).replace(/^#/, ""))).filter((n) => Number.isInteger(n));
88944
- } else {
88945
- meta[k] = [];
88946
- }
88947
- }
88948
- if (!Array.isArray(meta.questions)) {
88949
- meta.questions = meta.questions ? [normalizeQuestion(meta.questions)] : [];
88950
- }
88951
- meta.priority = typeof meta.priority === "string" ? meta.priority.trim() : "";
88952
- if (!Array.isArray(meta.modules)) meta.modules = [];
88953
- delete meta.channels;
88954
- delete meta.decided;
88955
- delete meta.verify;
88956
- delete meta.release;
88957
- delete meta.schedule;
88958
- delete meta.roi;
88959
- meta.workflow = typeof meta.workflow === "string" && meta.workflow.trim() ? meta.workflow.trim() : "";
88960
- meta.triage = typeof meta.triage === "string" ? meta.triage.trim() : "";
88961
- meta.source = (Array.isArray(meta.source) ? meta.source : typeof meta.source === "string" ? [meta.source] : []).map((ref) => String(ref).trim()).filter(Boolean);
88962
- delete meta.phases;
88963
- if (Array.isArray(meta.previews)) meta.previews = meta.previews.map((name) => String(name).trim()).filter(Boolean);
88964
- else delete meta.previews;
88965
- meta.stages = /^\d+$/.test(String(meta.stages ?? "").trim()) ? Number(meta.stages) : 0;
88966
- meta.phase = /^\d+$/.test(String(meta.phase ?? "").trim()) ? Number(meta.phase) : 0;
88967
- meta.preview_approved = meta.preview_approved === "true";
88968
- meta.archived = typeof meta.archived === "string" && meta.archived.trim() ? meta.archived.trim() : "";
88969
- meta.rejected = meta.rejected === "true";
88970
- meta.rejected_reason = typeof meta.rejected_reason === "string" ? meta.rejected_reason : "";
88971
- meta.rejected_at = typeof meta.rejected_at === "string" ? meta.rejected_at.trim() : "";
88972
- meta.rejected_by = meta.rejected_by === "user" || meta.rejected_by === "agent" ? meta.rejected_by : "";
88973
- return { meta, body: lines.slice(i + 1).join("\n") };
88974
- }
88975
-
88976
- // ../cli/src/lib/spec-agent-names.ts
88977
- var LEGACY_SPEC_AGENT_NAMES = {
88978
- "recommend-tech-stack": "tech-stack-advisor",
88979
- "technology-selection": "tech-stack-advisor",
88980
- "ui-design": "ui-designer",
88981
- // Renamed in #945 and folded into the editor in #1057; its asset memory stays in
88982
- // `memory/agents/video-assets/`.
88983
- "video-assets": "hyperframes-editor",
88984
- // Renamed in #1502: it reads chats, and writes memory as a result.
88985
- "memory-reviewer": "chat-reviewer",
88986
- // Folded into `copywriting` in #1582.
88987
- "user-docs": "copywriting"
88988
- };
88989
- var canonicalSpecAgent = (name) => {
88990
- const asked = name.trim();
88991
- return LEGACY_SPEC_AGENT_NAMES[asked] ?? asked;
88992
- };
88993
-
88994
- // ../cli/src/lib/slug.ts
88995
- function slugify(s) {
88996
- const out = String(s).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 60).replace(/-+$/g, "");
88997
- return out || "task";
88998
- }
88999
-
89000
- // ../cli/src/lib/memory.ts
89001
- var PLANNER_MEMORY_FILES = ["decisions.md", "rejected.md", "redesign.md"];
89002
- var STARTERS = {
89003
- "readme.md": `# Shipped
89004
-
89005
- User-facing work that has shipped, one line each \u2014 a link to the published doc that
89006
- covers it, or a plain-words note.
89007
-
89008
- _(nothing recorded yet \u2014 the first finished task fills it in.)_
89009
- `,
89010
- "decisions.md": `# Decisions
89011
-
89012
- Settled answers to cards' open questions, grouped by topic. Keep only **user-facing**
89013
- calls that guide future planning \u2014 what a user can see, do, or would care about.
89014
- Internal detail stays on the card.
89015
- `,
89016
- "redesign.md": `# Redesign
89017
-
89018
- Design mistakes to avoid when writing a card, grouped by topic. One entry each: the
89019
- mistake, then the design we actually want. Read before writing or reviewing a card.
89020
- `,
89021
- "rejected.md": `# Rejected
89022
-
89023
- Ideas we turned down, grouped by topic. One line each: the idea, and why we said no. Read
89024
- before proposing so you don't re-suggest them.
89025
- `,
89026
- // Only a header: `describe-project` writes the body, and runs while there is none (#1268).
89027
- "project.md": `# Project
89028
-
89029
- What the project is today, from its users' side. Rewritten whole by \`akb describe-project\`;
89030
- edits here do not last.
89031
- `
89032
- };
89033
- var RESERVED_MODULE_NAMES = PLANNER_MEMORY_FILES.map((name) => name.replace(/\.md$/, ""));
89034
- var PRODUCT_STARTER = STARTERS["project.md"].replaceAll("Project", "Product").replaceAll("project", "product");
89035
- var SEEDED_GOAL_PARAGRAPHS = new Set(
89036
- [
89037
- "# Goal",
89038
- "Where this is headed, in the user's own words: the long-term goal, the horizon it aims at, and the roadmap of what comes next, roughly in order. Not this week's work \u2014 that's the cards on the board. The user owns this file; the agent seeds it but does not invent the goal.",
89039
- "The direction, in the user's own words \u2014 where this is headed. One short statement. The user owns this file; the agent seeds it but does not invent the goal.",
89040
- "_(not filled in yet \u2014 the user writes this.)_"
89041
- ].map((p2) => p2.replace(/\s+/g, " "))
89042
- );
89043
-
89044
88813
  // ../cli/src/lib/agent/due.ts
89045
88814
  var AUTO_GAP = "6h";
89046
88815
  var DAY = 864e5;
@@ -89065,22 +88834,32 @@ function scheduleDue(ask, now = Date.now()) {
89065
88834
  }
89066
88835
  const newest2 = ask.attempts.reduce((a3, r2) => a3 && a3.startedAt >= r2.startedAt ? a3 : r2, null);
89067
88836
  const retrying = isAuto(ask.cadence) && newest2?.status === "error";
89068
- const wait3 = next.getTime() > now ? retrying ? "retrying" : "tooSoon" : !ask.newWork() ? "nothingNew" : ask.building?.() ? "building" : null;
88837
+ const wait3 = next.getTime() > now ? retrying ? "retrying" : "tooSoon" : !ask.newWork() ? "nothingNew" : null;
89069
88838
  const reason = !wait3 || wait3 === "tooSoon" ? void 0 : wait3 === "nothingNew" ? ask.reads : wait3;
89070
88839
  return { next, wait: wait3, ...reason ? { reason } : {} };
89071
88840
  }
89072
88841
 
89073
88842
  // src/agents.ts
89074
- var AGENTS_EVERY_MS = 6e4;
89075
- var ms = (at2) => at2 ? Date.parse(at2) || 0 : 0;
88843
+ function nextHour(now = Date.now()) {
88844
+ const at2 = new Date(now);
88845
+ at2.setMinutes(60, 0, 0);
88846
+ return at2.getTime();
88847
+ }
88848
+ function hourOf(at2) {
88849
+ const hour = new Date(at2 ?? NaN);
88850
+ if (Number.isNaN(hour.getTime())) return 0;
88851
+ hour.setMinutes(hour.getMinutes() + 30, 0, 0);
88852
+ hour.setMinutes(0, 0, 0);
88853
+ return hour.getTime();
88854
+ }
89076
88855
  function agentDue(agent, now = Date.now()) {
89077
88856
  if (agent.attempts.some((a3) => a3.status === "running")) return false;
89078
88857
  const due = scheduleDue({
89079
88858
  cadence: agent.cadence,
89080
88859
  fallback: agent.fallback,
89081
88860
  reads: agent.reads,
89082
- from: Math.max(ms(agent.lastSuccess), ms(agent.since)),
89083
- attempts: agent.attempts.map((a3) => ({ startedAt: ms(a3.startedAt), status: a3.status })),
88861
+ from: Math.max(hourOf(agent.lastSuccess), hourOf(agent.since)),
88862
+ attempts: agent.attempts.map((a3) => ({ startedAt: hourOf(a3.startedAt), status: a3.status })),
89084
88863
  newWork: () => agent.newWork
89085
88864
  }, now);
89086
88865
  return !due.wait;
@@ -89137,7 +88916,7 @@ exec ${line} "$@"
89137
88916
  }
89138
88917
  function akbEnv(akb, board, task, line) {
89139
88918
  const env2 = {};
89140
- const dropped = ["AI4KANBAN_BOARD", "AI4KANBAN_TASK", LANGUAGE_LINE_ENV];
88919
+ const dropped = ["AI4KANBAN_BOARD", "AI4KANBAN_TASK", LANGUAGE_LINE_ENV, SCHEDULED_AGENTS_ENV];
89141
88920
  for (const [k, v2] of Object.entries(process.env)) if (!k.startsWith("KANBAN_") && !dropped.includes(k)) env2[k] = v2;
89142
88921
  const key = Object.keys(env2).find((k) => k.toUpperCase() === "PATH") ?? "PATH";
89143
88922
  env2[key] = [shimDir(akb), env2[key]].filter(Boolean).join(path14.delimiter);
@@ -89158,7 +88937,7 @@ function runAkb(akb, args, opts) {
89158
88937
  };
89159
88938
  let child;
89160
88939
  try {
89161
- child = spawn3(akb.command, [...akb.args, ...args], { cwd: opts.cwd, env: akbEnv(akb, opts.board, opts.task, opts.line), stdio: ["ignore", "pipe", "pipe"] });
88940
+ child = spawn3(akb.command, [...akb.args, ...args], { cwd: opts.cwd, env: { ...akbEnv(akb, opts.board, opts.task, opts.line), ...opts.env }, stdio: ["ignore", "pipe", "pipe"] });
89162
88941
  } catch (e2) {
89163
88942
  return resolve2({ code: null, out: "", last: e2 instanceof Error ? e2.message : String(e2) });
89164
88943
  }
@@ -89783,10 +89562,11 @@ function numberOfCard(path34) {
89783
89562
  var cardSlug = (task) => task.toLowerCase().replace(/_/g, "-");
89784
89563
  var assetsFile = (task) => `assets/${task}.json`;
89785
89564
  var workflowFolder = (id) => id.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
89565
+ var OWN_FOLDER = /^wf-(?!builtin-)[a-z0-9-]+$/;
89786
89566
  var workflowName = (id) => id.startsWith("wf_builtin_") ? id.slice("wf_builtin_".length).replace(/_/g, "-") : workflowFolder(id);
89787
89567
  var BUILDER = "wf_builtin_workflow_builder";
89788
89568
  var draftFolder = (task) => cardSlug(task);
89789
- var unquote2 = (value) => value.trim().replace(/^(["'])(.*)\1$/, "$2");
89569
+ var unquote = (value) => value.trim().replace(/^(["'])(.*)\1$/, "$2");
89790
89570
  function cardFront(body) {
89791
89571
  const match = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/.exec(body);
89792
89572
  if (!match) return {};
@@ -89795,13 +89575,13 @@ function cardFront(body) {
89795
89575
  const field = /^(title|status|phase|stages|previews):\s*(.*)$/.exec(line);
89796
89576
  if (!field) continue;
89797
89577
  const [, key, value = ""] = field;
89798
- if (key === "title" && value.trim()) out.title = unquote2(value);
89799
- else if (key === "status" && value.trim()) out.status = unquote2(value);
89578
+ if (key === "title" && value.trim()) out.title = unquote(value);
89579
+ else if (key === "status" && value.trim()) out.status = unquote(value);
89800
89580
  else if (key === "phase" && Number.isInteger(Number(value)) && value.trim()) out.phase = Number(value);
89801
89581
  else if (key === "stages" && Number.isInteger(Number(value)) && value.trim()) out.stages = Number(value);
89802
89582
  else if (key === "previews") {
89803
89583
  const flow = /^\[(.*)\]\s*$/.exec(value.trim());
89804
- if (flow) out.previews = flow[1].split(",").map(unquote2).filter(Boolean);
89584
+ if (flow) out.previews = flow[1].split(",").map(unquote).filter(Boolean);
89805
89585
  }
89806
89586
  }
89807
89587
  return out;
@@ -90026,6 +89806,28 @@ function diff3Merge(a3, o2, b2, options) {
90026
89806
  return results;
90027
89807
  }
90028
89808
 
89809
+ // ../cli/src/lib/yaml.ts
89810
+ function yamlScalar(s) {
89811
+ const text3 = String(s);
89812
+ if (text3 === "") return '""';
89813
+ if (/^[-?:,[\]{}#&*!|>'"%@`]/.test(text3) || /:\s/.test(text3) || /[\n"]/.test(text3) || /^\s|\s$/.test(text3)) {
89814
+ return JSON.stringify(text3);
89815
+ }
89816
+ return text3;
89817
+ }
89818
+ function unquote2(v2) {
89819
+ const text3 = String(v2).trim();
89820
+ if (text3.startsWith('"') && text3.endsWith('"')) {
89821
+ try {
89822
+ return JSON.parse(text3);
89823
+ } catch {
89824
+ return text3.slice(1, -1);
89825
+ }
89826
+ }
89827
+ if (text3.startsWith("'") && text3.endsWith("'")) return text3.slice(1, -1);
89828
+ return text3;
89829
+ }
89830
+
90029
89831
  // ../cloud/src/triage-files.ts
90030
89832
  var ITEM = /^triage\/(?:(dismissed|archived)\/)?([^/]+)\.md$/;
90031
89833
  function itemAt(path34) {
@@ -90615,8 +90417,8 @@ function readMap(lines, start, indent) {
90615
90417
  }
90616
90418
  function readScalar(value) {
90617
90419
  const flow = value.match(/^\[(.*)\]$/);
90618
- if (!flow) return unquote(value);
90619
- return flow[1].split(",").map((item) => unquote(item.trim())).filter(Boolean);
90420
+ if (!flow) return unquote2(value);
90421
+ return flow[1].split(",").map((item) => unquote2(item.trim())).filter(Boolean);
90620
90422
  }
90621
90423
  function readBlock(lines, start, parentIndent) {
90622
90424
  if (start >= lines.length || lines[start].indent <= parentIndent) return ["", start];
@@ -90645,7 +90447,7 @@ function readList2(lines, start, indent) {
90645
90447
  }
90646
90448
  const item = {};
90647
90449
  const inline = stripComment(match[2].trim());
90648
- if (inline) item[match[1].trim()] = unquote(inline);
90450
+ if (inline) item[match[1].trim()] = unquote2(inline);
90649
90451
  else {
90650
90452
  const [value, next2] = readBlock(lines, i, keyIndent);
90651
90453
  item[match[1].trim()] = value;
@@ -91045,7 +90847,6 @@ async function pullWorkflow(ws, record, base) {
91045
90847
  record.agents = {};
91046
90848
  return { ok: true, value: void 0 };
91047
90849
  }
91048
- var OWN_FOLDER = /^wf-(?!builtin-)[a-z0-9-]+$/;
91049
90850
  var agentsRecord = (ws) => path23.join(ws.board, ".sync", "agents.json");
91050
90851
  function readPlaced(ws) {
91051
90852
  try {
@@ -91501,7 +91302,7 @@ function keptFolders() {
91501
91302
  }
91502
91303
  return [.../* @__PURE__ */ new Set([...allowedProjects(), ...cached2])].flatMap((dir) => [keptBoard(dir)].filter((ws) => !!ws));
91503
91304
  }
91504
- function watchBoards(machineId2, ms2, lookMs = LOOK_MS, pullMs = PULL_MS) {
91305
+ function watchBoards(machineId2, ms, lookMs = LOOK_MS, pullMs = PULL_MS) {
91505
91306
  const watched = /* @__PURE__ */ new Map();
91506
91307
  const due = /* @__PURE__ */ new Map();
91507
91308
  const afterJob = /* @__PURE__ */ new Set();
@@ -91525,7 +91326,7 @@ function watchBoards(machineId2, ms2, lookMs = LOOK_MS, pullMs = PULL_MS) {
91525
91326
  const held4 = watched.get(ws.cwd);
91526
91327
  if (closed || !p2 || !isBoardPath(p2) || !held4) return;
91527
91328
  clearTimeout(held4.timer);
91528
- held4.timer = setTimeout(() => void send3(ws), ms2);
91329
+ held4.timer = setTimeout(() => void send3(ws), ms);
91529
91330
  });
91530
91331
  } catch {
91531
91332
  return false;
@@ -91658,6 +91459,149 @@ async function answerHint(machineId2, hint2) {
91658
91459
  import fs25 from "node:fs";
91659
91460
  import path28 from "node:path";
91660
91461
 
91462
+ // ../cli/src/lib/question-block.ts
91463
+ var MODES = ["single", "multi"];
91464
+ var withoutTag = (text3) => text3.replace(/^\[user\]\s+/, "");
91465
+ function normalizeQuestion(raw) {
91466
+ if (raw && typeof raw === "object" && !Array.isArray(raw)) {
91467
+ const source = raw;
91468
+ const text3 = withoutTag(String(source.question ?? source.text ?? ""));
91469
+ const extra = {
91470
+ ...typeof source.agent === "string" && source.agent.trim() ? { agent: source.agent.trim() } : {},
91471
+ ...source.skipped === true || source.skipped === "true" ? { skipped: true } : {}
91472
+ };
91473
+ const options = (Array.isArray(source.options) ? source.options : []).map((o2) => String(o2).trim()).filter(Boolean);
91474
+ if (options.length === 0) return { text: text3, ...extra };
91475
+ const mode = MODES.includes(String(source.mode)) ? String(source.mode) : "single";
91476
+ const recommend = (Array.isArray(source.recommend) ? source.recommend : []).map(Number).filter((n) => Number.isInteger(n) && n >= 1 && n <= options.length);
91477
+ return { text: text3, mode, options, recommend: mode === "single" ? recommend.slice(0, 1) : recommend, ...extra };
91478
+ }
91479
+ return { text: withoutTag(String(raw)) };
91480
+ }
91481
+ function parseQuestionsBlock(lines) {
91482
+ const out = [];
91483
+ for (let i = 0; i < lines.length; i++) {
91484
+ const m = lines[i].match(/^\s*-\s+([\s\S]*)$/);
91485
+ if (!m) continue;
91486
+ const head2 = m[1];
91487
+ const opened = head2.match(/^question:\s*(.*)$/);
91488
+ if (!opened) {
91489
+ out.push(normalizeQuestion(unquote2(head2)));
91490
+ continue;
91491
+ }
91492
+ const q3 = {
91493
+ question: unquote2(opened[1]),
91494
+ options: [],
91495
+ recommend: []
91496
+ };
91497
+ while (i + 1 < lines.length && !/^\s*-\s/.test(lines[i + 1])) {
91498
+ const field = lines[i + 1].match(/^\s*([A-Za-z_]+):\s*(.*)$/);
91499
+ i++;
91500
+ if (!field) continue;
91501
+ const [, key, val] = field;
91502
+ if (key === "options") {
91503
+ while (i + 1 < lines.length && /^\s*-\s+/.test(lines[i + 1])) {
91504
+ q3.options.push(unquote2(lines[i + 1].replace(/^\s*-\s+/, "")));
91505
+ i++;
91506
+ }
91507
+ } else if (key === "recommend") {
91508
+ q3.recommend = val.replace(/^\[|\]$/g, "").split(",").map((s) => Number(s.trim())).filter((n) => Number.isInteger(n));
91509
+ } else if (key === "mode") {
91510
+ q3.mode = unquote2(val);
91511
+ } else if (key === "agent") {
91512
+ q3.agent = unquote2(val);
91513
+ } else if (key === "skipped") {
91514
+ q3.skipped = unquote2(val) === "true";
91515
+ }
91516
+ }
91517
+ out.push(normalizeQuestion(q3));
91518
+ }
91519
+ return out;
91520
+ }
91521
+
91522
+ // ../cli/src/lib/view/rules.ts
91523
+ var openOf = (questions) => questions.filter((q3) => !q3.skipped);
91524
+
91525
+ // ../cli/src/lib/frontmatter.ts
91526
+ function parseFrontmatter(text3) {
91527
+ const lines = text3.split("\n");
91528
+ if (lines[0].trim() !== "---") return { meta: null, body: text3 };
91529
+ let i = 1;
91530
+ const fm = [];
91531
+ while (i < lines.length && lines[i].trim() !== "---") {
91532
+ fm.push(lines[i]);
91533
+ i++;
91534
+ }
91535
+ if (i >= lines.length) return { meta: null, body: text3 };
91536
+ const meta = {};
91537
+ for (let j2 = 0; j2 < fm.length; j2++) {
91538
+ const m = fm[j2].match(/^([A-Za-z_]+):\s*(.*)$/);
91539
+ if (!m) continue;
91540
+ const key = m[1];
91541
+ const val = m[2];
91542
+ if (key === "questions") {
91543
+ if (val === "") {
91544
+ const block = [];
91545
+ while (j2 + 1 < fm.length && /^\s/.test(fm[j2 + 1]) && fm[j2 + 1].trim() !== "") {
91546
+ block.push(fm[j2 + 1]);
91547
+ j2++;
91548
+ }
91549
+ meta.questions = parseQuestionsBlock(block);
91550
+ } else {
91551
+ meta.questions = val.trim() === "[]" ? [] : [normalizeQuestion(unquote2(val))];
91552
+ }
91553
+ continue;
91554
+ }
91555
+ if (val === "") {
91556
+ const items = [];
91557
+ while (j2 + 1 < fm.length && /^\s*-\s+/.test(fm[j2 + 1])) {
91558
+ items.push(unquote2(fm[j2 + 1].replace(/^\s*-\s+/, "")));
91559
+ j2++;
91560
+ }
91561
+ meta[key] = items;
91562
+ } else if (val.startsWith("[")) {
91563
+ const inner = val.slice(1, val.lastIndexOf("]"));
91564
+ meta[key] = inner.split(",").map((s) => s.trim()).filter(Boolean).map(unquote2);
91565
+ } else {
91566
+ meta[key] = unquote2(val);
91567
+ }
91568
+ }
91569
+ for (const k of ["blocked_by", "related"]) {
91570
+ const value = meta[k];
91571
+ if (Array.isArray(value)) {
91572
+ meta[k] = value.map((x2) => Number(String(x2).replace(/^#/, ""))).filter((n) => Number.isInteger(n));
91573
+ } else {
91574
+ meta[k] = [];
91575
+ }
91576
+ }
91577
+ if (!Array.isArray(meta.questions)) {
91578
+ meta.questions = meta.questions ? [normalizeQuestion(meta.questions)] : [];
91579
+ }
91580
+ meta.priority = typeof meta.priority === "string" ? meta.priority.trim() : "";
91581
+ if (!Array.isArray(meta.modules)) meta.modules = [];
91582
+ delete meta.channels;
91583
+ delete meta.decided;
91584
+ delete meta.verify;
91585
+ delete meta.release;
91586
+ delete meta.schedule;
91587
+ delete meta.roi;
91588
+ meta.workflow = typeof meta.workflow === "string" && meta.workflow.trim() ? meta.workflow.trim() : "";
91589
+ meta.triage = typeof meta.triage === "string" ? meta.triage.trim() : "";
91590
+ meta.source = (Array.isArray(meta.source) ? meta.source : typeof meta.source === "string" ? [meta.source] : []).map((ref) => String(ref).trim()).filter(Boolean);
91591
+ delete meta.phases;
91592
+ if (Array.isArray(meta.previews)) meta.previews = meta.previews.map((name) => String(name).trim()).filter(Boolean);
91593
+ else delete meta.previews;
91594
+ meta.stages = /^\d+$/.test(String(meta.stages ?? "").trim()) ? Number(meta.stages) : 0;
91595
+ meta.phase = /^\d+$/.test(String(meta.phase ?? "").trim()) ? Number(meta.phase) : 0;
91596
+ meta.preview_approved = meta.preview_approved === "true";
91597
+ meta.archived = typeof meta.archived === "string" && meta.archived.trim() ? meta.archived.trim() : "";
91598
+ meta.rejected = meta.rejected === "true";
91599
+ meta.rejected_reason = typeof meta.rejected_reason === "string" ? meta.rejected_reason : "";
91600
+ meta.rejected_at = typeof meta.rejected_at === "string" ? meta.rejected_at.trim() : "";
91601
+ meta.rejected_by = meta.rejected_by === "user" || meta.rejected_by === "agent" ? meta.rejected_by : "";
91602
+ return { meta, body: lines.slice(i + 1).join("\n") };
91603
+ }
91604
+
91661
91605
  // src/triage.ts
91662
91606
  import fs23 from "node:fs";
91663
91607
  import path26 from "node:path";
@@ -91667,9 +91611,15 @@ import { createHash } from "node:crypto";
91667
91611
  var DERIVED = "derived-";
91668
91612
  var derivedSourceId = (seed) => `${DERIVED}${createHash("sha256").update(seed).digest("hex").slice(0, 16)}`;
91669
91613
 
91614
+ // ../cli/src/lib/slug.ts
91615
+ function slugify(s) {
91616
+ const out = String(s).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 60).replace(/-+$/g, "");
91617
+ return out || "task";
91618
+ }
91619
+
91670
91620
  // src/triage.ts
91671
91621
  var triageDir = (board) => path26.join(board, "triage");
91672
- var rejectedDir = (board) => path26.join(board, ".archive", ".sync");
91622
+ var rejectedDir = (board) => path26.join(board, ".archive", REJECTIONS_TO_REVIEW);
91673
91623
  var SCRATCH = ["dismissed", "archived"];
91674
91624
  var stamp = (at2) => formatStamp(at2 ? new Date(at2) : /* @__PURE__ */ new Date());
91675
91625
  function slugOf(title) {
@@ -91738,6 +91688,24 @@ function clearLaid(board) {
91738
91688
  import fs24 from "node:fs";
91739
91689
  import path27 from "node:path";
91740
91690
 
91691
+ // ../cli/src/lib/spec-agent-names.ts
91692
+ var LEGACY_SPEC_AGENT_NAMES = {
91693
+ "recommend-tech-stack": "tech-stack-advisor",
91694
+ "technology-selection": "tech-stack-advisor",
91695
+ "ui-design": "ui-designer",
91696
+ // Renamed in #945 and folded into the editor in #1057; its asset memory stays in
91697
+ // `memory/agents/video-assets/`.
91698
+ "video-assets": "hyperframes-editor",
91699
+ // Renamed in #1502: it reads chats, and writes memory as a result.
91700
+ "memory-reviewer": "chat-reviewer",
91701
+ // Folded into `copywriting` in #1582.
91702
+ "user-docs": "copywriting"
91703
+ };
91704
+ var canonicalSpecAgent = (name) => {
91705
+ const asked = name.trim();
91706
+ return LEGACY_SPEC_AGENT_NAMES[asked] ?? asked;
91707
+ };
91708
+
91741
91709
  // ../cli/src/lib/agent/workflow-def.ts
91742
91710
  var WORKFLOW_ID = /^[a-z0-9]+(-[a-z0-9]+)*$/;
91743
91711
  var OLD_KEYS = ["stages", "delivers", "helpers", "every"];
@@ -92002,9 +91970,9 @@ function mcpArgs(runtime, servers, file2) {
92002
91970
  ]).join(" ");
92003
91971
  }
92004
91972
  var MCP_KEY = "mcpConfig";
92005
- var wait = (ms2) => new Promise((resolve2) => setTimeout(resolve2, ms2));
92006
- async function stopRuns(akb, ws, id, since, ms2) {
92007
- const until = Date.now() + ms2;
91973
+ var wait = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
91974
+ async function stopRuns(akb, ws, id, since, ms) {
91975
+ const until = Date.now() + ms;
92008
91976
  const call = (args) => runAkb(akb, [...args, "--board", ws.board], { cwd: ws.cwd, board: ws.board });
92009
91977
  while (Date.now() < until) {
92010
91978
  const runs = answerOf2(await call(["run", "list", "--card", String(id), "--all", "--json"]))?.runs;
@@ -92016,8 +91984,8 @@ async function stopRuns(akb, ws, id, since, ms2) {
92016
91984
  }
92017
91985
  var working = /* @__PURE__ */ new Map();
92018
91986
  var workKey = (ws, id) => `${ws.board}#${id}`;
92019
- async function stopLeftBehind(akb, ws, id, ms2) {
92020
- if (!working.has(workKey(ws, id))) await stopRuns(akb, ws, id, 0, ms2);
91987
+ async function stopLeftBehind(akb, ws, id, ms) {
91988
+ if (!working.has(workKey(ws, id))) await stopRuns(akb, ws, id, 0, ms);
92021
91989
  }
92022
91990
  function deliveryEnding(ws, id) {
92023
91991
  if (!id) return null;
@@ -92094,11 +92062,11 @@ function logLines(show, event2) {
92094
92062
  };
92095
92063
  }
92096
92064
  function boardAkb(job, ws, deps, io, task) {
92097
- return async (args, show = false) => {
92065
+ return async (args, show = false, env2) => {
92098
92066
  const at2 = args.includes("--") ? args.indexOf("--") : args.length;
92099
92067
  const full = [...args.slice(0, at2), "--board", ws.board, ...args.slice(at2)];
92100
92068
  const log = show ? logLines(io.show, io.event) : void 0;
92101
- const ran = await runAkb(deps.akb, full, { cwd: ws.cwd, board: ws.board, task, line: job.languageLine ?? "", show: log?.push, track: io.track });
92069
+ const ran = await runAkb(deps.akb, full, { cwd: ws.cwd, board: ws.board, task, line: job.languageLine ?? "", env: env2, show: log?.push, track: io.track });
92102
92070
  log?.end();
92103
92071
  return ran;
92104
92072
  };
@@ -92179,7 +92147,7 @@ async function reviewRejections(job, ws, deps, io) {
92179
92147
  const akb = boardAkb(job, ws, deps, io);
92180
92148
  return withBoard(ws, async (push2) => {
92181
92149
  const laid = layOut(ws.board, read.value);
92182
- const ran = await akb(["review-dismissals", "--all", "--follow", "--events", "--json"], true);
92150
+ const ran = await akb(["review-dismissals", "--follow", "--events", "--json"], true);
92183
92151
  clearLaid(ws.board);
92184
92152
  resetSorted(ws);
92185
92153
  const runs = (answerOf2(await akb(["run", "list", "--all", "--json"]))?.runs ?? []).filter((r2) => (r2.startedAt ?? 0) >= since);
@@ -92196,6 +92164,15 @@ async function learnRejections(job, ws, deps, io) {
92196
92164
  if (failure) console.error(`runner: rejections not learned: ${failure}`);
92197
92165
  return runs;
92198
92166
  }
92167
+ async function scheduledEnv(ws, deps) {
92168
+ const read = await deps.api.readAgents(deps.machineId, ws.project);
92169
+ if (!read.ok) {
92170
+ console.error(`runner: scheduled agents not read: ${read.error}`);
92171
+ return {};
92172
+ }
92173
+ const names2 = read.value.agents.filter((a3) => a3.workflow).map((a3) => a3.name);
92174
+ return { [SCHEDULED_AGENTS_ENV]: [...new Set(names2)].join(",") };
92175
+ }
92199
92176
  async function runAgent(job, ws, deps, io) {
92200
92177
  const since = Date.now();
92201
92178
  const failed = await setUp(job, ws, deps, io);
@@ -92210,7 +92187,8 @@ async function runAgent(job, ws, deps, io) {
92210
92187
  const args = workflow ? ["agent", "run", workflowName(workflow), name] : name === "reflect" ? ["reflect", "--cards", ...tasks.map((t2) => String(t2.number))] : [name];
92211
92188
  const akb = boardAkb(job, ws, deps, io, ws.cloudTask ?? void 0);
92212
92189
  await akb(["run", "list", "--all", "--json"]);
92213
- const ran = await akb([...args, "--follow", "--events", "--json"], true);
92190
+ const env2 = name === "reflect" && !workflow ? await scheduledEnv(ws, deps) : void 0;
92191
+ const ran = await akb([...args, "--follow", "--events", "--json"], true, env2);
92214
92192
  if (io.lost()) return { ok: false, reason: "" };
92215
92193
  const answer = answerOf2(ran);
92216
92194
  if (ran.code !== 0) return { ok: false, reason: firstLine(answer?.error?.message?.replace(/^run \S+ ended \w+: /, "")) ?? refusal2(ran) };
@@ -92360,7 +92338,7 @@ ${draftLine(ws)}
92360
92338
  return { ok: true, report: { card: card2 } };
92361
92339
  }
92362
92340
  function carryArgs(verb) {
92363
- if (!["refine", "resolve", "revise"].includes(verb)) return [];
92341
+ if (!["refine", "resolve", "revise", "implement"].includes(verb)) return [];
92364
92342
  const transcript = writeTranscript(job, path28.join(ws.board, ".sync", `${ws.task}.discussion`));
92365
92343
  return [
92366
92344
  ...job.resume ? ["--session", job.resume, ...job.fork ? ["--fork"] : []] : [],
@@ -92389,8 +92367,8 @@ function holdMachine(kind, onHeld, onWaiting) {
92389
92367
  let waiting = null;
92390
92368
  let timer = null;
92391
92369
  const peers = /* @__PURE__ */ new Set();
92392
- const later = (ms2) => {
92393
- if (!closed) timer = setTimeout(attempt, ms2);
92370
+ const later = (ms) => {
92371
+ if (!closed) timer = setTimeout(attempt, ms);
92394
92372
  };
92395
92373
  const attempt = () => {
92396
92374
  timer = null;
@@ -92708,6 +92686,7 @@ function streamOut(deps, id, lease) {
92708
92686
  const stored = new Promise((resolve2) => ended2 = resolve2);
92709
92687
  const children = /* @__PURE__ */ new Set();
92710
92688
  const kill = (child) => {
92689
+ if (!child.pid) return;
92711
92690
  child.kill("SIGTERM");
92712
92691
  setTimeout(() => child.kill("SIGKILL"), KILL_GRACE_MS).unref();
92713
92692
  };
@@ -93073,10 +93052,11 @@ async function runAgentJob(job, deps, track, keep2) {
93073
93052
  var quietLines = (plan2, chunk) => chunk.split("\n").filter((line) => line && !plan2.quiet(line)).map((line) => `${line}
93074
93053
  `).join("");
93075
93054
  var stop = (child) => {
93055
+ if (!child.pid) return;
93076
93056
  child.kill("SIGTERM");
93077
93057
  setTimeout(() => child.kill("SIGKILL"), KILL_GRACE_MS).unref();
93078
93058
  };
93079
- var wait2 = (ms2) => new Promise((resolve2) => setTimeout(resolve2, ms2));
93059
+ var wait2 = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
93080
93060
  var held3 = (deps, lease) => Date.now() - lease.at < deps.leaseMs;
93081
93061
  async function whileOffline(deps, id, lease, attempt) {
93082
93062
  for (; ; ) {
@@ -93122,8 +93102,8 @@ async function runSecret(job, deps) {
93122
93102
  await deps.api.finishJob(deps.machineId, job.id, "done", "");
93123
93103
  }
93124
93104
  async function runTest(job, deps) {
93125
- const finish2 = async (outcome, reason, ms3) => {
93126
- await deps.api.finishJob(deps.machineId, job.id, outcome, reason, ms3 === void 0 ? void 0 : { ms: ms3 });
93105
+ const finish2 = async (outcome, reason, ms2) => {
93106
+ await deps.api.finishJob(deps.machineId, job.id, outcome, reason, ms2 === void 0 ? void 0 : { ms: ms2 });
93127
93107
  };
93128
93108
  const report2 = (await deps.runtimes()).find((r2) => r2.name === job.runtime);
93129
93109
  if (!report2?.installed) return finish2("failed", "not_installed");
@@ -93145,10 +93125,10 @@ async function runTest(job, deps) {
93145
93125
  ]);
93146
93126
  clearTimeout(timer);
93147
93127
  stop(child);
93148
- const ms3 = Date.now() - startedAt;
93149
- if (end === "timeout") return finish2("failed", "timeout", ms3);
93150
- if (end instanceof Error) return end.code === "ENOENT" ? finish2("failed", "not_installed") : finish2("failed", end.message.slice(0, 300), ms3);
93151
- return end.ok ? finish2("done", "", ms3) : finish2("failed", (end.error || "The connector stopped.").slice(0, 300), ms3);
93128
+ const ms2 = Date.now() - startedAt;
93129
+ if (end === "timeout") return finish2("failed", "timeout", ms2);
93130
+ if (end instanceof Error) return end.code === "ENOENT" ? finish2("failed", "not_installed") : finish2("failed", end.message.slice(0, 300), ms2);
93131
+ return end.ok ? finish2("done", "", ms2) : finish2("failed", (end.error || "The connector stopped.").slice(0, 300), ms2);
93152
93132
  }
93153
93133
  const renderer = run2.renderer;
93154
93134
  const ended2 = await new Promise((resolve2) => {
@@ -93182,13 +93162,13 @@ async function runTest(job, deps) {
93182
93162
  resolve2({ code, said });
93183
93163
  });
93184
93164
  });
93185
- const ms2 = Date.now() - startedAt;
93186
- if (ended2.timedOut) return finish2("failed", "timeout", ms2);
93165
+ const ms = Date.now() - startedAt;
93166
+ if (ended2.timedOut) return finish2("failed", "timeout", ms);
93187
93167
  if (ended2.error?.code === "ENOENT") return finish2("failed", "not_installed");
93188
93168
  renderer.flush();
93189
93169
  const failure = ended2.error?.message ?? renderer.failure?.() ?? (ended2.code === 0 ? void 0 : ended2.said.trim().split("\n").at(-1) || `Exited with code ${ended2.code}.`);
93190
- if (failure) return finish2("failed", failure.slice(0, 300), ms2);
93191
- return finish2("done", "", ms2);
93170
+ if (failure) return finish2("failed", failure.slice(0, 300), ms);
93171
+ return finish2("done", "", ms);
93192
93172
  }
93193
93173
  function report(job, run2, turn) {
93194
93174
  const context = turn ? turn.context : run2.renderer?.context?.();
@@ -93279,9 +93259,10 @@ function keepPresence(machineId2, pingMs = PING_MS) {
93279
93259
  }
93280
93260
 
93281
93261
  // src/connect.ts
93282
- var HEARTBEAT_MS2 = 5 * 6e4;
93262
+ var HEARTBEAT_MS2 = 10 * 6e4;
93283
93263
  var POLL_MS = 6e4;
93284
93264
  var BACKOFF_MS3 = [1e3, 2e3, 5e3, 1e4, 3e4];
93265
+ var LOOK_LATE_MS = 6e4;
93285
93266
  function startRunner(options) {
93286
93267
  let registration = null;
93287
93268
  let connected = false;
@@ -93313,10 +93294,10 @@ function startRunner(options) {
93313
93294
  return found;
93314
93295
  };
93315
93296
  const idle2 = () => running.size ? t.running(running.size) : t.connected(registration.machineName);
93316
- const schedule = (ms2) => {
93297
+ const schedule = (ms) => {
93317
93298
  if (closed) return;
93318
93299
  if (timer) clearTimeout(timer);
93319
- timer = setTimeout(tick, ms2);
93300
+ timer = setTimeout(tick, ms);
93320
93301
  };
93321
93302
  let looking = false;
93322
93303
  const agentsDue = async () => {
@@ -93330,8 +93311,18 @@ function startRunner(options) {
93330
93311
  looking = false;
93331
93312
  }
93332
93313
  };
93333
- const agentsTimer = setInterval(() => void agentsDue(), options.agentsMs ?? AGENTS_EVERY_MS);
93334
- agentsTimer.unref?.();
93314
+ let agentsTimer = null;
93315
+ const lookNext = () => {
93316
+ if (closed) return;
93317
+ const at2 = (options.nextLook ?? nextHour)(Date.now());
93318
+ agentsTimer = setTimeout(() => {
93319
+ const late = Date.now() - at2;
93320
+ if (late >= 0 && late < LOOK_LATE_MS) void agentsDue();
93321
+ lookNext();
93322
+ }, at2 - Date.now());
93323
+ agentsTimer.unref?.();
93324
+ };
93325
+ lookNext();
93335
93326
  let sweeping = false;
93336
93327
  let swept = false;
93337
93328
  const sweep = async () => {
@@ -93391,7 +93382,6 @@ function startRunner(options) {
93391
93382
  await readJobs();
93392
93383
  if (!live?.joined()) boards?.pullAll();
93393
93384
  void reviewDue();
93394
- void agentsDue();
93395
93385
  schedule(live?.joined() ? options.heartbeatMs ?? HEARTBEAT_MS2 : Math.min(options.pollMs ?? POLL_MS, options.heartbeatMs ?? HEARTBEAT_MS2));
93396
93386
  };
93397
93387
  const openLive = () => {
@@ -93487,7 +93477,7 @@ function startRunner(options) {
93487
93477
  closed = true;
93488
93478
  lock.release();
93489
93479
  if (timer) clearTimeout(timer);
93490
- clearInterval(agentsTimer);
93480
+ if (agentsTimer) clearTimeout(agentsTimer);
93491
93481
  clearInterval(sweepTimer);
93492
93482
  live?.close();
93493
93483
  presence?.close();
@@ -93655,7 +93645,7 @@ async function runDesktop(tell2) {
93655
93645
  const shown = /* @__PURE__ */ new Set();
93656
93646
  let wake = () => {
93657
93647
  };
93658
- const readInbox3 = () => {
93648
+ const readInbox2 = () => {
93659
93649
  if (inboxTimer) clearTimeout(inboxTimer);
93660
93650
  inboxTimer = setTimeout(async () => {
93661
93651
  const inbox = await readInbox();
@@ -93717,7 +93707,7 @@ async function runDesktop(tell2) {
93717
93707
  void readFolders();
93718
93708
  void readPlan2();
93719
93709
  void readAlerts();
93720
- readInbox3();
93710
+ readInbox2();
93721
93711
  };
93722
93712
  const onConnected = () => {
93723
93713
  tell2({ type: "connected" });
@@ -93755,11 +93745,11 @@ async function runDesktop(tell2) {
93755
93745
  notify = command.on;
93756
93746
  return runner?.renew();
93757
93747
  case "refresh":
93758
- readInbox3();
93748
+ readInbox2();
93759
93749
  return void readAlerts();
93760
93750
  case "read":
93761
93751
  await readAlert(command.alert);
93762
- return readInbox3();
93752
+ return readInbox2();
93763
93753
  case "addFolder": {
93764
93754
  const project = command.project;
93765
93755
  const why = refusal(command.path);
@@ -93829,11 +93819,11 @@ async function runDesktop(tell2) {
93829
93819
  onDisconnected: () => emit({ type: "connection", state: "reconnecting" }),
93830
93820
  onHint: (payload) => {
93831
93821
  if (payload.alertId || !payload.taskId) void readAlerts();
93832
- if (!payload.jobId) readInbox3();
93822
+ if (!payload.jobId) readInbox2();
93833
93823
  }
93834
93824
  });
93835
93825
  poller = setInterval(() => {
93836
- readInbox3();
93826
+ readInbox2();
93837
93827
  void readAlerts();
93838
93828
  }, POLL_MS2);
93839
93829
  void runner.stopped.then(wake);