wildcrane-runner 0.6.3 → 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.3 — 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;
@@ -426,19 +426,19 @@ var require_react_production = __commonJS({
426
426
  _init: lazyInitializer
427
427
  };
428
428
  };
429
- exports.memo = function(type, compare) {
429
+ exports.memo = function(type, compare2) {
430
430
  return {
431
431
  $$typeof: REACT_MEMO_TYPE,
432
432
  type,
433
- compare: void 0 === compare ? null : compare
433
+ compare: void 0 === compare2 ? null : compare2
434
434
  };
435
435
  };
436
436
  exports.startTransition = startTransition;
437
437
  exports.unstable_useCacheRefresh = function() {
438
438
  return ReactSharedInternals.H.useCacheRefresh();
439
439
  };
440
- exports.use = function(usable) {
441
- return ReactSharedInternals.H.use(usable);
440
+ exports.use = function(usable2) {
441
+ return ReactSharedInternals.H.use(usable2);
442
442
  };
443
443
  exports.useActionState = function(action, initialState, permalink) {
444
444
  return ReactSharedInternals.H.useActionState(action, initialState, permalink);
@@ -1386,18 +1386,18 @@ var require_react_development = __commonJS({
1386
1386
  lazyType._debugInfo = [{ awaited: ioInfo }];
1387
1387
  return lazyType;
1388
1388
  };
1389
- exports.memo = function(type, compare) {
1389
+ exports.memo = function(type, compare2) {
1390
1390
  null == type && console.error(
1391
1391
  "memo: The first argument must be a component. Instead received: %s",
1392
1392
  null === type ? "null" : typeof type
1393
1393
  );
1394
- compare = {
1394
+ compare2 = {
1395
1395
  $$typeof: REACT_MEMO_TYPE,
1396
1396
  type,
1397
- compare: void 0 === compare ? null : compare
1397
+ compare: void 0 === compare2 ? null : compare2
1398
1398
  };
1399
1399
  var ownName;
1400
- Object.defineProperty(compare, "displayName", {
1400
+ Object.defineProperty(compare2, "displayName", {
1401
1401
  enumerable: false,
1402
1402
  configurable: true,
1403
1403
  get: function() {
@@ -1408,14 +1408,14 @@ var require_react_development = __commonJS({
1408
1408
  type.name || type.displayName || (Object.defineProperty(type, "name", { value: name }), type.displayName = name);
1409
1409
  }
1410
1410
  });
1411
- return compare;
1411
+ return compare2;
1412
1412
  };
1413
1413
  exports.startTransition = startTransition;
1414
1414
  exports.unstable_useCacheRefresh = function() {
1415
1415
  return resolveDispatcher().useCacheRefresh();
1416
1416
  };
1417
- exports.use = function(usable) {
1418
- return resolveDispatcher().use(usable);
1417
+ exports.use = function(usable2) {
1418
+ return resolveDispatcher().use(usable2);
1419
1419
  };
1420
1420
  exports.useActionState = function(action, initialState, permalink) {
1421
1421
  return resolveDispatcher().useActionState(
@@ -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 },
@@ -4909,15 +4909,15 @@ var require_react_dom_server_legacy_node_production = __commonJS({
4909
4909
  readContext: function(context) {
4910
4910
  return context._currentValue2;
4911
4911
  },
4912
- use: function(usable) {
4913
- if (null !== usable && "object" === typeof usable) {
4914
- if ("function" === typeof usable.then) return unwrapThenable(usable);
4915
- if (usable.$$typeof === REACT_RECOVERABLE_TYPE)
4916
- throw createRecoverableError(usable);
4917
- if (usable.$$typeof === REACT_CONTEXT_TYPE)
4918
- return usable._currentValue2;
4919
- }
4920
- throw Error("An unsupported type was passed to use(): " + String(usable));
4912
+ use: function(usable2) {
4913
+ if (null !== usable2 && "object" === typeof usable2) {
4914
+ if ("function" === typeof usable2.then) return unwrapThenable(usable2);
4915
+ if (usable2.$$typeof === REACT_RECOVERABLE_TYPE)
4916
+ throw createRecoverableError(usable2);
4917
+ if (usable2.$$typeof === REACT_CONTEXT_TYPE)
4918
+ return usable2._currentValue2;
4919
+ }
4920
+ throw Error("An unsupported type was passed to use(): " + String(usable2));
4921
4921
  },
4922
4922
  useContext: function(context) {
4923
4923
  resolveCurrentlyRenderingComponent();
@@ -7517,7 +7517,7 @@ var require_react_dom_server_node_production = __commonJS({
7517
7517
  "node_modules/react-dom/cjs/react-dom-server.node.production.js"(exports) {
7518
7518
  "use strict";
7519
7519
  var util = __require("util");
7520
- var crypto5 = __require("crypto");
7520
+ var crypto6 = __require("crypto");
7521
7521
  var async_hooks = __require("async_hooks");
7522
7522
  var React4 = require_react();
7523
7523
  var ReactDOM = require_react_dom();
@@ -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
@@ -10382,7 +10382,7 @@ var require_react_dom_server_node_production = __commonJS({
10382
10382
  function createPostbackActionStateKey(permalink, componentKeyPath, hookIndex) {
10383
10383
  if (void 0 !== permalink) return "p" + permalink;
10384
10384
  permalink = JSON.stringify([componentKeyPath, null, hookIndex]);
10385
- componentKeyPath = crypto5.createHash("md5");
10385
+ componentKeyPath = crypto6.createHash("md5");
10386
10386
  componentKeyPath.update(permalink);
10387
10387
  return "k" + componentKeyPath.digest("hex");
10388
10388
  }
@@ -10440,14 +10440,14 @@ var require_react_dom_server_node_production = __commonJS({
10440
10440
  readContext: function(context) {
10441
10441
  return context._currentValue;
10442
10442
  },
10443
- use: function(usable) {
10444
- if (null !== usable && "object" === typeof usable) {
10445
- if ("function" === typeof usable.then) return unwrapThenable(usable);
10446
- if (usable.$$typeof === REACT_RECOVERABLE_TYPE)
10447
- throw createRecoverableError(usable);
10448
- if (usable.$$typeof === REACT_CONTEXT_TYPE) return usable._currentValue;
10449
- }
10450
- throw Error("An unsupported type was passed to use(): " + String(usable));
10443
+ use: function(usable2) {
10444
+ if (null !== usable2 && "object" === typeof usable2) {
10445
+ if ("function" === typeof usable2.then) return unwrapThenable(usable2);
10446
+ if (usable2.$$typeof === REACT_RECOVERABLE_TYPE)
10447
+ throw createRecoverableError(usable2);
10448
+ if (usable2.$$typeof === REACT_CONTEXT_TYPE) return usable2._currentValue;
10449
+ }
10450
+ throw Error("An unsupported type was passed to use(): " + String(usable2));
10451
10451
  },
10452
10452
  useContext: function(context) {
10453
10453
  resolveCurrentlyRenderingComponent();
@@ -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
  }
@@ -21050,17 +21050,17 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
21050
21050
  "Suspense Exception: This is not a real error! It's an implementation detail of `use` to interrupt the current render. You must either rethrow it immediately, or move the `use` call outside of the `try/catch` block. Capturing without rethrowing will lead to unexpected behavior.\n\nTo handle async errors, wrap your component in an error boundary, or call the promise's `.catch` method and pass the result to `use`."
21051
21051
  ), suspendedThenable = null, shouldCaptureSuspendedCallSite = false, suspendedCallSiteStack = null, suspendedCallSiteDebugTask = null, objectIs = "function" === typeof Object.is ? Object.is : is, currentlyRenderingComponent = null, currentlyRenderingTask = null, currentlyRenderingRequest = null, currentlyRenderingKeyPath = null, firstWorkInProgressHook = null, workInProgressHook = null, isReRender = false, didScheduleRenderPhaseUpdate = false, localIdCounter = 0, actionStateCounter = 0, actionStateMatchingIndex = -1, thenableIndexCounter = 0, thenableState = null, renderPhaseUpdates = null, numberOfReRenders = 0, isInHookUserCodeInDev = false, currentHookNameInDev, HooksDispatcher = {
21052
21052
  readContext,
21053
- use: function(usable) {
21054
- if (null !== usable && "object" === typeof usable) {
21055
- if ("function" === typeof usable.then)
21056
- return unwrapThenable(usable);
21057
- if (usable.$$typeof === REACT_RECOVERABLE_TYPE)
21058
- throw createRecoverableError(usable);
21059
- if (usable.$$typeof === REACT_CONTEXT_TYPE)
21060
- return readContext(usable);
21053
+ use: function(usable2) {
21054
+ if (null !== usable2 && "object" === typeof usable2) {
21055
+ if ("function" === typeof usable2.then)
21056
+ return unwrapThenable(usable2);
21057
+ if (usable2.$$typeof === REACT_RECOVERABLE_TYPE)
21058
+ throw createRecoverableError(usable2);
21059
+ if (usable2.$$typeof === REACT_CONTEXT_TYPE)
21060
+ return readContext(usable2);
21061
21061
  }
21062
21062
  throw Error(
21063
- "An unsupported type was passed to use(): " + String(usable)
21063
+ "An unsupported type was passed to use(): " + String(usable2)
21064
21064
  );
21065
21065
  },
21066
21066
  useContext: function(context) {
@@ -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),
@@ -24376,7 +24376,7 @@ var require_react_dom_server_node_development = __commonJS({
24376
24376
  function createPostbackActionStateKey(permalink, componentKeyPath, hookIndex) {
24377
24377
  if (void 0 !== permalink) return "p" + permalink;
24378
24378
  permalink = JSON.stringify([componentKeyPath, null, hookIndex]);
24379
- componentKeyPath = crypto5.createHash("md5");
24379
+ componentKeyPath = crypto6.createHash("md5");
24380
24380
  componentKeyPath.update(permalink);
24381
24381
  return "k" + componentKeyPath.digest("hex");
24382
24382
  }
@@ -28038,7 +28038,7 @@ var require_react_dom_server_node_development = __commonJS({
28038
28038
  }
28039
28039
  };
28040
28040
  }
28041
- var util = __require("util"), crypto5 = __require("crypto"), async_hooks = __require("async_hooks"), React4 = require_react(), ReactDOM = require_react_dom(), stream = __require("stream"), REACT_ELEMENT_TYPE = /* @__PURE__ */ Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = /* @__PURE__ */ Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = /* @__PURE__ */ Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = /* @__PURE__ */ Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = /* @__PURE__ */ Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = /* @__PURE__ */ Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = /* @__PURE__ */ Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = /* @__PURE__ */ Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = /* @__PURE__ */ Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = /* @__PURE__ */ Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = /* @__PURE__ */ Symbol.for("react.memo"), REACT_LAZY_TYPE = /* @__PURE__ */ Symbol.for("react.lazy"), REACT_SCOPE_TYPE = /* @__PURE__ */ Symbol.for("react.scope"), REACT_ACTIVITY_TYPE = /* @__PURE__ */ Symbol.for("react.activity"), REACT_LEGACY_HIDDEN_TYPE = /* @__PURE__ */ Symbol.for("react.legacy_hidden"), REACT_MEMO_CACHE_SENTINEL = /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel"), REACT_VIEW_TRANSITION_TYPE = /* @__PURE__ */ Symbol.for("react.view_transition"), REACT_RECOVERABLE_TYPE = /* @__PURE__ */ Symbol.for("react.recoverable"), MAYBE_ITERATOR_SYMBOL = Symbol.iterator, ASYNC_ITERATOR = Symbol.asyncIterator, REACT_OPTIMISTIC_KEY = /* @__PURE__ */ Symbol.for("react.optimistic_key"), isArrayImpl = Array.isArray, jsxPropsParents = /* @__PURE__ */ new WeakMap(), jsxChildrenParents = /* @__PURE__ */ new WeakMap(), CLIENT_REFERENCE_TAG = /* @__PURE__ */ Symbol.for("react.client.reference"), hasOwnProperty = Object.prototype.hasOwnProperty, supportsArrayBufferDetached = hasOwnProperty.call(
28041
+ var util = __require("util"), crypto6 = __require("crypto"), async_hooks = __require("async_hooks"), React4 = require_react(), ReactDOM = require_react_dom(), stream = __require("stream"), REACT_ELEMENT_TYPE = /* @__PURE__ */ Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = /* @__PURE__ */ Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = /* @__PURE__ */ Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = /* @__PURE__ */ Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = /* @__PURE__ */ Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = /* @__PURE__ */ Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = /* @__PURE__ */ Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = /* @__PURE__ */ Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = /* @__PURE__ */ Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = /* @__PURE__ */ Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = /* @__PURE__ */ Symbol.for("react.memo"), REACT_LAZY_TYPE = /* @__PURE__ */ Symbol.for("react.lazy"), REACT_SCOPE_TYPE = /* @__PURE__ */ Symbol.for("react.scope"), REACT_ACTIVITY_TYPE = /* @__PURE__ */ Symbol.for("react.activity"), REACT_LEGACY_HIDDEN_TYPE = /* @__PURE__ */ Symbol.for("react.legacy_hidden"), REACT_MEMO_CACHE_SENTINEL = /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel"), REACT_VIEW_TRANSITION_TYPE = /* @__PURE__ */ Symbol.for("react.view_transition"), REACT_RECOVERABLE_TYPE = /* @__PURE__ */ Symbol.for("react.recoverable"), MAYBE_ITERATOR_SYMBOL = Symbol.iterator, ASYNC_ITERATOR = Symbol.asyncIterator, REACT_OPTIMISTIC_KEY = /* @__PURE__ */ Symbol.for("react.optimistic_key"), isArrayImpl = Array.isArray, jsxPropsParents = /* @__PURE__ */ new WeakMap(), jsxChildrenParents = /* @__PURE__ */ new WeakMap(), CLIENT_REFERENCE_TAG = /* @__PURE__ */ Symbol.for("react.client.reference"), hasOwnProperty = Object.prototype.hasOwnProperty, supportsArrayBufferDetached = hasOwnProperty.call(
28042
28042
  ArrayBuffer.prototype,
28043
28043
  "detached"
28044
28044
  ), didWarnAboutMissingArrayBufferDetached = false, scheduleMicrotask = queueMicrotask, currentView = null, writtenBytes = 0, destinationHasCapacity$1 = true, textEncoder = new util.TextEncoder(), assign = Object.assign, VALID_ATTRIBUTE_NAME_REGEX = RegExp(
@@ -28999,17 +28999,17 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
28999
28999
  "Suspense Exception: This is not a real error! It's an implementation detail of `use` to interrupt the current render. You must either rethrow it immediately, or move the `use` call outside of the `try/catch` block. Capturing without rethrowing will lead to unexpected behavior.\n\nTo handle async errors, wrap your component in an error boundary, or call the promise's `.catch` method and pass the result to `use`."
29000
29000
  ), suspendedThenable = null, shouldCaptureSuspendedCallSite = false, suspendedCallSiteStack = null, suspendedCallSiteDebugTask = null, objectIs = "function" === typeof Object.is ? Object.is : is, currentlyRenderingComponent = null, currentlyRenderingTask = null, currentlyRenderingRequest = null, currentlyRenderingKeyPath = null, firstWorkInProgressHook = null, workInProgressHook = null, isReRender = false, didScheduleRenderPhaseUpdate = false, localIdCounter = 0, actionStateCounter = 0, actionStateMatchingIndex = -1, thenableIndexCounter = 0, thenableState = null, renderPhaseUpdates = null, numberOfReRenders = 0, isInHookUserCodeInDev = false, currentHookNameInDev, HooksDispatcher = {
29001
29001
  readContext,
29002
- use: function(usable) {
29003
- if (null !== usable && "object" === typeof usable) {
29004
- if ("function" === typeof usable.then)
29005
- return unwrapThenable(usable);
29006
- if (usable.$$typeof === REACT_RECOVERABLE_TYPE)
29007
- throw createRecoverableError(usable);
29008
- if (usable.$$typeof === REACT_CONTEXT_TYPE)
29009
- return readContext(usable);
29002
+ use: function(usable2) {
29003
+ if (null !== usable2 && "object" === typeof usable2) {
29004
+ if ("function" === typeof usable2.then)
29005
+ return unwrapThenable(usable2);
29006
+ if (usable2.$$typeof === REACT_RECOVERABLE_TYPE)
29007
+ throw createRecoverableError(usable2);
29008
+ if (usable2.$$typeof === REACT_CONTEXT_TYPE)
29009
+ return readContext(usable2);
29010
29010
  }
29011
29011
  throw Error(
29012
- "An unsupported type was passed to use(): " + String(usable)
29012
+ "An unsupported type was passed to use(): " + String(usable2)
29013
29013
  );
29014
29014
  },
29015
29015
  useContext: function(context) {
@@ -41256,8 +41256,8 @@ var require_JSXTransformer = __commonJS({
41256
41256
  }
41257
41257
  if (this.isAutomaticRuntime) {
41258
41258
  if (this.importProcessor) {
41259
- for (const [path31, resolvedName] of Object.entries(this.cjsAutomaticModuleNameResolutions)) {
41260
- prefix += `var ${resolvedName} = require("${path31}");`;
41259
+ for (const [path34, resolvedName] of Object.entries(this.cjsAutomaticModuleNameResolutions)) {
41260
+ prefix += `var ${resolvedName} = require("${path34}");`;
41261
41261
  }
41262
41262
  } else {
41263
41263
  const { createElement: createElementResolution, ...otherResolutions } = this.esmAutomaticImportNameResolutions;
@@ -41450,11 +41450,11 @@ var require_JSXTransformer = __commonJS({
41450
41450
  }
41451
41451
  claimAutoImportedName(funcName, importPathSuffix) {
41452
41452
  if (this.importProcessor) {
41453
- const path31 = this.jsxImportSource + importPathSuffix;
41454
- if (!this.cjsAutomaticModuleNameResolutions[path31]) {
41455
- this.cjsAutomaticModuleNameResolutions[path31] = this.importProcessor.getFreeIdentifierForPath(path31);
41453
+ const path34 = this.jsxImportSource + importPathSuffix;
41454
+ if (!this.cjsAutomaticModuleNameResolutions[path34]) {
41455
+ this.cjsAutomaticModuleNameResolutions[path34] = this.importProcessor.getFreeIdentifierForPath(path34);
41456
41456
  }
41457
- return `${this.cjsAutomaticModuleNameResolutions[path31]}.${funcName}`;
41457
+ return `${this.cjsAutomaticModuleNameResolutions[path34]}.${funcName}`;
41458
41458
  } else {
41459
41459
  if (!this.esmAutomaticImportNameResolutions[funcName]) {
41460
41460
  this.esmAutomaticImportNameResolutions[funcName] = this.nameManager.claimFreeName(
@@ -41890,7 +41890,7 @@ var require_CJSImportProcessor = __commonJS({
41890
41890
  */
41891
41891
  pruneTypeOnlyImports() {
41892
41892
  this.nonTypeIdentifiers = _getNonTypeIdentifiers.getNonTypeIdentifiers.call(void 0, this.tokens, this.options);
41893
- for (const [path31, importInfo] of this.importInfoByPath.entries()) {
41893
+ for (const [path34, importInfo] of this.importInfoByPath.entries()) {
41894
41894
  if (importInfo.hasBareImport || importInfo.hasStarExport || importInfo.exportStarNames.length > 0 || importInfo.namedExports.length > 0) {
41895
41895
  continue;
41896
41896
  }
@@ -41900,7 +41900,7 @@ var require_CJSImportProcessor = __commonJS({
41900
41900
  ...importInfo.namedImports.map(({ localName }) => localName)
41901
41901
  ];
41902
41902
  if (names2.every((name) => this.shouldAutomaticallyElideImportedName(name))) {
41903
- this.importsToReplace.set(path31, "");
41903
+ this.importsToReplace.set(path34, "");
41904
41904
  }
41905
41905
  }
41906
41906
  }
@@ -41908,7 +41908,7 @@ var require_CJSImportProcessor = __commonJS({
41908
41908
  return this.isTypeScriptTransformEnabled && !this.keepUnusedImports && !this.nonTypeIdentifiers.has(name);
41909
41909
  }
41910
41910
  generateImportReplacements() {
41911
- for (const [path31, importInfo] of this.importInfoByPath.entries()) {
41911
+ for (const [path34, importInfo] of this.importInfoByPath.entries()) {
41912
41912
  const {
41913
41913
  defaultNames,
41914
41914
  wildcardNames,
@@ -41918,17 +41918,17 @@ var require_CJSImportProcessor = __commonJS({
41918
41918
  hasStarExport
41919
41919
  } = importInfo;
41920
41920
  if (defaultNames.length === 0 && wildcardNames.length === 0 && namedImports.length === 0 && namedExports.length === 0 && exportStarNames.length === 0 && !hasStarExport) {
41921
- this.importsToReplace.set(path31, `require('${path31}');`);
41921
+ this.importsToReplace.set(path34, `require('${path34}');`);
41922
41922
  continue;
41923
41923
  }
41924
- const primaryImportName = this.getFreeIdentifierForPath(path31);
41924
+ const primaryImportName = this.getFreeIdentifierForPath(path34);
41925
41925
  let secondaryImportName;
41926
41926
  if (this.enableLegacyTypeScriptModuleInterop) {
41927
41927
  secondaryImportName = primaryImportName;
41928
41928
  } else {
41929
- secondaryImportName = wildcardNames.length > 0 ? wildcardNames[0] : this.getFreeIdentifierForPath(path31);
41929
+ secondaryImportName = wildcardNames.length > 0 ? wildcardNames[0] : this.getFreeIdentifierForPath(path34);
41930
41930
  }
41931
- let requireCode = `var ${primaryImportName} = require('${path31}');`;
41931
+ let requireCode = `var ${primaryImportName} = require('${path34}');`;
41932
41932
  if (wildcardNames.length > 0) {
41933
41933
  for (const wildcardName of wildcardNames) {
41934
41934
  const moduleExpr = this.enableLegacyTypeScriptModuleInterop ? primaryImportName : `${this.helperManager.getHelperName("interopRequireWildcard")}(${primaryImportName})`;
@@ -41956,7 +41956,7 @@ var require_CJSImportProcessor = __commonJS({
41956
41956
  "createStarExport"
41957
41957
  )}(${primaryImportName});`;
41958
41958
  }
41959
- this.importsToReplace.set(path31, requireCode);
41959
+ this.importsToReplace.set(path34, requireCode);
41960
41960
  for (const defaultName of defaultNames) {
41961
41961
  this.identifierReplacements.set(defaultName, `${secondaryImportName}.default`);
41962
41962
  }
@@ -41965,8 +41965,8 @@ var require_CJSImportProcessor = __commonJS({
41965
41965
  }
41966
41966
  }
41967
41967
  }
41968
- getFreeIdentifierForPath(path31) {
41969
- const components = path31.split("/");
41968
+ getFreeIdentifierForPath(path34) {
41969
+ const components = path34.split("/");
41970
41970
  const lastComponent = components[components.length - 1];
41971
41971
  const baseName = lastComponent.replace(/\W/g, "");
41972
41972
  return this.nameManager.claimFreeName(`_${baseName}`);
@@ -42011,8 +42011,8 @@ var require_CJSImportProcessor = __commonJS({
42011
42011
  if (!this.tokens.matches1AtIndex(index, _types.TokenType.string)) {
42012
42012
  throw new Error("Expected string token at the end of import statement.");
42013
42013
  }
42014
- const path31 = this.tokens.stringValueAtIndex(index);
42015
- const importInfo = this.getImportInfo(path31);
42014
+ const path34 = this.tokens.stringValueAtIndex(index);
42015
+ const importInfo = this.getImportInfo(path34);
42016
42016
  importInfo.defaultNames.push(...defaultNames);
42017
42017
  importInfo.wildcardNames.push(...wildcardNames);
42018
42018
  importInfo.namedImports.push(...namedImports);
@@ -42079,8 +42079,8 @@ var require_CJSImportProcessor = __commonJS({
42079
42079
  if (!this.tokens.matches1AtIndex(index, _types.TokenType.string)) {
42080
42080
  throw new Error("Expected string token at the end of import statement.");
42081
42081
  }
42082
- const path31 = this.tokens.stringValueAtIndex(index);
42083
- const importInfo = this.getImportInfo(path31);
42082
+ const path34 = this.tokens.stringValueAtIndex(index);
42083
+ const importInfo = this.getImportInfo(path34);
42084
42084
  importInfo.namedExports.push(...namedImports);
42085
42085
  }
42086
42086
  preprocessExportStarAtIndex(index) {
@@ -42095,8 +42095,8 @@ var require_CJSImportProcessor = __commonJS({
42095
42095
  if (!this.tokens.matches1AtIndex(index, _types.TokenType.string)) {
42096
42096
  throw new Error("Expected string token at the end of star export statement.");
42097
42097
  }
42098
- const path31 = this.tokens.stringValueAtIndex(index);
42099
- const importInfo = this.getImportInfo(path31);
42098
+ const path34 = this.tokens.stringValueAtIndex(index);
42099
+ const importInfo = this.getImportInfo(path34);
42100
42100
  if (exportedName !== null) {
42101
42101
  importInfo.exportStarNames.push(exportedName);
42102
42102
  } else {
@@ -42136,8 +42136,8 @@ var require_CJSImportProcessor = __commonJS({
42136
42136
  * Get a mutable import info object for this path, creating one if it doesn't
42137
42137
  * exist yet.
42138
42138
  */
42139
- getImportInfo(path31) {
42140
- const existingInfo = this.importInfoByPath.get(path31);
42139
+ getImportInfo(path34) {
42140
+ const existingInfo = this.importInfoByPath.get(path34);
42141
42141
  if (existingInfo) {
42142
42142
  return existingInfo;
42143
42143
  }
@@ -42150,7 +42150,7 @@ var require_CJSImportProcessor = __commonJS({
42150
42150
  exportStarNames: [],
42151
42151
  hasStarExport: false
42152
42152
  };
42153
- this.importInfoByPath.set(path31, newInfo);
42153
+ this.importInfoByPath.set(path34, newInfo);
42154
42154
  return newInfo;
42155
42155
  }
42156
42156
  addExportBinding(localName, exportedName) {
@@ -42730,16 +42730,16 @@ var require_resolve_uri_umd = __commonJS({
42730
42730
  }
42731
42731
  function parseFileUrl(input) {
42732
42732
  const match = fileRegex.exec(input);
42733
- const path31 = match[2];
42734
- return makeUrl("file:", "", match[1] || "", "", isAbsolutePath(path31) ? path31 : "/" + path31, match[3] || "", match[4] || "");
42733
+ const path34 = match[2];
42734
+ return makeUrl("file:", "", match[1] || "", "", isAbsolutePath(path34) ? path34 : "/" + path34, match[3] || "", match[4] || "");
42735
42735
  }
42736
- function makeUrl(scheme, user, host, port, path31, query, hash) {
42736
+ function makeUrl(scheme, user, host, port, path34, query, hash) {
42737
42737
  return {
42738
42738
  scheme,
42739
42739
  user,
42740
42740
  host,
42741
42741
  port,
42742
- path: path31,
42742
+ path: path34,
42743
42743
  query,
42744
42744
  hash,
42745
42745
  type: 7
@@ -42769,11 +42769,11 @@ var require_resolve_uri_umd = __commonJS({
42769
42769
  url.type = input ? input.startsWith("?") ? 3 : input.startsWith("#") ? 2 : 4 : 1;
42770
42770
  return url;
42771
42771
  }
42772
- function stripPathFilename(path31) {
42773
- if (path31.endsWith("/.."))
42774
- return path31;
42775
- const index = path31.lastIndexOf("/");
42776
- return path31.slice(0, index + 1);
42772
+ function stripPathFilename(path34) {
42773
+ if (path34.endsWith("/.."))
42774
+ return path34;
42775
+ const index = path34.lastIndexOf("/");
42776
+ return path34.slice(0, index + 1);
42777
42777
  }
42778
42778
  function mergePaths(url, base) {
42779
42779
  normalizePath(base, base.type);
@@ -42811,14 +42811,14 @@ var require_resolve_uri_umd = __commonJS({
42811
42811
  pieces[pointer++] = piece;
42812
42812
  positive++;
42813
42813
  }
42814
- let path31 = "";
42814
+ let path34 = "";
42815
42815
  for (let i = 1; i < pointer; i++) {
42816
- path31 += "/" + pieces[i];
42816
+ path34 += "/" + pieces[i];
42817
42817
  }
42818
- if (!path31 || addTrailingSlash && !path31.endsWith("/..")) {
42819
- path31 += "/";
42818
+ if (!path34 || addTrailingSlash && !path34.endsWith("/..")) {
42819
+ path34 += "/";
42820
42820
  }
42821
- url.path = path31;
42821
+ url.path = path34;
42822
42822
  }
42823
42823
  function resolve2(input, base) {
42824
42824
  if (!input && !base)
@@ -42859,13 +42859,13 @@ var require_resolve_uri_umd = __commonJS({
42859
42859
  case 3:
42860
42860
  return queryHash;
42861
42861
  case 4: {
42862
- const path31 = url.path.slice(1);
42863
- if (!path31)
42862
+ const path34 = url.path.slice(1);
42863
+ if (!path34)
42864
42864
  return queryHash || ".";
42865
- if (isRelative(base || input) && !isRelative(path31)) {
42866
- return "./" + path31 + queryHash;
42865
+ if (isRelative(base || input) && !isRelative(path34)) {
42866
+ return "./" + path34 + queryHash;
42867
42867
  }
42868
- return path31 + queryHash;
42868
+ return path34 + queryHash;
42869
42869
  }
42870
42870
  case 5:
42871
42871
  return url.path + queryHash;
@@ -42964,10 +42964,10 @@ var require_trace_mapping_umd = __commonJS({
42964
42964
  module2.exports = __toCommonJS(trace_mapping_exports);
42965
42965
  var import_sourcemap_codec = __toESM2(require_sourcemap_codec());
42966
42966
  var import_resolve_uri = __toESM2(require_resolve_uri());
42967
- function stripFilename(path31) {
42968
- if (!path31) return "";
42969
- const index = path31.lastIndexOf("/");
42970
- return path31.slice(0, index + 1);
42967
+ function stripFilename(path34) {
42968
+ if (!path34) return "";
42969
+ const index = path34.lastIndexOf("/");
42970
+ return path34.slice(0, index + 1);
42971
42971
  }
42972
42972
  function resolver(mapUrl, sourceRoot) {
42973
42973
  const from = stripFilename(mapUrl);
@@ -43091,11 +43091,11 @@ var require_trace_mapping_umd = __commonJS({
43091
43091
  state.lastNeedle = needle;
43092
43092
  return state.lastIndex = binarySearch(haystack, needle, low, high);
43093
43093
  }
43094
- function parse(map2) {
43094
+ function parse2(map2) {
43095
43095
  return typeof map2 === "string" ? JSON.parse(map2) : map2;
43096
43096
  }
43097
43097
  var FlattenMap = function(map2, mapUrl) {
43098
- const parsed = parse(map2);
43098
+ const parsed = parse2(map2);
43099
43099
  if (!("sections" in parsed)) {
43100
43100
  return new TraceMap(parsed, mapUrl);
43101
43101
  }
@@ -43159,7 +43159,7 @@ var require_trace_mapping_umd = __commonJS({
43159
43159
  }
43160
43160
  }
43161
43161
  function addSection(input, mapUrl, mappings, sources, sourcesContent, names2, ignoreList, lineOffset, columnOffset, stopLine, stopColumn) {
43162
- const parsed = parse(input);
43162
+ const parsed = parse2(input);
43163
43163
  if ("sections" in parsed) return recurse(...arguments);
43164
43164
  const map2 = new TraceMap(parsed, mapUrl);
43165
43165
  const sourcesOffset = sources.length;
@@ -43209,7 +43209,7 @@ var require_trace_mapping_umd = __commonJS({
43209
43209
  constructor(map2, mapUrl) {
43210
43210
  const isString = typeof map2 === "string";
43211
43211
  if (!isString && map2._decodedMemo) return map2;
43212
- const parsed = parse(map2);
43212
+ const parsed = parse2(map2);
43213
43213
  const { version, file: file2, names: names2, sourceRoot, sources, sourcesContent } = parsed;
43214
43214
  this.version = version;
43215
43215
  this.file = file2;
@@ -44175,9 +44175,9 @@ var require_util2 = __commonJS({
44175
44175
  /** @class */
44176
44176
  (function(_super) {
44177
44177
  __extends(VError2, _super);
44178
- function VError2(path31, message) {
44178
+ function VError2(path34, message) {
44179
44179
  var _this = _super.call(this, message) || this;
44180
- _this.path = path31;
44180
+ _this.path = path34;
44181
44181
  Object.setPrototypeOf(_this, VError2.prototype);
44182
44182
  return _this;
44183
44183
  }
@@ -44237,26 +44237,26 @@ var require_util2 = __commonJS({
44237
44237
  (_b = this._messages).push.apply(_b, best._messages);
44238
44238
  }
44239
44239
  };
44240
- DetailContext2.prototype.getError = function(path31) {
44240
+ DetailContext2.prototype.getError = function(path34) {
44241
44241
  var msgParts = [];
44242
44242
  for (var i = this._propNames.length - 1; i >= 0; i--) {
44243
44243
  var p2 = this._propNames[i];
44244
- path31 += typeof p2 === "number" ? "[" + p2 + "]" : p2 ? "." + p2 : "";
44244
+ path34 += typeof p2 === "number" ? "[" + p2 + "]" : p2 ? "." + p2 : "";
44245
44245
  var m = this._messages[i];
44246
44246
  if (m) {
44247
- msgParts.push(path31 + " " + m);
44247
+ msgParts.push(path34 + " " + m);
44248
44248
  }
44249
44249
  }
44250
- return new VError(path31, msgParts.join("; "));
44250
+ return new VError(path34, msgParts.join("; "));
44251
44251
  };
44252
- DetailContext2.prototype.getErrorDetail = function(path31) {
44252
+ DetailContext2.prototype.getErrorDetail = function(path34) {
44253
44253
  var details = [];
44254
44254
  for (var i = this._propNames.length - 1; i >= 0; i--) {
44255
44255
  var p2 = this._propNames[i];
44256
- path31 += typeof p2 === "number" ? "[" + p2 + "]" : p2 ? "." + p2 : "";
44256
+ path34 += typeof p2 === "number" ? "[" + p2 + "]" : p2 ? "." + p2 : "";
44257
44257
  var message = this._messages[i];
44258
44258
  if (message) {
44259
- details.push({ path: path31, message });
44259
+ details.push({ path: path34, message });
44260
44260
  }
44261
44261
  }
44262
44262
  var detail = null;
@@ -45069,8 +45069,8 @@ var require_dist = __commonJS({
45069
45069
  this.checkerPlain = this.ttype.getChecker(suite, false);
45070
45070
  this.checkerStrict = this.ttype.getChecker(suite, true);
45071
45071
  }
45072
- Checker2.prototype.setReportedPath = function(path31) {
45073
- this._path = path31;
45072
+ Checker2.prototype.setReportedPath = function(path34) {
45073
+ this._path = path34;
45074
45074
  };
45075
45075
  Checker2.prototype.check = function(value) {
45076
45076
  return this._doCheck(this.checkerPlain, value);
@@ -49654,7 +49654,7 @@ var require_parser = __commonJS({
49654
49654
  }
49655
49655
  };
49656
49656
  exports.File = File;
49657
- function parse(input, isJSXEnabled, isTypeScriptEnabled, isFlowEnabled) {
49657
+ function parse2(input, isJSXEnabled, isTypeScriptEnabled, isFlowEnabled) {
49658
49658
  if (isFlowEnabled && isTypeScriptEnabled) {
49659
49659
  throw new Error("Cannot combine flow and typescript plugins.");
49660
49660
  }
@@ -49665,7 +49665,7 @@ var require_parser = __commonJS({
49665
49665
  }
49666
49666
  return result;
49667
49667
  }
49668
- exports.parse = parse;
49668
+ exports.parse = parse2;
49669
49669
  }
49670
49670
  });
49671
49671
 
@@ -50503,9 +50503,9 @@ var require_CJSImportTransformer = __commonJS({
50503
50503
  if (shouldElideImport) {
50504
50504
  this.tokens.removeToken();
50505
50505
  } else {
50506
- const path31 = this.tokens.stringValue();
50507
- this.tokens.replaceTokenTrimmingLeftWhitespace(this.importProcessor.claimImportCode(path31));
50508
- this.tokens.appendCode(this.importProcessor.claimImportCode(path31));
50506
+ const path34 = this.tokens.stringValue();
50507
+ this.tokens.replaceTokenTrimmingLeftWhitespace(this.importProcessor.claimImportCode(path34));
50508
+ this.tokens.appendCode(this.importProcessor.claimImportCode(path34));
50509
50509
  }
50510
50510
  _removeMaybeImportAttributes.removeMaybeImportAttributes.call(void 0, this.tokens);
50511
50511
  if (this.tokens.matches1(_types.TokenType.semi)) {
@@ -51085,8 +51085,8 @@ var require_CJSImportTransformer = __commonJS({
51085
51085
  }
51086
51086
  if (this.tokens.matchesContextual(_keywords.ContextualKeyword._from)) {
51087
51087
  this.tokens.removeToken();
51088
- const path31 = this.tokens.stringValue();
51089
- this.tokens.replaceTokenTrimmingLeftWhitespace(this.importProcessor.claimImportCode(path31));
51088
+ const path34 = this.tokens.stringValue();
51089
+ this.tokens.replaceTokenTrimmingLeftWhitespace(this.importProcessor.claimImportCode(path34));
51090
51090
  _removeMaybeImportAttributes.removeMaybeImportAttributes.call(void 0, this.tokens);
51091
51091
  } else {
51092
51092
  this.tokens.appendCode(exportStatements.join(" "));
@@ -51100,8 +51100,8 @@ var require_CJSImportTransformer = __commonJS({
51100
51100
  while (!this.tokens.matches1(_types.TokenType.string)) {
51101
51101
  this.tokens.removeToken();
51102
51102
  }
51103
- const path31 = this.tokens.stringValue();
51104
- this.tokens.replaceTokenTrimmingLeftWhitespace(this.importProcessor.claimImportCode(path31));
51103
+ const path34 = this.tokens.stringValue();
51104
+ this.tokens.replaceTokenTrimmingLeftWhitespace(this.importProcessor.claimImportCode(path34));
51105
51105
  _removeMaybeImportAttributes.removeMaybeImportAttributes.call(void 0, this.tokens);
51106
51106
  if (this.tokens.matches1(_types.TokenType.semi)) {
51107
51107
  this.tokens.removeToken();
@@ -80745,9 +80745,9 @@ var init_bundle_mjs = __esm({
80745
80745
  processClassesRecursively(value, getPart(classPartObject, key), classGroupId, theme);
80746
80746
  }
80747
80747
  };
80748
- getPart = (classPartObject, path31) => {
80748
+ getPart = (classPartObject, path34) => {
80749
80749
  let current = classPartObject;
80750
- const parts = path31.split(CLASS_PART_SEPARATOR);
80750
+ const parts = path34.split(CLASS_PART_SEPARATOR);
80751
80751
  const len = parts.length;
80752
80752
  for (let i = 0; i < len; i++) {
80753
80753
  const part = parts[i];
@@ -84001,8 +84001,8 @@ var mockup_exports = {};
84001
84001
  __export(mockup_exports, {
84002
84002
  drawMockup: () => drawMockup
84003
84003
  });
84004
- import fs16 from "node:fs";
84005
- import path19 from "node:path";
84004
+ import fs19 from "node:fs";
84005
+ import path22 from "node:path";
84006
84006
  import vm from "node:vm";
84007
84007
  async function loadPackage(id) {
84008
84008
  if (id === "react") return import_react3.default;
@@ -84015,20 +84015,20 @@ async function loadPackage(id) {
84015
84015
  return { __esModule: true, ...await load() };
84016
84016
  }
84017
84017
  function resolveFile(id, from, folder) {
84018
- const at2 = path19.resolve(path19.dirname(from), id);
84019
- if (at2 !== folder && !at2.startsWith(folder + path19.sep)) throw new Error(`${id} is outside the mockup's folder`);
84020
- const tries = path19.extname(at2) ? [at2] : [...CODE_EXTS.map((e2) => at2 + e2), ...CODE_EXTS.map((e2) => path19.join(at2, `index${e2}`))];
84021
- const file2 = tries.find((f2) => fs16.statSync(f2, { throwIfNoEntry: false })?.isFile());
84018
+ const at2 = path22.resolve(path22.dirname(from), id);
84019
+ if (at2 !== folder && !at2.startsWith(folder + path22.sep)) throw new Error(`${id} is outside the mockup's folder`);
84020
+ const tries = path22.extname(at2) ? [at2] : [...CODE_EXTS.map((e2) => at2 + e2), ...CODE_EXTS.map((e2) => path22.join(at2, `index${e2}`))];
84021
+ const file2 = tries.find((f2) => fs19.statSync(f2, { throwIfNoEntry: false })?.isFile());
84022
84022
  if (!file2) throw new Error(`no such file: ${id}`);
84023
84023
  return file2;
84024
84024
  }
84025
84025
  async function readGraph(entry) {
84026
- const folder = path19.dirname(entry);
84026
+ const folder = path22.dirname(entry);
84027
84027
  const graph = { code: /* @__PURE__ */ new Map(), links: /* @__PURE__ */ new Map(), sheets: [], packages: /* @__PURE__ */ new Map() };
84028
84028
  const walk = async (file2) => {
84029
84029
  if (graph.code.has(file2)) return;
84030
84030
  if (graph.code.size >= MAX_FILES) throw new Error(`a mockup imports more than ${MAX_FILES} files`);
84031
- const js = (0, import_sucrase.transform)(fs16.readFileSync(file2, "utf8"), { transforms: ["typescript", "jsx", "imports"], jsxRuntime: "automatic", production: true, filePath: file2 }).code;
84031
+ const js = (0, import_sucrase.transform)(fs19.readFileSync(file2, "utf8"), { transforms: ["typescript", "jsx", "imports"], jsxRuntime: "automatic", production: true, filePath: file2 }).code;
84032
84032
  graph.code.set(file2, js);
84033
84033
  const link = /* @__PURE__ */ new Map();
84034
84034
  graph.links.set(file2, link);
@@ -84040,7 +84040,7 @@ async function readGraph(entry) {
84040
84040
  const target = resolveFile(id, file2, folder);
84041
84041
  link.set(id, target);
84042
84042
  if (!target.endsWith(".css")) await walk(target);
84043
- else if (!graph.sheets.some((s) => s.path === target)) graph.sheets.push({ path: target, content: fs16.readFileSync(target, "utf8") });
84043
+ else if (!graph.sheets.some((s) => s.path === target)) graph.sheets.push({ path: target, content: fs19.readFileSync(target, "utf8") });
84044
84044
  }
84045
84045
  };
84046
84046
  await walk(entry);
@@ -84054,25 +84054,25 @@ function run(script, context, name, deadline) {
84054
84054
  async function tailwindFor(markup, sheets) {
84055
84055
  const source = sheets.length ? sheets.map((s) => s.content).join("\n") : '@import "tailwindcss";';
84056
84056
  const compiler = await zf(source, {
84057
- base: sheets.length ? path19.dirname(sheets[0].path) : "/",
84057
+ base: sheets.length ? path22.dirname(sheets[0].path) : "/",
84058
84058
  loadStylesheet: async (id, from) => {
84059
84059
  if (id === "tailwindcss" || id.startsWith("tailwindcss/")) return { path: "tailwindcss/index.css", base: "/", content: tailwindcss_default };
84060
84060
  if (!id.startsWith(".")) throw new Error(`a mockup cannot import ${id}`);
84061
- const at2 = path19.resolve(from, id);
84062
- return { path: at2, base: path19.dirname(at2), content: fs16.readFileSync(at2, "utf8") };
84061
+ const at2 = path22.resolve(from, id);
84062
+ return { path: at2, base: path22.dirname(at2), content: fs19.readFileSync(at2, "utf8") };
84063
84063
  }
84064
84064
  });
84065
84065
  const classes = [...markup.matchAll(/class="([^"]*)"/g)].flatMap((m) => m[1].split(/\s+/));
84066
84066
  return compiler.build(classes.filter(Boolean));
84067
84067
  }
84068
84068
  function dressPage(file2) {
84069
- const folder = path19.dirname(file2);
84070
- const html = fs16.readFileSync(file2, "utf8").replace(/<link\b[^>]*>/gi, (tag) => {
84069
+ const folder = path22.dirname(file2);
84070
+ const html = fs19.readFileSync(file2, "utf8").replace(/<link\b[^>]*>/gi, (tag) => {
84071
84071
  const href = /\bhref\s*=\s*["']?([^"'\s>]+)/i.exec(tag)?.[1];
84072
84072
  if (!/\brel\s*=\s*["']?stylesheet/i.test(tag) || !href || /^[a-z][\w+.-]*:|^\/\//i.test(href)) return tag;
84073
- const at3 = path19.resolve(folder, href);
84074
- if (!at3.startsWith(folder + path19.sep) || !fs16.existsSync(at3)) return tag;
84075
- return `<style>${fs16.readFileSync(at3, "utf8").replace(/<\/style/gi, "<\\/style")}</style>`;
84073
+ const at3 = path22.resolve(folder, href);
84074
+ if (!at3.startsWith(folder + path22.sep) || !fs19.existsSync(at3)) return tag;
84075
+ return `<style>${fs19.readFileSync(at3, "utf8").replace(/<\/style/gi, "<\\/style")}</style>`;
84076
84076
  });
84077
84077
  const at2 = /^\uFEFF?\s*(?:<!--[\s\S]*?-->\s*)*(?:<!doctype\b[^>]*>)?/i.exec(html)[0].length;
84078
84078
  return /<!doctype\b|<html[\s>]|<head[\s>]/i.test(html) ? html.slice(0, at2) + head + html.slice(at2) : `<!doctype html><html><head>${head}</head><body>${html}</body></html>`;
@@ -84224,10 +84224,10 @@ function readSession() {
84224
84224
  return null;
84225
84225
  }
84226
84226
  try {
84227
- const held3 = JSON.parse(raw);
84228
- if (!held3.accessToken || !held3.refreshToken || !held3.subject) return null;
84229
- if (held3.supabaseUrl !== cloudEndpoints().supabaseUrl) return null;
84230
- return { ...held3, version: 1, expiresAt: Number(held3.expiresAt) || 0 };
84227
+ const held4 = JSON.parse(raw);
84228
+ if (!held4.accessToken || !held4.refreshToken || !held4.subject) return null;
84229
+ if (held4.supabaseUrl !== cloudEndpoints().supabaseUrl) return null;
84230
+ return { ...held4, version: 1, expiresAt: Number(held4.expiresAt) || 0 };
84231
84231
  } catch {
84232
84232
  return null;
84233
84233
  }
@@ -84246,9 +84246,9 @@ function clearSession() {
84246
84246
  }
84247
84247
  }
84248
84248
  async function accessToken() {
84249
- const held3 = readSession();
84250
- if (!held3) return { ok: false, reason: "signed-out" };
84251
- if (!expiringSoon(held3)) return { ok: true, token: held3.accessToken, session: held3 };
84249
+ const held4 = readSession();
84250
+ if (!held4) return { ok: false, reason: "signed-out" };
84251
+ if (!expiringSoon(held4)) return { ok: true, token: held4.accessToken, session: held4 };
84252
84252
  return refresh();
84253
84253
  }
84254
84254
  var expiringSoon = (session) => session.expiresAt - REFRESH_MARGIN_MS <= Date.now();
@@ -84333,14 +84333,14 @@ async function takeLock() {
84333
84333
  }
84334
84334
  }
84335
84335
  function stale() {
84336
- let held3;
84336
+ let held4;
84337
84337
  try {
84338
84338
  const pid = Number(fs.readFileSync(lockOwner(), "utf8").trim());
84339
- held3 = Number.isInteger(pid) && pid > 0 ? pid : void 0;
84339
+ held4 = Number.isInteger(pid) && pid > 0 ? pid : void 0;
84340
84340
  } catch {
84341
- held3 = void 0;
84341
+ held4 = void 0;
84342
84342
  }
84343
- if (held3 !== void 0 && !alive(held3)) return true;
84343
+ if (held4 !== void 0 && !alive(held4)) return true;
84344
84344
  try {
84345
84345
  return Date.now() - fs.statSync(lockDir()).mtimeMs > LOCK_STALE_MS;
84346
84346
  } catch {
@@ -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";
@@ -84371,8 +84371,8 @@ function useRunnerHome() {
84371
84371
  function machineId() {
84372
84372
  const file2 = path3.join(runnerHome(), "machine.json");
84373
84373
  try {
84374
- const held3 = JSON.parse(fs2.readFileSync(file2, "utf8"));
84375
- if (held3.id && /^[0-9a-f-]{36}$/i.test(held3.id)) return held3.id;
84374
+ const held4 = JSON.parse(fs2.readFileSync(file2, "utf8"));
84375
+ if (held4.id && /^[0-9a-f-]{36}$/i.test(held4.id)) return held4.id;
84376
84376
  } catch {
84377
84377
  }
84378
84378
  const id = crypto.randomUUID();
@@ -84453,7 +84453,9 @@ function status(line) {
84453
84453
  }
84454
84454
 
84455
84455
  // src/protocol.ts
84456
- var VERSION = true ? "0.6.3" : "0.0.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;
84457
84459
  var EXIT_REFUSED = 10;
84458
84460
  var EXIT_OUTDATED = 11;
84459
84461
 
@@ -84918,16 +84920,16 @@ function createEventCollector() {
84918
84920
  let queue = [];
84919
84921
  let said = "";
84920
84922
  const todoCalls = /* @__PURE__ */ new Set();
84921
- const held3 = /* @__PURE__ */ new Map();
84923
+ const held4 = /* @__PURE__ */ new Map();
84922
84924
  let todos = [];
84923
84925
  const close = () => {
84924
84926
  if (said.trim()) queue.push({ kind: "message", data: { text: said.trim() } });
84925
84927
  said = "";
84926
84928
  };
84927
84929
  const release2 = (id, target) => {
84928
- const call = held3.get(id);
84930
+ const call = held4.get(id);
84929
84931
  if (!call) return;
84930
- held3.delete(id);
84932
+ held4.delete(id);
84931
84933
  queue.push({ kind: "tool_call", data: { ...call, ...target ? { target } : {} } });
84932
84934
  };
84933
84935
  return {
@@ -84949,7 +84951,7 @@ function createEventCollector() {
84949
84951
  }
84950
84952
  const target = targetIn(u2);
84951
84953
  const data = { toolCallId: id, title: str(u2.title) || "tool", kind: toolKind(u2.kind), status: str(u2.status) || "pending", ...target ? { target } : {} };
84952
- if (u2.rawInput !== void 0 && !inputTarget(obj(u2.rawInput))) held3.set(id, data);
84954
+ if (u2.rawInput !== void 0 && !inputTarget(obj(u2.rawInput))) held4.set(id, data);
84953
84955
  else queue.push({ kind: "tool_call", data });
84954
84956
  return;
84955
84957
  }
@@ -85019,7 +85021,7 @@ function createEventCollector() {
85019
85021
  /** The turn is over: a half-held message is finished off. */
85020
85022
  end() {
85021
85023
  close();
85022
- for (const id of [...held3.keys()]) release2(id);
85024
+ for (const id of [...held4.keys()]) release2(id);
85023
85025
  },
85024
85026
  /** What arrived since the last call. */
85025
85027
  events() {
@@ -85115,12 +85117,19 @@ function promptSize(raw) {
85115
85117
  const size = num(u2.input_tokens) + num(u2.cache_creation_input_tokens) + num(u2.cache_read_input_tokens);
85116
85118
  return size > 0 ? size : void 0;
85117
85119
  }
85120
+ function windowOf(raw, model) {
85121
+ const entries = obj(raw);
85122
+ const names2 = Object.keys(entries);
85123
+ const name = model && names2.includes(model) ? model : names2.length === 1 ? names2[0] : void 0;
85124
+ return name ? num(obj(entries[name]).contextWindow) || void 0 : void 0;
85125
+ }
85118
85126
  function createStreamRenderer() {
85119
85127
  let final;
85120
85128
  let cost;
85121
85129
  let model;
85122
85130
  let usage;
85123
85131
  let context;
85132
+ let limit;
85124
85133
  let failure;
85125
85134
  let offStream;
85126
85135
  let background;
@@ -85175,6 +85184,7 @@ function createStreamRenderer() {
85175
85184
  }
85176
85185
  case "result": {
85177
85186
  if (typeof ev.result === "string") final = ev.result;
85187
+ limit = windowOf(ev.modelUsage, model) ?? limit;
85178
85188
  if (typeof ev.total_cost_usd === "number" && Number.isFinite(ev.total_cost_usd) && ev.total_cost_usd > 0) {
85179
85189
  cost = ev.total_cost_usd;
85180
85190
  }
@@ -85209,7 +85219,7 @@ function createStreamRenderer() {
85209
85219
  result: () => final,
85210
85220
  costUsd: () => cost,
85211
85221
  usage: () => usage,
85212
- context: () => context,
85222
+ context: () => context && limit ? { ...context, limit } : context,
85213
85223
  model: () => model,
85214
85224
  failure: () => failure,
85215
85225
  offStream: () => offStream,
@@ -85299,10 +85309,10 @@ function findRollout(threadId) {
85299
85309
  }
85300
85310
  for (const name of names2) {
85301
85311
  if (!name.startsWith("rollout-") || !name.endsWith(tail)) continue;
85302
- const path31 = join(dir, name);
85312
+ const path34 = join(dir, name);
85303
85313
  try {
85304
- const at2 = statSync(path31).mtimeMs;
85305
- if (!newest2 || at2 > newest2.at) newest2 = { path: path31, at: at2 };
85314
+ const at2 = statSync(path34).mtimeMs;
85315
+ if (!newest2 || at2 > newest2.at) newest2 = { path: path34, at: at2 };
85306
85316
  } catch {
85307
85317
  }
85308
85318
  }
@@ -85310,11 +85320,11 @@ function findRollout(threadId) {
85310
85320
  return newest2?.path;
85311
85321
  }
85312
85322
  function readCodexRunFacts(threadId) {
85313
- const path31 = findRollout(threadId);
85314
- if (!path31) return void 0;
85323
+ const path34 = findRollout(threadId);
85324
+ if (!path34) return void 0;
85315
85325
  let raw;
85316
85326
  try {
85317
- raw = readFileSync(path31, "utf8");
85327
+ raw = readFileSync(path34, "utf8");
85318
85328
  } catch {
85319
85329
  return void 0;
85320
85330
  }
@@ -85422,8 +85432,8 @@ function renderCompleted(item) {
85422
85432
  const changes = Array.isArray(item.changes) ? item.changes : [];
85423
85433
  return changes.map((raw) => {
85424
85434
  const change = obj(raw);
85425
- const path31 = str(change.path);
85426
- return path31 ? `\u23FA ${str(change.kind) || "change"}(${path31})
85435
+ const path34 = str(change.path);
85436
+ return path34 ? `\u23FA ${str(change.kind) || "change"}(${path34})
85427
85437
  ` : "";
85428
85438
  }).join("");
85429
85439
  }
@@ -85671,10 +85681,10 @@ function readKimiRunFacts(sessionId) {
85671
85681
  const total = { input: 0, cacheCreation: 0, cacheRead: 0, output: 0 };
85672
85682
  let model;
85673
85683
  let holding = 0;
85674
- for (const { path: path31, main: main2 } of wireFiles(entry.sessionDir)) {
85684
+ for (const { path: path34, main: main2 } of wireFiles(entry.sessionDir)) {
85675
85685
  let raw;
85676
85686
  try {
85677
- raw = readFileSync2(path31, "utf8");
85687
+ raw = readFileSync2(path34, "utf8");
85678
85688
  } catch {
85679
85689
  continue;
85680
85690
  }
@@ -85927,8 +85937,62 @@ function createTail(log) {
85927
85937
  };
85928
85938
  }
85929
85939
 
85940
+ // ../cli/package.json
85941
+ var package_default = {
85942
+ name: "wildcrane",
85943
+ version: "0.11.4",
85944
+ akbContract: 2,
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
+ keywords: [
85947
+ "kanban",
85948
+ "claude",
85949
+ "claude-code",
85950
+ "codex",
85951
+ "agent",
85952
+ "skill",
85953
+ "markdown",
85954
+ "board"
85955
+ ],
85956
+ license: "FSL-1.1-ALv2",
85957
+ homepage: "https://wildcrane.ai/",
85958
+ repository: {
85959
+ type: "git",
85960
+ url: "git+https://github.com/ai4kanban/ai4kanban.git",
85961
+ directory: "cli"
85962
+ },
85963
+ type: "module",
85964
+ bin: {
85965
+ akb: "bin/ai4kanban.mjs",
85966
+ wildcrane: "bin/ai4kanban.mjs"
85967
+ },
85968
+ files: [
85969
+ "bin/",
85970
+ "dist/"
85971
+ ],
85972
+ engines: {
85973
+ node: ">=18.0.0"
85974
+ },
85975
+ scripts: {
85976
+ build: "node scripts/build.mjs",
85977
+ prepare: "node scripts/build.mjs",
85978
+ typecheck: "tsc -p tsconfig.json --noEmit",
85979
+ test: "node scripts/test.mjs",
85980
+ lint: "npm run typecheck",
85981
+ prepublishOnly: "npm run build",
85982
+ "eval:qa": "node scripts/qa-eval.mjs"
85983
+ },
85984
+ devDependencies: {
85985
+ "@types/node": "^22.20.1",
85986
+ esbuild: "^0.28.2",
85987
+ typescript: "^5.9.3"
85988
+ },
85989
+ dependencies: {
85990
+ commander: "^13.1.0"
85991
+ }
85992
+ };
85993
+
85930
85994
  // ../cli/src/version.ts
85931
- var SKILL_VERSION = "0.11.2";
85995
+ var SKILL_VERSION = package_default.version;
85932
85996
 
85933
85997
  // ../cli/src/lib/agent/wire/acp.ts
85934
85998
  var PROTOCOL_VERSION = 1;
@@ -85938,8 +86002,8 @@ var CLIENT_CAPABILITIES = {
85938
86002
  };
85939
86003
  function whereHint(update2, title) {
85940
86004
  const locations = Array.isArray(update2.locations) ? update2.locations : [];
85941
- const path31 = str(obj(locations[0]).path);
85942
- return path31 && !title.includes(path31) ? hint(path31) : "";
86005
+ const path34 = str(obj(locations[0]).path);
86006
+ return path34 && !title.includes(path34) ? hint(path34) : "";
85943
86007
  }
85944
86008
  function saidBy(update2) {
85945
86009
  const content = Array.isArray(update2.content) ? update2.content : [];
@@ -85967,9 +86031,9 @@ function modelsIn(answer) {
85967
86031
  return modelId ? [{ modelId, name: str(m.name) || modelId }] : [];
85968
86032
  });
85969
86033
  }
85970
- function pickedModel(answer, wanted) {
86034
+ function pickedModel(answer, wanted2) {
85971
86035
  const list = modelsIn(answer);
85972
- return list.find((m) => m.modelId === wanted) ?? list.find((m) => m.name === wanted || m.modelId.split("[")[0] === wanted);
86036
+ return list.find((m) => m.modelId === wanted2) ?? list.find((m) => m.name === wanted2 || m.modelId.split("[")[0] === wanted2);
85973
86037
  }
85974
86038
  function usageOf2(value, grossInput = false) {
85975
86039
  const usage = obj(value);
@@ -86370,9 +86434,9 @@ async function oneTurn2(io, options) {
86370
86434
  }
86371
86435
  let model = modelOf2(obj(opened.session).model);
86372
86436
  if (options.model) {
86373
- const wanted = options.model.includes("/") ? { providerId: options.model.split("/")[0], modelId: options.model.split("/").slice(1).join("/") } : { providerId: str(obj(obj(opened.session).model).providerId) || "zai", modelId: options.model };
86374
- await rpc.call("session/setModel", { sessionId, model: wanted });
86375
- model = modelOf2(wanted);
86437
+ const wanted2 = options.model.includes("/") ? { providerId: options.model.split("/")[0], modelId: options.model.split("/").slice(1).join("/") } : { providerId: str(obj(obj(opened.session).model).providerId) || "zai", modelId: options.model };
86438
+ await rpc.call("session/setModel", { sessionId, model: wanted2 });
86439
+ model = modelOf2(wanted2);
86376
86440
  }
86377
86441
  if (model) io.gotModel(model);
86378
86442
  await rpc.call("session/subscribe", {
@@ -86872,6 +86936,7 @@ var REPO_ROOT = "";
86872
86936
  var KANBAN = "";
86873
86937
  var TODO = "";
86874
86938
  var ARCHIVE = "";
86939
+ var REJECTIONS_TO_REVIEW = ".sync";
86875
86940
  var ARCHIVE_MD = "";
86876
86941
  var README = "";
86877
86942
  var MODULES_MD = "";
@@ -86879,7 +86944,6 @@ var CONFIG = "";
86879
86944
  var KANBAN_GITIGNORE = "";
86880
86945
  var RELEASES = "";
86881
86946
  var RELEASE_SUMMARIES = "";
86882
- var SETUP_CHECKLIST = "";
86883
86947
  var AGENTS = "";
86884
86948
  var WORKFLOWS = "";
86885
86949
  var LEGACY_AGENTS = "";
@@ -86929,7 +86993,6 @@ function setBoard(kanban, root, flag) {
86929
86993
  KANBAN_GITIGNORE = path9.join(KANBAN, ".gitignore");
86930
86994
  RELEASES = path9.join(KANBAN, "releases.md");
86931
86995
  RELEASE_SUMMARIES = path9.join(KANBAN, ".release-summaries");
86932
- SETUP_CHECKLIST = path9.join(KANBAN, "setup-checklist.md");
86933
86996
  AGENTS = path9.join(KANBAN, "agents");
86934
86997
  WORKFLOWS = path9.join(KANBAN, "workflows");
86935
86998
  LEGACY_AGENTS = path9.join(KANBAN, "skills");
@@ -87777,7 +87840,7 @@ ${text3}
87777
87840
  // PROBE: on a machine that has `kimi`, run its login command's status form under a
87778
87841
  // throwaway HOME and under the real one. If it says which state it is in, declare it here.
87779
87842
  installs: () => [...process.env.KIMI_INSTALL_DIR ? [join5(process.env.KIMI_INSTALL_DIR, "bin", "kimi")] : [], home2(".kimi-code", "bin", "kimi")],
87780
- install: "curl -LsSf https://code.kimi.com/install.sh | bash"
87843
+ install: "curl -fsSL https://code.kimi.com/kimi-code/install.sh | bash"
87781
87844
  };
87782
87845
 
87783
87846
  // ../cli/src/lib/agent/harnesses/opencode.ts
@@ -87979,6 +88042,7 @@ var DEFAULT_HARNESS = HARNESSES[0];
87979
88042
  checkHarnesses(HARNESSES);
87980
88043
 
87981
88044
  // ../cli/src/lib/agent/env.ts
88045
+ var SCHEDULED_AGENTS_ENV = "AI4KANBAN_SCHEDULED_AGENTS";
87982
88046
  var SESSION_VARS = {
87983
88047
  "claude-code": "CLAUDE_CODE_SESSION_ID",
87984
88048
  codex: "CODEX_THREAD_ID"
@@ -88024,15 +88088,15 @@ function isFilled(harness, { values, secretsSet: secretsSet2 }) {
88024
88088
  return setting?.kind === "secret" ? secretsSet2.includes(key) : Boolean(values[key]);
88025
88089
  };
88026
88090
  }
88027
- function providerFor(harness, held3) {
88091
+ function providerFor(harness, held4) {
88028
88092
  const setting = providerSetting(harness.settings);
88029
88093
  if (!setting) return void 0;
88030
- return pickedProvider(setting, held3.values[setting.key] ?? "", isFilled(harness, held3));
88094
+ return pickedProvider(setting, held4.values[setting.key] ?? "", isFilled(harness, held4));
88031
88095
  }
88032
- function settingArgs(harness, held3) {
88033
- const { values } = held3;
88034
- const ignored = held3.ignored ?? [];
88035
- const picked = providerFor(harness, held3);
88096
+ function settingArgs(harness, held4) {
88097
+ const { values } = held4;
88098
+ const ignored = held4.ignored ?? [];
88099
+ const picked = providerFor(harness, held4);
88036
88100
  const list = providerSetting(harness.settings);
88037
88101
  const byHand = !!list && ignored.includes(list.key);
88038
88102
  const providerArgs = byHand ? [] : picked?.args ?? [];
@@ -88047,9 +88111,9 @@ function settingArgs(harness, held3) {
88047
88111
  });
88048
88112
  return [...providerArgs, ...flags, ...splitCommand(values[RAW_ARGS_KEY] ?? "")];
88049
88113
  }
88050
- function settingEnv(harness, held3, secrets, cwd) {
88051
- const { values } = held3;
88052
- const picked = providerFor(harness, held3);
88114
+ function settingEnv(harness, held4, secrets, cwd) {
88115
+ const { values } = held4;
88116
+ const picked = providerFor(harness, held4);
88053
88117
  const env2 = { ...harness.env() };
88054
88118
  for (const name of ownedVars(harness)) delete env2[name];
88055
88119
  for (const name of Object.values(SESSION_VARS)) delete env2[name];
@@ -88076,11 +88140,11 @@ function ownedVars(harness) {
88076
88140
  }
88077
88141
  return [...names2];
88078
88142
  }
88079
- function effectiveValues(harness, held3) {
88080
- const picked = providerFor(harness, held3);
88143
+ function effectiveValues(harness, held4) {
88144
+ const picked = providerFor(harness, held4);
88081
88145
  const out = {};
88082
88146
  for (const setting of harness.settings) {
88083
- const value = held3.values[setting.key];
88147
+ const value = held4.values[setting.key];
88084
88148
  if (!value || setting.kind === "secret") continue;
88085
88149
  if (!shownForProvider(harness.settings, setting.key, picked)) continue;
88086
88150
  out[setting.key] = value;
@@ -88128,6 +88192,7 @@ __export(api_exports, {
88128
88192
  readArtifact: () => readArtifact,
88129
88193
  readBoard: () => readBoard,
88130
88194
  readChat: () => readChat,
88195
+ readDecisions: () => readDecisions,
88131
88196
  readDiscussion: () => readDiscussion,
88132
88197
  readInbox: () => readInbox,
88133
88198
  readPlan: () => readPlan,
@@ -88162,8 +88227,8 @@ import path12 from "node:path";
88162
88227
  var file = () => path12.join(runnerHome(), "secrets.json");
88163
88228
  function readAll() {
88164
88229
  try {
88165
- const held3 = JSON.parse(fs9.readFileSync(file(), "utf8"));
88166
- return held3 && typeof held3 === "object" ? held3 : {};
88230
+ const held4 = JSON.parse(fs9.readFileSync(file(), "utf8"));
88231
+ return held4 && typeof held4 === "object" ? held4 : {};
88167
88232
  } catch {
88168
88233
  return {};
88169
88234
  }
@@ -88171,12 +88236,12 @@ function readAll() {
88171
88236
  var secretsOf = (runtime) => runtime ? readAll()[runtime] ?? {} : {};
88172
88237
  function keepSecrets(runtime, given) {
88173
88238
  const all = readAll();
88174
- const held3 = { ...all[runtime] };
88239
+ const held4 = { ...all[runtime] };
88175
88240
  for (const [key, value] of Object.entries(given)) {
88176
- if (value) held3[key] = value;
88177
- else delete held3[key];
88241
+ if (value) held4[key] = value;
88242
+ else delete held4[key];
88178
88243
  }
88179
- if (Object.keys(held3).length) all[runtime] = held3;
88244
+ if (Object.keys(held4).length) all[runtime] = held4;
88180
88245
  else delete all[runtime];
88181
88246
  fs9.mkdirSync(runnerHome(), { recursive: true, mode: 448 });
88182
88247
  const temp = `${file()}.${process.pid}.tmp`;
@@ -88190,7 +88255,7 @@ var secretsSet = () => Object.fromEntries(Object.entries(readAll()).map(([id, ke
88190
88255
  var RUNTIMES = ["claude-code", "codex", "cursor", "opencode", "kimi", "dsh", "zcode", "grok"];
88191
88256
  var PROTOCOL = 11;
88192
88257
  var TIMEOUT_MS = 2e4;
88193
- async function send(method, route, body, signedIn, ms2, type) {
88258
+ async function send(method, route, body, signedIn, ms, type) {
88194
88259
  const headers = { accept: "application/json" };
88195
88260
  if (signedIn) {
88196
88261
  const token = await accessToken();
@@ -88206,7 +88271,7 @@ async function send(method, route, body, signedIn, ms2, type) {
88206
88271
  method,
88207
88272
  headers,
88208
88273
  body: body === void 0 ? void 0 : raw ? body : JSON.stringify(body),
88209
- signal: AbortSignal.timeout(ms2)
88274
+ signal: AbortSignal.timeout(ms)
88210
88275
  });
88211
88276
  return { ok: true, value: response };
88212
88277
  } catch (e2) {
@@ -88242,7 +88307,7 @@ async function upload(route, bytes2, type) {
88242
88307
  const sent = await send("PUT", route, bytes2, true, FILE_TIMEOUT_MS, type);
88243
88308
  return sent.ok ? answerOf(sent.value) : sent;
88244
88309
  }
88245
- var register = (r2) => request("POST", "/v1/runner", { ...r2, secrets: secretsSet(), protocol: PROTOCOL });
88310
+ var register = (r2) => request("POST", "/v1/runner", { ...r2, secrets: secretsSet(), protocol: PROTOCOL, akbContract: AKB_CONTRACT });
88246
88311
  var readRunner = () => request("GET", "/v1/runner");
88247
88312
  var release = (machineId2) => request("POST", "/v1/runner/release", { machineId: machineId2 });
88248
88313
  var listJobs = (machineId2) => request("GET", `/v1/runner/jobs?machine=${encodeURIComponent(machineId2)}`);
@@ -88265,6 +88330,7 @@ var finishJob = (machineId2, job, outcome, reason = "", report2) => move(job, "f
88265
88330
  var answerDiff = (machineId2, id, answer) => request("POST", `/v1/runner/diffs/${encodeURIComponent(id)}`, { machineId: machineId2, ...answer });
88266
88331
  var listChats = (machineId2) => request("GET", `/v1/runner/chats?machine=${encodeURIComponent(machineId2)}`);
88267
88332
  var readChat = (task) => request("GET", `/v1/tasks/${encodeURIComponent(task)}/chat`);
88333
+ var readDecisions = (task, after) => request("GET", `/v1/tasks/${q(task)}/decisions?limit=100${after ? `&after=${q(after)}` : ""}`);
88268
88334
  var dispatchReview = (machineId2, project, tasks, runtime, model) => request("POST", "/v1/runner/reviews", { machineId: machineId2, project, tasks, runtime, model });
88269
88335
  var readAgents = (machineId2, project) => request("GET", `/v1/runner/agents?machine=${encodeURIComponent(machineId2)}&project=${encodeURIComponent(project)}`);
88270
88336
  var requestAgent = (machineId2, project, agent, workflow, seen) => request("POST", "/v1/runner/jobs", { machineId: machineId2, project, agent, workflow, seen });
@@ -88279,7 +88345,7 @@ var listFolders = (machineId2) => request("GET", `/v1/runner/folders?machine=${q
88279
88345
  var listElsewhere = (machineId2) => request("GET", `/v1/runner/folders?machine=${q(machineId2)}&elsewhere=1`);
88280
88346
  var listMachineTasks = (machineId2) => request("GET", `/v1/runner/tasks?machine=${q(machineId2)}`);
88281
88347
  var stopTask = (task, how) => request("POST", how === "chat" ? `/v1/tasks/${q(task)}/chat/stop` : `/v1/tasks/${q(task)}/stop`, {});
88282
- var addFolder = (machineId2, name, path31, project) => request("POST", "/v1/runner/folders", { machineId: machineId2, name, path: path31, ...project ? { project } : {} });
88348
+ var addFolder = (machineId2, name, path34, project) => request("POST", "/v1/runner/folders", { machineId: machineId2, name, path: path34, ...project ? { project } : {} });
88283
88349
  var removeFolder = (machineId2, project) => request("POST", `/v1/runner/folders/${q(project)}/remove`, { machineId: machineId2 });
88284
88350
  var readPlan = () => request("GET", "/v1/billing");
88285
88351
  var startTrial = () => request("POST", "/v1/billing/trial", {});
@@ -88352,6 +88418,7 @@ function plan(runtime, prompt, cwd, resume, model, given = {}, fork = false, lin
88352
88418
  if (harness.client) {
88353
88419
  const client = harness.client(effectiveValues(harness, values));
88354
88420
  let session;
88421
+ let named2;
88355
88422
  return {
88356
88423
  command: argv[0],
88357
88424
  args: argv.slice(1),
@@ -88367,12 +88434,12 @@ function plan(runtime, prompt, cwd, resume, model, given = {}, fork = false, lin
88367
88434
  gotResumeId: (got, restarted) => {
88368
88435
  if (restarted || !session) session = got;
88369
88436
  },
88370
- gotModel: () => {
88371
- },
88437
+ gotModel: (got) => named2 = got,
88372
88438
  event: event2
88373
88439
  }),
88374
88440
  quiet,
88375
- session: () => session ?? resume ?? void 0
88441
+ session: () => session ?? resume ?? void 0,
88442
+ model: () => named2
88376
88443
  };
88377
88444
  }
88378
88445
  const renderer = harness.renderer(cwd, argv[0], argv);
@@ -88384,7 +88451,8 @@ function plan(runtime, prompt, cwd, resume, model, given = {}, fork = false, lin
88384
88451
  stdin: toStdin?.(prompt),
88385
88452
  renderer,
88386
88453
  quiet,
88387
- session: () => renderer.resumeId?.() ?? resume ?? (harness.adoptsSessionId ? id : void 0)
88454
+ session: () => renderer.resumeId?.() ?? resume ?? (harness.adoptsSessionId ? id : void 0),
88455
+ model: () => renderer.model?.()
88388
88456
  };
88389
88457
  }
88390
88458
  function declOf(setting) {
@@ -88742,240 +88810,6 @@ function nextDue(lastRun, cadence) {
88742
88810
  return new Date(last2.getFullYear(), last2.getMonth(), last2.getDate() + c2.n, hour, minute, 0, 0);
88743
88811
  }
88744
88812
 
88745
- // ../cli/src/lib/yaml.ts
88746
- function yamlScalar(s) {
88747
- const text3 = String(s);
88748
- if (text3 === "") return '""';
88749
- if (/^[-?:,[\]{}#&*!|>'"%@`]/.test(text3) || /:\s/.test(text3) || /[\n"]/.test(text3) || /^\s|\s$/.test(text3)) {
88750
- return JSON.stringify(text3);
88751
- }
88752
- return text3;
88753
- }
88754
- function unquote(v2) {
88755
- const text3 = String(v2).trim();
88756
- if (text3.startsWith('"') && text3.endsWith('"')) {
88757
- try {
88758
- return JSON.parse(text3);
88759
- } catch {
88760
- return text3.slice(1, -1);
88761
- }
88762
- }
88763
- if (text3.startsWith("'") && text3.endsWith("'")) return text3.slice(1, -1);
88764
- return text3;
88765
- }
88766
-
88767
- // ../cli/src/lib/question-block.ts
88768
- var MODES = ["single", "multi"];
88769
- var withoutTag = (text3) => text3.replace(/^\[user\]\s+/, "");
88770
- function normalizeQuestion(raw) {
88771
- if (raw && typeof raw === "object" && !Array.isArray(raw)) {
88772
- const source = raw;
88773
- const text3 = withoutTag(String(source.question ?? source.text ?? ""));
88774
- const extra = {
88775
- ...typeof source.agent === "string" && source.agent.trim() ? { agent: source.agent.trim() } : {},
88776
- ...source.skipped === true || source.skipped === "true" ? { skipped: true } : {}
88777
- };
88778
- const options = (Array.isArray(source.options) ? source.options : []).map((o2) => String(o2).trim()).filter(Boolean);
88779
- if (options.length === 0) return { text: text3, ...extra };
88780
- const mode = MODES.includes(String(source.mode)) ? String(source.mode) : "single";
88781
- const recommend = (Array.isArray(source.recommend) ? source.recommend : []).map(Number).filter((n) => Number.isInteger(n) && n >= 1 && n <= options.length);
88782
- return { text: text3, mode, options, recommend: mode === "single" ? recommend.slice(0, 1) : recommend, ...extra };
88783
- }
88784
- return { text: withoutTag(String(raw)) };
88785
- }
88786
- function parseQuestionsBlock(lines) {
88787
- const out = [];
88788
- for (let i = 0; i < lines.length; i++) {
88789
- const m = lines[i].match(/^\s*-\s+([\s\S]*)$/);
88790
- if (!m) continue;
88791
- const head2 = m[1];
88792
- const opened = head2.match(/^question:\s*(.*)$/);
88793
- if (!opened) {
88794
- out.push(normalizeQuestion(unquote(head2)));
88795
- continue;
88796
- }
88797
- const q3 = {
88798
- question: unquote(opened[1]),
88799
- options: [],
88800
- recommend: []
88801
- };
88802
- while (i + 1 < lines.length && !/^\s*-\s/.test(lines[i + 1])) {
88803
- const field = lines[i + 1].match(/^\s*([A-Za-z_]+):\s*(.*)$/);
88804
- i++;
88805
- if (!field) continue;
88806
- const [, key, val] = field;
88807
- if (key === "options") {
88808
- while (i + 1 < lines.length && /^\s*-\s+/.test(lines[i + 1])) {
88809
- q3.options.push(unquote(lines[i + 1].replace(/^\s*-\s+/, "")));
88810
- i++;
88811
- }
88812
- } else if (key === "recommend") {
88813
- q3.recommend = val.replace(/^\[|\]$/g, "").split(",").map((s) => Number(s.trim())).filter((n) => Number.isInteger(n));
88814
- } else if (key === "mode") {
88815
- q3.mode = unquote(val);
88816
- } else if (key === "agent") {
88817
- q3.agent = unquote(val);
88818
- } else if (key === "skipped") {
88819
- q3.skipped = unquote(val) === "true";
88820
- }
88821
- }
88822
- out.push(normalizeQuestion(q3));
88823
- }
88824
- return out;
88825
- }
88826
-
88827
- // ../cli/src/lib/view/rules.ts
88828
- var openOf = (questions) => questions.filter((q3) => !q3.skipped);
88829
-
88830
- // ../cli/src/lib/frontmatter.ts
88831
- function parseFrontmatter(text3) {
88832
- const lines = text3.split("\n");
88833
- if (lines[0].trim() !== "---") return { meta: null, body: text3 };
88834
- let i = 1;
88835
- const fm = [];
88836
- while (i < lines.length && lines[i].trim() !== "---") {
88837
- fm.push(lines[i]);
88838
- i++;
88839
- }
88840
- if (i >= lines.length) return { meta: null, body: text3 };
88841
- const meta = {};
88842
- for (let j2 = 0; j2 < fm.length; j2++) {
88843
- const m = fm[j2].match(/^([A-Za-z_]+):\s*(.*)$/);
88844
- if (!m) continue;
88845
- const key = m[1];
88846
- const val = m[2];
88847
- if (key === "questions") {
88848
- if (val === "") {
88849
- const block = [];
88850
- while (j2 + 1 < fm.length && /^\s/.test(fm[j2 + 1]) && fm[j2 + 1].trim() !== "") {
88851
- block.push(fm[j2 + 1]);
88852
- j2++;
88853
- }
88854
- meta.questions = parseQuestionsBlock(block);
88855
- } else {
88856
- meta.questions = val.trim() === "[]" ? [] : [normalizeQuestion(unquote(val))];
88857
- }
88858
- continue;
88859
- }
88860
- if (val === "") {
88861
- const items = [];
88862
- while (j2 + 1 < fm.length && /^\s*-\s+/.test(fm[j2 + 1])) {
88863
- items.push(unquote(fm[j2 + 1].replace(/^\s*-\s+/, "")));
88864
- j2++;
88865
- }
88866
- meta[key] = items;
88867
- } else if (val.startsWith("[")) {
88868
- const inner = val.slice(1, val.lastIndexOf("]"));
88869
- meta[key] = inner.split(",").map((s) => s.trim()).filter(Boolean).map(unquote);
88870
- } else {
88871
- meta[key] = unquote(val);
88872
- }
88873
- }
88874
- for (const k of ["blocked_by", "related"]) {
88875
- const value = meta[k];
88876
- if (Array.isArray(value)) {
88877
- meta[k] = value.map((x2) => Number(String(x2).replace(/^#/, ""))).filter((n) => Number.isInteger(n));
88878
- } else {
88879
- meta[k] = [];
88880
- }
88881
- }
88882
- if (!Array.isArray(meta.questions)) {
88883
- meta.questions = meta.questions ? [normalizeQuestion(meta.questions)] : [];
88884
- }
88885
- for (const key of ["priority", "roi"]) {
88886
- meta[key] = typeof meta[key] === "string" && meta[key].trim() ? meta[key].trim() : "";
88887
- }
88888
- if (!Array.isArray(meta.modules)) meta.modules = [];
88889
- delete meta.channels;
88890
- delete meta.decided;
88891
- delete meta.verify;
88892
- delete meta.release;
88893
- delete meta.schedule;
88894
- meta.workflow = typeof meta.workflow === "string" && meta.workflow.trim() ? meta.workflow.trim() : "";
88895
- meta.triage = typeof meta.triage === "string" ? meta.triage.trim() : "";
88896
- meta.source = (Array.isArray(meta.source) ? meta.source : typeof meta.source === "string" ? [meta.source] : []).map((ref) => String(ref).trim()).filter(Boolean);
88897
- delete meta.phases;
88898
- if (Array.isArray(meta.previews)) meta.previews = meta.previews.map((name) => String(name).trim()).filter(Boolean);
88899
- else delete meta.previews;
88900
- meta.stages = /^\d+$/.test(String(meta.stages ?? "").trim()) ? Number(meta.stages) : 0;
88901
- meta.phase = /^\d+$/.test(String(meta.phase ?? "").trim()) ? Number(meta.phase) : 0;
88902
- meta.preview_approved = meta.preview_approved === "true";
88903
- meta.archived = typeof meta.archived === "string" && meta.archived.trim() ? meta.archived.trim() : "";
88904
- meta.rejected = meta.rejected === "true";
88905
- meta.rejected_reason = typeof meta.rejected_reason === "string" ? meta.rejected_reason : "";
88906
- meta.rejected_at = typeof meta.rejected_at === "string" ? meta.rejected_at.trim() : "";
88907
- meta.rejected_by = meta.rejected_by === "user" || meta.rejected_by === "agent" ? meta.rejected_by : "";
88908
- return { meta, body: lines.slice(i + 1).join("\n") };
88909
- }
88910
-
88911
- // ../cli/src/lib/spec-agent-names.ts
88912
- var LEGACY_SPEC_AGENT_NAMES = {
88913
- "recommend-tech-stack": "tech-stack-advisor",
88914
- "technology-selection": "tech-stack-advisor",
88915
- "ui-design": "ui-designer",
88916
- // Renamed in #945 and folded into the editor in #1057; its asset memory stays in
88917
- // `memory/agents/video-assets/`.
88918
- "video-assets": "hyperframes-editor",
88919
- // Renamed in #1502: it reads chats, and writes memory as a result.
88920
- "memory-reviewer": "chat-reviewer",
88921
- // Folded into `copywriting` in #1582.
88922
- "user-docs": "copywriting"
88923
- };
88924
- var canonicalSpecAgent = (name) => {
88925
- const asked = name.trim();
88926
- return LEGACY_SPEC_AGENT_NAMES[asked] ?? asked;
88927
- };
88928
-
88929
- // ../cli/src/lib/slug.ts
88930
- function slugify(s) {
88931
- const out = String(s).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 60).replace(/-+$/g, "");
88932
- return out || "task";
88933
- }
88934
-
88935
- // ../cli/src/lib/memory.ts
88936
- var PLANNER_MEMORY_FILES = ["decisions.md", "rejected.md", "redesign.md"];
88937
- var STARTERS = {
88938
- "readme.md": `# Shipped
88939
-
88940
- User-facing work that has shipped, one line each \u2014 a link to the published doc that
88941
- covers it, or a plain-words note.
88942
-
88943
- _(nothing recorded yet \u2014 the first finished task fills it in.)_
88944
- `,
88945
- "decisions.md": `# Decisions
88946
-
88947
- Settled answers to cards' open questions, grouped by topic. Keep only **user-facing**
88948
- calls that guide future planning \u2014 what a user can see, do, or would care about.
88949
- Internal detail stays on the card.
88950
- `,
88951
- "redesign.md": `# Redesign
88952
-
88953
- Design mistakes to avoid when writing a card, grouped by topic. One entry each: the
88954
- mistake, then the design we actually want. Read before writing or reviewing a card.
88955
- `,
88956
- "rejected.md": `# Rejected
88957
-
88958
- Ideas we turned down, grouped by topic. One line each: the idea, and why we said no. Read
88959
- before proposing so you don't re-suggest them.
88960
- `,
88961
- // Only a header: `describe-project` writes the body, and runs while there is none (#1268).
88962
- "project.md": `# Project
88963
-
88964
- What the project is today, from its users' side. Rewritten whole by \`akb describe-project\`;
88965
- edits here do not last.
88966
- `
88967
- };
88968
- var RESERVED_MODULE_NAMES = PLANNER_MEMORY_FILES.map((name) => name.replace(/\.md$/, ""));
88969
- var PRODUCT_STARTER = STARTERS["project.md"].replaceAll("Project", "Product").replaceAll("project", "product");
88970
- var SEEDED_GOAL_PARAGRAPHS = new Set(
88971
- [
88972
- "# Goal",
88973
- "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.",
88974
- "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.",
88975
- "_(not filled in yet \u2014 the user writes this.)_"
88976
- ].map((p2) => p2.replace(/\s+/g, " "))
88977
- );
88978
-
88979
88813
  // ../cli/src/lib/agent/due.ts
88980
88814
  var AUTO_GAP = "6h";
88981
88815
  var DAY = 864e5;
@@ -89000,22 +88834,32 @@ function scheduleDue(ask, now = Date.now()) {
89000
88834
  }
89001
88835
  const newest2 = ask.attempts.reduce((a3, r2) => a3 && a3.startedAt >= r2.startedAt ? a3 : r2, null);
89002
88836
  const retrying = isAuto(ask.cadence) && newest2?.status === "error";
89003
- 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;
89004
88838
  const reason = !wait3 || wait3 === "tooSoon" ? void 0 : wait3 === "nothingNew" ? ask.reads : wait3;
89005
88839
  return { next, wait: wait3, ...reason ? { reason } : {} };
89006
88840
  }
89007
88841
 
89008
88842
  // src/agents.ts
89009
- var AGENTS_EVERY_MS = 6e4;
89010
- 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
+ }
89011
88855
  function agentDue(agent, now = Date.now()) {
89012
88856
  if (agent.attempts.some((a3) => a3.status === "running")) return false;
89013
88857
  const due = scheduleDue({
89014
88858
  cadence: agent.cadence,
89015
88859
  fallback: agent.fallback,
89016
88860
  reads: agent.reads,
89017
- from: Math.max(ms(agent.lastSuccess), ms(agent.since)),
89018
- 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 })),
89019
88863
  newWork: () => agent.newWork
89020
88864
  }, now);
89021
88865
  return !due.wait;
@@ -89036,34 +88880,120 @@ async function askDueAgents(machineId2, now = Date.now()) {
89036
88880
  return started;
89037
88881
  }
89038
88882
 
88883
+ // src/akb-version.ts
88884
+ import { execFile } from "node:child_process";
88885
+ import fs15 from "node:fs";
88886
+ import path18 from "node:path";
88887
+
88888
+ // src/akb.ts
88889
+ import { spawn as spawn3 } from "node:child_process";
88890
+ import fs11 from "node:fs";
88891
+ import path14 from "node:path";
88892
+ import { fileURLToPath } from "node:url";
88893
+ var akbHome = () => path14.join(runnerHome(), "bin", "akb");
88894
+ var BUNDLED_SHIM = `bundled-${AKB_VERSION}`;
88895
+ var bundledAkb = () => ({
88896
+ command: process.execPath,
88897
+ args: [path14.join(path14.dirname(fileURLToPath(import.meta.url)), "akb", "bin", "ai4kanban.mjs")],
88898
+ version: AKB_VERSION,
88899
+ shim: path14.join(akbHome(), BUNDLED_SHIM)
88900
+ });
88901
+ var quote = (s) => /^[\w./:@=-]+$/.test(s) ? s : `"${s}"`;
88902
+ function shimDir(akb) {
88903
+ const dir = akb.shim;
88904
+ const line = [akb.command, ...akb.args].map(quote).join(" ");
88905
+ const [file2, text3] = process.platform === "win32" ? [path14.join(dir, "akb.cmd"), `@${line} %*\r
88906
+ `] : [path14.join(dir, "akb"), `#!/bin/sh
88907
+ exec ${line} "$@"
88908
+ `];
88909
+ try {
88910
+ if (fs11.readFileSync(file2, "utf8") === text3) return dir;
88911
+ } catch {
88912
+ }
88913
+ fs11.mkdirSync(dir, { recursive: true });
88914
+ fs11.writeFileSync(file2, text3, { mode: 493 });
88915
+ return dir;
88916
+ }
88917
+ function akbEnv(akb, board, task, line) {
88918
+ const env2 = {};
88919
+ const dropped = ["AI4KANBAN_BOARD", "AI4KANBAN_TASK", LANGUAGE_LINE_ENV, SCHEDULED_AGENTS_ENV];
88920
+ for (const [k, v2] of Object.entries(process.env)) if (!k.startsWith("KANBAN_") && !dropped.includes(k)) env2[k] = v2;
88921
+ const key = Object.keys(env2).find((k) => k.toUpperCase() === "PATH") ?? "PATH";
88922
+ env2[key] = [shimDir(akb), env2[key]].filter(Boolean).join(path14.delimiter);
88923
+ env2.AI4KANBAN_COMMAND = "akb";
88924
+ if (board) env2.AI4KANBAN_BOARD = board;
88925
+ if (task) env2.AI4KANBAN_TASK = task;
88926
+ if (line !== void 0) env2[LANGUAGE_LINE_ENV] = line;
88927
+ return env2;
88928
+ }
88929
+ var KEEP = 256 * 1024;
88930
+ function runAkb(akb, args, opts) {
88931
+ return new Promise((resolve2) => {
88932
+ let out = "";
88933
+ let last2 = "";
88934
+ const note = (text3) => {
88935
+ const line = text3.split("\n").map((l2) => l2.trim()).filter(Boolean).at(-1);
88936
+ if (line) last2 = line;
88937
+ };
88938
+ let child;
88939
+ try {
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"] });
88941
+ } catch (e2) {
88942
+ return resolve2({ code: null, out: "", last: e2 instanceof Error ? e2.message : String(e2) });
88943
+ }
88944
+ opts.track?.(child);
88945
+ child.stdout.setEncoding("utf8");
88946
+ child.stderr.setEncoding("utf8");
88947
+ child.stdout.on("data", (chunk) => {
88948
+ out = (out + chunk).slice(-KEEP);
88949
+ note(chunk);
88950
+ opts.show?.(chunk);
88951
+ });
88952
+ child.stderr.on("data", (chunk) => {
88953
+ note(chunk);
88954
+ opts.show?.(chunk);
88955
+ });
88956
+ child.on("error", (e2) => resolve2({ code: null, out, last: e2.message }));
88957
+ child.on("close", (code) => resolve2({ code, out, last: last2 }));
88958
+ });
88959
+ }
88960
+ function answerOf2(ran) {
88961
+ const line = ran.out.trim().split("\n").at(-1) ?? "";
88962
+ try {
88963
+ return JSON.parse(line);
88964
+ } catch {
88965
+ return null;
88966
+ }
88967
+ }
88968
+
89039
88969
  // src/cache.ts
89040
88970
  import { spawnSync as spawnSync3 } from "node:child_process";
89041
- import fs12 from "node:fs";
89042
- import path15 from "node:path";
88971
+ import fs13 from "node:fs";
88972
+ import path16 from "node:path";
89043
88973
 
89044
88974
  // src/folders.ts
89045
- import fs11 from "node:fs";
88975
+ import fs12 from "node:fs";
89046
88976
  import os5 from "node:os";
89047
- import path14 from "node:path";
89048
- var projectsFile = () => path14.join(runnerHome(), "projects.json");
88977
+ import path15 from "node:path";
88978
+ var projectsFile = () => path15.join(runnerHome(), "projects.json");
89049
88979
  function realpath(p2) {
89050
88980
  try {
89051
- return fs11.realpathSync(p2);
88981
+ return fs12.realpathSync(p2);
89052
88982
  } catch {
89053
88983
  return null;
89054
88984
  }
89055
88985
  }
89056
88986
  function readList() {
89057
88987
  try {
89058
- const held3 = JSON.parse(fs11.readFileSync(projectsFile(), "utf8"));
89059
- return Array.isArray(held3.projects) ? held3.projects.filter((p2) => typeof p2 === "string") : [];
88988
+ const held4 = JSON.parse(fs12.readFileSync(projectsFile(), "utf8"));
88989
+ return Array.isArray(held4.projects) ? held4.projects.filter((p2) => typeof p2 === "string") : [];
89060
88990
  } catch {
89061
88991
  return [];
89062
88992
  }
89063
88993
  }
89064
88994
  function writeList(list) {
89065
- fs11.mkdirSync(runnerHome(), { recursive: true, mode: 448 });
89066
- fs11.writeFileSync(projectsFile(), `${JSON.stringify({ projects: [...new Set(list)] }, null, 2)}
88995
+ fs12.mkdirSync(runnerHome(), { recursive: true, mode: 448 });
88996
+ fs12.writeFileSync(projectsFile(), `${JSON.stringify({ projects: [...new Set(list)] }, null, 2)}
89067
88997
  `);
89068
88998
  }
89069
88999
  function allowedProjects() {
@@ -89087,7 +89017,7 @@ var SYSTEM_WIN = ["Windows", "Program Files", "Program Files (x86)", "ProgramDat
89087
89017
  var here = () => ({ platform: process.platform, home: os5.homedir(), resolve: realpath });
89088
89018
  function refusal(picked, where = here()) {
89089
89019
  const win = where.platform === "win32";
89090
- const p2 = win ? path14.win32 : path14.posix;
89020
+ const p2 = win ? path15.win32 : path15.posix;
89091
89021
  const real = where.resolve(picked);
89092
89022
  if (!real || !p2.isAbsolute(real)) return "missing";
89093
89023
  const norm = (d2) => {
@@ -89113,40 +89043,40 @@ function refusal(picked, where = here()) {
89113
89043
  var IDLE_MS = 7 * 24 * 60 * 6e4;
89114
89044
  var SWEEP_MS = 24 * 60 * 6e4;
89115
89045
  var PROJECT_ID = /^[\w-]{1,100}$/;
89116
- var cacheRoot = () => path15.join(runnerHome(), "cache");
89046
+ var cacheRoot = () => path16.join(runnerHome(), "cache");
89117
89047
  function cacheDir(project) {
89118
89048
  if (!PROJECT_ID.test(project)) throw new Error("This job names no project.");
89119
- return path15.join(cacheRoot(), project);
89049
+ return path16.join(cacheRoot(), project);
89120
89050
  }
89121
- var akbDir = (dir) => path15.join(dir, ".akb");
89122
- var usedFile = (dir) => path15.join(akbDir(dir), "used.json");
89123
- var unsentFile = (dir) => path15.join(akbDir(dir), "unsent");
89051
+ var akbDir = (dir) => path16.join(dir, ".akb");
89052
+ var usedFile = (dir) => path16.join(akbDir(dir), "used.json");
89053
+ var unsentFile = (dir) => path16.join(akbDir(dir), "unsent");
89124
89054
  function markUsed(dir, at2 = Date.now()) {
89125
- fs12.mkdirSync(akbDir(dir), { recursive: true });
89126
- fs12.writeFileSync(usedFile(dir), `${JSON.stringify({ at: at2 })}
89055
+ fs13.mkdirSync(akbDir(dir), { recursive: true });
89056
+ fs13.writeFileSync(usedFile(dir), `${JSON.stringify({ at: at2 })}
89127
89057
  `);
89128
89058
  }
89129
89059
  function usedAt(dir) {
89130
89060
  try {
89131
- const at2 = JSON.parse(fs12.readFileSync(usedFile(dir), "utf8")).at;
89061
+ const at2 = JSON.parse(fs13.readFileSync(usedFile(dir), "utf8")).at;
89132
89062
  return typeof at2 === "number" ? at2 : null;
89133
89063
  } catch {
89134
89064
  return null;
89135
89065
  }
89136
89066
  }
89137
- var unsent = (dir) => fs12.existsSync(unsentFile(dir));
89067
+ var unsent = (dir) => fs13.existsSync(unsentFile(dir));
89138
89068
  function markUnsent(dir, unsent2) {
89139
- if (!unsent2) return void fs12.rmSync(unsentFile(dir), { force: true });
89140
- fs12.mkdirSync(akbDir(dir), { recursive: true });
89141
- fs12.writeFileSync(unsentFile(dir), "");
89069
+ if (!unsent2) return void fs13.rmSync(unsentFile(dir), { force: true });
89070
+ fs13.mkdirSync(akbDir(dir), { recursive: true });
89071
+ fs13.writeFileSync(unsentFile(dir), "");
89142
89072
  }
89143
89073
  var holds = /* @__PURE__ */ new Map();
89144
89074
  function hold(dir) {
89145
89075
  holds.set(dir, (holds.get(dir) ?? 0) + 1);
89146
- let held3 = true;
89076
+ let held4 = true;
89147
89077
  return () => {
89148
- if (!held3) return;
89149
- held3 = false;
89078
+ if (!held4) return;
89079
+ held4 = false;
89150
89080
  const left = holds.get(dir) - 1;
89151
89081
  if (left) holds.set(dir, left);
89152
89082
  else holds.delete(dir);
@@ -89154,9 +89084,9 @@ function hold(dir) {
89154
89084
  }
89155
89085
  function paused(dir) {
89156
89086
  try {
89157
- const file2 = path15.join(projectStateDir(path15.join(akbDir(dir), "kanban")), SESSIONS_FILE);
89158
- const held3 = JSON.parse(fs12.readFileSync(file2, "utf8"));
89159
- return (held3.deliveries ?? []).some((d2) => d2.status === "active");
89087
+ const file2 = path16.join(projectStateDir(path16.join(akbDir(dir), "kanban")), SESSIONS_FILE);
89088
+ const held4 = JSON.parse(fs13.readFileSync(file2, "utf8"));
89089
+ return (held4.deliveries ?? []).some((d2) => d2.status === "active");
89160
89090
  } catch {
89161
89091
  return false;
89162
89092
  }
@@ -89168,11 +89098,11 @@ function clearAkb(dir) {
89168
89098
  if (kept2(dir)) return false;
89169
89099
  let entries;
89170
89100
  try {
89171
- entries = fs12.readdirSync(akbDir(dir));
89101
+ entries = fs13.readdirSync(akbDir(dir));
89172
89102
  } catch {
89173
89103
  return true;
89174
89104
  }
89175
- for (const name of entries) fs12.rmSync(path15.join(akbDir(dir), name), { recursive: true, force: true });
89105
+ for (const name of entries) fs13.rmSync(path16.join(akbDir(dir), name), { recursive: true, force: true });
89176
89106
  spawnSync3("git", ["-C", dir, "worktree", "prune"], { stdio: "ignore" });
89177
89107
  return true;
89178
89108
  }
@@ -89187,7 +89117,7 @@ async function readAccess(machineId2) {
89187
89117
  }
89188
89118
  function realpath2(p2) {
89189
89119
  try {
89190
- return fs12.realpathSync(p2);
89120
+ return fs13.realpathSync(p2);
89191
89121
  } catch {
89192
89122
  return p2;
89193
89123
  }
@@ -89202,25 +89132,25 @@ async function sweepCache(machineId2, now = Date.now()) {
89202
89132
  const swept = [];
89203
89133
  let cached2 = [];
89204
89134
  try {
89205
- cached2 = fs12.readdirSync(cacheRoot(), { withFileTypes: true });
89135
+ cached2 = fs13.readdirSync(cacheRoot(), { withFileTypes: true });
89206
89136
  } catch {
89207
89137
  }
89208
89138
  for (const e2 of cached2) {
89209
- const dir = path15.join(cacheRoot(), e2.name);
89139
+ const dir = path16.join(cacheRoot(), e2.name);
89210
89140
  if (!e2.isDirectory() || kept2(dir)) continue;
89211
89141
  const gone = access && !access.projects.has(e2.name);
89212
89142
  if (idle(dir, now) || gone) {
89213
- fs12.rmSync(dir, { recursive: true, force: true });
89143
+ fs13.rmSync(dir, { recursive: true, force: true });
89214
89144
  swept.push(dir);
89215
89145
  }
89216
89146
  }
89217
89147
  for (const dir of allowedProjects()) {
89218
- let held3 = [];
89148
+ let held4 = [];
89219
89149
  try {
89220
- held3 = fs12.readdirSync(akbDir(dir));
89150
+ held4 = fs13.readdirSync(akbDir(dir));
89221
89151
  } catch {
89222
89152
  }
89223
- if (!held3.length) continue;
89153
+ if (!held4.length) continue;
89224
89154
  const gone = access && !access.folders.has(dir);
89225
89155
  if ((idle(dir, now) || gone) && clearAkb(dir)) swept.push(dir);
89226
89156
  }
@@ -89228,24 +89158,231 @@ async function sweepCache(machineId2, now = Date.now()) {
89228
89158
  }
89229
89159
  function removeLegacy() {
89230
89160
  const home4 = runnerHome();
89231
- for (const name of ["boards", "akb-bin"]) fs12.rmSync(path15.join(home4, name), { recursive: true, force: true });
89161
+ for (const name of ["boards", "akb-bin"]) fs13.rmSync(path16.join(home4, name), { recursive: true, force: true });
89232
89162
  let entries = [];
89233
89163
  try {
89234
- entries = fs12.readdirSync(home4, { withFileTypes: true });
89164
+ entries = fs13.readdirSync(home4, { withFileTypes: true });
89235
89165
  } catch {
89236
89166
  return;
89237
89167
  }
89238
89168
  for (const e2 of entries) {
89239
- const account = path15.join(home4, e2.name);
89240
- if (!e2.isDirectory() || !fs12.existsSync(path15.join(account, "unfiled"))) continue;
89241
- fs12.rmSync(path15.join(account, "unfiled"), { recursive: true, force: true });
89242
- if (!fs12.readdirSync(account).length) fs12.rmdirSync(account);
89169
+ const account = path16.join(home4, e2.name);
89170
+ if (!e2.isDirectory() || !fs13.existsSync(path16.join(account, "unfiled"))) continue;
89171
+ fs13.rmSync(path16.join(account, "unfiled"), { recursive: true, force: true });
89172
+ if (!fs13.readdirSync(account).length) fs13.rmdirSync(account);
89243
89173
  }
89244
89174
  }
89245
89175
 
89246
- // src/chats.ts
89176
+ // src/update.ts
89177
+ import crypto2 from "node:crypto";
89247
89178
  import fs14 from "node:fs";
89248
89179
  import path17 from "node:path";
89180
+ import zlib from "node:zlib";
89181
+ var TIMEOUT_MS2 = 6e4;
89182
+ var registry = () => (process.env.npm_config_registry || "https://registry.npmjs.org").replace(/\/+$/, "");
89183
+ async function installPackage(pkg, version, nodeVersion = process.versions.node) {
89184
+ const dir = pkg.dirOf(version);
89185
+ if (fs14.existsSync(pkg.entryOf(dir))) return { ok: true, dir };
89186
+ let meta;
89187
+ let tarball;
89188
+ try {
89189
+ const answer = await fetch(`${registry()}/${pkg.name}/${encodeURIComponent(version)}`, { signal: AbortSignal.timeout(TIMEOUT_MS2) });
89190
+ if (!answer.ok) return { ok: false, why: "unreachable", detail: `registry answered ${answer.status}` };
89191
+ meta = await answer.json();
89192
+ const range = meta.engines?.node;
89193
+ if (range && !satisfies(nodeVersion, range)) return { ok: false, why: "node", detail: range };
89194
+ if (!meta.dist?.tarball) return { ok: false, why: "unreachable", detail: "no tarball" };
89195
+ const download2 = await fetch(meta.dist.tarball, { signal: AbortSignal.timeout(TIMEOUT_MS2) });
89196
+ if (!download2.ok) return { ok: false, why: "unreachable", detail: `download answered ${download2.status}` };
89197
+ tarball = Buffer.from(await download2.arrayBuffer());
89198
+ } catch (e2) {
89199
+ return { ok: false, why: "unreachable", detail: e2 instanceof Error ? e2.message : String(e2) };
89200
+ }
89201
+ const expected = /^sha512-(.+)$/.exec(meta.dist.integrity ?? "")?.[1];
89202
+ const actual = crypto2.createHash("sha512").update(tarball).digest("base64");
89203
+ if (!expected || expected !== actual) return { ok: false, why: "integrity", detail: "sha512 mismatch" };
89204
+ const staging = `${dir}.${process.pid}.tmp`;
89205
+ try {
89206
+ fs14.rmSync(staging, { recursive: true, force: true });
89207
+ extract(zlib.gunzipSync(tarball), staging);
89208
+ if (!fs14.existsSync(pkg.entryOf(staging))) throw new Error(`the package carries no ${path17.relative(staging, pkg.entryOf(staging))}`);
89209
+ fs14.rmSync(dir, { recursive: true, force: true });
89210
+ fs14.renameSync(staging, dir);
89211
+ } catch (e2) {
89212
+ fs14.rmSync(staging, { recursive: true, force: true });
89213
+ return { ok: false, why: "integrity", detail: e2 instanceof Error ? e2.message : String(e2) };
89214
+ }
89215
+ return { ok: true, dir };
89216
+ }
89217
+ function extract(tar, into) {
89218
+ let offset = 0;
89219
+ let longName = null;
89220
+ while (offset + 512 <= tar.length) {
89221
+ const header = tar.subarray(offset, offset + 512);
89222
+ if (header.every((b2) => b2 === 0)) break;
89223
+ const field = (start, length) => header.subarray(start, start + length).toString("utf8").replace(/\0.*$/s, "");
89224
+ const size = parseInt(field(124, 12).trim() || "0", 8);
89225
+ const type = field(156, 1) || "0";
89226
+ const body = tar.subarray(offset + 512, offset + 512 + size);
89227
+ offset += 512 + Math.ceil(size / 512) * 512;
89228
+ if (type === "x") {
89229
+ longName = /(?:^|\n)\d+ path=([^\n]*)\n/.exec(body.toString("utf8"))?.[1] ?? null;
89230
+ continue;
89231
+ }
89232
+ if (type === "L") {
89233
+ longName = body.toString("utf8").replace(/\0.*$/s, "");
89234
+ continue;
89235
+ }
89236
+ const prefix = field(345, 155);
89237
+ const name = longName ?? (prefix ? `${prefix}/${field(0, 100)}` : field(0, 100));
89238
+ longName = null;
89239
+ if (type !== "0" && type !== "5") continue;
89240
+ const relative = name.replace(/^[^/]+\//, "");
89241
+ if (!relative) continue;
89242
+ const target = path17.resolve(into, relative);
89243
+ if (!target.startsWith(path17.resolve(into) + path17.sep)) throw new Error(`refusing ${name}`);
89244
+ if (type === "5") fs14.mkdirSync(target, { recursive: true });
89245
+ else {
89246
+ fs14.mkdirSync(path17.dirname(target), { recursive: true });
89247
+ fs14.writeFileSync(target, body);
89248
+ }
89249
+ }
89250
+ }
89251
+ var parse = (v2) => {
89252
+ const m = /^v?(\d+)(?:\.(\d+|x|\*))?(?:\.(\d+|x|\*))?/.exec(v2.trim());
89253
+ return m ? [Number(m[1]), Number(m[2]) || 0, Number(m[3]) || 0] : null;
89254
+ };
89255
+ function compare(a3, b2) {
89256
+ const [x2, y2] = [parse(a3) ?? [0, 0, 0], parse(b2) ?? [0, 0, 0]];
89257
+ for (let i = 0; i < 3; i++) if (x2[i] !== y2[i]) return x2[i] - y2[i];
89258
+ return 0;
89259
+ }
89260
+ function satisfies(version, range) {
89261
+ return range.split("||").some((alternative) => {
89262
+ const parts = alternative.trim().split(/\s+/).filter(Boolean);
89263
+ return parts.length > 0 && parts.every((part) => meets(version, part));
89264
+ });
89265
+ }
89266
+ function meets(version, comparator) {
89267
+ const m = /^(>=|<=|>|<|=|\^|~)?\s*(.+)$/.exec(comparator);
89268
+ const bound = m && parse(m[2]);
89269
+ if (!m || !bound) return false;
89270
+ const v2 = parse(version);
89271
+ const c2 = compare(version, m[2]);
89272
+ switch (m[1]) {
89273
+ case ">=":
89274
+ return c2 >= 0;
89275
+ case ">":
89276
+ return c2 > 0;
89277
+ case "<=":
89278
+ return c2 <= 0;
89279
+ case "<":
89280
+ return c2 < 0;
89281
+ case "^":
89282
+ return c2 >= 0 && v2[0] === bound[0];
89283
+ case "~":
89284
+ return c2 >= 0 && v2[0] === bound[0] && v2[1] === bound[1];
89285
+ default: {
89286
+ const given = m[2].split(".").filter((p2) => /^\d+$/.test(p2)).length;
89287
+ return [0, 1, 2].slice(0, given).every((i) => v2[i] === bound[i]);
89288
+ }
89289
+ }
89290
+ }
89291
+
89292
+ // src/akb-version.ts
89293
+ var CHECK_MS2 = 1e4;
89294
+ var VERSION2 = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;
89295
+ var stateFile = () => path18.join(akbHome(), "state.json");
89296
+ var akbVersionDir = (version) => path18.join(akbHome(), version);
89297
+ var entryOf = (dir) => path18.join(dir, "bin", "ai4kanban.mjs");
89298
+ var AKB = { name: "wildcrane", dirOf: akbVersionDir, entryOf };
89299
+ function readAkbState() {
89300
+ try {
89301
+ const held4 = JSON.parse(fs15.readFileSync(stateFile(), "utf8"));
89302
+ return { current: held4.current ?? null, bad: held4.bad ?? [] };
89303
+ } catch {
89304
+ return { current: null, bad: [] };
89305
+ }
89306
+ }
89307
+ function writeAkbState(state) {
89308
+ fs15.mkdirSync(akbHome(), { recursive: true });
89309
+ const staging = `${stateFile()}.${process.pid}.tmp`;
89310
+ fs15.writeFileSync(staging, `${JSON.stringify(state, null, 2)}
89311
+ `);
89312
+ fs15.renameSync(staging, stateFile());
89313
+ }
89314
+ function contractOf(dir) {
89315
+ try {
89316
+ return JSON.parse(fs15.readFileSync(path18.join(dir, "package.json"), "utf8")).akbContract ?? null;
89317
+ } catch {
89318
+ return null;
89319
+ }
89320
+ }
89321
+ var usable = (dir) => fs15.existsSync(entryOf(dir)) && contractOf(dir) === AKB_CONTRACT;
89322
+ function currentAkb() {
89323
+ const { current } = readAkbState();
89324
+ if (!current) return bundledAkb();
89325
+ const dir = akbVersionDir(current);
89326
+ if (!usable(dir)) return bundledAkb();
89327
+ try {
89328
+ const now = /* @__PURE__ */ new Date();
89329
+ fs15.utimesSync(dir, now, now);
89330
+ } catch {
89331
+ }
89332
+ return { command: process.execPath, args: [entryOf(dir)], version: current, shim: path18.join(dir, "shim") };
89333
+ }
89334
+ var answers2 = (dir, version) => new Promise((resolve2) => {
89335
+ execFile(process.execPath, [entryOf(dir), "--version"], { timeout: CHECK_MS2, killSignal: "SIGKILL" }, (error, stdout) => resolve2(!error && stdout.trim().split(/\s+/).at(-1) === version));
89336
+ });
89337
+ var wanted = null;
89338
+ var fetching = false;
89339
+ function useVersion(current) {
89340
+ const state = readAkbState();
89341
+ if (state.current !== current) writeAkbState({ ...state, current });
89342
+ }
89343
+ async function fetchVersion(version) {
89344
+ const got = await installPackage(AKB, version);
89345
+ if (!got.ok) return console.error(`runner: akb ${version} was not fetched: ${got.detail}`);
89346
+ if (contractOf(got.dir) !== AKB_CONTRACT || !await answers2(got.dir, version)) {
89347
+ console.error(`runner: akb ${version} failed its check and will not be used`);
89348
+ const state = readAkbState();
89349
+ return writeAkbState({ ...state, bad: [.../* @__PURE__ */ new Set([...state.bad, version])] });
89350
+ }
89351
+ if (wanted === version) useVersion(version);
89352
+ }
89353
+ async function followAkb(named2) {
89354
+ if (!named2) return;
89355
+ const { version } = named2;
89356
+ try {
89357
+ if (version !== null && !VERSION2.test(version)) return;
89358
+ wanted = version;
89359
+ if (version === null || version === AKB_VERSION) return useVersion(null);
89360
+ const state = readAkbState();
89361
+ if (fetching || state.bad.includes(version) || state.current === version && usable(akbVersionDir(version))) return;
89362
+ fetching = true;
89363
+ await fetchVersion(version).finally(() => fetching = false);
89364
+ } catch (e2) {
89365
+ console.error(`runner: the akb version was not followed: ${e2 instanceof Error ? e2.message : String(e2)}`);
89366
+ }
89367
+ }
89368
+ function sweepAkb(now = Date.now()) {
89369
+ const { current } = readAkbState();
89370
+ let entries = [];
89371
+ try {
89372
+ entries = fs15.readdirSync(akbHome(), { withFileTypes: true });
89373
+ } catch {
89374
+ return;
89375
+ }
89376
+ for (const e2 of entries) {
89377
+ if (!e2.isDirectory() || e2.name === current || e2.name === BUNDLED_SHIM) continue;
89378
+ const dir = path18.join(akbHome(), e2.name);
89379
+ if (now - fs15.statSync(dir).mtimeMs > IDLE_MS) fs15.rmSync(dir, { recursive: true, force: true });
89380
+ }
89381
+ }
89382
+
89383
+ // src/chats.ts
89384
+ import fs17 from "node:fs";
89385
+ import path20 from "node:path";
89249
89386
 
89250
89387
  // ../cloud/src/config.ts
89251
89388
  var CLAIM_LEASE_SECONDS = 15 * 60;
@@ -89261,18 +89398,18 @@ var CONTACT_ATTEMPT_WINDOW_SECONDS = 60 * 60;
89261
89398
  var CHAT_KEEP_DAYS = 30;
89262
89399
 
89263
89400
  // ../cli/src/lib/agent/task-chats.ts
89264
- import fs13 from "node:fs";
89265
- import path16 from "node:path";
89401
+ import fs16 from "node:fs";
89402
+ import path19 from "node:path";
89266
89403
  var TASK = /^[\w-]{1,100}$/;
89267
- var taskChatsDir = (home4 = machineHome()) => path16.join(home4, "chats");
89404
+ var taskChatsDir = (home4 = machineHome()) => path19.join(home4, "chats");
89268
89405
  function taskChatFile(task, home4) {
89269
89406
  if (!TASK.test(task)) throw new Error(`${task} is not a task id.`);
89270
- return path16.join(taskChatsDir(home4), `${task}.jsonl`);
89407
+ return path19.join(taskChatsDir(home4), `${task}.jsonl`);
89271
89408
  }
89272
89409
  function readTaskChat(task, home4) {
89273
89410
  let text3;
89274
89411
  try {
89275
- text3 = fs13.readFileSync(taskChatFile(task, home4), "utf8");
89412
+ text3 = fs16.readFileSync(taskChatFile(task, home4), "utf8");
89276
89413
  } catch {
89277
89414
  return [];
89278
89415
  }
@@ -89293,18 +89430,18 @@ var DAY_MS = 24 * 60 * 6e4;
89293
89430
  var REVIEW_EVERY_MS = DAY_MS;
89294
89431
  var KEEP_MS2 = CHAT_KEEP_DAYS * DAY_MS;
89295
89432
  var home3 = () => runnerHome();
89296
- var reviewedFile = () => path17.join(taskChatsDir(home3()), "reviewed.json");
89433
+ var reviewedFile = () => path20.join(taskChatsDir(home3()), "reviewed.json");
89297
89434
  function readReviewed() {
89298
89435
  try {
89299
- const held3 = JSON.parse(fs14.readFileSync(reviewedFile(), "utf8"));
89300
- return { checkedAt: Number(held3.checkedAt) || 0, tasks: held3.tasks ?? {} };
89436
+ const held4 = JSON.parse(fs17.readFileSync(reviewedFile(), "utf8"));
89437
+ return { checkedAt: Number(held4.checkedAt) || 0, tasks: held4.tasks ?? {} };
89301
89438
  } catch {
89302
89439
  return { checkedAt: 0, tasks: {} };
89303
89440
  }
89304
89441
  }
89305
89442
  function writeReviewed(reviewed) {
89306
- fs14.mkdirSync(path17.dirname(reviewedFile()), { recursive: true });
89307
- fs14.writeFileSync(reviewedFile(), `${JSON.stringify(reviewed, null, 2)}
89443
+ fs17.mkdirSync(path20.dirname(reviewedFile()), { recursive: true });
89444
+ fs17.writeFileSync(reviewedFile(), `${JSON.stringify(reviewed, null, 2)}
89308
89445
  `);
89309
89446
  }
89310
89447
  function keepChat(job, reply, at2 = Date.now()) {
@@ -89314,21 +89451,40 @@ function keepChat(job, reply, at2 = Date.now()) {
89314
89451
  { id: job.id, role: "agent", text: reply, at: at2, runtime: job.runtime, model: job.model ?? null }
89315
89452
  ];
89316
89453
  const file2 = taskChatFile(job.task, home3());
89317
- fs14.mkdirSync(path17.dirname(file2), { recursive: true });
89318
- fs14.appendFileSync(file2, lines.map((l2) => `${JSON.stringify(l2)}
89454
+ fs17.mkdirSync(path20.dirname(file2), { recursive: true });
89455
+ fs17.appendFileSync(file2, lines.map((l2) => `${JSON.stringify(l2)}
89319
89456
  `).join(""));
89320
89457
  }
89321
89458
  function keepCloudChat(task, messages) {
89322
89459
  const file2 = taskChatFile(task, home3());
89323
- if (!messages.length) return fs14.rmSync(file2, { force: true });
89460
+ if (!messages.length) return fs17.rmSync(file2, { force: true });
89324
89461
  const lines = messages.map((m) => ({ id: m.id, role: m.role, text: m.body, at: Date.parse(m.created_at) || Date.now() }));
89325
- fs14.mkdirSync(path17.dirname(file2), { recursive: true });
89326
- fs14.writeFileSync(file2, lines.map((l2) => `${JSON.stringify(l2)}
89462
+ fs17.mkdirSync(path20.dirname(file2), { recursive: true });
89463
+ fs17.writeFileSync(file2, lines.map((l2) => `${JSON.stringify(l2)}
89464
+ `).join(""));
89465
+ }
89466
+ async function keepDecisions(task, read) {
89467
+ const comments = [];
89468
+ let after = null;
89469
+ do {
89470
+ const page = await read(task, after);
89471
+ if (!page.ok) return;
89472
+ for (const d2 of page.value.data) {
89473
+ if (d2.comment.trim()) comments.push({ id: d2.id, role: "user", text: d2.comment, at: Date.parse(d2.created_at) || Date.now() });
89474
+ }
89475
+ after = page.value.next;
89476
+ } while (after);
89477
+ if (!comments.length) return;
89478
+ const ids = new Set(comments.map((c2) => c2.id));
89479
+ const lines = [...readTaskChat(task, home3()).filter((l2) => !ids.has(l2.id)), ...comments].sort((a3, b2) => a3.at - b2.at);
89480
+ const file2 = taskChatFile(task, home3());
89481
+ fs17.mkdirSync(path20.dirname(file2), { recursive: true });
89482
+ fs17.writeFileSync(file2, lines.map((l2) => `${JSON.stringify(l2)}
89327
89483
  `).join(""));
89328
89484
  }
89329
89485
  var tasksKept = () => {
89330
89486
  try {
89331
- return fs14.readdirSync(taskChatsDir(home3())).map((n) => /^([\w-]{1,100})\.jsonl$/.exec(n)?.[1]).filter((t2) => !!t2);
89487
+ return fs17.readdirSync(taskChatsDir(home3())).map((n) => /^([\w-]{1,100})\.jsonl$/.exec(n)?.[1]).filter((t2) => !!t2);
89332
89488
  } catch {
89333
89489
  return [];
89334
89490
  }
@@ -89339,9 +89495,9 @@ function pruneChats(now = Date.now()) {
89339
89495
  const kept4 = lines.filter((l2) => now - l2.at < KEEP_MS2);
89340
89496
  if (kept4.length === lines.length) continue;
89341
89497
  const file2 = taskChatFile(task, home3());
89342
- if (kept4.length) fs14.writeFileSync(file2, kept4.map((l2) => `${JSON.stringify(l2)}
89498
+ if (kept4.length) fs17.writeFileSync(file2, kept4.map((l2) => `${JSON.stringify(l2)}
89343
89499
  `).join(""));
89344
- else fs14.rmSync(file2, { force: true });
89500
+ else fs17.rmSync(file2, { force: true });
89345
89501
  }
89346
89502
  }
89347
89503
  var lastOf = (task) => readTaskChat(task, home3()).at(-1);
@@ -89374,42 +89530,43 @@ async function reviewChats(machineId2, runtimes, now = Date.now()) {
89374
89530
  if (!sent.ok) console.error(`runner: the chats of ${project} were not sent for review: ${sent.error}`);
89375
89531
  }
89376
89532
  const listed2 = new Set(owned.value.chats.map((c2) => c2.task));
89377
- const held3 = readReviewed();
89378
- writeReviewed({ checkedAt: now, tasks: Object.fromEntries(Object.entries(held3.tasks).filter(([t2]) => listed2.has(t2))) });
89533
+ const held4 = readReviewed();
89534
+ writeReviewed({ checkedAt: now, tasks: Object.fromEntries(Object.entries(held4.tasks).filter(([t2]) => listed2.has(t2))) });
89379
89535
  }
89380
89536
 
89381
89537
  // src/board-watch.ts
89382
- import fs18 from "node:fs";
89383
- import path21 from "node:path";
89538
+ import fs21 from "node:fs";
89539
+ import path24 from "node:path";
89384
89540
 
89385
89541
  // ../cloud/src/board-files.ts
89386
89542
  var ROOTS = ["todo/", ".archive/", "memory/", "workflows/", "triage/", "assets/", "rules/"];
89387
89543
  var SETTINGS = ["modules.md", "config.md"];
89388
- var isSettingsPath = (path31) => SETTINGS.includes(path31) || /^rules\/(?:workflows\/)?[^/]+\.md$/.test(path31);
89544
+ var isSettingsPath = (path34) => SETTINGS.includes(path34) || /^rules\/(?:workflows\/)?[^/]+\.md$/.test(path34);
89389
89545
  var BOARD_FILE_LIMIT = 256 * 1024;
89390
- function isBoardPath(path31) {
89391
- if (!path31 || path31.length > 500 || path31.startsWith("/") || path31.includes("\\") || path31.includes("\0")) return false;
89392
- if (path31.split("/").some((part) => !part || part === "." || part === "..")) return false;
89393
- if (path31 === "todo/README.md" || path31.split("/").includes(".sync")) return false;
89394
- if (path31.startsWith("workflows/")) return true;
89395
- if (SETTINGS.includes(path31)) return true;
89396
- if (path31.startsWith("rules/")) return isSettingsPath(path31);
89397
- if (path31.startsWith("assets/")) return path31.endsWith(".json");
89398
- return ROOTS.some((root) => path31.startsWith(root)) && path31.endsWith(".md");
89546
+ function isBoardPath(path34) {
89547
+ if (!path34 || path34.length > 500 || path34.startsWith("/") || path34.includes("\\") || path34.includes("\0")) return false;
89548
+ if (path34.split("/").some((part) => !part || part === "." || part === "..")) return false;
89549
+ if (path34 === "todo/README.md" || path34.split("/").includes(".sync")) return false;
89550
+ if (path34.startsWith("workflows/")) return true;
89551
+ if (SETTINGS.includes(path34)) return true;
89552
+ if (path34.startsWith("rules/")) return isSettingsPath(path34);
89553
+ if (path34.startsWith("assets/")) return path34.endsWith(".json");
89554
+ return ROOTS.some((root) => path34.startsWith(root)) && path34.endsWith(".md");
89399
89555
  }
89400
89556
  var CARD = /^(?:todo|\.archive)\/(?:[^/]+\/)*(\d+)-[^/]*\.md$/;
89401
89557
  var ROOT = /^(?:todo|\.archive)\/(?:[^/]+\/)*(\d+)-[^/]+\/root\.md$/;
89402
- function numberOfCard(path31) {
89403
- const n = ROOT.exec(path31)?.[1] ?? CARD.exec(path31)?.[1];
89558
+ function numberOfCard(path34) {
89559
+ const n = ROOT.exec(path34)?.[1] ?? CARD.exec(path34)?.[1];
89404
89560
  return n ? Number(n) : null;
89405
89561
  }
89406
89562
  var cardSlug = (task) => task.toLowerCase().replace(/_/g, "-");
89407
89563
  var assetsFile = (task) => `assets/${task}.json`;
89408
89564
  var workflowFolder = (id) => id.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
89565
+ var OWN_FOLDER = /^wf-(?!builtin-)[a-z0-9-]+$/;
89409
89566
  var workflowName = (id) => id.startsWith("wf_builtin_") ? id.slice("wf_builtin_".length).replace(/_/g, "-") : workflowFolder(id);
89410
89567
  var BUILDER = "wf_builtin_workflow_builder";
89411
89568
  var draftFolder = (task) => cardSlug(task);
89412
- var unquote2 = (value) => value.trim().replace(/^(["'])(.*)\1$/, "$2");
89569
+ var unquote = (value) => value.trim().replace(/^(["'])(.*)\1$/, "$2");
89413
89570
  function cardFront(body) {
89414
89571
  const match = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/.exec(body);
89415
89572
  if (!match) return {};
@@ -89418,13 +89575,13 @@ function cardFront(body) {
89418
89575
  const field = /^(title|status|phase|stages|previews):\s*(.*)$/.exec(line);
89419
89576
  if (!field) continue;
89420
89577
  const [, key, value = ""] = field;
89421
- if (key === "title" && value.trim()) out.title = unquote2(value);
89422
- 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);
89423
89580
  else if (key === "phase" && Number.isInteger(Number(value)) && value.trim()) out.phase = Number(value);
89424
89581
  else if (key === "stages" && Number.isInteger(Number(value)) && value.trim()) out.stages = Number(value);
89425
89582
  else if (key === "previews") {
89426
89583
  const flow = /^\[(.*)\]\s*$/.exec(value.trim());
89427
- if (flow) out.previews = flow[1].split(",").map(unquote2).filter(Boolean);
89584
+ if (flow) out.previews = flow[1].split(",").map(unquote).filter(Boolean);
89428
89585
  }
89429
89586
  }
89430
89587
  return out;
@@ -89432,9 +89589,9 @@ function cardFront(body) {
89432
89589
 
89433
89590
  // src/task-folder.ts
89434
89591
  import { spawnSync as spawnSync4 } from "node:child_process";
89435
- import crypto2 from "node:crypto";
89436
- import fs17 from "node:fs";
89437
- import path20 from "node:path";
89592
+ import crypto3 from "node:crypto";
89593
+ import fs20 from "node:fs";
89594
+ import path23 from "node:path";
89438
89595
 
89439
89596
  // node_modules/node-diff3/dist/diff3.mjs
89440
89597
  function LCS(buffer1, buffer2) {
@@ -89649,10 +89806,32 @@ function diff3Merge(a3, o2, b2, options) {
89649
89806
  return results;
89650
89807
  }
89651
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
+
89652
89831
  // ../cloud/src/triage-files.ts
89653
89832
  var ITEM = /^triage\/(?:(dismissed|archived)\/)?([^/]+)\.md$/;
89654
- function itemAt(path31) {
89655
- const m = ITEM.exec(path31);
89833
+ function itemAt(path34) {
89834
+ const m = ITEM.exec(path34);
89656
89835
  if (!m) return null;
89657
89836
  return { state: m[1] === "dismissed" ? "dismissed" : m[1] === "archived" ? "carded" : "open", name: m[2] };
89658
89837
  }
@@ -89669,8 +89848,8 @@ function stampItem(content, fields) {
89669
89848
  }
89670
89849
 
89671
89850
  // ../cli/src/lib/agents/shared-memory.ts
89672
- import fs15 from "node:fs";
89673
- import path18 from "node:path";
89851
+ import fs18 from "node:fs";
89852
+ import path21 from "node:path";
89674
89853
 
89675
89854
  // ../cli/src/agents/api-designer/AGENT.md
89676
89855
  var AGENT_default = "---\nname: api-designer\ndescription: Writes the caller's documentation for the APIs a card changes.\nakb:\n when: A card adds or changes a surface a user or third party calls directly, such as HTTP routes, WebSocket messages, MCP tools, or CLI commands and flags. Not a protocol between the project's own components.\n i18n:\n en:\n title: API docs\n zh:\n title: \u63A5\u53E3\u6587\u6863\n description: \u4E3A\u5361\u7247\u6539\u52A8\u7684\u63A5\u53E3\u5199\u51FA\u8C03\u7528\u65B9\u6587\u6863\u3002\n when: \u5361\u7247\u65B0\u589E\u6216\u4FEE\u6539\u7528\u6237\u6216\u7B2C\u4E09\u65B9\u76F4\u63A5\u8C03\u7528\u7684\u63A5\u53E3\u65F6\uFF0C\u5982 HTTP \u8DEF\u7531\u3001WebSocket \u6D88\u606F\u3001MCP \u5DE5\u5177\u3001CLI \u547D\u4EE4\u548C\u53C2\u6570\u3002\u4E0D\u542B\u9879\u76EE\u81EA\u8EAB\u7EC4\u4EF6\u4E4B\u95F4\u7684\u534F\u8BAE\u3002\n---\n\nWrite each surface this card changes as the documentation entry that will be committed, in\nthe project's existing docs style: inputs, outputs, errors and one example call. Use a\n`diff` when an entry already exists, and a `mermaid` `sequenceDiagram` for a message\nexchange. One design, no alternatives, nothing else in the section.\n\n- **Glanceable**: a junior engineer understands each entry in one read. Plain names, short\n lines, no field or error the card does not change.\n";
@@ -90128,7 +90307,7 @@ var music_default = "# Music\n\nScore the clone with new music that follows the
90128
90307
  var AGENT_default24 = "---\nname: video-template-builder\ndescription: Builds a video clone's reusable beat-table template from its approved drafts, renders it once and checks it against the source beat by beat.\nakb:\n after: [video-cloner]\n session: new\n i18n:\n en:\n title: Video template\n zh:\n title: \u89C6\u9891\u6A21\u677F\n description: \u6309\u786E\u8BA4\u7684\u590D\u523B\u5206\u955C\u505A\u6210\u4FDD\u7559\u62CD\u6CD5\u3001\u53EF\u6362\u5185\u5BB9\u7684 beat \u8868\u6A21\u677F\uFF0C\u6E32\u67D3\u4E00\u652F\u5E76\u4E0E\u539F\u7247\u9010\u955C\u5BF9\u6BD4\u3002\n---\n\nBuild the template the approved drafts in ``## By `video-cloner` agent`` describe: it reproduces the source's craft and renders the user's content in place of the source's. You are done, with no further question, when the clone's comparison with the source and the render command are recorded on the card.\n\nFollow Terms, Deciding, Files and Memory in `akb raw agent-file video-cloner AGENT.md`; its memory folder is yours.\n\n## Steps\n\n- **Recipe**: write the format (size, frame rate, length, fonts, colours) to `recipe.md` in the files folder; it is your working file, never shown on the card.\n- **Template**: build a project that renders `clone.json` beat by beat, picking for each motion an animation library that fits its style; one project may combine several. The beat table and all content live in one file, holding the user's content from the start, so a beat can be removed or reordered and the content swapped without code changes; the code holds only craft and props. Its `template.md` states that the content in that file is to be replaced with the user's own and that the template reproduces only the source's craft.\n- **Cached clips**: render each beat to its own cached clip and splice the clips into the full video; a change re-renders only the clips it touches.\n- **Check**: render it once and compare it with the source beat by beat side by side on rhythm, motion and layout, and check every on-screen step makes sense to a viewer. A beat that misses the source's structure means the template is wrong: fix it and render again, never hand over the breakdown instead.\n- **Music**: in the template and check, also follow `akb raw agent-file video-cloner references/music.md`.\n- **Card**: under your section heading, show only the clone against the source as a `<Compare>` with `breakdown.json` as `shots`, and each difference left in one line, naming its beat id; append a ticked todo with the template folder's absolute path and, in backticks, its render command.\n- **Changes**: a change to a beat updates only that beat in the template.\n";
90129
90308
 
90130
90309
  // ../cli/src/agents/workflow-writer/AGENT.md
90131
- var AGENT_default25 = "---\nname: workflow-writer\ndescription: Writes a new workflow, or changes one of the user's own, as a `WORKFLOW.md` and the agents it names.\nakb:\n i18n:\n en:\n title: Workflow\n zh:\n title: \u5DE5\u4F5C\u6D41\n description: \u6309\u4F60\u7684\u63CF\u8FF0\u5199\u51FA\u4E00\u4E2A\u5DE5\u4F5C\u6D41\u53CA\u5176 agent\uFF0C\u6216\u4FEE\u6539\u4F60\u5DF2\u6709\u7684\u5DE5\u4F5C\u6D41\u3002\n---\n\nYou write a workflow from the user's request: a kind of work the user runs again and again, where each task shows a person previews to approve before the work goes on.\n\n## Read first\n\n- **The project**: when the board belongs to a project folder, read its README and agent instruction files (such as `AGENTS.md` or `CLAUDE.md`) for what it makes, and its existing outputs of this kind for their format and destination.\n- **This board**: run `akb workflow list` and read `docs/kanban/agents/`, so a new workflow does not repeat one the board already has.\n\n## What to write\n\n- **The workflow**: when the card names a workflow folder, the workflow is that folder: keep its id and change it in place. Otherwise create it with `akb workflow new`. Name it with `akb workflow rename`, and list its agents in its `WORKFLOW.md`: `previews` the agents whose drafts a person approves, `land` the agents that run unattended in order after the last approval, and `scheduled`. Its body is how a card of this kind is written.\n- **Its agents**: write each agent it names as `akb guide write-agent` says.\n- **Approvals**: default to previews a person approves once. Give an agent `after` only when its preview is too costly to make before another is approved, such as a video before its script; it then waits for that approval.\n- **Previews**: give each part a person must see its own agent, such as the screens of a UI change or the script of a video. Show only what the person decides on, and keep previews from overlapping: a UI preview already shows its text, so add no separate copy preview.\n- **Land**: add agents to `land` only for work that needs no review, such as building and merging an approved change; leave it empty when the last approved preview is the deliverable.\n- **Memory**: for each agent, decide whether a user's correction should change its next output, such as a writer's tone or a designer's look; if so, declare its memory as `akb guide write-agent` says, otherwise give it none.\n- **Changing a workflow**: edit its `WORKFLOW.md` and its agents under `docs/kanban/agents/` in place, and keep what the request does not ask to change.\n\n## Check it\n\nRun `akb spec` and `akb workflow list`, and fix every problem reported for this workflow or its agents before finishing.\n\n## Card\n\nUnder your section heading, say in a few lines, for a reader who has never seen a workflow file, what the workflow is for, what each approval shows, what runs after the last one, and what each agent remembers; then embed each file you wrote as an `<Asset>`.\n";
90310
+ var AGENT_default25 = "---\nname: workflow-writer\ndescription: Writes or changes a workflow, one of its preview agents or a scheduled agent, as a `WORKFLOW.md` and the agents it names.\nakb:\n i18n:\n en:\n title: Workflow\n zh:\n title: \u5DE5\u4F5C\u6D41\n description: \u6309\u4F60\u7684\u63CF\u8FF0\u5199\u51FA\u6216\u4FEE\u6539\u5DE5\u4F5C\u6D41\u53CA\u5176 Preview Agent\uFF0C\u6216\u628A\u91CD\u590D\u6027\u5DE5\u4F5C\u5199\u6210\u5B9A\u65F6 agent\u3002\n---\n\nYou write a workflow from the user's request: a kind of work the user runs again and again, where each task shows a person previews to approve before the work goes on. A request may also change one preview agent in a workflow, or ask for work that repeats on a schedule.\n\n## Read first\n\n- **The project**: when the board belongs to a project folder, read its README and agent instruction files (such as `AGENTS.md` or `CLAUDE.md`) for what it makes, and its existing outputs of this kind for their format and destination.\n- **This board**: run `akb workflow list` and read `docs/kanban/agents/`, so a new workflow does not repeat one the board already has.\n\n## What to write\n\n- **The workflow**: when the card names a workflow folder, the workflow is that folder: keep its id and change it in place. Otherwise create it with `akb workflow new`. Name it with `akb workflow rename`, and list its agents in its `WORKFLOW.md`: `previews` the agents whose drafts a person approves, `land` the agents that run unattended in order after the last approval, and `scheduled`. Its body is how a card of this kind is written.\n- **Its agents**: write each agent it names as `akb guide write-agent` says.\n- **Approvals**: default to previews a person approves once. Give an agent `after` only when its preview is too costly to make before another is approved, such as a video before its script; it then waits for that approval.\n- **Previews**: give each part a person must see its own agent, such as the screens of a UI change or the script of a video. Show only what the person decides on, and keep previews from overlapping: a UI preview already shows its text, so add no separate copy preview.\n- **Land**: add agents to `land` only for work that needs no review, such as building and merging an approved change; leave it empty when the last approved preview is the deliverable.\n- **Memory**: for each agent, decide whether a user's correction should change its next output, such as a writer's tone or a designer's look; if so, declare its memory as `akb guide write-agent` says, otherwise give it none.\n- **Changing a workflow**: edit its `WORKFLOW.md` and its agents under `docs/kanban/agents/` in place, and keep what the request does not ask to change.\n- **Preview agents it does not hold**: when the request changes a preview agent of a built-in or another workflow, run `akb workflow duplicate <id>` on that workflow and change the copy of that agent.\n- **Saving a copy**: when the card names a folder, move the copy's `WORKFLOW.md` over the one there and remove the copy's empty folder, because only that folder is saved. Never run `akb workflow delete` on the copy: it deletes the agents too.\n- **Copied schedules**: remove the copy's `scheduled` entries and their agents unless the request is about them, so that work does not run twice.\n- **Repeating work**: write a scheduled agent as `akb guide write-agent` says. It goes in this workflow, which may hold nothing else.\n\n## Check it\n\nRun `akb spec` and `akb workflow list`, and fix every problem reported for this workflow or its agents before finishing.\n\n## Card\n\nUnder your section heading, say in a few lines, for a reader who has never seen a workflow file, what the workflow is for, what each approval shows, what runs after the last one, what runs on a schedule, and what each agent remembers; then embed each file you wrote as an `<Asset>`. When the work is a copy, say that new tasks must pick the copy and that open cards stay on the original.\n";
90132
90311
 
90133
90312
  // ../cli/src/lib/agents/bundled.ts
90134
90313
  var BUNDLED_AGENT_FILES = {
@@ -90238,8 +90417,8 @@ function readMap(lines, start, indent) {
90238
90417
  }
90239
90418
  function readScalar(value) {
90240
90419
  const flow = value.match(/^\[(.*)\]$/);
90241
- if (!flow) return unquote(value);
90242
- 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);
90243
90422
  }
90244
90423
  function readBlock(lines, start, parentIndent) {
90245
90424
  if (start >= lines.length || lines[start].indent <= parentIndent) return ["", start];
@@ -90268,7 +90447,7 @@ function readList2(lines, start, indent) {
90268
90447
  }
90269
90448
  const item = {};
90270
90449
  const inline = stripComment(match[2].trim());
90271
- if (inline) item[match[1].trim()] = unquote(inline);
90450
+ if (inline) item[match[1].trim()] = unquote2(inline);
90272
90451
  else {
90273
90452
  const [value, next2] = readBlock(lines, i, keyIndent);
90274
90453
  item[match[1].trim()] = value;
@@ -90399,16 +90578,16 @@ function sharedMemory(board) {
90399
90578
  const at2 = /^([^/]+)\/AGENT\.md$/.exec(key);
90400
90579
  if (at2) take(at2[1], text3, true);
90401
90580
  }
90402
- const root = path18.join(board, "agents");
90581
+ const root = path21.join(board, "agents");
90403
90582
  let folders2 = [];
90404
90583
  try {
90405
- folders2 = fs15.readdirSync(root, { withFileTypes: true }).filter((e2) => e2.isDirectory() && !e2.name.startsWith(".")).map((e2) => e2.name);
90584
+ folders2 = fs18.readdirSync(root, { withFileTypes: true }).filter((e2) => e2.isDirectory() && !e2.name.startsWith(".")).map((e2) => e2.name);
90406
90585
  } catch {
90407
90586
  }
90408
90587
  for (const folder of folders2.sort()) {
90409
90588
  let text3 = null;
90410
90589
  try {
90411
- text3 = fs15.readFileSync(path18.join(root, folder, "AGENT.md"), "utf8");
90590
+ text3 = fs18.readFileSync(path21.join(root, folder, "AGENT.md"), "utf8");
90412
90591
  } catch {
90413
90592
  }
90414
90593
  take(folder, text3, false);
@@ -90432,16 +90611,16 @@ function openTaskFolder(job, projectDir2) {
90432
90611
  projectDir2 ??= openCached(job.project);
90433
90612
  keepOutOfGit(projectDir2);
90434
90613
  markUsed(projectDir2);
90435
- const board = path20.join(projectDir2, ".akb", "kanban");
90436
- fs17.mkdirSync(board, { recursive: true });
90614
+ const board = path23.join(projectDir2, ".akb", "kanban");
90615
+ fs20.mkdirSync(board, { recursive: true });
90437
90616
  return { task, cloudTask: task, board, cwd: projectDir2, project: job.project, number: job.number ?? null, workflow: job.workflow ?? job.flow?.workflow ?? null };
90438
90617
  }
90439
90618
  function openAgentFolder(job, projectDir2) {
90440
90619
  if (!job.project || !job.agent) throw new Error("This job names no project.");
90441
90620
  keepOutOfGit(projectDir2);
90442
90621
  markUsed(projectDir2);
90443
- const board = path20.join(projectDir2, ".akb", "kanban");
90444
- fs17.mkdirSync(board, { recursive: true });
90622
+ const board = path23.join(projectDir2, ".akb", "kanban");
90623
+ fs20.mkdirSync(board, { recursive: true });
90445
90624
  return {
90446
90625
  task: `agent-${safe(job.agent.workflow ? `${job.agent.workflow}-${job.agent.name}` : job.agent.name)}`,
90447
90626
  cloudTask: job.agent.tasks?.[0]?.id ?? null,
@@ -90456,13 +90635,13 @@ function openDiscussionFolder(job, projectDir2) {
90456
90635
  if (!job.project) throw new Error("This job names no project.");
90457
90636
  keepOutOfGit(projectDir2);
90458
90637
  markUsed(projectDir2);
90459
- const board = path20.join(projectDir2, ".akb", "kanban");
90460
- fs17.mkdirSync(board, { recursive: true });
90638
+ const board = path23.join(projectDir2, ".akb", "kanban");
90639
+ fs20.mkdirSync(board, { recursive: true });
90461
90640
  return { task: "discussion", cloudTask: null, board, cwd: projectDir2, project: job.project, number: null, workflow: null };
90462
90641
  }
90463
90642
  var boardFolder = (ws) => ({ task: "board", cloudTask: null, board: ws.board, cwd: ws.cwd, project: ws.project, number: null, workflow: null });
90464
90643
  function keptBoard(cwd) {
90465
- const board = path20.join(cwd, ".akb", "kanban");
90644
+ const board = path23.join(cwd, ".akb", "kanban");
90466
90645
  const base = readBase({ cwd });
90467
90646
  const project = base.project ?? /^projects\/([^/]+)\//.exec(Object.keys(base.files).find((p2) => p2.startsWith("projects/")) ?? "")?.[1];
90468
90647
  return base.head_seq === null || !project ? null : boardFolder({ board, cwd, project });
@@ -90470,17 +90649,17 @@ function keptBoard(cwd) {
90470
90649
  var turns = /* @__PURE__ */ new Map();
90471
90650
  function inFolder(dir, work) {
90472
90651
  const next = (turns.get(dir) ?? Promise.resolve()).then(work, work);
90473
- const held3 = next.catch(() => {
90652
+ const held4 = next.catch(() => {
90474
90653
  });
90475
- turns.set(dir, held3);
90476
- void held3.then(() => turns.get(dir) === held3 && turns.delete(dir));
90654
+ turns.set(dir, held4);
90655
+ void held4.then(() => turns.get(dir) === held4 && turns.delete(dir));
90477
90656
  return next;
90478
90657
  }
90479
90658
  var safe = (name) => name.replace(/[^\w.-]/g, "_") || "default";
90480
90659
  function openCached(project) {
90481
90660
  const dir = cacheDir(project);
90482
- if (fs17.existsSync(path20.join(dir, ".git"))) return dir;
90483
- fs17.mkdirSync(dir, { recursive: true });
90661
+ if (fs20.existsSync(path23.join(dir, ".git"))) return dir;
90662
+ fs20.mkdirSync(dir, { recursive: true });
90484
90663
  const git3 = (...args) => spawnSync4("git", ["-C", dir, ...args], { encoding: "utf8" }).status === 0;
90485
90664
  if (git3("init", "-q")) git3("-c", "user.name=WildCrane", "-c", "user.email=runner@wildcrane.ai", "commit", "-q", "--allow-empty", "-m", "general");
90486
90665
  return dir;
@@ -90493,56 +90672,56 @@ function keepOutOfGit(dir, folders2 = SKILL_FOLDERS) {
90493
90672
  if (inside.status !== 0) return;
90494
90673
  const missing = [".akb/", ...folders2.map((f2) => `${f2}/`)].filter((p2) => git3("check-ignore", "-q", p2).status !== 0);
90495
90674
  if (!missing.length) return;
90496
- const exclude = path20.resolve(dir, inside.stdout.trim());
90497
- fs17.mkdirSync(path20.dirname(exclude), { recursive: true });
90498
- const held3 = fs17.existsSync(exclude) ? fs17.readFileSync(exclude, "utf8") : "";
90499
- fs17.writeFileSync(exclude, `${held3}${held3 && !held3.endsWith("\n") ? "\n" : ""}${missing.join("\n")}
90675
+ const exclude = path23.resolve(dir, inside.stdout.trim());
90676
+ fs20.mkdirSync(path23.dirname(exclude), { recursive: true });
90677
+ const held4 = fs20.existsSync(exclude) ? fs20.readFileSync(exclude, "utf8") : "";
90678
+ fs20.writeFileSync(exclude, `${held4}${held4 && !held4.endsWith("\n") ? "\n" : ""}${missing.join("\n")}
90500
90679
  `);
90501
90680
  }
90502
- var cardFile = (ws) => (ws.number ? findCard(ws.board, ws.number) : null) ?? path20.join(ws.board, "todo", `${ws.number ?? 0}-task.md`);
90681
+ var cardFile = (ws) => (ws.number ? findCard(ws.board, ws.number) : null) ?? path23.join(ws.board, "todo", `${ws.number ?? 0}-task.md`);
90503
90682
  function findCard(board, number) {
90504
90683
  const named2 = new RegExp(`^${number}-`);
90505
90684
  const walk = (dir) => {
90506
90685
  let entries;
90507
90686
  try {
90508
- entries = fs17.readdirSync(dir, { withFileTypes: true });
90687
+ entries = fs20.readdirSync(dir, { withFileTypes: true });
90509
90688
  } catch {
90510
90689
  return null;
90511
90690
  }
90512
90691
  for (const e2 of entries) {
90513
90692
  if (!named2.test(e2.name)) continue;
90514
- if (e2.isFile() && e2.name.endsWith(".md")) return path20.join(dir, e2.name);
90515
- const root = path20.join(dir, e2.name, "root.md");
90516
- if (e2.isDirectory() && fs17.existsSync(root)) return root;
90693
+ if (e2.isFile() && e2.name.endsWith(".md")) return path23.join(dir, e2.name);
90694
+ const root = path23.join(dir, e2.name, "root.md");
90695
+ if (e2.isDirectory() && fs20.existsSync(root)) return root;
90517
90696
  }
90518
90697
  for (const e2 of entries) if (e2.isDirectory() && !e2.name.startsWith(".")) {
90519
- const hit = walk(path20.join(dir, e2.name));
90698
+ const hit = walk(path23.join(dir, e2.name));
90520
90699
  if (hit) return hit;
90521
90700
  }
90522
90701
  return null;
90523
90702
  };
90524
- return walk(path20.join(board, "todo")) ?? walk(path20.join(board, ".archive"));
90703
+ return walk(path23.join(board, "todo")) ?? walk(path23.join(board, ".archive"));
90525
90704
  }
90526
90705
  function akbCardOf(ws) {
90527
90706
  return ws.number && findCard(ws.board, ws.number) ? ws.number : void 0;
90528
90707
  }
90529
- var recordFile = (ws) => path20.join(ws.board, ".sync", `${ws.task}.json`);
90708
+ var recordFile = (ws) => path23.join(ws.board, ".sync", `${ws.task}.json`);
90530
90709
  function readRecord(ws) {
90531
90710
  try {
90532
- return { ...EMPTY, ...JSON.parse(fs17.readFileSync(recordFile(ws), "utf8")) };
90711
+ return { ...EMPTY, ...JSON.parse(fs20.readFileSync(recordFile(ws), "utf8")) };
90533
90712
  } catch {
90534
90713
  return structuredClone(EMPTY);
90535
90714
  }
90536
90715
  }
90537
90716
  function writeRecord(ws, record) {
90538
- fs17.mkdirSync(path20.dirname(recordFile(ws)), { recursive: true });
90539
- fs17.writeFileSync(recordFile(ws), `${JSON.stringify(record, null, 2)}
90717
+ fs20.mkdirSync(path23.dirname(recordFile(ws)), { recursive: true });
90718
+ fs20.writeFileSync(recordFile(ws), `${JSON.stringify(record, null, 2)}
90540
90719
  `);
90541
90720
  }
90542
- var baseFile = (ws) => path20.join(ws.cwd, ".akb", "base.json");
90721
+ var baseFile = (ws) => path23.join(ws.cwd, ".akb", "base.json");
90543
90722
  function readBase(ws) {
90544
90723
  try {
90545
- const base = JSON.parse(fs17.readFileSync(baseFile(ws), "utf8"));
90724
+ const base = JSON.parse(fs20.readFileSync(baseFile(ws), "utf8"));
90546
90725
  if (base.layout === "workspace") return base;
90547
90726
  } catch {
90548
90727
  }
@@ -90550,25 +90729,25 @@ function readBase(ws) {
90550
90729
  }
90551
90730
  function writeBase(ws, base) {
90552
90731
  const file2 = baseFile(ws);
90553
- fs17.mkdirSync(path20.dirname(file2), { recursive: true });
90554
- fs17.writeFileSync(`${file2}.tmp`, JSON.stringify(base));
90555
- fs17.renameSync(`${file2}.tmp`, file2);
90732
+ fs20.mkdirSync(path23.dirname(file2), { recursive: true });
90733
+ fs20.writeFileSync(`${file2}.tmp`, JSON.stringify(base));
90734
+ fs20.renameSync(`${file2}.tmp`, file2);
90556
90735
  }
90557
- var hashOf = (bytes2) => crypto2.createHash("sha256").update(bytes2).digest("hex");
90736
+ var hashOf = (bytes2) => crypto3.createHash("sha256").update(bytes2).digest("hex");
90558
90737
  function hashFile(file2) {
90559
90738
  try {
90560
- return hashOf(fs17.readFileSync(file2));
90739
+ return hashOf(fs20.readFileSync(file2));
90561
90740
  } catch {
90562
90741
  return null;
90563
90742
  }
90564
90743
  }
90565
90744
  function write(file2, bytes2) {
90566
- fs17.mkdirSync(path20.dirname(file2), { recursive: true });
90567
- fs17.writeFileSync(file2, bytes2);
90745
+ fs20.mkdirSync(path23.dirname(file2), { recursive: true });
90746
+ fs20.writeFileSync(file2, bytes2);
90568
90747
  }
90569
90748
  function readText(file2) {
90570
90749
  try {
90571
- return fs17.readFileSync(file2, "utf8");
90750
+ return fs20.readFileSync(file2, "utf8");
90572
90751
  } catch {
90573
90752
  return null;
90574
90753
  }
@@ -90576,14 +90755,14 @@ function readText(file2) {
90576
90755
  function filesUnder(dir, base = dir) {
90577
90756
  let entries;
90578
90757
  try {
90579
- entries = fs17.readdirSync(dir, { withFileTypes: true });
90758
+ entries = fs20.readdirSync(dir, { withFileTypes: true });
90580
90759
  } catch {
90581
90760
  return [];
90582
90761
  }
90583
90762
  return entries.flatMap((e2) => {
90584
- const full = path20.join(dir, e2.name);
90763
+ const full = path23.join(dir, e2.name);
90585
90764
  if (e2.isDirectory()) return filesUnder(full, base);
90586
- return e2.isFile() ? [path20.relative(base, full).split(path20.sep).join("/")] : [];
90765
+ return e2.isFile() ? [path23.relative(base, full).split(path23.sep).join("/")] : [];
90587
90766
  });
90588
90767
  }
90589
90768
  var kept3 = isBoardPath;
@@ -90599,7 +90778,7 @@ function viewOf(ws, base, shared) {
90599
90778
  }
90600
90779
  function assetFiles(ws, list) {
90601
90780
  const card = cardFile(ws);
90602
- return new Set(Object.keys(assetsOf(list)).map((name) => assetPath(ws, name, card)).filter((f2) => !!f2).map((f2) => path20.relative(ws.board, f2).split(path20.sep).join("/")));
90781
+ return new Set(Object.keys(assetsOf(list)).map((name) => assetPath(ws, name, card)).filter((f2) => !!f2).map((f2) => path23.relative(ws.board, f2).split(path23.sep).join("/")));
90603
90782
  }
90604
90783
  var assetsListOf = (ws, base) => base.files[rootOf(ws) + assetsFile(ws.task)]?.content;
90605
90784
  var localFiles = (ws, base) => {
@@ -90608,9 +90787,9 @@ var localFiles = (ws, base) => {
90608
90787
  };
90609
90788
  var SKILL_PATH = /^skills\/([a-z0-9]+(?:-[a-z0-9]+)*)\/((?:[\w.-]+\/)*[\w.-]+)$/;
90610
90789
  function pullTools(ws, record, files) {
90611
- const held3 = record.tools?.skills ?? {};
90612
- const ours = new Set(Object.keys(held3).map((name) => name.split("/")[1]));
90613
- const theirs = (skill) => !ours.has(skill) && SKILL_ROOTS.some((root) => fs17.existsSync(path20.join(ws.cwd, root, skill)));
90790
+ const held4 = record.tools?.skills ?? {};
90791
+ const ours = new Set(Object.keys(held4).map((name) => name.split("/")[1]));
90792
+ const theirs = (skill) => !ours.has(skill) && SKILL_ROOTS.some((root) => fs20.existsSync(path23.join(ws.cwd, root, skill)));
90614
90793
  const kept4 = Object.keys(files).map((name) => SKILL_PATH.exec(name)?.[1]).filter((skill) => skill && !theirs(skill));
90615
90794
  const skills = {};
90616
90795
  for (const [name, text3] of Object.entries(files)) {
@@ -90618,17 +90797,17 @@ function pullTools(ws, record, files) {
90618
90797
  if (!at2 || at2[1] === "kanban" || !kept4.includes(at2[1]) || at2[2].split("/").includes("..")) continue;
90619
90798
  skills[name] = hashOf(text3);
90620
90799
  for (const root of SKILL_ROOTS) {
90621
- const file2 = path20.join(ws.cwd, root, at2[1], at2[2]);
90622
- if (held3[name] !== skills[name] || hashFile(file2) !== skills[name]) write(file2, text3);
90800
+ const file2 = path23.join(ws.cwd, root, at2[1], at2[2]);
90801
+ if (held4[name] !== skills[name] || hashFile(file2) !== skills[name]) write(file2, text3);
90623
90802
  }
90624
90803
  }
90625
- for (const name of Object.keys(held3)) {
90804
+ for (const name of Object.keys(held4)) {
90626
90805
  if (skills[name]) continue;
90627
90806
  const [, skill, rest] = SKILL_PATH.exec(name) ?? [];
90628
90807
  if (!skill || !rest) continue;
90629
90808
  for (const root of SKILL_ROOTS) {
90630
- fs17.rmSync(path20.join(ws.cwd, root, skill, rest), { force: true });
90631
- if (!Object.keys(skills).some((n) => n.startsWith(`skills/${skill}/`))) fs17.rmSync(path20.join(ws.cwd, root, skill), { recursive: true, force: true });
90809
+ fs20.rmSync(path23.join(ws.cwd, root, skill, rest), { force: true });
90810
+ if (!Object.keys(skills).some((n) => n.startsWith(`skills/${skill}/`))) fs20.rmSync(path23.join(ws.cwd, root, skill), { recursive: true, force: true });
90632
90811
  }
90633
90812
  }
90634
90813
  const names2 = [...new Set(Object.keys(skills).map((name) => name.split("/")[1]))];
@@ -90645,8 +90824,8 @@ async function pullWorkflow(ws, record, base) {
90645
90824
  let files = {};
90646
90825
  if (ws.workflow) {
90647
90826
  const root = `workflows/${workflowFolder(ws.workflow)}/`;
90648
- const held3 = rootOf(ws) + root;
90649
- files = Object.fromEntries(Object.entries(base.files).filter(([p2]) => p2.startsWith(held3) && isBoardPath(p2.slice(rootOf(ws).length))).map(([p2, f2]) => [p2.slice(held3.length), f2.content]));
90827
+ const held4 = rootOf(ws) + root;
90828
+ files = Object.fromEntries(Object.entries(base.files).filter(([p2]) => p2.startsWith(held4) && isBoardPath(p2.slice(rootOf(ws).length))).map(([p2, f2]) => [p2.slice(held4.length), f2.content]));
90650
90829
  record.builtin = ws.workflow.startsWith("wf_builtin_");
90651
90830
  let found = Object.keys(files).length > 0;
90652
90831
  if (!found && ws.cloudTask) {
@@ -90656,7 +90835,7 @@ async function pullWorkflow(ws, record, base) {
90656
90835
  files = read.value.files;
90657
90836
  found = true;
90658
90837
  if (!record.builtin) {
90659
- for (const [name, text3] of Object.entries(files)) if (isBoardPath(root + name)) write(path20.join(ws.board, root, name), text3);
90838
+ for (const [name, text3] of Object.entries(files)) if (isBoardPath(root + name)) write(path23.join(ws.board, root, name), text3);
90660
90839
  }
90661
90840
  }
90662
90841
  }
@@ -90664,15 +90843,14 @@ async function pullWorkflow(ws, record, base) {
90664
90843
  }
90665
90844
  pullAgents(ws, base, ws.workflow && !record.builtin ? files : {});
90666
90845
  const placed = readPlaced(ws);
90667
- for (const name of Object.keys(record.agents ?? {})) if (!placed[name]) fs17.rmSync(path20.join(ws.board, name), { force: true });
90846
+ for (const name of Object.keys(record.agents ?? {})) if (!placed[name]) fs20.rmSync(path23.join(ws.board, name), { force: true });
90668
90847
  record.agents = {};
90669
90848
  return { ok: true, value: void 0 };
90670
90849
  }
90671
- var OWN_FOLDER = /^wf-(?!builtin-)[a-z0-9-]+$/;
90672
- var agentsRecord = (ws) => path20.join(ws.board, ".sync", "agents.json");
90850
+ var agentsRecord = (ws) => path23.join(ws.board, ".sync", "agents.json");
90673
90851
  function readPlaced(ws) {
90674
90852
  try {
90675
- return JSON.parse(fs17.readFileSync(agentsRecord(ws), "utf8"));
90853
+ return JSON.parse(fs20.readFileSync(agentsRecord(ws), "utf8"));
90676
90854
  } catch {
90677
90855
  return {};
90678
90856
  }
@@ -90693,8 +90871,8 @@ function pullAgents(ws, base, own) {
90693
90871
  const names2 = /* @__PURE__ */ new Set();
90694
90872
  for (const [name, text3] of Object.entries(files)) {
90695
90873
  const agent = /^agents\/([^/]+)\//.exec(name)?.[1];
90696
- const file2 = path20.resolve(ws.board, name);
90697
- if (!agent || taken.has(agent) || !file2.startsWith(path20.join(ws.board, "agents") + path20.sep)) continue;
90874
+ const file2 = path23.resolve(ws.board, name);
90875
+ if (!agent || taken.has(agent) || !file2.startsWith(path23.join(ws.board, "agents") + path23.sep)) continue;
90698
90876
  names2.add(agent);
90699
90877
  agents[name] = text3;
90700
90878
  }
@@ -90704,42 +90882,42 @@ function pullAgents(ws, base, own) {
90704
90882
  const hashes = {};
90705
90883
  for (const [name, text3] of Object.entries(agents)) {
90706
90884
  hashes[name] = hashOf(text3);
90707
- if (hashFile(path20.join(ws.board, name)) !== hashes[name]) write(path20.join(ws.board, name), text3);
90885
+ if (hashFile(path23.join(ws.board, name)) !== hashes[name]) write(path23.join(ws.board, name), text3);
90708
90886
  }
90709
- for (const name of Object.keys(before)) if (!hashes[name]) fs17.rmSync(path20.join(ws.board, name), { force: true });
90887
+ for (const name of Object.keys(before)) if (!hashes[name]) fs20.rmSync(path23.join(ws.board, name), { force: true });
90710
90888
  write(agentsRecord(ws), `${JSON.stringify(hashes, null, 2)}
90711
90889
  `);
90712
90890
  }
90713
90891
  function pullDraftAgents(ws, record) {
90714
90892
  if (ws.workflow !== BUILDER) return;
90715
- const root = path20.join(ws.board, "workflows", draftFolder(ws.task), "agents");
90893
+ const root = path23.join(ws.board, "workflows", draftFolder(ws.task), "agents");
90716
90894
  record.agents ??= {};
90717
90895
  for (const name of filesUnder(root)) {
90718
- const text3 = fs17.readFileSync(path20.join(root, name));
90896
+ const text3 = fs20.readFileSync(path23.join(root, name));
90719
90897
  const at2 = `agents/${name}`;
90720
90898
  record.agents[at2] = hashOf(text3);
90721
- if (hashFile(path20.join(ws.board, at2)) !== record.agents[at2]) write(path20.join(ws.board, at2), text3);
90899
+ if (hashFile(path23.join(ws.board, at2)) !== record.agents[at2]) write(path23.join(ws.board, at2), text3);
90722
90900
  }
90723
90901
  }
90724
90902
  function workflowFile(ws) {
90725
90903
  if (!ws.workflow || readRecord(ws).builtin) return null;
90726
- const file2 = path20.join(ws.board, "workflows", workflowFolder(ws.workflow), "WORKFLOW.md");
90727
- return fs17.existsSync(file2) ? file2 : null;
90904
+ const file2 = path23.join(ws.board, "workflows", workflowFolder(ws.workflow), "WORKFLOW.md");
90905
+ return fs20.existsSync(file2) ? file2 : null;
90728
90906
  }
90729
90907
  function assetPath(ws, name, card) {
90730
90908
  if (/^[a-z][\w+.-]*:/i.test(name) || name.startsWith("/") || name.startsWith("#")) return null;
90731
- const held3 = /^\.(assets|mockups)\//.exec(name);
90732
- if (held3) {
90909
+ const held4 = /^\.(assets|mockups)\//.exec(name);
90910
+ if (held4) {
90733
90911
  const state = stateDir(ws);
90734
- const file3 = state && path20.resolve(state, held3[1], name.slice(held3[0].length));
90735
- return file3 && file3.startsWith(path20.join(state, held3[1]) + path20.sep) ? file3 : null;
90912
+ const file3 = state && path23.resolve(state, held4[1], name.slice(held4[0].length));
90913
+ return file3 && file3.startsWith(path23.join(state, held4[1]) + path23.sep) ? file3 : null;
90736
90914
  }
90737
- const file2 = path20.resolve(path20.dirname(card), name);
90738
- return file2.startsWith(ws.board + path20.sep) ? file2 : null;
90915
+ const file2 = path23.resolve(path23.dirname(card), name);
90916
+ return file2.startsWith(ws.board + path23.sep) ? file2 : null;
90739
90917
  }
90740
90918
  function cardAssetsDir(ws, id) {
90741
90919
  const state = stateDir(ws);
90742
- return state && path20.join(state, "assets", String(id));
90920
+ return state && path23.join(state, "assets", String(id));
90743
90921
  }
90744
90922
  function stateDir(ws) {
90745
90923
  try {
@@ -90750,8 +90928,8 @@ function stateDir(ws) {
90750
90928
  }
90751
90929
  function assetsOf(text3) {
90752
90930
  try {
90753
- const held3 = JSON.parse(text3 ?? "{}");
90754
- return held3 && typeof held3 === "object" && !Array.isArray(held3) ? held3 : {};
90931
+ const held4 = JSON.parse(text3 ?? "{}");
90932
+ return held4 && typeof held4 === "object" && !Array.isArray(held4) ? held4 : {};
90755
90933
  } catch {
90756
90934
  return {};
90757
90935
  }
@@ -90778,13 +90956,13 @@ var pullChanges = (ws) => inFolder(ws.cwd, async () => {
90778
90956
  const p2 = f2.path.startsWith(root) ? f2.path.slice(root.length) : f2.path;
90779
90957
  const isShared = p2.startsWith(MEMORY2) && shared(p2.slice(MEMORY2.length));
90780
90958
  if (kept3(p2) && isShared === !f2.path.startsWith(root)) {
90781
- const file2 = path20.join(ws.board, p2);
90959
+ const file2 = path23.join(ws.board, p2);
90782
90960
  const here2 = readText(file2);
90783
90961
  if (here2 !== f2.content && here2 !== (base.files[f2.path]?.content ?? null)) {
90784
90962
  skipped = true;
90785
90963
  continue;
90786
90964
  }
90787
- if (f2.content === null) fs17.rmSync(file2, { force: true });
90965
+ if (f2.content === null) fs20.rmSync(file2, { force: true });
90788
90966
  else if (here2 !== f2.content) write(file2, f2.content);
90789
90967
  }
90790
90968
  if (f2.content === null) delete base.files[f2.path];
@@ -90815,13 +90993,13 @@ async function readCloud(ws) {
90815
90993
  writeBase(ws, base);
90816
90994
  const reset = (view2) => {
90817
90995
  for (const [p2, content] of view2) {
90818
- const file2 = path20.join(ws.board, p2);
90996
+ const file2 = path23.join(ws.board, p2);
90819
90997
  if (kept3(p2) && readText(file2) !== content) write(file2, content);
90820
90998
  }
90821
90999
  };
90822
91000
  const view = viewOf(ws, base, sharedMemory(ws.board));
90823
91001
  const first = (p2) => isSettingsPath(p2) && !known2.has(rootOf(ws) + p2);
90824
- for (const p2 of localFiles(ws, base)) if (!view.has(p2) && !first(p2)) fs17.rmSync(path20.join(ws.board, p2), { force: true });
91002
+ for (const p2 of localFiles(ws, base)) if (!view.has(p2) && !first(p2)) fs20.rmSync(path23.join(ws.board, p2), { force: true });
90825
91003
  reset(view);
90826
91004
  const record = readRecord(ws);
90827
91005
  const workflow = await pullWorkflow(ws, record, base);
@@ -90835,18 +91013,18 @@ async function readCloud(ws) {
90835
91013
  return { ok: true, value: void 0 };
90836
91014
  }
90837
91015
  function writeIndex(board) {
90838
- const todo = path20.join(board, "todo");
91016
+ const todo = path23.join(board, "todo");
90839
91017
  const cards = [];
90840
91018
  let entries = [];
90841
91019
  try {
90842
- entries = fs17.readdirSync(todo, { withFileTypes: true });
91020
+ entries = fs20.readdirSync(todo, { withFileTypes: true });
90843
91021
  } catch {
90844
91022
  }
90845
91023
  for (const e2 of entries) {
90846
91024
  const id = /^(\d+)-/.exec(e2.name)?.[1];
90847
91025
  if (!id) continue;
90848
91026
  const link = e2.isDirectory() ? `${e2.name}/root.md` : e2.name.endsWith(".md") ? e2.name : null;
90849
- const text4 = link && readText(path20.join(todo, link));
91027
+ const text4 = link && readText(path23.join(todo, link));
90850
91028
  if (text4 === null || !link) continue;
90851
91029
  cards.push({ id: Number(id), title: cardFront(text4).title ?? e2.name.replace(/\.md$/, ""), link });
90852
91030
  }
@@ -90861,7 +91039,7 @@ the number at the front of a filename is the task id.
90861
91039
 
90862
91040
  ${list}
90863
91041
  `;
90864
- if (readText(path20.join(todo, "README.md")) !== text3) write(path20.join(todo, "README.md"), text3);
91042
+ if (readText(path23.join(todo, "README.md")) !== text3) write(path23.join(todo, "README.md"), text3);
90865
91043
  }
90866
91044
  var workspaceOf = (ws) => readBase(ws).workspace ?? null;
90867
91045
  async function pullAssets(ws, record, assets) {
@@ -90876,13 +91054,13 @@ async function pullAssets(ws, record, assets) {
90876
91054
  if (!latest.ok) return latest;
90877
91055
  version = latest.value.latest_version ?? 0;
90878
91056
  }
90879
- const held3 = record.assets[name];
90880
- if (held3?.kind === "html" && held3.artifact === ref.artifact) {
90881
- out[name] = { ...held3, version };
91057
+ const held4 = record.assets[name];
91058
+ if (held4?.kind === "html" && held4.artifact === ref.artifact) {
91059
+ out[name] = { ...held4, version };
90882
91060
  continue;
90883
91061
  }
90884
- if (held3?.artifact === ref.artifact && held3.version === version && hashFile(target) === held3.hash) {
90885
- out[name] = held3;
91062
+ if (held4?.artifact === ref.artifact && held4.version === version && hashFile(target) === held4.hash) {
91063
+ out[name] = held4;
90886
91064
  continue;
90887
91065
  }
90888
91066
  const bytes2 = await readAsset(ref.artifact, version);
@@ -90894,10 +91072,10 @@ async function pullAssets(ws, record, assets) {
90894
91072
  return { ok: true, value: void 0 };
90895
91073
  }
90896
91074
  async function readAsset(artifact, version) {
90897
- const held3 = await readVersion(artifact, version);
90898
- if (!held3.ok) return held3;
90899
- if (held3.value.file) return download(held3.value.file.url);
90900
- const content = held3.value.content;
91075
+ const held4 = await readVersion(artifact, version);
91076
+ if (!held4.ok) return held4;
91077
+ if (held4.value.file) return download(held4.value.file.url);
91078
+ const content = held4.value.content;
90901
91079
  return { ok: true, value: Buffer.from(typeof content === "string" ? content : JSON.stringify(content)) };
90902
91080
  }
90903
91081
  var TYPES = {
@@ -90928,14 +91106,14 @@ function kindOf(ext) {
90928
91106
  return type.startsWith("video/") || type.startsWith("audio/") ? "video" : "asset";
90929
91107
  }
90930
91108
  async function sentOf(file2) {
90931
- const ext = path20.extname(file2).toLowerCase();
91109
+ const ext = path23.extname(file2).toLowerCase();
90932
91110
  const kind = kindOf(ext);
90933
- if (kind !== "html") return { bytes: fs17.readFileSync(file2), type: TYPES[ext] ?? "application/octet-stream", kind };
91111
+ if (kind !== "html") return { bytes: fs20.readFileSync(file2), type: TYPES[ext] ?? "application/octet-stream", kind };
90934
91112
  let page;
90935
91113
  try {
90936
91114
  page = await (await Promise.resolve().then(() => (init_mockup(), mockup_exports))).drawMockup(file2);
90937
91115
  } catch (e2) {
90938
- console.error(`runner: ${path20.basename(file2)} could not be drawn: ${e2 instanceof Error ? e2.message : String(e2)}`);
91116
+ console.error(`runner: ${path23.basename(file2)} could not be drawn: ${e2 instanceof Error ? e2.message : String(e2)}`);
90939
91117
  page = UNDRAWN;
90940
91118
  }
90941
91119
  return { bytes: Buffer.from(page), type: "text/html", kind };
@@ -90963,23 +91141,23 @@ async function pushAssets(ws, record, before) {
90963
91141
  for (const [name, ref] of Object.entries(before)) {
90964
91142
  if (!body.includes(name)) continue;
90965
91143
  const target = assetPath(ws, name, file2);
90966
- const held3 = record.assets[name];
90967
- const out = target && held3 && fs17.existsSync(target) ? await sentOf(target) : null;
91144
+ const held4 = record.assets[name];
91145
+ const out = target && held4 && fs20.existsSync(target) ? await sentOf(target) : null;
90968
91146
  const hash = out && hashOf(out.bytes);
90969
- if (out && held3 && held3.kind === "html" !== (out.kind === "html")) continue;
90970
- if (held3 && out && hash !== held3.hash) {
90971
- const sent = await uploadAsset(held3.artifact, out);
91147
+ if (out && held4 && held4.kind === "html" !== (out.kind === "html")) continue;
91148
+ if (held4 && out && hash !== held4.hash) {
91149
+ const sent = await uploadAsset(held4.artifact, out);
90972
91150
  if (!sent.ok) return sent;
90973
- assets[name] = { artifact: held3.artifact, version: sent.value, hash, kind: out.kind };
90974
- refs[name] = { artifact: held3.artifact, version: sent.value };
91151
+ assets[name] = { artifact: held4.artifact, version: sent.value, hash, kind: out.kind };
91152
+ refs[name] = { artifact: held4.artifact, version: sent.value };
90975
91153
  } else {
90976
- if (held3) assets[name] = held3;
91154
+ if (held4) assets[name] = held4;
90977
91155
  refs[name] = ref;
90978
91156
  }
90979
91157
  }
90980
91158
  for (const name of namedFiles(body)) {
90981
91159
  const target = assetPath(ws, name, file2);
90982
- if (refs[name] || !target || !fs17.statSync(target, { throwIfNoEntry: false })?.isFile()) continue;
91160
+ if (refs[name] || !target || !fs20.statSync(target, { throwIfNoEntry: false })?.isFile()) continue;
90983
91161
  const out = await sentOf(target);
90984
91162
  if (!ws.cloudTask) continue;
90985
91163
  const made = await createArtifact(ws.cloudTask, name.slice(0, 200), out.kind);
@@ -90990,24 +91168,24 @@ async function pushAssets(ws, record, before) {
90990
91168
  refs[name] = { artifact: made.value.id, version: sent.value };
90991
91169
  }
90992
91170
  record.assets = assets;
90993
- const list = path20.join(ws.board, assetsFile(ws.task));
90994
- if (Object.keys(refs).length || fs17.existsSync(list)) {
91171
+ const list = path23.join(ws.board, assetsFile(ws.task));
91172
+ if (Object.keys(refs).length || fs20.existsSync(list)) {
90995
91173
  if (JSON.stringify(assetsOf(readText(list))) !== JSON.stringify(refs)) write(list, assetsText(refs));
90996
91174
  }
90997
91175
  return { ok: true, value: void 0 };
90998
91176
  }
90999
91177
  function resetSorted(ws) {
91000
- for (const sub of ["dismissed", "archived"]) fs17.rmSync(path20.join(ws.board, "triage", sub), { recursive: true, force: true });
91178
+ for (const sub of ["dismissed", "archived"]) fs20.rmSync(path23.join(ws.board, "triage", sub), { recursive: true, force: true });
91001
91179
  for (const [p2, content] of viewOf(ws, readBase(ws), sharedMemory(ws.board))) {
91002
- if (/^triage\/(?:dismissed|archived)\//.test(p2)) write(path20.join(ws.board, p2), content);
91180
+ if (/^triage\/(?:dismissed|archived)\//.test(p2)) write(path23.join(ws.board, p2), content);
91003
91181
  }
91004
91182
  }
91005
91183
  function proposeItems(ws, base) {
91006
91184
  const root = rootOf(ws);
91007
91185
  for (const p2 of localFiles(ws, base)) {
91008
91186
  if (itemAt(p2)?.state !== "open" || base.files[root + p2]) continue;
91009
- const file2 = path20.join(ws.board, p2);
91010
- const content = fs17.readFileSync(file2, "utf8");
91187
+ const file2 = path23.join(ws.board, p2);
91188
+ const content = fs20.readFileSync(file2, "utf8");
91011
91189
  const said = (key) => new RegExp(`^${key}:`, "m").test(content.split(/\n---/)[0] ?? "");
91012
91190
  const fields = {
91013
91191
  ...ws.cloudTask && !said("source_task") ? { source_task: ws.cloudTask } : {},
@@ -91058,13 +91236,13 @@ async function send2(ws, job) {
91058
91236
  const owed = (p2) => !job.id && busy(ws.cwd) && itemAt(p2)?.state === "open" && !base.files[rootOf(ws) + p2];
91059
91237
  for (const p2 of local) {
91060
91238
  if (owed(p2)) continue;
91061
- const content = fs17.readFileSync(path20.join(ws.board, p2), "utf8");
91239
+ const content = fs20.readFileSync(path23.join(ws.board, p2), "utf8");
91062
91240
  const remote = remoteOf(ws, shared, p2);
91063
91241
  localOf.set(remote, p2);
91064
- const held3 = base.files[remote];
91065
- if (held3?.content === content) continue;
91242
+ const held4 = base.files[remote];
91243
+ if (held4?.content === content) continue;
91066
91244
  if (Buffer.byteLength(content) > BOARD_FILE_LIMIT) return fail(`${p2} is over ${BOARD_FILE_LIMIT / 1024} KB; keep large files as assets.`, false, "too_large");
91067
- changes.push({ path: remote, content, base_seq: held3?.seq ?? 0 });
91245
+ changes.push({ path: remote, content, base_seq: held4?.seq ?? 0 });
91068
91246
  }
91069
91247
  for (const p2 of viewOf(ws, base, shared).keys()) {
91070
91248
  const remote = remoteOf(ws, shared, p2);
@@ -91090,15 +91268,15 @@ async function send2(ws, job) {
91090
91268
  changes.splice(at2, 1);
91091
91269
  delete base.files[theirs.path];
91092
91270
  writeBase(ws, base);
91093
- fs17.rmSync(path20.join(ws.board, p2), { force: true });
91271
+ fs20.rmSync(path23.join(ws.board, p2), { force: true });
91094
91272
  writeIndex(ws.board);
91095
91273
  continue;
91096
91274
  }
91097
91275
  if (at2 < 0) continue;
91098
91276
  const merged = itemAt(p2) ? { content: theirs.content } : mergeFile(base.files[theirs.path]?.content ?? null, changes[at2].content, theirs.content);
91099
91277
  changes[at2] = { path: theirs.path, content: merged.content, base_seq: theirs.seq };
91100
- if (merged.content === null) fs17.rmSync(path20.join(ws.board, p2), { force: true });
91101
- else write(path20.join(ws.board, p2), merged.content);
91278
+ if (merged.content === null) fs20.rmSync(path23.join(ws.board, p2), { force: true });
91279
+ else write(path23.join(ws.board, p2), merged.content);
91102
91280
  }
91103
91281
  if (!changes.length) return { ok: true, changed: false };
91104
91282
  sent = await commitBoard(ws.project, job.id, job.machineId, changes);
@@ -91119,12 +91297,12 @@ var PULL_MS = 2e3;
91119
91297
  function keptFolders() {
91120
91298
  let cached2 = [];
91121
91299
  try {
91122
- cached2 = fs18.readdirSync(cacheRoot()).map((name) => path21.join(cacheRoot(), name));
91300
+ cached2 = fs21.readdirSync(cacheRoot()).map((name) => path24.join(cacheRoot(), name));
91123
91301
  } catch {
91124
91302
  }
91125
91303
  return [.../* @__PURE__ */ new Set([...allowedProjects(), ...cached2])].flatMap((dir) => [keptBoard(dir)].filter((ws) => !!ws));
91126
91304
  }
91127
- function watchBoards(machineId2, ms2, lookMs = LOOK_MS, pullMs = PULL_MS) {
91305
+ function watchBoards(machineId2, ms, lookMs = LOOK_MS, pullMs = PULL_MS) {
91128
91306
  const watched = /* @__PURE__ */ new Map();
91129
91307
  const due = /* @__PURE__ */ new Map();
91130
91308
  const afterJob = /* @__PURE__ */ new Set();
@@ -91143,12 +91321,12 @@ function watchBoards(machineId2, ms2, lookMs = LOOK_MS, pullMs = PULL_MS) {
91143
91321
  const watch = (ws) => {
91144
91322
  let watcher;
91145
91323
  try {
91146
- watcher = fs18.watch(ws.board, { recursive: true }, (_event, name) => {
91147
- const p2 = name && String(name).split(path21.sep).join("/");
91148
- const held3 = watched.get(ws.cwd);
91149
- if (closed || !p2 || !isBoardPath(p2) || !held3) return;
91150
- clearTimeout(held3.timer);
91151
- held3.timer = setTimeout(() => void send3(ws), ms2);
91324
+ watcher = fs21.watch(ws.board, { recursive: true }, (_event, name) => {
91325
+ const p2 = name && String(name).split(path24.sep).join("/");
91326
+ const held4 = watched.get(ws.cwd);
91327
+ if (closed || !p2 || !isBoardPath(p2) || !held4) return;
91328
+ clearTimeout(held4.timer);
91329
+ held4.timer = setTimeout(() => void send3(ws), ms);
91152
91330
  });
91153
91331
  } catch {
91154
91332
  return false;
@@ -91192,9 +91370,9 @@ function watchBoards(machineId2, ms2, lookMs = LOOK_MS, pullMs = PULL_MS) {
91192
91370
  clearInterval(timer);
91193
91371
  for (const t2 of due.values()) clearTimeout(t2);
91194
91372
  due.clear();
91195
- for (const held3 of watched.values()) {
91196
- clearTimeout(held3.timer);
91197
- held3.watcher.close();
91373
+ for (const held4 of watched.values()) {
91374
+ clearTimeout(held4.timer);
91375
+ held4.watcher.close();
91198
91376
  }
91199
91377
  watched.clear();
91200
91378
  }
@@ -91202,16 +91380,16 @@ function watchBoards(machineId2, ms2, lookMs = LOOK_MS, pullMs = PULL_MS) {
91202
91380
  }
91203
91381
 
91204
91382
  // src/diff.ts
91205
- import { execFile } from "node:child_process";
91206
- import fs19 from "node:fs";
91207
- import path22 from "node:path";
91383
+ import { execFile as execFile2 } from "node:child_process";
91384
+ import fs22 from "node:fs";
91385
+ import path25 from "node:path";
91208
91386
  var FILE_BYTES = 256 * 1024;
91209
91387
  var TOTAL_BYTES = 1024 * 1024;
91210
91388
  var EMPTY_TREE = "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
91211
91389
  var PATHS = ["--", ".", ":(exclude).akb"];
91212
91390
  var STATUS = { A: "added", D: "deleted" };
91213
91391
  var git2 = (dir, args, maxBuffer = 4 * TOTAL_BYTES) => new Promise(
91214
- (resolve2) => execFile(
91392
+ (resolve2) => execFile2(
91215
91393
  "git",
91216
91394
  ["-C", dir, "-c", "core.quotePath=false", ...args],
91217
91395
  { encoding: "utf8", maxBuffer },
@@ -91221,7 +91399,7 @@ var git2 = (dir, args, maxBuffer = 4 * TOTAL_BYTES) => new Promise(
91221
91399
  function projectDir(placed, project) {
91222
91400
  if (placed) {
91223
91401
  const real = realpath3(placed);
91224
- return real && allowedProjects().some((root) => real === root || real.startsWith(root + path22.sep)) ? real : null;
91402
+ return real && allowedProjects().some((root) => real === root || real.startsWith(root + path25.sep)) ? real : null;
91225
91403
  }
91226
91404
  let cached2;
91227
91405
  try {
@@ -91229,11 +91407,11 @@ function projectDir(placed, project) {
91229
91407
  } catch {
91230
91408
  return null;
91231
91409
  }
91232
- return fs19.existsSync(path22.join(cached2, ".git")) ? cached2 : null;
91410
+ return fs22.existsSync(path25.join(cached2, ".git")) ? cached2 : null;
91233
91411
  }
91234
91412
  function realpath3(p2) {
91235
91413
  try {
91236
- return fs19.realpathSync(p2);
91414
+ return fs22.realpathSync(p2);
91237
91415
  } catch {
91238
91416
  return null;
91239
91417
  }
@@ -91278,98 +91456,170 @@ async function answerHint(machineId2, hint2) {
91278
91456
  }
91279
91457
 
91280
91458
  // src/flow.ts
91281
- import fs23 from "node:fs";
91282
- import path26 from "node:path";
91459
+ import fs25 from "node:fs";
91460
+ import path28 from "node:path";
91283
91461
 
91284
- // src/akb.ts
91285
- import { spawn as spawn3 } from "node:child_process";
91286
- import fs20 from "node:fs";
91287
- import path23 from "node:path";
91288
- import { fileURLToPath } from "node:url";
91289
- var bundledAkb = () => ({
91290
- command: process.execPath,
91291
- args: [path23.join(path23.dirname(fileURLToPath(import.meta.url)), "akb", "bin", "ai4kanban.mjs")]
91292
- });
91293
- var quote = (s) => /^[\w./:@=-]+$/.test(s) ? s : `"${s}"`;
91294
- function shimDir(akb) {
91295
- const dir = path23.join(runnerHome(), "bin", "akb");
91296
- const line = [akb.command, ...akb.args].map(quote).join(" ");
91297
- const [file2, text3] = process.platform === "win32" ? [path23.join(dir, "akb.cmd"), `@${line} %*\r
91298
- `] : [path23.join(dir, "akb"), `#!/bin/sh
91299
- exec ${line} "$@"
91300
- `];
91301
- try {
91302
- if (fs20.readFileSync(file2, "utf8") === text3) return dir;
91303
- } catch {
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 };
91304
91478
  }
91305
- fs20.mkdirSync(dir, { recursive: true });
91306
- fs20.writeFileSync(file2, text3, { mode: 493 });
91307
- return dir;
91308
- }
91309
- function akbEnv(akb, board, task, line) {
91310
- const env2 = {};
91311
- const dropped = ["AI4KANBAN_BOARD", "AI4KANBAN_TASK", LANGUAGE_LINE_ENV];
91312
- for (const [k, v2] of Object.entries(process.env)) if (!k.startsWith("KANBAN_") && !dropped.includes(k)) env2[k] = v2;
91313
- const key = Object.keys(env2).find((k) => k.toUpperCase() === "PATH") ?? "PATH";
91314
- env2[key] = [shimDir(akb), env2[key]].filter(Boolean).join(path23.delimiter);
91315
- env2.AI4KANBAN_COMMAND = "akb";
91316
- if (board) env2.AI4KANBAN_BOARD = board;
91317
- if (task) env2.AI4KANBAN_TASK = task;
91318
- if (line !== void 0) env2[LANGUAGE_LINE_ENV] = line;
91319
- return env2;
91479
+ return { text: withoutTag(String(raw)) };
91320
91480
  }
91321
- var KEEP = 256 * 1024;
91322
- function runAkb(akb, args, opts) {
91323
- return new Promise((resolve2) => {
91324
- let out = "";
91325
- let last2 = "";
91326
- const note = (text3) => {
91327
- const line = text3.split("\n").map((l2) => l2.trim()).filter(Boolean).at(-1);
91328
- if (line) last2 = line;
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: []
91329
91496
  };
91330
- let child;
91331
- try {
91332
- child = spawn3(akb.command, [...akb.args, ...args], { cwd: opts.cwd, env: akbEnv(akb, opts.board, opts.task, opts.line), stdio: ["ignore", "pipe", "pipe"] });
91333
- } catch (e2) {
91334
- return resolve2({ code: null, out: "", last: e2 instanceof Error ? e2.message : String(e2) });
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
+ }
91335
91516
  }
91336
- opts.track?.(child);
91337
- child.stdout.setEncoding("utf8");
91338
- child.stderr.setEncoding("utf8");
91339
- child.stdout.on("data", (chunk) => {
91340
- out = (out + chunk).slice(-KEEP);
91341
- note(chunk);
91342
- opts.show?.(chunk);
91343
- });
91344
- child.stderr.on("data", (chunk) => {
91345
- note(chunk);
91346
- opts.show?.(chunk);
91347
- });
91348
- child.on("error", (e2) => resolve2({ code: null, out, last: e2.message }));
91349
- child.on("close", (code) => resolve2({ code, out, last: last2 }));
91350
- });
91517
+ out.push(normalizeQuestion(q3));
91518
+ }
91519
+ return out;
91351
91520
  }
91352
- function answerOf2(ran) {
91353
- const line = ran.out.trim().split("\n").at(-1) ?? "";
91354
- try {
91355
- return JSON.parse(line);
91356
- } catch {
91357
- return null;
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++;
91358
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") };
91359
91603
  }
91360
91604
 
91361
91605
  // src/triage.ts
91362
- import fs21 from "node:fs";
91363
- import path24 from "node:path";
91606
+ import fs23 from "node:fs";
91607
+ import path26 from "node:path";
91364
91608
 
91365
91609
  // ../cli/src/lib/signals/identity.ts
91366
91610
  import { createHash } from "node:crypto";
91367
91611
  var DERIVED = "derived-";
91368
91612
  var derivedSourceId = (seed) => `${DERIVED}${createHash("sha256").update(seed).digest("hex").slice(0, 16)}`;
91369
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
+
91370
91620
  // src/triage.ts
91371
- var triageDir = (board) => path24.join(board, "triage");
91372
- var rejectedDir = (board) => path24.join(board, ".archive", ".sync");
91621
+ var triageDir = (board) => path26.join(board, "triage");
91622
+ var rejectedDir = (board) => path26.join(board, ".archive", REJECTIONS_TO_REVIEW);
91373
91623
  var SCRATCH = ["dismissed", "archived"];
91374
91624
  var stamp = (at2) => formatStamp(at2 ? new Date(at2) : /* @__PURE__ */ new Date());
91375
91625
  function slugOf(title) {
@@ -91378,7 +91628,7 @@ function slugOf(title) {
91378
91628
  function freeName(dir, title) {
91379
91629
  const stem = slugOf(title);
91380
91630
  let name = `${stem}.md`;
91381
- for (let n = 2; fs21.existsSync(path24.join(dir, name)); n++) name = `${stem}-${n}.md`;
91631
+ for (let n = 2; fs23.existsSync(path26.join(dir, name)); n++) name = `${stem}-${n}.md`;
91382
91632
  return name;
91383
91633
  }
91384
91634
  function itemText(item, fields = {}) {
@@ -91398,17 +91648,17 @@ ${item.text.trim()}
91398
91648
  `;
91399
91649
  }
91400
91650
  function writeItem(dir, item, fields = {}) {
91401
- fs21.mkdirSync(dir, { recursive: true });
91651
+ fs23.mkdirSync(dir, { recursive: true });
91402
91652
  const name = freeName(dir, item.title);
91403
- fs21.writeFileSync(path24.join(dir, name), itemText(item, item.workflow ? { workflow: workflowName(item.workflow), ...fields } : fields));
91653
+ fs23.writeFileSync(path26.join(dir, name), itemText(item, item.workflow ? { workflow: workflowName(item.workflow), ...fields } : fields));
91404
91654
  return name;
91405
91655
  }
91406
91656
  function layOut(board, rejections) {
91407
91657
  clearLaid(board);
91408
91658
  const dir = rejectedDir(board);
91409
- fs21.mkdirSync(dir, { recursive: true });
91659
+ fs23.mkdirSync(dir, { recursive: true });
91410
91660
  for (const t2 of rejections.tasks) {
91411
- fs21.writeFileSync(path24.join(dir, `${t2.number}-${slugify(t2.title)}.md`), [
91661
+ fs23.writeFileSync(path26.join(dir, `${t2.number}-${slugify(t2.title)}.md`), [
91412
91662
  "---",
91413
91663
  `title: ${yamlScalar(t2.title)}`,
91414
91664
  "status: todo",
@@ -91423,20 +91673,38 @@ function layOut(board, rejections) {
91423
91673
  ].join("\n"));
91424
91674
  }
91425
91675
  for (const item of rejections.triage) {
91426
- const sub = path24.join(triageDir(board), item.state === "dismissed" ? "dismissed" : "archived");
91676
+ const sub = path26.join(triageDir(board), item.state === "dismissed" ? "dismissed" : "archived");
91427
91677
  const fields = item.state === "dismissed" ? { dismissed_at: stamp(item.dismissed_at), dismissed_by: "user", ...item.dismissed_reason ? { dismissed_reason: item.dismissed_reason } : {} } : {};
91428
91678
  writeItem(sub, item, fields);
91429
91679
  }
91430
91680
  return { tasks: rejections.tasks.map((t2) => t2.id), triage: rejections.triage.map((i) => i.id) };
91431
91681
  }
91432
91682
  function clearLaid(board) {
91433
- fs21.rmSync(rejectedDir(board), { recursive: true, force: true });
91434
- for (const sub of SCRATCH) fs21.rmSync(path24.join(triageDir(board), sub), { recursive: true, force: true });
91683
+ fs23.rmSync(rejectedDir(board), { recursive: true, force: true });
91684
+ for (const sub of SCRATCH) fs23.rmSync(path26.join(triageDir(board), sub), { recursive: true, force: true });
91435
91685
  }
91436
91686
 
91437
91687
  // src/built.ts
91438
- import fs22 from "node:fs";
91439
- import path25 from "node:path";
91688
+ import fs24 from "node:fs";
91689
+ import path27 from "node:path";
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
+ };
91440
91708
 
91441
91709
  // ../cli/src/lib/agent/workflow-def.ts
91442
91710
  var WORKFLOW_ID = /^[a-z0-9]+(-[a-z0-9]+)*$/;
@@ -91594,26 +91862,26 @@ function checkWorkflowFiles(value, official = false) {
91594
91862
 
91595
91863
  // src/built.ts
91596
91864
  var isBuilder = (ws) => ws.workflow === BUILDER;
91597
- var draftDir = (ws) => path25.join(ws.board, "workflows", draftFolder(ws.task));
91598
- var draftLine = (ws) => `<!-- workflow folder: ${path25.relative(ws.cwd, draftDir(ws)).split(path25.sep).join("/")}/ -->`;
91865
+ var draftDir = (ws) => path27.join(ws.board, "workflows", draftFolder(ws.task));
91866
+ var draftLine = (ws) => `<!-- workflow folder: ${path27.relative(ws.cwd, draftDir(ws)).split(path27.sep).join("/")}/ -->`;
91599
91867
  var skeleton = (name) => ["---", `name: ${/\s#/.test(name) ? JSON.stringify(name) : yamlScalar(name)}`, "needsArtifact: false", "---", ""].join("\n");
91600
91868
  async function placeDraft(ws, read) {
91601
91869
  const dir = draftDir(ws);
91602
- if (fs22.existsSync(path25.join(dir, WORKFLOW_FILE))) return { ok: true, value: void 0 };
91870
+ if (fs24.existsSync(path27.join(dir, WORKFLOW_FILE))) return { ok: true, value: void 0 };
91603
91871
  const task = await read.readTask(ws.task);
91604
91872
  if (!task.ok) return task;
91605
91873
  let files = { [WORKFLOW_FILE]: skeleton(task.value.title.trim() || "Untitled") };
91606
91874
  const changes = task.value.context?.workflow;
91607
91875
  if (changes) {
91608
- const held3 = await read.readWorkflow(changes);
91609
- if (!held3.ok) return held3;
91610
- files = held3.value.files;
91876
+ const held4 = await read.readWorkflow(changes);
91877
+ if (!held4.ok) return held4;
91878
+ files = held4.value.files;
91611
91879
  }
91612
91880
  for (const [name, text3] of Object.entries(files)) {
91613
- const file2 = path25.resolve(dir, name);
91614
- if (!file2.startsWith(dir + path25.sep)) continue;
91615
- fs22.mkdirSync(path25.dirname(file2), { recursive: true });
91616
- fs22.writeFileSync(file2, text3);
91881
+ const file2 = path27.resolve(dir, name);
91882
+ if (!file2.startsWith(dir + path27.sep)) continue;
91883
+ fs24.mkdirSync(path27.dirname(file2), { recursive: true });
91884
+ fs24.writeFileSync(file2, text3);
91617
91885
  }
91618
91886
  return { ok: true, value: void 0 };
91619
91887
  }
@@ -91625,19 +91893,19 @@ async function builtWorkflow(ws, akb) {
91625
91893
  const dir = draftDir(ws);
91626
91894
  let source;
91627
91895
  try {
91628
- source = fs22.readFileSync(path25.join(dir, WORKFLOW_FILE), "utf8");
91896
+ source = fs24.readFileSync(path27.join(dir, WORKFLOW_FILE), "utf8");
91629
91897
  } catch {
91630
91898
  return fail(`workflows/${id}/${WORKFLOW_FILE} is missing.`);
91631
91899
  }
91632
91900
  const read = parseWorkflowFile(id, source, `workflows/${id}/${WORKFLOW_FILE}`);
91633
91901
  if ("problem" in read) return fail(read.problem);
91634
91902
  const names2 = named(read.def);
91635
- fs22.rmSync(path25.join(dir, "agents"), { recursive: true, force: true });
91903
+ fs24.rmSync(path27.join(dir, "agents"), { recursive: true, force: true });
91636
91904
  for (const name of names2) {
91637
- const from = path25.join(ws.board, "agents", name);
91638
- if (fs22.existsSync(from)) fs22.cpSync(from, path25.join(dir, "agents", name), { recursive: true });
91905
+ const from = path27.join(ws.board, "agents", name);
91906
+ if (fs24.existsSync(from)) fs24.cpSync(from, path27.join(dir, "agents", name), { recursive: true });
91639
91907
  }
91640
- const files = Object.fromEntries(filesUnder(dir).map((f2) => [f2, fs22.readFileSync(path25.join(dir, f2), "utf8")]));
91908
+ const files = Object.fromEntries(filesUnder(dir).map((f2) => [f2, fs24.readFileSync(path27.join(dir, f2), "utf8")]));
91641
91909
  const checked = checkWorkflowFiles(files);
91642
91910
  if (!checked.ok) return fail(`${checked.file} ${checked.reason}.`);
91643
91911
  const run2 = async (args) => answerOf2(await runAkb(akb, [...args, "--json", "--board", ws.board], { cwd: ws.cwd, board: ws.board }));
@@ -91653,10 +91921,10 @@ async function builtWorkflow(ws, akb) {
91653
91921
  }
91654
91922
 
91655
91923
  // src/flow.ts
91656
- function unavailable(wanted, reports) {
91657
- const report2 = reports.find((r2) => r2.name === wanted);
91658
- if (!report2?.installed) return `${LABELS[wanted]} is not installed on this computer.`;
91659
- if (report2.loggedIn === false) return `${LABELS[wanted]} is not signed in on this computer.`;
91924
+ function unavailable(wanted2, reports) {
91925
+ const report2 = reports.find((r2) => r2.name === wanted2);
91926
+ if (!report2?.installed) return `${LABELS[wanted2]} is not installed on this computer.`;
91927
+ if (report2.loggedIn === false) return `${LABELS[wanted2]} is not signed in on this computer.`;
91660
91928
  return null;
91661
91929
  }
91662
91930
  function spentBy(runs) {
@@ -91670,11 +91938,10 @@ function spentBy(runs) {
91670
91938
  ...context ? { context: { used: context.used, limit: context.limit } } : {}
91671
91939
  };
91672
91940
  }
91673
- var SETUP_STEPS = ["project", "agent", "decisions", "modules", "tasks"];
91674
91941
  function reviewOf(file2) {
91675
91942
  let text3;
91676
91943
  try {
91677
- text3 = fs23.readFileSync(file2, "utf8");
91944
+ text3 = fs25.readFileSync(file2, "utf8");
91678
91945
  } catch {
91679
91946
  return void 0;
91680
91947
  }
@@ -91688,8 +91955,8 @@ function reviewOf(file2) {
91688
91955
  }
91689
91956
  function mcpConfig(servers, file2) {
91690
91957
  if (!Object.keys(servers).length) return null;
91691
- fs23.mkdirSync(path26.dirname(file2), { recursive: true });
91692
- fs23.writeFileSync(file2, `${JSON.stringify({ mcpServers: servers }, null, 2)}
91958
+ fs25.mkdirSync(path28.dirname(file2), { recursive: true });
91959
+ fs25.writeFileSync(file2, `${JSON.stringify({ mcpServers: servers }, null, 2)}
91693
91960
  `);
91694
91961
  return file2;
91695
91962
  }
@@ -91703,9 +91970,9 @@ function mcpArgs(runtime, servers, file2) {
91703
91970
  ]).join(" ");
91704
91971
  }
91705
91972
  var MCP_KEY = "mcpConfig";
91706
- var wait = (ms2) => new Promise((resolve2) => setTimeout(resolve2, ms2));
91707
- async function stopRuns(akb, ws, id, since, ms2) {
91708
- 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;
91709
91976
  const call = (args) => runAkb(akb, [...args, "--board", ws.board], { cwd: ws.cwd, board: ws.board });
91710
91977
  while (Date.now() < until) {
91711
91978
  const runs = answerOf2(await call(["run", "list", "--card", String(id), "--all", "--json"]))?.runs;
@@ -91717,36 +91984,36 @@ async function stopRuns(akb, ws, id, since, ms2) {
91717
91984
  }
91718
91985
  var working = /* @__PURE__ */ new Map();
91719
91986
  var workKey = (ws, id) => `${ws.board}#${id}`;
91720
- async function stopLeftBehind(akb, ws, id, ms2) {
91721
- 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);
91722
91989
  }
91723
91990
  function deliveryEnding(ws, id) {
91724
91991
  if (!id) return null;
91725
- let held3;
91992
+ let held4;
91726
91993
  try {
91727
- held3 = JSON.parse(fs23.readFileSync(path26.join(ws.board, "deliveries", `${path26.basename(id)}.json`), "utf8"));
91994
+ held4 = JSON.parse(fs25.readFileSync(path28.join(ws.board, "deliveries", `${path28.basename(id)}.json`), "utf8"));
91728
91995
  } catch {
91729
91996
  return null;
91730
91997
  }
91731
- const stopped2 = held3.review?.stopped;
91732
- if (held3.status === "cancelled") {
91733
- return held3.steps?.some((s) => s.step === "discarded") ? { ok: false, reason: "The build was discarded." } : { ok: false, reason: "", stopped: true };
91998
+ const stopped2 = held4.review?.stopped;
91999
+ if (held4.status === "cancelled") {
92000
+ return held4.steps?.some((s) => s.step === "discarded") ? { ok: false, reason: "The build was discarded." } : { ok: false, reason: "", stopped: true };
91734
92001
  }
91735
- if (held3.status === "active" && stopped2?.reason === "landing") return { ok: false, reason: firstLine(stopped2.why) ?? "The build could not land." };
92002
+ if (held4.status === "active" && stopped2?.reason === "landing") return { ok: false, reason: firstLine(stopped2.why) ?? "The build could not land." };
91736
92003
  return null;
91737
92004
  }
91738
92005
  function checkoutsOf(ws, id) {
91739
- const dir = path26.join(ws.board, "deliveries");
92006
+ const dir = path28.join(ws.board, "deliveries");
91740
92007
  let names2;
91741
92008
  try {
91742
- names2 = fs23.readdirSync(dir).filter((n) => n.endsWith(".json"));
92009
+ names2 = fs25.readdirSync(dir).filter((n) => n.endsWith(".json"));
91743
92010
  } catch {
91744
92011
  return [];
91745
92012
  }
91746
92013
  return names2.flatMap((n) => {
91747
92014
  try {
91748
- const held3 = JSON.parse(fs23.readFileSync(path26.join(dir, n), "utf8"));
91749
- return held3.cardId === id && held3.worktree && held3.deliveryId ? [held3.deliveryId] : [];
92015
+ const held4 = JSON.parse(fs25.readFileSync(path28.join(dir, n), "utf8"));
92016
+ return held4.cardId === id && held4.worktree && held4.deliveryId ? [held4.deliveryId] : [];
91750
92017
  } catch {
91751
92018
  return [];
91752
92019
  }
@@ -91755,7 +92022,7 @@ function checkoutsOf(ws, id) {
91755
92022
  var refusal2 = (ran) => ran.last.replace(/^akb( raw)?: /, "").slice(0, 300) || "akb stopped with an error.";
91756
92023
  var firstLine = (text3) => (text3 ?? "").split("\n").map((l2) => l2.trim()).find(Boolean)?.slice(0, 300);
91757
92024
  function logLines(show, event2) {
91758
- let held3 = "";
92025
+ let held4 = "";
91759
92026
  const said = (line) => {
91760
92027
  if (line.startsWith('{"kind":')) {
91761
92028
  let parsed;
@@ -91781,40 +92048,47 @@ function logLines(show, event2) {
91781
92048
  };
91782
92049
  return {
91783
92050
  push: (chunk) => {
91784
- const lines = (held3 + chunk).split("\n");
91785
- held3 = lines.pop();
92051
+ const lines = (held4 + chunk).split("\n");
92052
+ held4 = lines.pop();
91786
92053
  for (const line of lines) {
91787
92054
  const out = said(line);
91788
92055
  if (out) show(out);
91789
92056
  }
91790
92057
  },
91791
92058
  end: () => {
91792
- const out = held3 ? said(held3) : "";
92059
+ const out = held4 ? said(held4) : "";
91793
92060
  if (out) show(out);
91794
92061
  }
91795
92062
  };
91796
92063
  }
91797
92064
  function boardAkb(job, ws, deps, io, task) {
91798
- return async (args, show = false) => {
92065
+ return async (args, show = false, env2) => {
91799
92066
  const at2 = args.includes("--") ? args.indexOf("--") : args.length;
91800
92067
  const full = [...args.slice(0, at2), "--board", ws.board, ...args.slice(at2)];
91801
92068
  const log = show ? logLines(io.show, io.event) : void 0;
91802
- 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 });
91803
92070
  log?.end();
91804
92071
  return ran;
91805
92072
  };
91806
92073
  }
92074
+ function skillStale(dir, version) {
92075
+ try {
92076
+ const text3 = fs25.readFileSync(path28.join(dir, "SKILL.md"), "utf8");
92077
+ return !fs25.lstatSync(dir).isSymbolicLink() && /<!-- ai4kanban (\S+) -->\s*$/.exec(text3)?.[1] !== version;
92078
+ } catch {
92079
+ return true;
92080
+ }
92081
+ }
91807
92082
  async function setUp(job, ws, deps, io) {
91808
92083
  const akb = boardAkb(job, ws, deps, io);
91809
92084
  const runtime = job.runtime;
91810
92085
  const missing = unavailable(runtime, await deps.runtimes());
91811
92086
  if (missing) return missing;
91812
- if (!fs23.existsSync(path26.join(ws.board, "config.md"))) {
92087
+ if (!fs25.existsSync(path28.join(ws.board, "config.md"))) {
91813
92088
  const init = await akb(["raw", "init"]);
91814
92089
  if (init.code !== 0) return refusal2(init);
91815
- for (const step of SETUP_STEPS) await akb(["raw", "setup-done", step]);
91816
92090
  }
91817
- if (SKILL_FOLDERS.some((f2) => !fs23.existsSync(path26.join(ws.cwd, f2, "SKILL.md")))) {
92091
+ if (SKILL_FOLDERS.some((f2) => skillStale(path28.join(ws.cwd, f2), deps.akb.version))) {
91818
92092
  const skill = await runAkb(deps.akb, ["skill", "install", "--dir", ws.cwd], { cwd: ws.cwd, track: io.track });
91819
92093
  if (skill.code !== 0) return refusal2(skill);
91820
92094
  }
@@ -91823,7 +92097,7 @@ async function setUp(job, ws, deps, io) {
91823
92097
  const used = await akb(["agent", "use", runtime]);
91824
92098
  if (used.code !== 0) return refusal2(used);
91825
92099
  const servers = mcpServersOf(ws);
91826
- const mcpFile = path26.join(ws.board, ".sync", `${ws.task}.mcp.json`);
92100
+ const mcpFile = path28.join(ws.board, ".sync", `${ws.task}.mcp.json`);
91827
92101
  const takes = new Set(settingKeys(runtime));
91828
92102
  const given = job.settings ?? {};
91829
92103
  const values = { ...given, model: job.model ?? "" };
@@ -91873,7 +92147,7 @@ async function reviewRejections(job, ws, deps, io) {
91873
92147
  const akb = boardAkb(job, ws, deps, io);
91874
92148
  return withBoard(ws, async (push2) => {
91875
92149
  const laid = layOut(ws.board, read.value);
91876
- const ran = await akb(["review-dismissals", "--all", "--follow", "--events", "--json"], true);
92150
+ const ran = await akb(["review-dismissals", "--follow", "--events", "--json"], true);
91877
92151
  clearLaid(ws.board);
91878
92152
  resetSorted(ws);
91879
92153
  const runs = (answerOf2(await akb(["run", "list", "--all", "--json"]))?.runs ?? []).filter((r2) => (r2.startedAt ?? 0) >= since);
@@ -91890,6 +92164,15 @@ async function learnRejections(job, ws, deps, io) {
91890
92164
  if (failure) console.error(`runner: rejections not learned: ${failure}`);
91891
92165
  return runs;
91892
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
+ }
91893
92176
  async function runAgent(job, ws, deps, io) {
91894
92177
  const since = Date.now();
91895
92178
  const failed = await setUp(job, ws, deps, io);
@@ -91904,7 +92187,8 @@ async function runAgent(job, ws, deps, io) {
91904
92187
  const args = workflow ? ["agent", "run", workflowName(workflow), name] : name === "reflect" ? ["reflect", "--cards", ...tasks.map((t2) => String(t2.number))] : [name];
91905
92188
  const akb = boardAkb(job, ws, deps, io, ws.cloudTask ?? void 0);
91906
92189
  await akb(["run", "list", "--all", "--json"]);
91907
- 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);
91908
92192
  if (io.lost()) return { ok: false, reason: "" };
91909
92193
  const answer = answerOf2(ran);
91910
92194
  if (ran.code !== 0) return { ok: false, reason: firstLine(answer?.error?.message?.replace(/^run \S+ ended \w+: /, "")) ?? refusal2(ran) };
@@ -91913,19 +92197,19 @@ async function runAgent(job, ws, deps, io) {
91913
92197
  }
91914
92198
  function writeTranscript(job, dir) {
91915
92199
  if (!job.transcript) return "";
91916
- const file2 = path26.join(dir, "discussion.md");
91917
- fs23.mkdirSync(dir, { recursive: true });
91918
- fs23.writeFileSync(file2, `${job.transcript}
92200
+ const file2 = path28.join(dir, "discussion.md");
92201
+ fs25.mkdirSync(dir, { recursive: true });
92202
+ fs25.writeFileSync(file2, `${job.transcript}
91919
92203
  `);
91920
92204
  return file2;
91921
92205
  }
91922
92206
  function pictures(job, ws, id) {
91923
92207
  const dir = cardAssetsDir(ws, id);
91924
92208
  if (!job.attachments.length || !dir) return "";
91925
- fs23.mkdirSync(dir, { recursive: true });
92209
+ fs25.mkdirSync(dir, { recursive: true });
91926
92210
  return job.attachments.map((a3, i) => {
91927
- const file2 = `${i + 1}-${path26.basename(a3.name).replace(/[^\w.-]+/g, "-")}`;
91928
- fs23.writeFileSync(path26.join(dir, file2), Buffer.from(a3.content, "base64"));
92211
+ const file2 = `${i + 1}-${path28.basename(a3.name).replace(/[^\w.-]+/g, "-")}`;
92212
+ fs25.writeFileSync(path28.join(dir, file2), Buffer.from(a3.content, "base64"));
91929
92213
  return `
91930
92214
  <Asset src=".assets/${id}/${file2}" label="${a3.name.replace(/["<>]/g, "") || file2}" />
91931
92215
  `;
@@ -91933,11 +92217,10 @@ function pictures(job, ws, id) {
91933
92217
  }
91934
92218
  function cardFlags(ws, fields) {
91935
92219
  if (!fields) return [];
91936
- const open = (keys) => (keys ?? []).map((k) => Number(/(\d+)$/.exec(k)?.[1])).filter((n) => n > 0 && n !== ws.number && findCard(ws.board, n)?.startsWith(path26.join(ws.board, "todo") + path26.sep));
92220
+ const open = (keys) => (keys ?? []).map((k) => Number(/(\d+)$/.exec(k)?.[1])).filter((n) => n > 0 && n !== ws.number && findCard(ws.board, n)?.startsWith(path28.join(ws.board, "todo") + path28.sep));
91937
92221
  const lists = [["--modules", fields.modules ?? []], ["--related", open(fields.related)], ["--blocked-by", open(fields.blocked_by)]];
91938
92222
  return [
91939
92223
  ...fields.priority ? ["--priority", fields.priority] : [],
91940
- ...fields.roi ? ["--roi", fields.roi] : [],
91941
92224
  ...lists.flatMap(([flag, list]) => list.length ? [flag, list.join(",")] : [])
91942
92225
  ];
91943
92226
  }
@@ -91968,10 +92251,10 @@ async function runFlow(job, ws, deps, io) {
91968
92251
  const placed = await placeDraft(ws, deps.api);
91969
92252
  if (!placed.ok) return fail(placed.error);
91970
92253
  }
91971
- const body = path26.join(ws.board, ".sync", `${ws.task}.request.md`);
91972
- fs23.mkdirSync(path26.dirname(body), { recursive: true });
92254
+ const body = path28.join(ws.board, ".sync", `${ws.task}.request.md`);
92255
+ fs25.mkdirSync(path28.dirname(body), { recursive: true });
91973
92256
  if (!ws.number) return fail("This task has no number yet.");
91974
- fs23.writeFileSync(body, `${said.request || title}
92257
+ fs25.writeFileSync(body, `${said.request || title}
91975
92258
  ${isBuilder(ws) ? `
91976
92259
  ${draftLine(ws)}
91977
92260
  ` : ""}${pictures(job, ws, ws.number)}`);
@@ -91989,21 +92272,21 @@ ${draftLine(ws)}
91989
92272
  ...cardFlags(ws, flow.metadata),
91990
92273
  "--json"
91991
92274
  ]));
91992
- fs23.rmSync(body, { force: true });
92275
+ fs25.rmSync(body, { force: true });
91993
92276
  if (!created.ok) return fail(created.error);
91994
92277
  id = created.value;
91995
92278
  }
91996
92279
  if (!id) return fail("This task has no card on this computer.");
91997
92280
  const card = id;
91998
92281
  const key = workKey(ws, card);
91999
- const held3 = working.get(key) ?? 0;
92000
- working.set(key, held3 + 1);
92282
+ const held4 = working.get(key) ?? 0;
92283
+ working.set(key, held4 + 1);
92001
92284
  try {
92002
- if (!held3) await stopRuns(deps.akb, ws, card, 0, deps.stopMs);
92285
+ if (!held4) await stopRuns(deps.akb, ws, card, 0, deps.stopMs);
92003
92286
  if (io.lost()) return fail("");
92004
92287
  return await workOn(card);
92005
92288
  } finally {
92006
- fs23.rmSync(path26.join(ws.board, ".sync", `${ws.task}.discussion`), { recursive: true, force: true });
92289
+ fs25.rmSync(path28.join(ws.board, ".sync", `${ws.task}.discussion`), { recursive: true, force: true });
92007
92290
  const left = working.get(key) - 1;
92008
92291
  if (left) working.set(key, left);
92009
92292
  else working.delete(key);
@@ -92055,8 +92338,8 @@ ${draftLine(ws)}
92055
92338
  return { ok: true, report: { card: card2 } };
92056
92339
  }
92057
92340
  function carryArgs(verb) {
92058
- if (!["refine", "resolve", "revise"].includes(verb)) return [];
92059
- const transcript = writeTranscript(job, path26.join(ws.board, ".sync", `${ws.task}.discussion`));
92341
+ if (!["refine", "resolve", "revise", "implement"].includes(verb)) return [];
92342
+ const transcript = writeTranscript(job, path28.join(ws.board, ".sync", `${ws.task}.discussion`));
92060
92343
  return [
92061
92344
  ...job.resume ? ["--session", job.resume, ...job.fork ? ["--fork"] : []] : [],
92062
92345
  ...transcript ? ["--transcript", transcript] : []
@@ -92065,17 +92348,17 @@ ${draftLine(ws)}
92065
92348
  }
92066
92349
 
92067
92350
  // src/lock.ts
92068
- import crypto3 from "node:crypto";
92069
- import fs24 from "node:fs";
92351
+ import crypto4 from "node:crypto";
92352
+ import fs26 from "node:fs";
92070
92353
  import net from "node:net";
92071
- import path27 from "node:path";
92354
+ import path29 from "node:path";
92072
92355
  var RETRY_MS = 5e3;
92073
92356
  var KIND_MS = 1e3;
92074
92357
  var HOLDERS = ["claude-code", "codex", "terminal", "desktop"];
92075
92358
  function lockPath() {
92076
92359
  const home4 = runnerHome();
92077
- if (process.platform === "win32") return `\\\\.\\pipe\\wildcrane-${crypto3.createHash("sha256").update(home4).digest("hex").slice(0, 16)}`;
92078
- return path27.join(home4, "runner.sock");
92360
+ if (process.platform === "win32") return `\\\\.\\pipe\\wildcrane-${crypto4.createHash("sha256").update(home4).digest("hex").slice(0, 16)}`;
92361
+ return path29.join(home4, "runner.sock");
92079
92362
  }
92080
92363
  function holdMachine(kind, onHeld, onWaiting) {
92081
92364
  const where = lockPath();
@@ -92084,13 +92367,13 @@ function holdMachine(kind, onHeld, onWaiting) {
92084
92367
  let waiting = null;
92085
92368
  let timer = null;
92086
92369
  const peers = /* @__PURE__ */ new Set();
92087
- const later = (ms2) => {
92088
- if (!closed) timer = setTimeout(attempt, ms2);
92370
+ const later = (ms) => {
92371
+ if (!closed) timer = setTimeout(attempt, ms);
92089
92372
  };
92090
92373
  const attempt = () => {
92091
92374
  timer = null;
92092
92375
  if (closed) return;
92093
- if (process.platform !== "win32") fs24.mkdirSync(path27.dirname(where), { recursive: true, mode: 448 });
92376
+ if (process.platform !== "win32") fs26.mkdirSync(path29.dirname(where), { recursive: true, mode: 448 });
92094
92377
  const s = net.createServer((peer) => {
92095
92378
  peers.add(peer);
92096
92379
  peer.on("error", () => {
@@ -92138,7 +92421,7 @@ function holdMachine(kind, onHeld, onWaiting) {
92138
92421
  later(0);
92139
92422
  });
92140
92423
  removeIfStill.once("error", () => {
92141
- fs24.rmSync(where, { force: true });
92424
+ fs26.rmSync(where, { force: true });
92142
92425
  later(50 + Math.random() * 200);
92143
92426
  });
92144
92427
  return;
@@ -92167,13 +92450,117 @@ function holdMachine(kind, onHeld, onWaiting) {
92167
92450
 
92168
92451
  // src/jobs.ts
92169
92452
  import { spawn as spawn4 } from "node:child_process";
92170
- import fs26 from "node:fs";
92171
- import path29 from "node:path";
92453
+ import fs29 from "node:fs";
92454
+ import path32 from "node:path";
92455
+
92456
+ // ../cli/src/lib/agent/catalog.ts
92457
+ import fs27 from "node:fs";
92458
+ import path30 from "node:path";
92459
+ var CATALOGUE = "https://models.dev/api.json";
92460
+ var FRESH_FOR_MS = 24 * 60 * 6e4;
92461
+ var ANSWER_BY_MS = 2e4;
92462
+ function cacheFile() {
92463
+ return path30.join(machineHome(), "models-dev.json");
92464
+ }
92465
+ var held2;
92466
+ function readCache() {
92467
+ const file2 = cacheFile();
92468
+ let stamp2;
92469
+ try {
92470
+ const stat = fs27.statSync(file2);
92471
+ stamp2 = `${stat.mtimeMs}:${stat.size}`;
92472
+ } catch {
92473
+ return void 0;
92474
+ }
92475
+ if (held2?.stamp === stamp2) return held2.cached;
92476
+ try {
92477
+ const data = JSON.parse(fs27.readFileSync(file2, "utf8"));
92478
+ if (!data || typeof data.limits !== "object" || !data.limits) return void 0;
92479
+ const cached2 = {
92480
+ fetchedAt: typeof data.fetchedAt === "number" ? data.fetchedAt : 0,
92481
+ limits: data.limits
92482
+ };
92483
+ held2 = { stamp: stamp2, cached: cached2 };
92484
+ return cached2;
92485
+ } catch {
92486
+ return void 0;
92487
+ }
92488
+ }
92489
+ function limitsIn(data) {
92490
+ const limits = {};
92491
+ if (!data || typeof data !== "object") return limits;
92492
+ for (const [provider, raw] of Object.entries(data)) {
92493
+ const models = raw?.models;
92494
+ if (!models || typeof models !== "object") continue;
92495
+ for (const [model, entry] of Object.entries(models)) {
92496
+ const context = entry?.limit?.context;
92497
+ if (typeof context === "number" && Number.isFinite(context) && context > 0) {
92498
+ limits[`${provider}/${model}`] = context;
92499
+ }
92500
+ }
92501
+ }
92502
+ return limits;
92503
+ }
92504
+ var fetching2;
92505
+ function refreshCatalog() {
92506
+ if (fetching2) return fetching2;
92507
+ const cached2 = readCache();
92508
+ if (cached2 && Date.now() - cached2.fetchedAt < FRESH_FOR_MS) return Promise.resolve();
92509
+ fetching2 = (async () => {
92510
+ try {
92511
+ const answer = await fetch(CATALOGUE, { signal: AbortSignal.timeout(ANSWER_BY_MS) });
92512
+ if (!answer.ok) return;
92513
+ const limits = limitsIn(await answer.json());
92514
+ if (Object.keys(limits).length === 0) return;
92515
+ const file2 = cacheFile();
92516
+ fs27.mkdirSync(path30.dirname(file2), { recursive: true });
92517
+ fs27.writeFileSync(file2, JSON.stringify({ fetchedAt: Date.now(), limits }));
92518
+ } catch {
92519
+ }
92520
+ })();
92521
+ return fetching2;
92522
+ }
92523
+ var PROVIDERS = {
92524
+ "claude-code": ["anthropic"],
92525
+ zcode: ["zai", "zhipuai"],
92526
+ kimi: ["moonshotai", "moonshotai-cn"],
92527
+ opencode: ["opencode"]
92528
+ };
92529
+ function spellings(model) {
92530
+ const id = model.trim().toLowerCase();
92531
+ if (!id) return [];
92532
+ const undated = id.replace(/-\d{8}$/, "");
92533
+ return [.../* @__PURE__ */ new Set([id, undated])];
92534
+ }
92535
+ function contextLimit(harness, model) {
92536
+ if (!model?.trim()) return void 0;
92537
+ const limits = readCache()?.limits;
92538
+ if (!limits) return void 0;
92539
+ const cut2 = model.lastIndexOf("/");
92540
+ if (cut2 > 0) {
92541
+ const whole = model.trim().toLowerCase();
92542
+ if (limits[whole]) return limits[whole];
92543
+ }
92544
+ const bare = cut2 > 0 ? model.slice(cut2 + 1) : model;
92545
+ const ids = spellings(bare);
92546
+ for (const provider of PROVIDERS[harness] ?? []) {
92547
+ for (const id of ids) {
92548
+ const found = limits[`${provider}/${id}`];
92549
+ if (found) return found;
92550
+ }
92551
+ }
92552
+ let widest = 0;
92553
+ for (const [key, limit] of Object.entries(limits)) {
92554
+ const id = key.slice(key.indexOf("/") + 1);
92555
+ if (ids.includes(id) && limit > widest) widest = limit;
92556
+ }
92557
+ return widest || void 0;
92558
+ }
92172
92559
 
92173
92560
  // src/ideas.ts
92174
- import fs25 from "node:fs";
92175
- import path28 from "node:path";
92176
- var ideasFileOf = (job) => path28.join(runnerHome(), "ideas", `${job.id}.json`);
92561
+ import fs28 from "node:fs";
92562
+ import path31 from "node:path";
92563
+ var ideasFileOf = (job) => path31.join(runnerHome(), "ideas", `${job.id}.json`);
92177
92564
  async function writeIdeas(job, list) {
92178
92565
  const workflows = [];
92179
92566
  let after = null;
@@ -92184,24 +92571,23 @@ async function writeIdeas(job, list) {
92184
92571
  after = page.value.next;
92185
92572
  } while (after);
92186
92573
  const file2 = ideasFileOf(job);
92187
- fs25.mkdirSync(path28.dirname(file2), { recursive: true });
92188
- fs25.writeFileSync(file2, `${JSON.stringify({ workflows, ideas: job.discussion.ideas }, null, 2)}
92574
+ fs28.mkdirSync(path31.dirname(file2), { recursive: true });
92575
+ fs28.writeFileSync(file2, `${JSON.stringify({ workflows, ideas: job.discussion.ideas }, null, 2)}
92189
92576
  `);
92190
92577
  return { file: file2 };
92191
92578
  }
92192
92579
  function readIdeas(file2) {
92193
92580
  try {
92194
- return JSON.parse(fs25.readFileSync(file2, "utf8")).ideas;
92581
+ return JSON.parse(fs28.readFileSync(file2, "utf8")).ideas;
92195
92582
  } catch {
92196
92583
  return void 0;
92197
92584
  } finally {
92198
- fs25.rmSync(file2, { force: true });
92585
+ fs28.rmSync(file2, { force: true });
92199
92586
  }
92200
92587
  }
92201
92588
 
92202
92589
  // src/jobs.ts
92203
- var WATCHED_MS = 2e3;
92204
- var QUIET_MS = 15e3;
92590
+ var FLUSH_MS = 2e3;
92205
92591
  var FLUSH_CHARS = 32 * 1024;
92206
92592
  var BATCH_EVENTS = 500;
92207
92593
  var BATCH_CHARS = 512 * 1024;
@@ -92209,6 +92595,7 @@ var EVENT_CHARS = 64 * 1024;
92209
92595
  var END_MS = 1e4;
92210
92596
  var RECONNECT_MS = [1e3, 2e3, 5e3, 1e4, 3e4];
92211
92597
  var RENEW_MS = 5 * 6e4;
92598
+ var LOG_PING_MS = 3e4;
92212
92599
  var LEASE_MS = 15 * 6e4;
92213
92600
  var RETRY_MS2 = 3e4;
92214
92601
  var KILL_GRACE_MS = 5e3;
@@ -92219,7 +92606,8 @@ var defaultDeps = (machineId2) => ({
92219
92606
  machineId: machineId2,
92220
92607
  api: api_exports,
92221
92608
  plan,
92222
- flushMs: { watched: WATCHED_MS, quiet: QUIET_MS },
92609
+ flushMs: FLUSH_MS,
92610
+ logPingMs: LOG_PING_MS,
92223
92611
  endMs: END_MS,
92224
92612
  renewMs: RENEW_MS,
92225
92613
  leaseMs: LEASE_MS,
@@ -92227,35 +92615,35 @@ var defaultDeps = (machineId2) => ({
92227
92615
  testMs: TEST_MS,
92228
92616
  stopMs: STOP_MS,
92229
92617
  watchMs: WATCH_MS,
92230
- akb: bundledAkb(),
92618
+ akb: currentAkb,
92231
92619
  runtimes: detectRuntimes
92232
92620
  });
92233
- var ownFolder = () => path29.join(runnerHome(), "work");
92621
+ var ownFolder = () => path32.join(runnerHome(), "work");
92234
92622
  function folderFor(job) {
92235
92623
  if (!job.projectDir) {
92236
- const cwd = path29.join(ownFolder(), job.id);
92237
- fs26.mkdirSync(cwd, { recursive: true });
92624
+ const cwd = path32.join(ownFolder(), job.id);
92625
+ fs29.mkdirSync(cwd, { recursive: true });
92238
92626
  return { cwd };
92239
92627
  }
92240
92628
  const real = realpath4(job.projectDir);
92241
- if (real && allowedProjects().some((root) => real === root || real.startsWith(root + path29.sep))) return { cwd: real };
92629
+ if (real && allowedProjects().some((root) => real === root || real.startsWith(root + path32.sep))) return { cwd: real };
92242
92630
  return { refused: `This Runner is not allowed to work in ${job.projectDir}.` };
92243
92631
  }
92244
92632
  function realpath4(p2) {
92245
92633
  try {
92246
- return fs26.realpathSync(p2);
92634
+ return fs29.realpathSync(p2);
92247
92635
  } catch {
92248
92636
  return null;
92249
92637
  }
92250
92638
  }
92251
- var attachmentsOf = (job) => path29.join(runnerHome(), "attachments", job.id);
92639
+ var attachmentsOf = (job) => path32.join(runnerHome(), "attachments", job.id);
92252
92640
  function writeAttachments(job) {
92253
92641
  if (!job.attachments.length) return "";
92254
92642
  const dir = attachmentsOf(job);
92255
- fs26.mkdirSync(dir, { recursive: true });
92643
+ fs29.mkdirSync(dir, { recursive: true });
92256
92644
  const files = job.attachments.map((a3) => {
92257
- const file2 = path29.join(dir, path29.basename(a3.name));
92258
- fs26.writeFileSync(file2, Buffer.from(a3.content, "base64"));
92645
+ const file2 = path32.join(dir, path32.basename(a3.name));
92646
+ fs29.writeFileSync(file2, Buffer.from(a3.content, "base64"));
92259
92647
  return file2;
92260
92648
  });
92261
92649
  return `
@@ -92292,12 +92680,13 @@ function streamOut(deps, id, lease) {
92292
92680
  let ending = false;
92293
92681
  let closed = false;
92294
92682
  let flushedAt = Date.now();
92295
- const log = { ws: null, after: null, watched: false, tries: 0, retry: void 0 };
92683
+ const log = { ws: null, after: null, watched: false, heard: 0, tries: 0, retry: void 0 };
92296
92684
  let ended2 = () => {
92297
92685
  };
92298
92686
  const stored = new Promise((resolve2) => ended2 = resolve2);
92299
92687
  const children = /* @__PURE__ */ new Set();
92300
92688
  const kill = (child) => {
92689
+ if (!child.pid) return;
92301
92690
  child.kill("SIGTERM");
92302
92691
  setTimeout(() => child.kill("SIGKILL"), KILL_GRACE_MS).unref();
92303
92692
  };
@@ -92326,7 +92715,7 @@ function streamOut(deps, id, lease) {
92326
92715
  const ws = log.ws;
92327
92716
  if (!ws || ws.readyState !== WebSocket.OPEN || log.after === null) return;
92328
92717
  const after = log.after;
92329
- const unsent2 = wire.filter((e2) => e2.seq > after);
92718
+ const unsent2 = log.watched ? wire.filter((e2) => e2.seq > after) : [];
92330
92719
  let batch = [];
92331
92720
  let chars = 0;
92332
92721
  const out = () => {
@@ -92357,7 +92746,9 @@ function streamOut(deps, id, lease) {
92357
92746
  if (closed) return ws?.close();
92358
92747
  if (!ws) return reconnect();
92359
92748
  log.ws = ws;
92749
+ log.heard = Date.now();
92360
92750
  ws.addEventListener("message", (m) => {
92751
+ log.heard = Date.now();
92361
92752
  let said;
92362
92753
  try {
92363
92754
  said = JSON.parse(String(m.data));
@@ -92368,22 +92759,23 @@ function streamOut(deps, id, lease) {
92368
92759
  log.tries = 0;
92369
92760
  log.after = Number.isInteger(said.after) ? said.after : -1;
92370
92761
  log.watched = said.watched === true;
92371
- send3();
92762
+ flush();
92372
92763
  } else if (said.type === "watched") {
92373
92764
  log.watched = said.on === true;
92374
92765
  if (log.watched) flush();
92375
92766
  } else if (said.type === "ended") ended2();
92376
92767
  else if (said.type === "stop") ask();
92377
92768
  });
92378
- ws.addEventListener("close", () => {
92379
- if (log.ws !== ws) return;
92380
- log.ws = null;
92381
- log.after = null;
92382
- reconnect();
92383
- });
92769
+ ws.addEventListener("close", () => drop(ws));
92384
92770
  ws.addEventListener("error", () => {
92385
92771
  });
92386
92772
  };
92773
+ const drop = (ws) => {
92774
+ if (log.ws !== ws) return;
92775
+ log.ws = null;
92776
+ log.after = null;
92777
+ reconnect();
92778
+ };
92387
92779
  const reconnect = () => {
92388
92780
  if (log.retry || lost || closed) return;
92389
92781
  log.retry = setTimeout(() => void connect2(), RECONNECT_MS[Math.min(log.tries++, RECONNECT_MS.length - 1)]);
@@ -92393,12 +92785,18 @@ function streamOut(deps, id, lease) {
92393
92785
  if (e2.kind === "message") messages.push(e2.data.text);
92394
92786
  pending.push(e2);
92395
92787
  size += JSON.stringify(e2.data).length;
92396
- if (size >= FLUSH_CHARS) flush();
92788
+ if (log.watched && size >= FLUSH_CHARS) flush();
92397
92789
  };
92398
- const tick = Math.min(deps.flushMs.watched, 1e3);
92399
92790
  const flusher = setInterval(() => {
92400
- if (pending.length && Date.now() - flushedAt >= (log.watched ? deps.flushMs.watched : deps.flushMs.quiet)) flush();
92401
- }, tick);
92791
+ if (log.watched && pending.length && Date.now() - flushedAt >= deps.flushMs) flush();
92792
+ }, Math.min(deps.flushMs, 1e3));
92793
+ const pinger = setInterval(() => {
92794
+ const ws = log.ws;
92795
+ if (ws?.readyState !== WebSocket.OPEN) return;
92796
+ if (Date.now() - log.heard <= deps.logPingMs * 2) return ws.send("ping");
92797
+ drop(ws);
92798
+ ws.close();
92799
+ }, deps.logPingMs);
92402
92800
  const renewer = setInterval(async () => {
92403
92801
  const renewed = await deps.api.renewJob(deps.machineId, id);
92404
92802
  if (renewed.ok && !renewed.value.renewed) return void loseLease();
@@ -92432,6 +92830,7 @@ function streamOut(deps, id, lease) {
92432
92830
  /** The rest sent and the log stored, or given up on after a while: `finish` comes after. */
92433
92831
  end: async () => {
92434
92832
  clearInterval(flusher);
92833
+ clearInterval(pinger);
92435
92834
  clearInterval(renewer);
92436
92835
  ending = !lost;
92437
92836
  flush();
@@ -92453,12 +92852,12 @@ async function runJob(id, deps, track = () => {
92453
92852
  const claim = await deps.api.claimJob(deps.machineId, id);
92454
92853
  if (!claim.ok || !claim.value.claimed) return;
92455
92854
  const job = claim.value.job;
92456
- const held3 = [];
92855
+ const held4 = [];
92457
92856
  try {
92458
- await runClaimed(job, deps, track, (dir) => held3.push(hold(dir)));
92857
+ await runClaimed(job, { ...deps, akb: deps.akb() }, track, (dir) => held4.push(hold(dir)));
92459
92858
  } finally {
92460
- for (const release2 of held3) release2();
92461
- fs26.rmSync(attachmentsOf(job), { recursive: true, force: true });
92859
+ for (const release2 of held4) release2();
92860
+ fs29.rmSync(attachmentsOf(job), { recursive: true, force: true });
92462
92861
  }
92463
92862
  }
92464
92863
  async function runClaimed(job, deps, track, keep2) {
@@ -92502,6 +92901,7 @@ async function runClaimed(job, deps, track, keep2) {
92502
92901
  ideas = wrote.file;
92503
92902
  }
92504
92903
  if (!job.flow && !job.review) {
92904
+ void refreshCatalog();
92505
92905
  const head2 = folderLines(ws) + writeAttachments(job);
92506
92906
  const file2 = writeTranscript(job, attachmentsOf(job));
92507
92907
  const transcript = file2 ? `
@@ -92538,6 +92938,7 @@ ${job.prompt}` : job.prompt;
92538
92938
  for (const task2 of job.review.tasks) {
92539
92939
  const chat = await deps.api.readChat(task2);
92540
92940
  if (chat.ok) keepCloudChat(task2, chat.value.messages);
92941
+ await keepDecisions(task2, deps.api.readDecisions);
92541
92942
  }
92542
92943
  const listed2 = await deps.api.listChats(deps.machineId);
92543
92944
  if (!listed2.ok) {
@@ -92583,7 +92984,7 @@ ${job.prompt}` : job.prompt;
92583
92984
  await stream.end();
92584
92985
  if (stream.lost()) return;
92585
92986
  const ok = end.ok || stream.asked();
92586
- const said2 = told(stream.asked() ? cutShort(report(plan3, end), stream.said()) : report(plan3, end));
92987
+ const said2 = told(stream.asked() ? cutShort(report(job, plan3, end), stream.said()) : report(job, plan3, end));
92587
92988
  if (!ok || !ws) return finish(deps, id, lease, ok ? "done" : "failed", ok ? "" : end.error ?? "", said2);
92588
92989
  return sendBack(deps, id, lease, ws, said2, () => keepChat(job, said2.reply));
92589
92990
  }
@@ -92624,7 +93025,7 @@ ${job.prompt}` : job.prompt;
92624
93025
  await stream.end();
92625
93026
  if (stream.lost()) return;
92626
93027
  const failure = stream.asked() ? void 0 : ended2.error ?? renderer.failure?.() ?? (ended2.code === 0 ? void 0 : `Exited with code ${ended2.code}.`);
92627
- const said = told(stream.asked() ? cutShort(report(plan2), stream.said()) : report(plan2));
93028
+ const said = told(stream.asked() ? cutShort(report(job, plan2), stream.said()) : report(job, plan2));
92628
93029
  if (failure || !ws) return finish(deps, id, lease, failure ? "failed" : "done", failure, said);
92629
93030
  return sendBack(deps, id, lease, ws, said, () => keepChat(job, said.reply));
92630
93031
  }
@@ -92651,15 +93052,16 @@ async function runAgentJob(job, deps, track, keep2) {
92651
93052
  var quietLines = (plan2, chunk) => chunk.split("\n").filter((line) => line && !plan2.quiet(line)).map((line) => `${line}
92652
93053
  `).join("");
92653
93054
  var stop = (child) => {
93055
+ if (!child.pid) return;
92654
93056
  child.kill("SIGTERM");
92655
93057
  setTimeout(() => child.kill("SIGKILL"), KILL_GRACE_MS).unref();
92656
93058
  };
92657
- var wait2 = (ms2) => new Promise((resolve2) => setTimeout(resolve2, ms2));
92658
- var held2 = (deps, lease) => Date.now() - lease.at < deps.leaseMs;
93059
+ var wait2 = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
93060
+ var held3 = (deps, lease) => Date.now() - lease.at < deps.leaseMs;
92659
93061
  async function whileOffline(deps, id, lease, attempt) {
92660
93062
  for (; ; ) {
92661
93063
  const out = await attempt();
92662
- if (!("offline" in out && out.offline) || !held2(deps, lease)) return out;
93064
+ if (!("offline" in out && out.offline) || !held3(deps, lease)) return out;
92663
93065
  await wait2(deps.retryMs);
92664
93066
  const renewed = await deps.api.renewJob(deps.machineId, id);
92665
93067
  if (renewed.ok && renewed.value.renewed) lease.at = Date.now();
@@ -92700,14 +93102,14 @@ async function runSecret(job, deps) {
92700
93102
  await deps.api.finishJob(deps.machineId, job.id, "done", "");
92701
93103
  }
92702
93104
  async function runTest(job, deps) {
92703
- const finish2 = async (outcome, reason, ms3) => {
92704
- 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 });
92705
93107
  };
92706
93108
  const report2 = (await deps.runtimes()).find((r2) => r2.name === job.runtime);
92707
93109
  if (!report2?.installed) return finish2("failed", "not_installed");
92708
93110
  if (report2.loggedIn === false) return finish2("failed", "signed_out");
92709
- const cwd = path29.join(ownFolder(), "test");
92710
- fs26.mkdirSync(cwd, { recursive: true });
93111
+ const cwd = path32.join(ownFolder(), "test");
93112
+ fs29.mkdirSync(cwd, { recursive: true });
92711
93113
  const run2 = deps.plan(job.runtime, job.prompt, cwd, null, job.model, settingsOf(job));
92712
93114
  const startedAt = Date.now();
92713
93115
  if (run2.converse) {
@@ -92723,10 +93125,10 @@ async function runTest(job, deps) {
92723
93125
  ]);
92724
93126
  clearTimeout(timer);
92725
93127
  stop(child);
92726
- const ms3 = Date.now() - startedAt;
92727
- if (end === "timeout") return finish2("failed", "timeout", ms3);
92728
- if (end instanceof Error) return end.code === "ENOENT" ? finish2("failed", "not_installed") : finish2("failed", end.message.slice(0, 300), ms3);
92729
- 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);
92730
93132
  }
92731
93133
  const renderer = run2.renderer;
92732
93134
  const ended2 = await new Promise((resolve2) => {
@@ -92760,16 +93162,17 @@ async function runTest(job, deps) {
92760
93162
  resolve2({ code, said });
92761
93163
  });
92762
93164
  });
92763
- const ms2 = Date.now() - startedAt;
92764
- if (ended2.timedOut) return finish2("failed", "timeout", ms2);
93165
+ const ms = Date.now() - startedAt;
93166
+ if (ended2.timedOut) return finish2("failed", "timeout", ms);
92765
93167
  if (ended2.error?.code === "ENOENT") return finish2("failed", "not_installed");
92766
93168
  renderer.flush();
92767
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}.`);
92768
- if (failure) return finish2("failed", failure.slice(0, 300), ms2);
92769
- return finish2("done", "", ms2);
93170
+ if (failure) return finish2("failed", failure.slice(0, 300), ms);
93171
+ return finish2("done", "", ms);
92770
93172
  }
92771
- function report(run2, turn) {
93173
+ function report(job, run2, turn) {
92772
93174
  const context = turn ? turn.context : run2.renderer?.context?.();
93175
+ const limit = context?.limit ?? contextLimit(job.runtime, run2.model?.() ?? job.model ?? void 0);
92773
93176
  const usage = turn ? turn.usage : run2.renderer?.usage?.();
92774
93177
  const costUsd = turn ? turn.costUsd : run2.renderer?.costUsd?.();
92775
93178
  return {
@@ -92777,7 +93180,7 @@ function report(run2, turn) {
92777
93180
  session: run2.session(),
92778
93181
  ...usage ? { usage } : {},
92779
93182
  ...costUsd !== void 0 ? { costUsd } : {},
92780
- ...context?.used !== void 0 && context.limit ? { context: { used: context.used, limit: context.limit } } : {}
93183
+ ...context?.used !== void 0 && limit ? { context: { used: context.used, limit } } : {}
92781
93184
  };
92782
93185
  }
92783
93186
  var cutShort = (said, text3) => ({ ...said, reply: said.reply || text3 || void 0, stopped: true });
@@ -92856,9 +93259,10 @@ function keepPresence(machineId2, pingMs = PING_MS) {
92856
93259
  }
92857
93260
 
92858
93261
  // src/connect.ts
92859
- var HEARTBEAT_MS2 = 5 * 6e4;
93262
+ var HEARTBEAT_MS2 = 10 * 6e4;
92860
93263
  var POLL_MS = 6e4;
92861
93264
  var BACKOFF_MS3 = [1e3, 2e3, 5e3, 1e4, 3e4];
93265
+ var LOOK_LATE_MS = 6e4;
92862
93266
  function startRunner(options) {
92863
93267
  let registration = null;
92864
93268
  let connected = false;
@@ -92878,17 +93282,22 @@ function startRunner(options) {
92878
93282
  const base = options.deps ?? defaultDeps(registration.machineId);
92879
93283
  return { ...base, runtimes: () => base.runtimes().then(redetected) };
92880
93284
  };
93285
+ const register2 = async () => {
93286
+ const answer = await register(options.notify ? { ...registration, notify: options.notify() } : registration);
93287
+ if (answer.ok) void followAkb(answer.value.akb);
93288
+ return answer;
93289
+ };
92881
93290
  const redetected = async (found) => {
92882
93291
  if (closed || !registration || JSON.stringify(found) === JSON.stringify(registration.runtimes)) return found;
92883
93292
  registration = { ...registration, runtimes: found };
92884
- await register(options.notify ? { ...registration, notify: options.notify() } : registration);
93293
+ await register2();
92885
93294
  return found;
92886
93295
  };
92887
93296
  const idle2 = () => running.size ? t.running(running.size) : t.connected(registration.machineName);
92888
- const schedule = (ms2) => {
93297
+ const schedule = (ms) => {
92889
93298
  if (closed) return;
92890
93299
  if (timer) clearTimeout(timer);
92891
- timer = setTimeout(tick, ms2);
93300
+ timer = setTimeout(tick, ms);
92892
93301
  };
92893
93302
  let looking = false;
92894
93303
  const agentsDue = async () => {
@@ -92902,14 +93311,25 @@ function startRunner(options) {
92902
93311
  looking = false;
92903
93312
  }
92904
93313
  };
92905
- const agentsTimer = setInterval(() => void agentsDue(), options.agentsMs ?? AGENTS_EVERY_MS);
92906
- 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();
92907
93326
  let sweeping = false;
92908
93327
  let swept = false;
92909
93328
  const sweep = async () => {
92910
93329
  if (sweeping || closed || !registration) return;
92911
93330
  sweeping = true;
92912
93331
  try {
93332
+ sweepAkb();
92913
93333
  await sweepCache(registration.machineId);
92914
93334
  } catch (e2) {
92915
93335
  console.error(`runner: the cache was not cleaned: ${e2 instanceof Error ? e2.message : String(e2)}`);
@@ -92934,12 +93354,12 @@ function startRunner(options) {
92934
93354
  swept = true;
92935
93355
  void sweep();
92936
93356
  }
92937
- const answer = await register(options.notify ? { ...registration, notify: options.notify() } : registration);
93357
+ const answer = await register2();
92938
93358
  if (closed) return;
92939
93359
  if (!answer.ok) {
92940
93360
  if (answer.code === "runner_elsewhere") {
92941
- const held3 = await readRunner();
92942
- return finish2({ reason: "elsewhere", machine: held3.ok && held3.value.runner?.machineName || "?" });
93361
+ const held4 = await readRunner();
93362
+ return finish2({ reason: "elsewhere", machine: held4.ok && held4.value.runner?.machineName || "?" });
92943
93363
  }
92944
93364
  if (answer.code === "runner_outdated") return finish2({ reason: "outdated" });
92945
93365
  if (answer.code) return finish2({ reason: "refused", message: answer.error });
@@ -92962,7 +93382,6 @@ function startRunner(options) {
92962
93382
  await readJobs();
92963
93383
  if (!live?.joined()) boards?.pullAll();
92964
93384
  void reviewDue();
92965
- void agentsDue();
92966
93385
  schedule(live?.joined() ? options.heartbeatMs ?? HEARTBEAT_MS2 : Math.min(options.pollMs ?? POLL_MS, options.heartbeatMs ?? HEARTBEAT_MS2));
92967
93386
  };
92968
93387
  const openLive = () => {
@@ -93024,7 +93443,7 @@ function startRunner(options) {
93024
93443
  if (folder && "refused" in folder) return;
93025
93444
  const ws = openTaskFolder(job, folder?.cwd ?? null);
93026
93445
  const card = akbCardOf(ws);
93027
- if (card) await stopLeftBehind(deps().akb, ws, card, deps().stopMs);
93446
+ if (card) await stopLeftBehind(deps().akb(), ws, card, deps().stopMs);
93028
93447
  } catch (e2) {
93029
93448
  console.error(`runner: the runs left on job ${job.id}'s card were not stopped: ${e2 instanceof Error ? e2.message : String(e2)}`);
93030
93449
  }
@@ -93058,7 +93477,7 @@ function startRunner(options) {
93058
93477
  closed = true;
93059
93478
  lock.release();
93060
93479
  if (timer) clearTimeout(timer);
93061
- clearInterval(agentsTimer);
93480
+ if (agentsTimer) clearTimeout(agentsTimer);
93062
93481
  clearInterval(sweepTimer);
93063
93482
  live?.close();
93064
93483
  presence?.close();
@@ -93080,13 +93499,13 @@ function startRunner(options) {
93080
93499
 
93081
93500
  // src/desktop.ts
93082
93501
  import { spawnSync as spawnSync5 } from "node:child_process";
93083
- import fs27 from "node:fs";
93084
- import path30 from "node:path";
93502
+ import fs30 from "node:fs";
93503
+ import path33 from "node:path";
93085
93504
  import readline from "node:readline";
93086
93505
 
93087
93506
  // src/signin.ts
93088
93507
  import { spawn as spawn5 } from "node:child_process";
93089
- import crypto4 from "node:crypto";
93508
+ import crypto5 from "node:crypto";
93090
93509
  import http from "node:http";
93091
93510
  var WAIT_MS = 10 * 60 * 1e3;
93092
93511
  var CRANE = "M2 55.75C2 55.69 2.69 55.09 3.55 54.37L5.09 53.1L6.61 53.1L8.13 53.1L12.49 49.87C14.9 48.07 16.83 46.58 16.77 46.53C16.75 46.47 15.56 46.64 14.15 46.89C12.74 47.13 11.55 47.3 11.53 47.24C11.47 47.19 12.02 46.22 12.71 45.06L14.01 42.96L18.21 41.34C20.53 40.45 22.41 39.65 22.41 39.57C22.41 39.49 21.27 38.55 19.92 37.5C15.92 34.4 13.13 31.31 10.86 27.47L10.01 26.01L10.53 26.18C10.84 26.26 12.96 27.2 15.28 28.25C17.6 29.32 19.53 30.12 19.59 30.07C19.64 30.01 17.68 28.69 15.25 27.11C12.8 25.57 10.56 23.97 10.31 23.58C9.15 21.95 7.25 17.5 7.25 16.46C7.25 16.26 10.01 17.95 13.38 20.18C16.77 22.45 19.73 24.38 19.95 24.49C20.42 24.74 20.25 24.57 13.9 19.02L9.18 14.88L8.6 13.36C7.72 10.96 6.97 7.54 6.97 5.77L6.97 4.14L9.4 6.46C12.66 9.61 15.56 12.01 23.57 18.25C27.32 21.18 30.5 23.72 30.64 23.91C30.8 24.08 31.68 26.51 32.6 29.3L34.28 34.35L35.72 35.65C37.54 37.3 37.98 37.47 36.85 36.09L35.96 35.01L37.12 34.71C39.11 34.21 40.16 33.52 42.54 31.12L44.8 28.8L46.02 28.96C46.71 29.07 47.56 29.07 47.95 28.96L48.67 28.8L48.67 28.25L48.67 27.69L49.27 27.69C49.63 27.69 50.1 27.58 50.32 27.42L50.71 27.17L51.01 27.42C51.18 27.56 52.78 27.86 54.58 28.08C56.37 28.3 57.86 28.52 57.94 28.58C58 28.63 56.73 28.85 55.13 29.05C53.53 29.24 50.96 29.77 49.44 30.21C47.92 30.65 46.57 31.01 46.43 31.01C46.29 31.01 44.22 32.97 41.85 35.37C37.57 39.62 34.42 42.14 30.83 44.15L29.14 45.09L25.97 45.73L22.77 46.39L14.59 51.11L6.42 55.86L4.21 55.86C2.99 55.86 2 55.8 2 55.75Z";
@@ -93111,8 +93530,8 @@ var PAGE = (outcome, lang) => {
93111
93530
  return `<!doctype html><html lang="${lang === "zh" ? "zh-CN" : "en"}"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>${title} \xB7 WildCrane</title><style>*{margin:0;box-sizing:border-box}body{display:flex;flex-direction:column;min-height:100dvh;background:#fff;color:#24231f;font-family:ui-sans-serif,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif}header{padding:16px 36px 0}main{flex:1;display:flex;align-items:center;justify-content:center;padding:0 36px 64px;text-align:center}.icon{display:flex;margin:0 auto;width:44px;height:44px;border-radius:50%;align-items:center;justify-content:center;background:${ok ? "#e4f3ea" : "#f7ddce"};color:${ok ? "#2f6b46" : "#b83a12"}}h1{margin-top:16px;font-size:24px;font-weight:850;line-height:1.25;letter-spacing:-0.02em}p{margin:8px auto 0;max-width:38ch;font-size:13px;line-height:19px;color:#565550}</style><header><svg viewBox="2 4 56 52" width="23.7" height="22" aria-hidden="true"><path d="${CRANE}" fill="#24231f"/><path d="${CREST}" fill="#dd4f1e"/></svg></header><main><div><span class="icon"><svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">${icon}</svg></span><h1>${title}</h1><p>${body}</p></div></main></html>`;
93112
93531
  };
93113
93532
  async function signIn(options = {}) {
93114
- const verifier = base64url(crypto4.randomBytes(32));
93115
- const challenge = base64url(crypto4.createHash("sha256").update(verifier).digest());
93533
+ const verifier = base64url(crypto5.randomBytes(32));
93534
+ const challenge = base64url(crypto5.createHash("sha256").update(verifier).digest());
93116
93535
  let finish2 = () => {
93117
93536
  };
93118
93537
  const answered = new Promise((resolve2) => finish2 = resolve2);
@@ -93226,7 +93645,7 @@ async function runDesktop(tell2) {
93226
93645
  const shown = /* @__PURE__ */ new Set();
93227
93646
  let wake = () => {
93228
93647
  };
93229
- const readInbox3 = () => {
93648
+ const readInbox2 = () => {
93230
93649
  if (inboxTimer) clearTimeout(inboxTimer);
93231
93650
  inboxTimer = setTimeout(async () => {
93232
93651
  const inbox = await readInbox();
@@ -93261,12 +93680,12 @@ async function runDesktop(tell2) {
93261
93680
  const readProfile2 = async () => {
93262
93681
  const session = readSession();
93263
93682
  const profile = await readProfile();
93264
- const held3 = profile.ok ? profile.value.session : {};
93683
+ const held4 = profile.ok ? profile.value.session : {};
93265
93684
  emit({
93266
93685
  type: "account",
93267
- name: held3.name || held3.handle || session?.name || session?.handle || "",
93268
- email: held3.email || session?.email || "",
93269
- avatar: held3.avatarUrl || session?.avatarUrl || ""
93686
+ name: held4.name || held4.handle || session?.name || session?.handle || "",
93687
+ email: held4.email || session?.email || "",
93688
+ avatar: held4.avatarUrl || session?.avatarUrl || ""
93270
93689
  });
93271
93690
  };
93272
93691
  const readPlan2 = async () => {
@@ -93288,7 +93707,7 @@ async function runDesktop(tell2) {
93288
93707
  void readFolders();
93289
93708
  void readPlan2();
93290
93709
  void readAlerts();
93291
- readInbox3();
93710
+ readInbox2();
93292
93711
  };
93293
93712
  const onConnected = () => {
93294
93713
  tell2({ type: "connected" });
@@ -93326,17 +93745,17 @@ async function runDesktop(tell2) {
93326
93745
  notify = command.on;
93327
93746
  return runner?.renew();
93328
93747
  case "refresh":
93329
- readInbox3();
93748
+ readInbox2();
93330
93749
  return void readAlerts();
93331
93750
  case "read":
93332
93751
  await readAlert(command.alert);
93333
- return readInbox3();
93752
+ return readInbox2();
93334
93753
  case "addFolder": {
93335
93754
  const project = command.project;
93336
93755
  const why = refusal(command.path);
93337
93756
  if (why) return emit({ type: "folderRefused", why, project });
93338
- const real = fs27.realpathSync(command.path);
93339
- const added = await addFolder(id, path30.basename(real) || real, real, project);
93757
+ const real = fs30.realpathSync(command.path);
93758
+ const added = await addFolder(id, path33.basename(real) || real, real, project);
93340
93759
  if (!added.ok) {
93341
93760
  const taken = added.code === "folder_taken";
93342
93761
  return emit({ type: "folderRefused", why: taken ? "taken" : "failed", project, ...taken ? { taken: added.project } : {} });
@@ -93345,9 +93764,9 @@ async function runDesktop(tell2) {
93345
93764
  return readFolders();
93346
93765
  }
93347
93766
  case "removeFolder": {
93348
- const held3 = folders2.find((f2) => f2.project === command.project);
93767
+ const held4 = folders2.find((f2) => f2.project === command.project);
93349
93768
  const removed = await removeFolder(id, command.project);
93350
- if (removed.ok && held3) for (const dir of disallow(held3.path)) clearAkb(dir);
93769
+ if (removed.ok && held4) for (const dir of disallow(held4.path)) clearAkb(dir);
93351
93770
  return readFolders();
93352
93771
  }
93353
93772
  case "folderNotify":
@@ -93400,11 +93819,11 @@ async function runDesktop(tell2) {
93400
93819
  onDisconnected: () => emit({ type: "connection", state: "reconnecting" }),
93401
93820
  onHint: (payload) => {
93402
93821
  if (payload.alertId || !payload.taskId) void readAlerts();
93403
- if (!payload.jobId) readInbox3();
93822
+ if (!payload.jobId) readInbox2();
93404
93823
  }
93405
93824
  });
93406
93825
  poller = setInterval(() => {
93407
- readInbox3();
93826
+ readInbox2();
93408
93827
  void readAlerts();
93409
93828
  }, POLL_MS2);
93410
93829
  void runner.stopped.then(wake);