wildcrane-runner 0.6.8 → 0.6.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/runner.mjs CHANGED
@@ -1,4 +1,4 @@
1
- // wildcrane-runner 0.6.8 — built by runner/scripts/build.mjs. Do not edit.
1
+ // wildcrane-runner 0.6.9 — 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;
@@ -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 crypto6 = __require("crypto");
7520
+ var crypto7 = __require("crypto");
7521
7521
  var async_hooks = __require("async_hooks");
7522
7522
  var React4 = require_react();
7523
7523
  var ReactDOM = require_react_dom();
@@ -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 = crypto6.createHash("md5");
10385
+ componentKeyPath = crypto7.createHash("md5");
10386
10386
  componentKeyPath.update(permalink);
10387
10387
  return "k" + componentKeyPath.digest("hex");
10388
10388
  }
@@ -17474,9 +17474,9 @@ var require_react_dom_server_legacy_node_development = __commonJS({
17474
17474
  });
17475
17475
  return errorInfo;
17476
17476
  }
17477
- function encodeErrorForBoundary(boundary, digest, error, thrownInfo, wasAborted) {
17478
- boundary.errorDigest = digest;
17479
- isRecoverableError(error) ? boundary.errorMessage = wasAborted ? "Switched to client rendering because the server render was aborted with a request to render on the client." : "Switched to client rendering because a component requested it." : (error instanceof Error ? (digest = String(error.message), error = String(error.stack)) : (digest = "object" === typeof error && null !== error ? describeObjectForErrorMessage(error) : String(error), error = null), wasAborted = wasAborted ? "Switched to client rendering because the server rendering aborted due to:\n\n" : "Switched to client rendering because the server rendering errored:\n\n", boundary.errorMessage = wasAborted + digest, boundary.errorStack = null !== error ? wasAborted + error : null);
17477
+ function encodeErrorForBoundary(boundary, digest2, error, thrownInfo, wasAborted) {
17478
+ boundary.errorDigest = digest2;
17479
+ isRecoverableError(error) ? boundary.errorMessage = wasAborted ? "Switched to client rendering because the server render was aborted with a request to render on the client." : "Switched to client rendering because a component requested it." : (error instanceof Error ? (digest2 = String(error.message), error = String(error.stack)) : (digest2 = "object" === typeof error && null !== error ? describeObjectForErrorMessage(error) : String(error), error = null), wasAborted = wasAborted ? "Switched to client rendering because the server rendering aborted due to:\n\n" : "Switched to client rendering because the server rendering errored:\n\n", boundary.errorMessage = wasAborted + digest2, boundary.errorStack = null !== error ? wasAborted + error : null);
17480
17480
  boundary.errorComponentStack = thrownInfo.componentStack;
17481
17481
  }
17482
17482
  function logRecoverableError(request2, error, errorInfo, debugTask) {
@@ -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 = crypto6.createHash("md5");
24379
+ componentKeyPath = crypto7.createHash("md5");
24380
24380
  componentKeyPath.update(permalink);
24381
24381
  return "k" + componentKeyPath.digest("hex");
24382
24382
  }
@@ -25186,9 +25186,9 @@ var require_react_dom_server_node_development = __commonJS({
25186
25186
  });
25187
25187
  return errorInfo;
25188
25188
  }
25189
- function encodeErrorForBoundary(boundary, digest, error, thrownInfo, wasAborted) {
25190
- boundary.errorDigest = digest;
25191
- isRecoverableError(error) ? boundary.errorMessage = wasAborted ? "Switched to client rendering because the server render was aborted with a request to render on the client." : "Switched to client rendering because a component requested it." : (error instanceof Error ? (digest = String(error.message), error = String(error.stack)) : (digest = "object" === typeof error && null !== error ? describeObjectForErrorMessage(error) : String(error), error = null), wasAborted = wasAborted ? "Switched to client rendering because the server rendering aborted due to:\n\n" : "Switched to client rendering because the server rendering errored:\n\n", boundary.errorMessage = wasAborted + digest, boundary.errorStack = null !== error ? wasAborted + error : null);
25189
+ function encodeErrorForBoundary(boundary, digest2, error, thrownInfo, wasAborted) {
25190
+ boundary.errorDigest = digest2;
25191
+ isRecoverableError(error) ? boundary.errorMessage = wasAborted ? "Switched to client rendering because the server render was aborted with a request to render on the client." : "Switched to client rendering because a component requested it." : (error instanceof Error ? (digest2 = String(error.message), error = String(error.stack)) : (digest2 = "object" === typeof error && null !== error ? describeObjectForErrorMessage(error) : String(error), error = null), wasAborted = wasAborted ? "Switched to client rendering because the server rendering aborted due to:\n\n" : "Switched to client rendering because the server rendering errored:\n\n", boundary.errorMessage = wasAborted + digest2, boundary.errorStack = null !== error ? wasAborted + error : null);
25192
25192
  boundary.errorComponentStack = thrownInfo.componentStack;
25193
25193
  }
25194
25194
  function logRecoverableError(request2, error, errorInfo, debugTask) {
@@ -28038,7 +28038,7 @@ var require_react_dom_server_node_development = __commonJS({
28038
28038
  }
28039
28039
  };
28040
28040
  }
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(
28041
+ var util = __require("util"), crypto7 = __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(
@@ -41256,8 +41256,8 @@ var require_JSXTransformer = __commonJS({
41256
41256
  }
41257
41257
  if (this.isAutomaticRuntime) {
41258
41258
  if (this.importProcessor) {
41259
- for (const [path36, resolvedName] of Object.entries(this.cjsAutomaticModuleNameResolutions)) {
41260
- prefix += `var ${resolvedName} = require("${path36}");`;
41259
+ for (const [path37, resolvedName] of Object.entries(this.cjsAutomaticModuleNameResolutions)) {
41260
+ prefix += `var ${resolvedName} = require("${path37}");`;
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 path36 = this.jsxImportSource + importPathSuffix;
41454
- if (!this.cjsAutomaticModuleNameResolutions[path36]) {
41455
- this.cjsAutomaticModuleNameResolutions[path36] = this.importProcessor.getFreeIdentifierForPath(path36);
41453
+ const path37 = this.jsxImportSource + importPathSuffix;
41454
+ if (!this.cjsAutomaticModuleNameResolutions[path37]) {
41455
+ this.cjsAutomaticModuleNameResolutions[path37] = this.importProcessor.getFreeIdentifierForPath(path37);
41456
41456
  }
41457
- return `${this.cjsAutomaticModuleNameResolutions[path36]}.${funcName}`;
41457
+ return `${this.cjsAutomaticModuleNameResolutions[path37]}.${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 [path36, importInfo] of this.importInfoByPath.entries()) {
41893
+ for (const [path37, 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(path36, "");
41903
+ this.importsToReplace.set(path37, "");
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 [path36, importInfo] of this.importInfoByPath.entries()) {
41911
+ for (const [path37, 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(path36, `require('${path36}');`);
41921
+ this.importsToReplace.set(path37, `require('${path37}');`);
41922
41922
  continue;
41923
41923
  }
41924
- const primaryImportName = this.getFreeIdentifierForPath(path36);
41924
+ const primaryImportName = this.getFreeIdentifierForPath(path37);
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(path36);
41929
+ secondaryImportName = wildcardNames.length > 0 ? wildcardNames[0] : this.getFreeIdentifierForPath(path37);
41930
41930
  }
41931
- let requireCode = `var ${primaryImportName} = require('${path36}');`;
41931
+ let requireCode = `var ${primaryImportName} = require('${path37}');`;
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(path36, requireCode);
41959
+ this.importsToReplace.set(path37, 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(path36) {
41969
- const components = path36.split("/");
41968
+ getFreeIdentifierForPath(path37) {
41969
+ const components = path37.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 path36 = this.tokens.stringValueAtIndex(index);
42015
- const importInfo = this.getImportInfo(path36);
42014
+ const path37 = this.tokens.stringValueAtIndex(index);
42015
+ const importInfo = this.getImportInfo(path37);
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 path36 = this.tokens.stringValueAtIndex(index);
42083
- const importInfo = this.getImportInfo(path36);
42082
+ const path37 = this.tokens.stringValueAtIndex(index);
42083
+ const importInfo = this.getImportInfo(path37);
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 path36 = this.tokens.stringValueAtIndex(index);
42099
- const importInfo = this.getImportInfo(path36);
42098
+ const path37 = this.tokens.stringValueAtIndex(index);
42099
+ const importInfo = this.getImportInfo(path37);
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(path36) {
42140
- const existingInfo = this.importInfoByPath.get(path36);
42139
+ getImportInfo(path37) {
42140
+ const existingInfo = this.importInfoByPath.get(path37);
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(path36, newInfo);
42153
+ this.importInfoByPath.set(path37, 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 path36 = match[2];
42734
- return makeUrl("file:", "", match[1] || "", "", isAbsolutePath(path36) ? path36 : "/" + path36, match[3] || "", match[4] || "");
42733
+ const path37 = match[2];
42734
+ return makeUrl("file:", "", match[1] || "", "", isAbsolutePath(path37) ? path37 : "/" + path37, match[3] || "", match[4] || "");
42735
42735
  }
42736
- function makeUrl(scheme, user, host, port, path36, query, hash) {
42736
+ function makeUrl(scheme, user, host, port, path37, query, hash) {
42737
42737
  return {
42738
42738
  scheme,
42739
42739
  user,
42740
42740
  host,
42741
42741
  port,
42742
- path: path36,
42742
+ path: path37,
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(path36) {
42773
- if (path36.endsWith("/.."))
42774
- return path36;
42775
- const index = path36.lastIndexOf("/");
42776
- return path36.slice(0, index + 1);
42772
+ function stripPathFilename(path37) {
42773
+ if (path37.endsWith("/.."))
42774
+ return path37;
42775
+ const index = path37.lastIndexOf("/");
42776
+ return path37.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 path36 = "";
42814
+ let path37 = "";
42815
42815
  for (let i = 1; i < pointer; i++) {
42816
- path36 += "/" + pieces[i];
42816
+ path37 += "/" + pieces[i];
42817
42817
  }
42818
- if (!path36 || addTrailingSlash && !path36.endsWith("/..")) {
42819
- path36 += "/";
42818
+ if (!path37 || addTrailingSlash && !path37.endsWith("/..")) {
42819
+ path37 += "/";
42820
42820
  }
42821
- url.path = path36;
42821
+ url.path = path37;
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 path36 = url.path.slice(1);
42863
- if (!path36)
42862
+ const path37 = url.path.slice(1);
42863
+ if (!path37)
42864
42864
  return queryHash || ".";
42865
- if (isRelative(base || input) && !isRelative(path36)) {
42866
- return "./" + path36 + queryHash;
42865
+ if (isRelative(base || input) && !isRelative(path37)) {
42866
+ return "./" + path37 + queryHash;
42867
42867
  }
42868
- return path36 + queryHash;
42868
+ return path37 + 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(path36) {
42968
- if (!path36) return "";
42969
- const index = path36.lastIndexOf("/");
42970
- return path36.slice(0, index + 1);
42967
+ function stripFilename(path37) {
42968
+ if (!path37) return "";
42969
+ const index = path37.lastIndexOf("/");
42970
+ return path37.slice(0, index + 1);
42971
42971
  }
42972
42972
  function resolver(mapUrl, sourceRoot) {
42973
42973
  const from = stripFilename(mapUrl);
@@ -44175,9 +44175,9 @@ var require_util2 = __commonJS({
44175
44175
  /** @class */
44176
44176
  (function(_super) {
44177
44177
  __extends(VError2, _super);
44178
- function VError2(path36, message) {
44178
+ function VError2(path37, message) {
44179
44179
  var _this = _super.call(this, message) || this;
44180
- _this.path = path36;
44180
+ _this.path = path37;
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(path36) {
44240
+ DetailContext2.prototype.getError = function(path37) {
44241
44241
  var msgParts = [];
44242
44242
  for (var i = this._propNames.length - 1; i >= 0; i--) {
44243
44243
  var p2 = this._propNames[i];
44244
- path36 += typeof p2 === "number" ? "[" + p2 + "]" : p2 ? "." + p2 : "";
44244
+ path37 += typeof p2 === "number" ? "[" + p2 + "]" : p2 ? "." + p2 : "";
44245
44245
  var m = this._messages[i];
44246
44246
  if (m) {
44247
- msgParts.push(path36 + " " + m);
44247
+ msgParts.push(path37 + " " + m);
44248
44248
  }
44249
44249
  }
44250
- return new VError(path36, msgParts.join("; "));
44250
+ return new VError(path37, msgParts.join("; "));
44251
44251
  };
44252
- DetailContext2.prototype.getErrorDetail = function(path36) {
44252
+ DetailContext2.prototype.getErrorDetail = function(path37) {
44253
44253
  var details = [];
44254
44254
  for (var i = this._propNames.length - 1; i >= 0; i--) {
44255
44255
  var p2 = this._propNames[i];
44256
- path36 += typeof p2 === "number" ? "[" + p2 + "]" : p2 ? "." + p2 : "";
44256
+ path37 += typeof p2 === "number" ? "[" + p2 + "]" : p2 ? "." + p2 : "";
44257
44257
  var message = this._messages[i];
44258
44258
  if (message) {
44259
- details.push({ path: path36, message });
44259
+ details.push({ path: path37, 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(path36) {
45073
- this._path = path36;
45072
+ Checker2.prototype.setReportedPath = function(path37) {
45073
+ this._path = path37;
45074
45074
  };
45075
45075
  Checker2.prototype.check = function(value) {
45076
45076
  return this._doCheck(this.checkerPlain, value);
@@ -50503,9 +50503,9 @@ var require_CJSImportTransformer = __commonJS({
50503
50503
  if (shouldElideImport) {
50504
50504
  this.tokens.removeToken();
50505
50505
  } else {
50506
- const path36 = this.tokens.stringValue();
50507
- this.tokens.replaceTokenTrimmingLeftWhitespace(this.importProcessor.claimImportCode(path36));
50508
- this.tokens.appendCode(this.importProcessor.claimImportCode(path36));
50506
+ const path37 = this.tokens.stringValue();
50507
+ this.tokens.replaceTokenTrimmingLeftWhitespace(this.importProcessor.claimImportCode(path37));
50508
+ this.tokens.appendCode(this.importProcessor.claimImportCode(path37));
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 path36 = this.tokens.stringValue();
51089
- this.tokens.replaceTokenTrimmingLeftWhitespace(this.importProcessor.claimImportCode(path36));
51088
+ const path37 = this.tokens.stringValue();
51089
+ this.tokens.replaceTokenTrimmingLeftWhitespace(this.importProcessor.claimImportCode(path37));
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 path36 = this.tokens.stringValue();
51104
- this.tokens.replaceTokenTrimmingLeftWhitespace(this.importProcessor.claimImportCode(path36));
51103
+ const path37 = this.tokens.stringValue();
51104
+ this.tokens.replaceTokenTrimmingLeftWhitespace(this.importProcessor.claimImportCode(path37));
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, path36) => {
80748
+ getPart = (classPartObject, path37) => {
80749
80749
  let current = classPartObject;
80750
- const parts = path36.split(CLASS_PART_SEPARATOR);
80750
+ const parts = path37.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];
@@ -84435,9 +84435,9 @@ function status(line) {
84435
84435
  }
84436
84436
 
84437
84437
  // src/protocol.ts
84438
- var VERSION = true ? "0.6.8" : "0.0.0";
84439
- var AKB_VERSION = true ? "0.11.7" : "0.0.0";
84440
- var AKB_CONTRACT = true ? 3 : 0;
84438
+ var VERSION = true ? "0.6.9" : "0.0.0";
84439
+ var AKB_VERSION = true ? "0.11.8" : "0.0.0";
84440
+ var AKB_CONTRACT = true ? 4 : 0;
84441
84441
  var EXIT_REFUSED = 10;
84442
84442
  var EXIT_OUTDATED = 11;
84443
84443
  var EXIT_UPDATE = 12;
@@ -85292,10 +85292,10 @@ function findRollout(threadId) {
85292
85292
  }
85293
85293
  for (const name of names2) {
85294
85294
  if (!name.startsWith("rollout-") || !name.endsWith(tail)) continue;
85295
- const path36 = join(dir, name);
85295
+ const path37 = join(dir, name);
85296
85296
  try {
85297
- const at2 = statSync(path36).mtimeMs;
85298
- if (!newest2 || at2 > newest2.at) newest2 = { path: path36, at: at2 };
85297
+ const at2 = statSync(path37).mtimeMs;
85298
+ if (!newest2 || at2 > newest2.at) newest2 = { path: path37, at: at2 };
85299
85299
  } catch {
85300
85300
  }
85301
85301
  }
@@ -85303,11 +85303,11 @@ function findRollout(threadId) {
85303
85303
  return newest2?.path;
85304
85304
  }
85305
85305
  function readCodexRunFacts(threadId) {
85306
- const path36 = findRollout(threadId);
85307
- if (!path36) return void 0;
85306
+ const path37 = findRollout(threadId);
85307
+ if (!path37) return void 0;
85308
85308
  let raw;
85309
85309
  try {
85310
- raw = readFileSync(path36, "utf8");
85310
+ raw = readFileSync(path37, "utf8");
85311
85311
  } catch {
85312
85312
  return void 0;
85313
85313
  }
@@ -85415,8 +85415,8 @@ function renderCompleted(item) {
85415
85415
  const changes = Array.isArray(item.changes) ? item.changes : [];
85416
85416
  return changes.map((raw) => {
85417
85417
  const change = obj(raw);
85418
- const path36 = str(change.path);
85419
- return path36 ? `\u23FA ${str(change.kind) || "change"}(${path36})
85418
+ const path37 = str(change.path);
85419
+ return path37 ? `\u23FA ${str(change.kind) || "change"}(${path37})
85420
85420
  ` : "";
85421
85421
  }).join("");
85422
85422
  }
@@ -85664,10 +85664,10 @@ function readKimiRunFacts(sessionId) {
85664
85664
  const total = { input: 0, cacheCreation: 0, cacheRead: 0, output: 0 };
85665
85665
  let model;
85666
85666
  let holding = 0;
85667
- for (const { path: path36, main: main2 } of wireFiles(entry.sessionDir)) {
85667
+ for (const { path: path37, main: main2 } of wireFiles(entry.sessionDir)) {
85668
85668
  let raw;
85669
85669
  try {
85670
- raw = readFileSync2(path36, "utf8");
85670
+ raw = readFileSync2(path37, "utf8");
85671
85671
  } catch {
85672
85672
  continue;
85673
85673
  }
@@ -85923,8 +85923,8 @@ function createTail(log) {
85923
85923
  // ../cli/package.json
85924
85924
  var package_default = {
85925
85925
  name: "wildcrane",
85926
- version: "0.11.7",
85927
- akbContract: 3,
85926
+ version: "0.11.8",
85927
+ akbContract: 4,
85928
85928
  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.",
85929
85929
  keywords: [
85930
85930
  "kanban",
@@ -85985,8 +85985,8 @@ var CLIENT_CAPABILITIES = {
85985
85985
  };
85986
85986
  function whereHint(update2, title) {
85987
85987
  const locations = Array.isArray(update2.locations) ? update2.locations : [];
85988
- const path36 = str(obj(locations[0]).path);
85989
- return path36 && !title.includes(path36) ? hint(path36) : "";
85988
+ const path37 = str(obj(locations[0]).path);
85989
+ return path37 && !title.includes(path37) ? hint(path37) : "";
85990
85990
  }
85991
85991
  function saidBy(update2) {
85992
85992
  const content = Array.isArray(update2.content) ? update2.content : [];
@@ -88025,6 +88025,7 @@ var DEFAULT_HARNESS = HARNESSES[0];
88025
88025
  checkHarnesses(HARNESSES);
88026
88026
 
88027
88027
  // ../cli/src/lib/agent/env.ts
88028
+ var RUN_ENV = "KANBAN_RUN";
88028
88029
  var SCHEDULED_AGENTS_ENV = "AI4KANBAN_SCHEDULED_AGENTS";
88029
88030
  var SESSION_VARS = {
88030
88031
  "claude-code": "CLAUDE_CODE_SESSION_ID",
@@ -88227,7 +88228,7 @@ var secretsSet = () => Object.fromEntries(Object.entries(readAll()).map(([id, ke
88227
88228
 
88228
88229
  // src/api.ts
88229
88230
  var RUNTIMES = ["claude-code", "codex", "cursor", "opencode", "kimi", "dsh", "zcode", "grok"];
88230
- var PROTOCOL = 11;
88231
+ var PROTOCOL = 12;
88231
88232
  var TIMEOUT_MS = 2e4;
88232
88233
  async function send(method, route, body, signedIn, ms, type) {
88233
88234
  const headers = { accept: "application/json" };
@@ -88314,7 +88315,7 @@ var listFolders = (machineId2) => request("GET", `/v1/runner/folders?machine=${q
88314
88315
  var listElsewhere = (machineId2) => request("GET", `/v1/runner/folders?machine=${q(machineId2)}&elsewhere=1`);
88315
88316
  var listMachineTasks = (machineId2) => request("GET", `/v1/runner/tasks?machine=${q(machineId2)}`);
88316
88317
  var stopTask = (task, how) => request("POST", how === "chat" ? `/v1/tasks/${q(task)}/chat/stop` : `/v1/tasks/${q(task)}/stop`, {});
88317
- var addFolder = (machineId2, name, path36, project) => request("POST", "/v1/runner/folders", { machineId: machineId2, name, path: path36, ...project ? { project } : {} });
88318
+ var addFolder = (machineId2, name, path37, project) => request("POST", "/v1/runner/folders", { machineId: machineId2, name, path: path37, ...project ? { project } : {} });
88318
88319
  var removeFolder = (machineId2, project) => request("POST", `/v1/runner/folders/${q(project)}/remove`, { machineId: machineId2 });
88319
88320
  var readBoard = (project, since) => request("GET", `/v1/projects/${q(project)}/board${since === null ? "" : `?since=${since}`}`);
88320
88321
  async function commitBoard(project, job, machine, files) {
@@ -88882,7 +88883,7 @@ exec ${line} "$@"
88882
88883
  }
88883
88884
  function akbEnv(akb, board, task, line) {
88884
88885
  const env2 = {};
88885
- const dropped = ["AI4KANBAN_BOARD", "AI4KANBAN_TASK", LANGUAGE_LINE_ENV, SCHEDULED_AGENTS_ENV];
88886
+ const dropped = ["AI4KANBAN_BOARD", "AI4KANBAN_TASK", "AI4KANBAN_EXECUTION", LANGUAGE_LINE_ENV, SCHEDULED_AGENTS_ENV];
88886
88887
  for (const [k, v2] of Object.entries(process.env)) if (!k.startsWith("KANBAN_") && !dropped.includes(k)) env2[k] = v2;
88887
88888
  const key = Object.keys(env2).find((k) => k.toUpperCase() === "PATH") ?? "PATH";
88888
88889
  env2[key] = [shimDir(akb), env2[key]].filter(Boolean).join(path14.delimiter);
@@ -88903,7 +88904,7 @@ function runAkb(akb, args, opts) {
88903
88904
  };
88904
88905
  let child;
88905
88906
  try {
88906
- 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"] });
88907
+ child = spawn3(akb.command, [...akb.args, ...args], { cwd: opts.cwd, env: { ...akbEnv(akb, opts.board, opts.task, opts.line), ...opts.env }, detached: process.platform !== "win32", stdio: ["ignore", "pipe", "pipe"] });
88907
88908
  } catch (e2) {
88908
88909
  return resolve2({ code: null, out: "", last: e2 instanceof Error ? e2.message : String(e2) });
88909
88910
  }
@@ -89462,22 +89463,22 @@ import path24 from "node:path";
89462
89463
  // ../cloud/src/board-files.ts
89463
89464
  var ROOTS = ["todo/", ".archive/", "memory/", "workflows/", "triage/", "assets/", "rules/"];
89464
89465
  var SETTINGS = ["modules.md", "config.md"];
89465
- var isSettingsPath = (path36) => SETTINGS.includes(path36) || /^rules\/(?:workflows\/)?[^/]+\.md$/.test(path36);
89466
+ var isSettingsPath = (path37) => SETTINGS.includes(path37) || /^rules\/(?:workflows\/)?[^/]+\.md$/.test(path37);
89466
89467
  var BOARD_FILE_LIMIT = 256 * 1024;
89467
- function isBoardPath(path36) {
89468
- if (!path36 || path36.length > 500 || path36.startsWith("/") || path36.includes("\\") || path36.includes("\0")) return false;
89469
- if (path36.split("/").some((part) => !part || part === "." || part === "..")) return false;
89470
- if (path36 === "todo/README.md" || path36.split("/").includes(".sync")) return false;
89471
- if (path36.startsWith("workflows/")) return true;
89472
- if (SETTINGS.includes(path36)) return true;
89473
- if (path36.startsWith("rules/")) return isSettingsPath(path36);
89474
- if (path36.startsWith("assets/")) return path36.endsWith(".json");
89475
- return ROOTS.some((root) => path36.startsWith(root)) && path36.endsWith(".md");
89468
+ function isBoardPath(path37) {
89469
+ if (!path37 || path37.length > 500 || path37.startsWith("/") || path37.includes("\\") || path37.includes("\0")) return false;
89470
+ if (path37.split("/").some((part) => !part || part === "." || part === "..")) return false;
89471
+ if (path37 === "todo/README.md" || path37.split("/").includes(".sync")) return false;
89472
+ if (path37.startsWith("workflows/")) return true;
89473
+ if (SETTINGS.includes(path37)) return true;
89474
+ if (path37.startsWith("rules/")) return isSettingsPath(path37);
89475
+ if (path37.startsWith("assets/")) return path37.endsWith(".json");
89476
+ return ROOTS.some((root) => path37.startsWith(root)) && path37.endsWith(".md");
89476
89477
  }
89477
89478
  var CARD = /^(?:todo|\.archive)\/(?:[^/]+\/)*(\d+)-[^/]*\.md$/;
89478
89479
  var ROOT = /^(?:todo|\.archive)\/(?:[^/]+\/)*(\d+)-[^/]+\/root\.md$/;
89479
- function numberOfCard(path36) {
89480
- const n = ROOT.exec(path36)?.[1] ?? CARD.exec(path36)?.[1];
89480
+ function numberOfCard(path37) {
89481
+ const n = ROOT.exec(path37)?.[1] ?? CARD.exec(path37)?.[1];
89481
89482
  return n ? Number(n) : null;
89482
89483
  }
89483
89484
  var cardSlug = (task) => task.toLowerCase().replace(/_/g, "-");
@@ -89751,8 +89752,8 @@ function unquote2(v2) {
89751
89752
 
89752
89753
  // ../cloud/src/triage-files.ts
89753
89754
  var ITEM = /^triage\/(?:(dismissed|archived)\/)?([^/]+)\.md$/;
89754
- function itemAt(path36) {
89755
- const m = ITEM.exec(path36);
89755
+ function itemAt(path37) {
89756
+ const m = ITEM.exec(path37);
89756
89757
  if (!m) return null;
89757
89758
  return { state: m[1] === "dismissed" ? "dismissed" : m[1] === "archived" ? "carded" : "open", name: m[2] };
89758
89759
  }
@@ -90581,17 +90582,17 @@ function openCached(project) {
90581
90582
  const dir = cacheDir(project);
90582
90583
  if (fs20.existsSync(path23.join(dir, ".git"))) return dir;
90583
90584
  fs20.mkdirSync(dir, { recursive: true });
90584
- const git3 = (...args) => spawnSync4("git", ["-C", dir, ...args], { encoding: "utf8" }).status === 0;
90585
- if (git3("init", "-q")) git3("-c", "user.name=WildCrane", "-c", "user.email=runner@wildcrane.ai", "commit", "-q", "--allow-empty", "-m", "general");
90585
+ const git4 = (...args) => spawnSync4("git", ["-C", dir, ...args], { encoding: "utf8" }).status === 0;
90586
+ if (git4("init", "-q")) git4("-c", "user.name=WildCrane", "-c", "user.email=runner@wildcrane.ai", "commit", "-q", "--allow-empty", "-m", "general");
90586
90587
  return dir;
90587
90588
  }
90588
90589
  var SKILL_FOLDERS = [".claude/skills/kanban", ".agents/skills/kanban"];
90589
90590
  var SKILL_ROOTS = [".claude/skills", ".agents/skills"];
90590
90591
  function keepOutOfGit(dir, folders2 = SKILL_FOLDERS) {
90591
- const git3 = (...args) => spawnSync4("git", ["-C", dir, ...args], { encoding: "utf8" });
90592
- const inside = git3("rev-parse", "--git-path", "info/exclude");
90592
+ const git4 = (...args) => spawnSync4("git", ["-C", dir, ...args], { encoding: "utf8" });
90593
+ const inside = git4("rev-parse", "--git-path", "info/exclude");
90593
90594
  if (inside.status !== 0) return;
90594
- const missing = [".akb/", ...folders2.map((f2) => `${f2}/`)].filter((p2) => git3("check-ignore", "-q", p2).status !== 0);
90595
+ const missing = [".akb/", ...folders2.map((f2) => `${f2}/`)].filter((p2) => git4("check-ignore", "-q", p2).status !== 0);
90595
90596
  if (!missing.length) return;
90596
90597
  const exclude = path23.resolve(dir, inside.stdout.trim());
90597
90598
  fs20.mkdirSync(path23.dirname(exclude), { recursive: true });
@@ -91393,8 +91394,113 @@ async function answerHint(machineId2, hint2) {
91393
91394
  if (!sent.ok) console.error(`runner: the diff of ${commit.slice(0, 7)} was not sent: ${sent.error}`);
91394
91395
  }
91395
91396
 
91397
+ // ../cli/src/lib/agent/stop.ts
91398
+ import { spawnSync as spawnSync5 } from "node:child_process";
91399
+ import fs23 from "node:fs";
91400
+ var runMark = (sessionId) => ({ name: RUN_ENV, value: sessionId });
91401
+ var WINDOWS3 = process.platform === "win32";
91402
+ function markedInProc(entry, strict = false) {
91403
+ const pids = [];
91404
+ for (const name of fs23.readdirSync("/proc")) {
91405
+ if (!/^\d+$/.test(name)) continue;
91406
+ try {
91407
+ if (fs23.readFileSync(`/proc/${name}/environ`, "utf8").split("\0").includes(entry)) pids.push(Number(name));
91408
+ } catch (error) {
91409
+ if (strict && !["ENOENT", "ESRCH"].includes(error.code ?? "")) {
91410
+ const stat = fs23.statSync(`/proc/${name}`, { throwIfNoEntry: false });
91411
+ if (stat?.uid === process.getuid?.()) throw error;
91412
+ }
91413
+ }
91414
+ }
91415
+ return pids;
91416
+ }
91417
+ function markedInPs(entry, roots) {
91418
+ const ps = spawnSync5("ps", ["-A", "-E", "-ww", "-o", "pid=,ppid=,command="], {
91419
+ encoding: "utf8",
91420
+ maxBuffer: 64 * 1024 * 1024,
91421
+ timeout: 5e3
91422
+ });
91423
+ if (ps.status !== 0 || !ps.stdout) throw new Error("\u65E0\u6CD5\u67E5\u8BE2\u8FDB\u7A0B\u6811\u3002");
91424
+ const children = /* @__PURE__ */ new Map();
91425
+ const listed2 = /* @__PURE__ */ new Set();
91426
+ const found = /* @__PURE__ */ new Set();
91427
+ for (const line of ps.stdout.split("\n")) {
91428
+ const m = /^\s*(\d+)\s+(\d+)\s(.*)$/.exec(line);
91429
+ if (!m) continue;
91430
+ const pid = Number(m[1]);
91431
+ const ppid = Number(m[2]);
91432
+ listed2.add(pid);
91433
+ children.set(ppid, [...children.get(ppid) ?? [], pid]);
91434
+ if (`${m[3]} `.includes(` ${entry} `)) found.add(pid);
91435
+ }
91436
+ const queue = [...found, ...roots.filter((pid) => listed2.has(pid))];
91437
+ for (const pid of queue) {
91438
+ found.add(pid);
91439
+ for (const child of children.get(pid) ?? []) if (!found.has(child)) queue.push(child);
91440
+ }
91441
+ return [...found];
91442
+ }
91443
+ function startedUnder(list, root, since) {
91444
+ const self2 = list.procs.find((p2) => p2.pid === root);
91445
+ const from = since ?? self2?.startedAt;
91446
+ if (from === void 0 || list.bootedAt > from) return [];
91447
+ if (self2 && self2.startedAt > from) return [];
91448
+ const found = self2 ? [root] : [];
91449
+ const seen = /* @__PURE__ */ new Set([root]);
91450
+ const queue = [{ pid: root, startedAt: from }];
91451
+ for (const parent of queue) {
91452
+ for (const p2 of list.procs) {
91453
+ if (p2.ppid !== parent.pid || seen.has(p2.pid) || p2.startedAt < parent.startedAt) continue;
91454
+ seen.add(p2.pid);
91455
+ found.push(p2.pid);
91456
+ queue.push(p2);
91457
+ }
91458
+ }
91459
+ return found.reverse();
91460
+ }
91461
+ var LIST_PROCS = [
91462
+ "$ErrorActionPreference = 'Stop'",
91463
+ "Get-CimInstance Win32_Process | ForEach-Object { if ($_.CreationDate) { '{0} {1} {2}' -f $_.ProcessId, $_.ParentProcessId, ([DateTimeOffset]$_.CreationDate).ToUnixTimeMilliseconds() } }",
91464
+ "'boot {0}' -f ([DateTimeOffset](Get-CimInstance Win32_OperatingSystem).LastBootUpTime).ToUnixTimeMilliseconds()"
91465
+ ].join("; ");
91466
+ function readProcList(out) {
91467
+ const procs = [];
91468
+ let bootedAt;
91469
+ for (const line of out.split(/\r?\n/)) {
91470
+ const boot = /^boot (\d+)$/.exec(line.trim());
91471
+ if (boot) bootedAt = Number(boot[1]);
91472
+ const m = /^(\d+) (\d+) (\d+)$/.exec(line.trim());
91473
+ if (m) procs.push({ pid: Number(m[1]), ppid: Number(m[2]), startedAt: Number(m[3]) });
91474
+ }
91475
+ return bootedAt !== void 0 && procs.length ? { procs, bootedAt } : void 0;
91476
+ }
91477
+ function procsOnWindows() {
91478
+ const ps = spawnSync5("powershell.exe", ["-NoProfile", "-NonInteractive", "-Command", LIST_PROCS], {
91479
+ encoding: "utf8",
91480
+ maxBuffer: 64 * 1024 * 1024,
91481
+ timeout: 5e3,
91482
+ windowsHide: true
91483
+ });
91484
+ return ps.status === 0 && ps.stdout ? readProcList(ps.stdout) : void 0;
91485
+ }
91486
+ function processesStopped(mark, root) {
91487
+ try {
91488
+ if (WINDOWS3) {
91489
+ const list = procsOnWindows();
91490
+ if (!list || !root) return false;
91491
+ const current = list.procs.find((p2) => p2.pid === root.pid);
91492
+ if (current && current.startedAt > root.since) return false;
91493
+ return startedUnder(list, root.pid, root.since).length === 0;
91494
+ }
91495
+ const entry = `${mark.name}=${mark.value}`;
91496
+ return (process.platform === "linux" ? markedInProc(entry, true) : markedInPs(entry, root ? [root.pid] : [])).length === 0;
91497
+ } catch {
91498
+ return false;
91499
+ }
91500
+ }
91501
+
91396
91502
  // src/flow.ts
91397
- import fs27 from "node:fs";
91503
+ import fs28 from "node:fs";
91398
91504
  import path30 from "node:path";
91399
91505
 
91400
91506
  // ../cli/src/lib/question-block.ts
@@ -91553,7 +91659,7 @@ function reviewOf(meta) {
91553
91659
  }
91554
91660
 
91555
91661
  // src/triage.ts
91556
- import fs23 from "node:fs";
91662
+ import fs24 from "node:fs";
91557
91663
  import path26 from "node:path";
91558
91664
 
91559
91665
  // ../cli/src/lib/signals/identity.ts
@@ -91578,7 +91684,7 @@ function slugOf(title) {
91578
91684
  function freeName(dir, title) {
91579
91685
  const stem = slugOf(title);
91580
91686
  let name = `${stem}.md`;
91581
- for (let n = 2; fs23.existsSync(path26.join(dir, name)); n++) name = `${stem}-${n}.md`;
91687
+ for (let n = 2; fs24.existsSync(path26.join(dir, name)); n++) name = `${stem}-${n}.md`;
91582
91688
  return name;
91583
91689
  }
91584
91690
  function itemText(item, fields = {}) {
@@ -91598,17 +91704,17 @@ ${item.text.trim()}
91598
91704
  `;
91599
91705
  }
91600
91706
  function writeItem(dir, item, fields = {}) {
91601
- fs23.mkdirSync(dir, { recursive: true });
91707
+ fs24.mkdirSync(dir, { recursive: true });
91602
91708
  const name = freeName(dir, item.title);
91603
- fs23.writeFileSync(path26.join(dir, name), itemText(item, item.workflow ? { workflow: workflowName(item.workflow), ...fields } : fields));
91709
+ fs24.writeFileSync(path26.join(dir, name), itemText(item, item.workflow ? { workflow: workflowName(item.workflow), ...fields } : fields));
91604
91710
  return name;
91605
91711
  }
91606
91712
  function layOut(board, rejections) {
91607
91713
  clearLaid(board);
91608
91714
  const dir = rejectedDir(board);
91609
- fs23.mkdirSync(dir, { recursive: true });
91715
+ fs24.mkdirSync(dir, { recursive: true });
91610
91716
  for (const t2 of rejections.tasks) {
91611
- fs23.writeFileSync(path26.join(dir, `${t2.number}-${slugify(t2.title)}.md`), [
91717
+ fs24.writeFileSync(path26.join(dir, `${t2.number}-${slugify(t2.title)}.md`), [
91612
91718
  "---",
91613
91719
  `title: ${yamlScalar(t2.title)}`,
91614
91720
  "status: todo",
@@ -91630,12 +91736,12 @@ function layOut(board, rejections) {
91630
91736
  return { tasks: rejections.tasks.map((t2) => t2.id), triage: rejections.triage.map((i) => i.id) };
91631
91737
  }
91632
91738
  function clearLaid(board) {
91633
- fs23.rmSync(rejectedDir(board), { recursive: true, force: true });
91634
- for (const sub of SCRATCH) fs23.rmSync(path26.join(triageDir(board), sub), { recursive: true, force: true });
91739
+ fs24.rmSync(rejectedDir(board), { recursive: true, force: true });
91740
+ for (const sub of SCRATCH) fs24.rmSync(path26.join(triageDir(board), sub), { recursive: true, force: true });
91635
91741
  }
91636
91742
 
91637
91743
  // src/kanban-skill.ts
91638
- import fs24 from "node:fs";
91744
+ import fs25 from "node:fs";
91639
91745
  import path27 from "node:path";
91640
91746
 
91641
91747
  // ../skill/SKILL.md
@@ -91656,17 +91762,17 @@ function prepareKanbanSkill(root) {
91656
91762
  let at2 = root;
91657
91763
  for (const name of `${folder}/SKILL.md`.split("/")) {
91658
91764
  at2 = path27.join(at2, name);
91659
- if (fs24.lstatSync(at2, { throwIfNoEntry: false })?.isSymbolicLink()) linked = true;
91765
+ if (fs25.lstatSync(at2, { throwIfNoEntry: false })?.isSymbolicLink()) linked = true;
91660
91766
  }
91661
- const held4 = fs24.existsSync(file2) ? fs24.readFileSync(file2, "utf8") : null;
91662
- const exists = fs24.lstatSync(dir, { throwIfNoEntry: false }) !== void 0;
91767
+ const held4 = fs25.existsSync(file2) ? fs25.readFileSync(file2, "utf8") : null;
91768
+ const exists = fs25.lstatSync(dir, { throwIfNoEntry: false }) !== void 0;
91663
91769
  if (linked || exists && !MANAGED.test(held4 ?? "")) {
91664
91770
  if (!held4?.trim()) throw new Error("\u7528\u6237\u81EA\u6709\u76EE\u5F55\u6216\u7B26\u53F7\u94FE\u63A5\u4E2D\u7F3A\u5C11\u53EF\u8BFB\u7684 SKILL.md");
91665
91771
  continue;
91666
91772
  }
91667
91773
  if (held4 !== CONTENT) {
91668
- fs24.mkdirSync(dir, { recursive: true });
91669
- fs24.writeFileSync(file2, CONTENT);
91774
+ fs25.mkdirSync(dir, { recursive: true });
91775
+ fs25.writeFileSync(file2, CONTENT);
91670
91776
  }
91671
91777
  } catch (e2) {
91672
91778
  throw new Error(`\u65E0\u6CD5\u51C6\u5907 ${folder}\uFF1A${e2 instanceof Error ? e2.message : String(e2)}`);
@@ -91675,8 +91781,8 @@ function prepareKanbanSkill(root) {
91675
91781
  }
91676
91782
 
91677
91783
  // ../cli/src/lib/skill/hook.ts
91678
- import { spawnSync as spawnSync5 } from "node:child_process";
91679
- import fs25 from "node:fs";
91784
+ import { spawnSync as spawnSync6 } from "node:child_process";
91785
+ import fs26 from "node:fs";
91680
91786
  import path28 from "node:path";
91681
91787
  var MARKER = "# ai4kanban commit guard";
91682
91788
  var MARKER_LINE = new RegExp(`^${MARKER}\\b`, "m");
@@ -91711,13 +91817,13 @@ function hookScript(sessions) {
91711
91817
  }
91712
91818
  var read = (file2) => {
91713
91819
  try {
91714
- return fs25.readFileSync(file2, "utf8");
91820
+ return fs26.readFileSync(file2, "utf8");
91715
91821
  } catch {
91716
91822
  return null;
91717
91823
  }
91718
91824
  };
91719
91825
  function hooksDir(root) {
91720
- const out = spawnSync5("git", ["rev-parse", "--git-path", "hooks"], {
91826
+ const out = spawnSync6("git", ["rev-parse", "--git-path", "hooks"], {
91721
91827
  cwd: root,
91722
91828
  encoding: "utf8",
91723
91829
  windowsHide: true
@@ -91726,7 +91832,7 @@ function hooksDir(root) {
91726
91832
  return path28.resolve(root, out.stdout.trim());
91727
91833
  }
91728
91834
  function hasOwnHooksPath(root) {
91729
- const out = spawnSync5("git", ["config", "--get", "core.hooksPath"], {
91835
+ const out = spawnSync6("git", ["config", "--get", "core.hooksPath"], {
91730
91836
  cwd: root,
91731
91837
  encoding: "utf8",
91732
91838
  windowsHide: true
@@ -91741,7 +91847,7 @@ function readCommitHook(root, board = path28.join(root, "docs", "kanban")) {
91741
91847
  const line = guardLine(sessionsPath(root, board));
91742
91848
  if (hasOwnHooksPath(root)) return { state: "hooks-path", path: where, line };
91743
91849
  const file2 = path28.join(dir, "pre-commit");
91744
- if (fs25.lstatSync(file2, { throwIfNoEntry: false })?.isSymbolicLink()) return { state: "foreign", path: where, line };
91850
+ if (fs26.lstatSync(file2, { throwIfNoEntry: false })?.isSymbolicLink()) return { state: "foreign", path: where, line };
91745
91851
  const text3 = read(file2);
91746
91852
  if (text3 === null) return { state: "absent", path: where };
91747
91853
  return MARKER_LINE.test(text3) ? { state: "ours", path: where } : { state: "foreign", path: where, line };
@@ -91766,10 +91872,10 @@ ${hook.line}`
91766
91872
  }
91767
91873
  const file2 = path28.join(root, hook.path);
91768
91874
  try {
91769
- fs25.mkdirSync(path28.dirname(file2), { recursive: true });
91875
+ fs26.mkdirSync(path28.dirname(file2), { recursive: true });
91770
91876
  const text3 = hookScript(sessionsPath(root, board));
91771
- if (read(file2) !== text3) fs25.writeFileSync(file2, text3, { mode: 493 });
91772
- fs25.chmodSync(file2, 493);
91877
+ if (read(file2) !== text3) fs26.writeFileSync(file2, text3, { mode: 493 });
91878
+ fs26.chmodSync(file2, 493);
91773
91879
  } catch (e2) {
91774
91880
  return { note: `${hook.path} could not be written \u2014 ${e2 instanceof Error ? e2.message : String(e2)}` };
91775
91881
  }
@@ -91777,7 +91883,7 @@ ${hook.line}`
91777
91883
  }
91778
91884
 
91779
91885
  // src/built.ts
91780
- import fs26 from "node:fs";
91886
+ import fs27 from "node:fs";
91781
91887
  import path29 from "node:path";
91782
91888
 
91783
91889
  // ../cli/src/lib/spec-agent-names.ts
@@ -91959,7 +92065,7 @@ var draftLine = (ws) => `<!-- workflow folder: ${path29.relative(ws.cwd, draftDi
91959
92065
  var skeleton = (name) => ["---", `name: ${/\s#/.test(name) ? JSON.stringify(name) : yamlScalar(name)}`, "needsArtifact: false", "---", ""].join("\n");
91960
92066
  async function placeDraft(ws, read2) {
91961
92067
  const dir = draftDir(ws);
91962
- if (fs26.existsSync(path29.join(dir, WORKFLOW_FILE))) return { ok: true, value: void 0 };
92068
+ if (fs27.existsSync(path29.join(dir, WORKFLOW_FILE))) return { ok: true, value: void 0 };
91963
92069
  const task = await read2.readTask(ws.task);
91964
92070
  if (!task.ok) return task;
91965
92071
  let files = { [WORKFLOW_FILE]: skeleton(task.value.title.trim() || "Untitled") };
@@ -91972,8 +92078,8 @@ async function placeDraft(ws, read2) {
91972
92078
  for (const [name, text3] of Object.entries(files)) {
91973
92079
  const file2 = path29.resolve(dir, name);
91974
92080
  if (!file2.startsWith(dir + path29.sep)) continue;
91975
- fs26.mkdirSync(path29.dirname(file2), { recursive: true });
91976
- fs26.writeFileSync(file2, text3);
92081
+ fs27.mkdirSync(path29.dirname(file2), { recursive: true });
92082
+ fs27.writeFileSync(file2, text3);
91977
92083
  }
91978
92084
  return { ok: true, value: void 0 };
91979
92085
  }
@@ -91985,19 +92091,19 @@ async function builtWorkflow(ws, akb) {
91985
92091
  const dir = draftDir(ws);
91986
92092
  let source;
91987
92093
  try {
91988
- source = fs26.readFileSync(path29.join(dir, WORKFLOW_FILE), "utf8");
92094
+ source = fs27.readFileSync(path29.join(dir, WORKFLOW_FILE), "utf8");
91989
92095
  } catch {
91990
92096
  return fail(`workflows/${id}/${WORKFLOW_FILE} is missing.`);
91991
92097
  }
91992
92098
  const read2 = parseWorkflowFile(id, source, `workflows/${id}/${WORKFLOW_FILE}`);
91993
92099
  if ("problem" in read2) return fail(read2.problem);
91994
92100
  const names2 = named(read2.def);
91995
- fs26.rmSync(path29.join(dir, "agents"), { recursive: true, force: true });
92101
+ fs27.rmSync(path29.join(dir, "agents"), { recursive: true, force: true });
91996
92102
  for (const name of names2) {
91997
92103
  const from = path29.join(ws.board, "agents", name);
91998
- if (fs26.existsSync(from)) fs26.cpSync(from, path29.join(dir, "agents", name), { recursive: true });
92104
+ if (fs27.existsSync(from)) fs27.cpSync(from, path29.join(dir, "agents", name), { recursive: true });
91999
92105
  }
92000
- const files = Object.fromEntries(filesUnder(dir).map((f2) => [f2, fs26.readFileSync(path29.join(dir, f2), "utf8")]));
92106
+ const files = Object.fromEntries(filesUnder(dir).map((f2) => [f2, fs27.readFileSync(path29.join(dir, f2), "utf8")]));
92001
92107
  const checked = checkWorkflowFiles(files);
92002
92108
  if (!checked.ok) return fail(`${checked.file} ${checked.reason}.`);
92003
92109
  const run2 = async (args) => answerOf2(await runAkb(akb, [...args, "--json", "--board", ws.board], { cwd: ws.cwd, board: ws.board }));
@@ -92032,7 +92138,7 @@ function spentBy(runs) {
92032
92138
  }
92033
92139
  function reviewOf2(file2) {
92034
92140
  try {
92035
- const meta = parseFrontmatter(fs27.readFileSync(file2, "utf8")).meta;
92141
+ const meta = parseFrontmatter(fs28.readFileSync(file2, "utf8")).meta;
92036
92142
  return meta ? reviewOf(meta) : null;
92037
92143
  } catch {
92038
92144
  return null;
@@ -92040,8 +92146,8 @@ function reviewOf2(file2) {
92040
92146
  }
92041
92147
  function mcpConfig(servers, file2) {
92042
92148
  if (!Object.keys(servers).length) return null;
92043
- fs27.mkdirSync(path30.dirname(file2), { recursive: true });
92044
- fs27.writeFileSync(file2, `${JSON.stringify({ mcpServers: servers }, null, 2)}
92149
+ fs28.mkdirSync(path30.dirname(file2), { recursive: true });
92150
+ fs28.writeFileSync(file2, `${JSON.stringify({ mcpServers: servers }, null, 2)}
92045
92151
  `);
92046
92152
  return file2;
92047
92153
  }
@@ -92063,7 +92169,7 @@ async function stopRuns(akb, ws, id, since, ms) {
92063
92169
  const runs = answerOf2(await call(["run", "list", "--card", String(id), "--all", "--json"]))?.runs;
92064
92170
  const live = (runs ?? []).filter((r2) => r2.status === "running" && (r2.startedAt ?? 0) >= since);
92065
92171
  if (!runs) return false;
92066
- if (!live.length) return true;
92172
+ if (!live.length && (runs ?? []).filter((r2) => (r2.startedAt ?? 0) >= since).every((r2) => processesStopped(runMark(r2.sessionId), r2.agentPid && r2.agentStartedAt ? { pid: r2.agentPid, since: r2.agentStartedAt } : void 0))) return true;
92067
92173
  for (const r2 of live) await call(["run", "stop", r2.sessionId]);
92068
92174
  await wait(250);
92069
92175
  }
@@ -92080,7 +92186,7 @@ function deliveryEnding(ws, id) {
92080
92186
  if (!id) return null;
92081
92187
  let held4;
92082
92188
  try {
92083
- held4 = JSON.parse(fs27.readFileSync(path30.join(ws.board, "deliveries", `${path30.basename(id)}.json`), "utf8"));
92189
+ held4 = JSON.parse(fs28.readFileSync(path30.join(ws.board, "deliveries", `${path30.basename(id)}.json`), "utf8"));
92084
92190
  } catch {
92085
92191
  return null;
92086
92192
  }
@@ -92095,13 +92201,13 @@ function checkoutsOf(ws, id) {
92095
92201
  const dir = path30.join(ws.board, "deliveries");
92096
92202
  let names2;
92097
92203
  try {
92098
- names2 = fs27.readdirSync(dir).filter((n) => n.endsWith(".json"));
92204
+ names2 = fs28.readdirSync(dir).filter((n) => n.endsWith(".json"));
92099
92205
  } catch {
92100
92206
  return [];
92101
92207
  }
92102
92208
  return names2.flatMap((n) => {
92103
92209
  try {
92104
- const held4 = JSON.parse(fs27.readFileSync(path30.join(dir, n), "utf8"));
92210
+ const held4 = JSON.parse(fs28.readFileSync(path30.join(dir, n), "utf8"));
92105
92211
  return held4.cardId === id && held4.worktree && held4.deliveryId ? [held4.deliveryId] : [];
92106
92212
  } catch {
92107
92213
  return [];
@@ -92155,7 +92261,7 @@ function boardAkb(job, ws, deps, io, task) {
92155
92261
  const at2 = args.includes("--") ? args.indexOf("--") : args.length;
92156
92262
  const full = [...args.slice(0, at2), "--board", ws.board, ...args.slice(at2)];
92157
92263
  const log = show ? logLines(io.show, io.event) : void 0;
92158
- 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 });
92264
+ const ran = await runAkb(deps.akb, full, { cwd: ws.cwd, board: ws.board, task, line: job.languageLine ?? "", env: { ...env2, AI4KANBAN_EXECUTION: JSON.stringify({ job: job.id, machine: deps.machineId }) }, show: log?.push, track: io.track });
92159
92265
  log?.end();
92160
92266
  return ran;
92161
92267
  };
@@ -92165,7 +92271,7 @@ async function setUp(job, ws, deps, io) {
92165
92271
  const runtime = job.runtime;
92166
92272
  const missing = unavailable(runtime, await deps.runtimes());
92167
92273
  if (missing) return missing;
92168
- if (!fs27.existsSync(path30.join(ws.board, "config.md"))) {
92274
+ if (!fs28.existsSync(path30.join(ws.board, "config.md"))) {
92169
92275
  const init = await akb(["raw", "init"]);
92170
92276
  if (init.code !== 0) return refusal(init);
92171
92277
  }
@@ -92283,18 +92389,18 @@ async function runAgent(job, ws, deps, io) {
92283
92389
  function writeTranscript(job, dir) {
92284
92390
  if (!job.transcript) return "";
92285
92391
  const file2 = path30.join(dir, "discussion.md");
92286
- fs27.mkdirSync(dir, { recursive: true });
92287
- fs27.writeFileSync(file2, `${job.transcript}
92392
+ fs28.mkdirSync(dir, { recursive: true });
92393
+ fs28.writeFileSync(file2, `${job.transcript}
92288
92394
  `);
92289
92395
  return file2;
92290
92396
  }
92291
92397
  function pictures(job, ws, id) {
92292
92398
  const dir = cardAssetsDir(ws, id);
92293
92399
  if (!job.attachments.length || !dir) return "";
92294
- fs27.mkdirSync(dir, { recursive: true });
92400
+ fs28.mkdirSync(dir, { recursive: true });
92295
92401
  return job.attachments.map((a3, i) => {
92296
92402
  const file2 = `${i + 1}-${path30.basename(a3.name).replace(/[^\w.-]+/g, "-")}`;
92297
- fs27.writeFileSync(path30.join(dir, file2), Buffer.from(a3.content, "base64"));
92403
+ fs28.writeFileSync(path30.join(dir, file2), Buffer.from(a3.content, "base64"));
92298
92404
  return `
92299
92405
  <Asset src=".assets/${id}/${file2}" label="${a3.name.replace(/["<>]/g, "") || file2}" />
92300
92406
  `;
@@ -92337,9 +92443,9 @@ async function runFlow(job, ws, deps, io) {
92337
92443
  if (!placed.ok) return fail(placed.error);
92338
92444
  }
92339
92445
  const body = path30.join(ws.board, ".sync", `${ws.task}.request.md`);
92340
- fs27.mkdirSync(path30.dirname(body), { recursive: true });
92446
+ fs28.mkdirSync(path30.dirname(body), { recursive: true });
92341
92447
  if (!ws.number) return fail("This task has no number yet.");
92342
- fs27.writeFileSync(body, `${said.request || title}
92448
+ fs28.writeFileSync(body, `${said.request || title}
92343
92449
  ${isBuilder(ws) ? `
92344
92450
  ${draftLine(ws)}
92345
92451
  ` : ""}${pictures(job, ws, ws.number)}`);
@@ -92357,7 +92463,7 @@ ${draftLine(ws)}
92357
92463
  ...cardFlags(ws, flow.metadata),
92358
92464
  "--json"
92359
92465
  ]));
92360
- fs27.rmSync(body, { force: true });
92466
+ fs28.rmSync(body, { force: true });
92361
92467
  if (!created.ok) return fail(created.error);
92362
92468
  id = created.value;
92363
92469
  }
@@ -92373,14 +92479,14 @@ ${draftLine(ws)}
92373
92479
  if (io.lost()) return fail("");
92374
92480
  return await workOn(card);
92375
92481
  } finally {
92376
- fs27.rmSync(path30.join(ws.board, ".sync", `${ws.task}.discussion`), { recursive: true, force: true });
92482
+ fs28.rmSync(path30.join(ws.board, ".sync", `${ws.task}.discussion`), { recursive: true, force: true });
92377
92483
  const left = working.get(key) - 1;
92378
92484
  if (left) working.set(key, left);
92379
92485
  else working.delete(key);
92380
92486
  }
92381
92487
  async function workOn(id2) {
92382
92488
  io.onStop(async () => {
92383
- await stopRuns(deps.akb, ws, id2, since, deps.stopMs);
92489
+ if (!await stopRuns(deps.akb, ws, id2, since, deps.stopMs)) throw new Error("\u672A\u80FD\u786E\u8BA4\u539F\u6267\u884C\u5DF2\u505C\u6B62\u3002");
92384
92490
  });
92385
92491
  const verb = flow.verb === "create" ? flow.skip_plan ? "implement" : "refine" : flow.verb;
92386
92492
  const text3 = flow.verb === "create" ? "" : (flow.text ?? "").trim();
@@ -92440,9 +92546,19 @@ ${draftLine(ws)}
92440
92546
  ];
92441
92547
  }
92442
92548
  }
92549
+ async function confirmFlowStopped(ws, job, deps) {
92550
+ const id = akbCardOf(ws) ?? job.number;
92551
+ if (!id) return false;
92552
+ const ran = await runAkb(deps.akb, ["run", "list", "--card", String(id), "--all", "--json", "--board", ws.board], { cwd: ws.cwd, board: ws.board });
92553
+ const runs = answerOf2(ran)?.runs;
92554
+ return !!runs && runs.every((r2) => r2.status !== "running" && processesStopped(
92555
+ runMark(r2.sessionId),
92556
+ r2.agentPid && r2.agentStartedAt ? { pid: r2.agentPid, since: r2.agentStartedAt } : void 0
92557
+ ));
92558
+ }
92443
92559
 
92444
92560
  // src/recovery.ts
92445
- import fs28 from "node:fs";
92561
+ import fs29 from "node:fs";
92446
92562
  import path31 from "node:path";
92447
92563
  var PREPARE_REASON = "Runner update prepare.";
92448
92564
  var UPDATE_REASON = "Runner update checkpoint.";
@@ -92450,7 +92566,7 @@ var UNCERTAIN = "\u66F4\u65B0\u4E2D\u65AD\u65F6\u6709\u64CD\u4F5C\u7ED3\u679C\u5
92450
92566
  var fileOf = (id) => path31.join(runnerHome(), "checkpoints", `${encodeURIComponent(id)}.json`);
92451
92567
  function readCheckpoint(id) {
92452
92568
  try {
92453
- const held4 = JSON.parse(fs28.readFileSync(fileOf(id), "utf8"));
92569
+ const held4 = JSON.parse(fs29.readFileSync(fileOf(id), "utf8"));
92454
92570
  if (!held4 || !Array.isArray(held4.pending) || !held4.pending.every((id2) => typeof id2 === "string")) throw new Error("\u8FDB\u5EA6\u683C\u5F0F\u9519\u8BEF");
92455
92571
  return held4;
92456
92572
  } catch (e2) {
@@ -92460,12 +92576,12 @@ function readCheckpoint(id) {
92460
92576
  }
92461
92577
  function saveCheckpoint(id, checkpoint) {
92462
92578
  const file2 = fileOf(id);
92463
- fs28.mkdirSync(path31.dirname(file2), { recursive: true, mode: 448 });
92464
- fs28.writeFileSync(`${file2}.tmp`, JSON.stringify(checkpoint), { mode: 384 });
92465
- fs28.renameSync(`${file2}.tmp`, file2);
92579
+ fs29.mkdirSync(path31.dirname(file2), { recursive: true, mode: 448 });
92580
+ fs29.writeFileSync(`${file2}.tmp`, JSON.stringify(checkpoint), { mode: 384 });
92581
+ fs29.renameSync(`${file2}.tmp`, file2);
92466
92582
  }
92467
92583
  function clearCheckpoint(id) {
92468
- fs28.rmSync(fileOf(id), { force: true });
92584
+ fs29.rmSync(fileOf(id), { force: true });
92469
92585
  }
92470
92586
  function checkpointEvent(checkpoint, event2) {
92471
92587
  if (event2.kind === "tool_call") {
@@ -92480,7 +92596,7 @@ function checkpointEvent(checkpoint, event2) {
92480
92596
 
92481
92597
  // src/lock.ts
92482
92598
  import crypto4 from "node:crypto";
92483
- import fs29 from "node:fs";
92599
+ import fs30 from "node:fs";
92484
92600
  import net from "node:net";
92485
92601
  import path32 from "node:path";
92486
92602
  var RETRY_MS = 5e3;
@@ -92504,7 +92620,7 @@ function holdMachine(kind, onHeld, onWaiting) {
92504
92620
  const attempt = () => {
92505
92621
  timer = null;
92506
92622
  if (closed) return;
92507
- if (process.platform !== "win32") fs29.mkdirSync(path32.dirname(where), { recursive: true, mode: 448 });
92623
+ if (process.platform !== "win32") fs30.mkdirSync(path32.dirname(where), { recursive: true, mode: 448 });
92508
92624
  const s = net.createServer((peer) => {
92509
92625
  peers.add(peer);
92510
92626
  peer.on("error", () => {
@@ -92552,7 +92668,7 @@ function holdMachine(kind, onHeld, onWaiting) {
92552
92668
  later(0);
92553
92669
  });
92554
92670
  removeIfStill.once("error", () => {
92555
- fs29.rmSync(where, { force: true });
92671
+ fs30.rmSync(where, { force: true });
92556
92672
  later(50 + Math.random() * 200);
92557
92673
  });
92558
92674
  return;
@@ -92580,33 +92696,140 @@ function holdMachine(kind, onHeld, onWaiting) {
92580
92696
  };
92581
92697
  }
92582
92698
 
92699
+ // src/handoff.ts
92700
+ import crypto5 from "node:crypto";
92701
+ import fs31 from "node:fs";
92702
+ import path33 from "node:path";
92703
+ import { execFileSync } from "node:child_process";
92704
+ var digest = (value) => crypto5.createHash("sha256").update(value).digest("hex");
92705
+ var git3 = (cwd, ...args) => execFileSync("git", ["-C", cwd, ...args], { encoding: "utf8", timeout: 15e3, maxBuffer: 16 * 1024 * 1024, stdio: ["ignore", "pipe", "ignore"] });
92706
+ function authorizedFolder(folder) {
92707
+ if (!folder) return null;
92708
+ try {
92709
+ const real = fs31.realpathSync(folder);
92710
+ return allowedProjects().some((root) => real === root || real.startsWith(root + path33.sep)) ? real : null;
92711
+ } catch {
92712
+ return null;
92713
+ }
92714
+ }
92715
+ function progressFolder(job, folder) {
92716
+ const token = job.handoff?.progressIsolation;
92717
+ if (!token) return folder;
92718
+ if (!/^[a-zA-Z0-9-]{1,80}$/.test(token)) return null;
92719
+ try {
92720
+ const dir = fs31.realpathSync(path33.join(folder, ".akb", "handoffs", token));
92721
+ if (!dir.startsWith(fs31.realpathSync(folder) + path33.sep)) return null;
92722
+ const marker = JSON.parse(fs31.readFileSync(path33.join(dir, ".akb", "handoff.json"), "utf8"));
92723
+ return marker.task === job.task && marker.isolation === token ? dir : null;
92724
+ } catch {
92725
+ return null;
92726
+ }
92727
+ }
92728
+ function progressEvidence(job, folder) {
92729
+ try {
92730
+ const board = path33.join(folder, ".akb", "kanban");
92731
+ const deliveries = path33.join(board, "deliveries");
92732
+ const rows = fs31.readdirSync(deliveries).filter((name) => name.endsWith(".json")).map((name) => JSON.parse(fs31.readFileSync(path33.join(deliveries, name), "utf8"))).filter((row2) => row2.cardId === job.number).sort((a3, b2) => (b2.startedAt ?? 0) - (a3.startedAt ?? 0));
92733
+ const row = rows[0];
92734
+ if (!row?.deliveryId || !row.base || !row.branch || !row.worktree || row.commitMode !== "auto") return null;
92735
+ const tree = fs31.realpathSync(path33.resolve(folder, row.worktree));
92736
+ if (!tree.startsWith(fs31.realpathSync(folder) + path33.sep)) return null;
92737
+ if (git3(tree, "rev-parse", "--show-toplevel").trim() !== tree) return null;
92738
+ if (git3(tree, "branch", "--show-current").trim() !== row.branch) return null;
92739
+ git3(tree, "cat-file", "-e", `${row.base}^{commit}`);
92740
+ const changed = git3(tree, "ls-files", "-z", "--cached", "--others", "--exclude-standard").split("\0").filter(Boolean).sort();
92741
+ const files = changed.map((name) => {
92742
+ const file2 = path33.join(tree, name);
92743
+ try {
92744
+ const stat = fs31.lstatSync(file2);
92745
+ if (stat.isSymbolicLink()) return [name, "link", digest(fs31.readlinkSync(file2))];
92746
+ if (!stat.isFile()) throw new Error("\u65E0\u6CD5\u9A8C\u8BC1\u6587\u4EF6\u7C7B\u578B");
92747
+ return [name, stat.mode & 511, digest(fs31.readFileSync(file2))];
92748
+ } catch (e2) {
92749
+ if (e2.code === "ENOENT") return [name, "deleted"];
92750
+ throw e2;
92751
+ }
92752
+ });
92753
+ return digest(JSON.stringify({
92754
+ task: job.task,
92755
+ number: job.number,
92756
+ verb: job.flow?.verb,
92757
+ delivery: row.deliveryId,
92758
+ record: digest(JSON.stringify(row)),
92759
+ base: row.base,
92760
+ branch: row.branch,
92761
+ head: git3(tree, "rev-parse", "HEAD").trim(),
92762
+ index: digest(git3(tree, "diff", "--cached", "--binary")),
92763
+ files
92764
+ }));
92765
+ } catch {
92766
+ return null;
92767
+ }
92768
+ }
92769
+ function checkProgress(job) {
92770
+ const folder = authorizedFolder(job.projectDir);
92771
+ if (!folder) return { handoffIssue: "folder_unavailable" };
92772
+ if (!job.handoff?.started) return {};
92773
+ const progress = progressFolder(job, folder);
92774
+ if (!progress) return { handoffIssue: "progress_missing" };
92775
+ const evidence = progressEvidence({ ...job, flow: { verb: job.handoff.verb ?? "implement", workflow: job.workflow ?? "" } }, progress);
92776
+ if (!evidence) return { handoffIssue: "progress_missing" };
92777
+ if (!job.handoff.evidence || evidence !== job.handoff.evidence) return { handoffIssue: "progress_unknown", evidence };
92778
+ return { evidence };
92779
+ }
92780
+ function restartFolder(job, folder) {
92781
+ const token = job.handoff?.isolation ?? job.id;
92782
+ if (!/^[a-zA-Z0-9-]{1,80}$/.test(token)) throw new Error("\u9694\u79BB\u76EE\u5F55\u7F16\u53F7\u65E0\u6548\u3002");
92783
+ const dir = path33.join(folder, ".akb", "handoffs", token);
92784
+ const marker = path33.join(dir, ".akb", "handoff.json");
92785
+ for (const parent of [path33.join(folder, ".akb"), path33.dirname(dir), dir]) {
92786
+ if (fs31.lstatSync(parent, { throwIfNoEntry: false })?.isSymbolicLink()) throw new Error("\u9694\u79BB\u76EE\u5F55\u4E0D\u80FD\u901A\u8FC7\u7B26\u53F7\u94FE\u63A5\u521B\u5EFA\u3002");
92787
+ }
92788
+ if (fs31.existsSync(dir)) {
92789
+ if (job.handoff?.recovering) {
92790
+ try {
92791
+ const saved = JSON.parse(fs31.readFileSync(marker, "utf8"));
92792
+ if (saved.task === job.task && saved.isolation === token && git3(dir, "rev-parse", "--show-toplevel").trim() === fs31.realpathSync(dir)) return dir;
92793
+ } catch {
92794
+ }
92795
+ }
92796
+ throw new Error("\u91CD\u542F\u76EE\u5F55\u5DF2\u5B58\u5728\uFF0C\u8BF7\u91CD\u65B0\u68C0\u67E5\u3002");
92797
+ }
92798
+ fs31.mkdirSync(path33.dirname(dir), { recursive: true });
92799
+ git3(folder, "worktree", "add", "--detach", dir, "HEAD");
92800
+ if (fs31.lstatSync(path33.dirname(marker), { throwIfNoEntry: false })?.isSymbolicLink()) throw new Error("\u9694\u79BB\u6807\u8BB0\u76EE\u5F55\u65E0\u6548\u3002");
92801
+ fs31.mkdirSync(path33.dirname(marker), { recursive: true });
92802
+ fs31.writeFileSync(marker, JSON.stringify({ task: job.task, isolation: token }), { flag: "wx" });
92803
+ return dir;
92804
+ }
92805
+
92583
92806
  // src/jobs.ts
92584
92807
  import { spawn as spawn4 } from "node:child_process";
92585
- import fs32 from "node:fs";
92586
- import path35 from "node:path";
92808
+ import fs34 from "node:fs";
92809
+ import path36 from "node:path";
92587
92810
 
92588
92811
  // ../cli/src/lib/agent/catalog.ts
92589
- import fs30 from "node:fs";
92590
- import path33 from "node:path";
92812
+ import fs32 from "node:fs";
92813
+ import path34 from "node:path";
92591
92814
  var CATALOGUE = "https://models.dev/api.json";
92592
92815
  var FRESH_FOR_MS = 24 * 60 * 6e4;
92593
92816
  var ANSWER_BY_MS = 2e4;
92594
92817
  function cacheFile() {
92595
- return path33.join(machineHome(), "models-dev.json");
92818
+ return path34.join(machineHome(), "models-dev.json");
92596
92819
  }
92597
92820
  var held2;
92598
92821
  function readCache() {
92599
92822
  const file2 = cacheFile();
92600
92823
  let stamp2;
92601
92824
  try {
92602
- const stat = fs30.statSync(file2);
92825
+ const stat = fs32.statSync(file2);
92603
92826
  stamp2 = `${stat.mtimeMs}:${stat.size}`;
92604
92827
  } catch {
92605
92828
  return void 0;
92606
92829
  }
92607
92830
  if (held2?.stamp === stamp2) return held2.cached;
92608
92831
  try {
92609
- const data = JSON.parse(fs30.readFileSync(file2, "utf8"));
92832
+ const data = JSON.parse(fs32.readFileSync(file2, "utf8"));
92610
92833
  if (!data || typeof data.limits !== "object" || !data.limits) return void 0;
92611
92834
  const cached2 = {
92612
92835
  fetchedAt: typeof data.fetchedAt === "number" ? data.fetchedAt : 0,
@@ -92645,8 +92868,8 @@ function refreshCatalog() {
92645
92868
  const limits = limitsIn(await answer.json());
92646
92869
  if (Object.keys(limits).length === 0) return;
92647
92870
  const file2 = cacheFile();
92648
- fs30.mkdirSync(path33.dirname(file2), { recursive: true });
92649
- fs30.writeFileSync(file2, JSON.stringify({ fetchedAt: Date.now(), limits }));
92871
+ fs32.mkdirSync(path34.dirname(file2), { recursive: true });
92872
+ fs32.writeFileSync(file2, JSON.stringify({ fetchedAt: Date.now(), limits }));
92650
92873
  } catch {
92651
92874
  }
92652
92875
  })();
@@ -92690,9 +92913,9 @@ function contextLimit(harness, model) {
92690
92913
  }
92691
92914
 
92692
92915
  // src/ideas.ts
92693
- import fs31 from "node:fs";
92694
- import path34 from "node:path";
92695
- var ideasFileOf = (job) => path34.join(runnerHome(), "ideas", `${job.id}.json`);
92916
+ import fs33 from "node:fs";
92917
+ import path35 from "node:path";
92918
+ var ideasFileOf = (job) => path35.join(runnerHome(), "ideas", `${job.id}.json`);
92696
92919
  async function writeIdeas(job, list) {
92697
92920
  const workflows = [];
92698
92921
  let after = null;
@@ -92703,18 +92926,18 @@ async function writeIdeas(job, list) {
92703
92926
  after = page.value.next;
92704
92927
  } while (after);
92705
92928
  const file2 = ideasFileOf(job);
92706
- fs31.mkdirSync(path34.dirname(file2), { recursive: true });
92707
- fs31.writeFileSync(file2, `${JSON.stringify({ workflows, ideas: job.discussion.ideas }, null, 2)}
92929
+ fs33.mkdirSync(path35.dirname(file2), { recursive: true });
92930
+ fs33.writeFileSync(file2, `${JSON.stringify({ workflows, ideas: job.discussion.ideas }, null, 2)}
92708
92931
  `);
92709
92932
  return { file: file2 };
92710
92933
  }
92711
92934
  function readIdeas(file2) {
92712
92935
  try {
92713
- return JSON.parse(fs31.readFileSync(file2, "utf8")).ideas;
92936
+ return JSON.parse(fs33.readFileSync(file2, "utf8")).ideas;
92714
92937
  } catch {
92715
92938
  return void 0;
92716
92939
  } finally {
92717
- fs31.rmSync(file2, { force: true });
92940
+ fs33.rmSync(file2, { force: true });
92718
92941
  }
92719
92942
  }
92720
92943
 
@@ -92750,32 +92973,32 @@ var defaultDeps = (machineId2) => ({
92750
92973
  akb: currentAkb,
92751
92974
  runtimes: detectRuntimes
92752
92975
  });
92753
- var ownFolder = () => path35.join(runnerHome(), "work");
92976
+ var ownFolder = () => path36.join(runnerHome(), "work");
92754
92977
  function folderFor(job) {
92755
92978
  if (!job.projectDir) {
92756
- const cwd = path35.join(ownFolder(), job.id);
92757
- fs32.mkdirSync(cwd, { recursive: true });
92979
+ const cwd = path36.join(ownFolder(), job.id);
92980
+ fs34.mkdirSync(cwd, { recursive: true });
92758
92981
  return { cwd };
92759
92982
  }
92760
92983
  const real = realpath4(job.projectDir);
92761
- if (real && allowedProjects().some((root) => real === root || real.startsWith(root + path35.sep))) return { cwd: real };
92984
+ if (real && allowedProjects().some((root) => real === root || real.startsWith(root + path36.sep))) return { cwd: real };
92762
92985
  return { refused: `This Runner is not allowed to work in ${job.projectDir}.` };
92763
92986
  }
92764
92987
  function realpath4(p2) {
92765
92988
  try {
92766
- return fs32.realpathSync(p2);
92989
+ return fs34.realpathSync(p2);
92767
92990
  } catch {
92768
92991
  return null;
92769
92992
  }
92770
92993
  }
92771
- var attachmentsOf = (job) => path35.join(runnerHome(), "attachments", job.id);
92994
+ var attachmentsOf = (job) => path36.join(runnerHome(), "attachments", job.id);
92772
92995
  function writeAttachments(job) {
92773
92996
  if (!job.attachments.length) return "";
92774
92997
  const dir = attachmentsOf(job);
92775
- fs32.mkdirSync(dir, { recursive: true });
92998
+ fs34.mkdirSync(dir, { recursive: true });
92776
92999
  const files = job.attachments.map((a3) => {
92777
- const file2 = path35.join(dir, path35.basename(a3.name));
92778
- fs32.writeFileSync(file2, Buffer.from(a3.content, "base64"));
93000
+ const file2 = path36.join(dir, path36.basename(a3.name));
93001
+ fs34.writeFileSync(file2, Buffer.from(a3.content, "base64"));
92779
93002
  return file2;
92780
93003
  });
92781
93004
  return `
@@ -92819,6 +93042,8 @@ function streamOut(deps, id, lease) {
92819
93042
  };
92820
93043
  const stored = new Promise((resolve2) => ended2 = resolve2);
92821
93044
  const children = /* @__PURE__ */ new Set();
93045
+ const groups = /* @__PURE__ */ new Set();
93046
+ let stopConfirmed = true;
92822
93047
  const killed = /* @__PURE__ */ new Set();
92823
93048
  const kill = (child) => {
92824
93049
  if (!child.pid) return;
@@ -92841,7 +93066,9 @@ function streamOut(deps, id, lease) {
92841
93066
  if (asked || lost) return;
92842
93067
  asked = true;
92843
93068
  for (const child of children) kill(child);
92844
- if (halt) stopping = halt();
93069
+ if (halt) stopping = halt().catch(() => {
93070
+ stopConfirmed = false;
93071
+ });
92845
93072
  onAsked();
92846
93073
  };
92847
93074
  const loseLease = () => {
@@ -92850,6 +93077,8 @@ function streamOut(deps, id, lease) {
92850
93077
  lease.lost = true;
92851
93078
  for (const child of children) kill(child);
92852
93079
  stopping = Promise.all([halt?.(), ...killed]).then(() => {
93080
+ }).catch(() => {
93081
+ stopConfirmed = false;
92853
93082
  });
92854
93083
  return stopping;
92855
93084
  };
@@ -92962,7 +93191,7 @@ function streamOut(deps, id, lease) {
92962
93191
  if (!renewed.ok) return;
92963
93192
  Object.assign(lease, requestedAt);
92964
93193
  if (renewed.value.stop) ask();
92965
- if (log.ws?.readyState === WebSocket.OPEN) log.ws.send(JSON.stringify({ type: "alive" }));
93194
+ if (!ending && log.ws?.readyState === WebSocket.OPEN) log.ws.send(JSON.stringify({ type: "alive" }));
92966
93195
  }, deps.renewMs);
92967
93196
  return {
92968
93197
  event: event2,
@@ -92970,16 +93199,38 @@ function streamOut(deps, id, lease) {
92970
93199
  if (text3) event2({ kind: "log", data: { text: text3 } });
92971
93200
  },
92972
93201
  adopt: (child) => {
93202
+ if (child.pid) groups.add(child.pid);
92973
93203
  if (!valid() || asked) return kill(child);
92974
93204
  children.add(child);
92975
93205
  child.on("close", () => children.delete(child));
92976
93206
  },
92977
93207
  onStop: (stop2) => {
92978
93208
  halt = stop2;
92979
- if (lost || asked) stopping = stop2();
93209
+ if (lost || asked) stopping = stop2().catch(() => {
93210
+ stopConfirmed = false;
93211
+ });
92980
93212
  },
92981
93213
  /** What stopping the job's board runs is still doing. */
92982
93214
  halted: () => stopping,
93215
+ confirmed: async () => {
93216
+ await stopping;
93217
+ if (!stopConfirmed) return false;
93218
+ const until = Date.now() + deps.stopMs;
93219
+ const alive2 = (pid) => {
93220
+ try {
93221
+ process.kill(-pid, 0);
93222
+ return true;
93223
+ } catch (e2) {
93224
+ return e2.code !== "ESRCH";
93225
+ }
93226
+ };
93227
+ if (process.platform === "win32") return children.size === 0;
93228
+ while ([...groups].some(alive2)) {
93229
+ if (Date.now() >= until) return false;
93230
+ await new Promise((resolve2) => setTimeout(resolve2, 50));
93231
+ }
93232
+ return true;
93233
+ },
92983
93234
  stop: loseLease,
92984
93235
  lost: () => !valid(),
92985
93236
  asked: () => asked,
@@ -93019,7 +93270,7 @@ async function runJob(id, deps, track = () => {
93019
93270
  await runClaimed(job, { ...deps, akb: deps.akb() }, track, (dir) => releases.push(hold(dir)), lease);
93020
93271
  } finally {
93021
93272
  for (const release2 of releases) release2();
93022
- fs32.rmSync(attachmentsOf(job), { recursive: true, force: true });
93273
+ fs34.rmSync(attachmentsOf(job), { recursive: true, force: true });
93023
93274
  }
93024
93275
  }
93025
93276
  async function runClaimed(job, deps, track, keep2, lease) {
@@ -93036,6 +93287,33 @@ async function runClaimed(job, deps, track, keep2, lease) {
93036
93287
  }
93037
93288
  if (recovering && checkpoint.session) job = { ...job, resume: checkpoint.session, fork: false };
93038
93289
  if (!recovering) persist();
93290
+ if (job.handoff?.kind === "check") {
93291
+ const runtime = (await deps.runtimes()).find((r2) => r2.name === job.runtime);
93292
+ const report2 = !runtime?.installed || runtime.loggedIn === false ? { handoffIssue: "runtime_unavailable" } : checkProgress(job);
93293
+ return finish(deps, id, lease, "done", "", report2);
93294
+ }
93295
+ if (job.handoff?.kind === "execution") {
93296
+ if (recovering) job = { ...job, handoff: { ...job.handoff, recovering: true } };
93297
+ const handoff = job.handoff;
93298
+ const runtime = (await deps.runtimes()).find((r2) => r2.name === job.runtime);
93299
+ if (!runtime?.installed || runtime.loggedIn === false) return finish(deps, id, lease, "failed", "\u76EE\u6807\u8FD0\u884C\u5DE5\u5177\u5DF2\u4E0D\u53EF\u7528\uFF0C\u8BF7\u91CD\u65B0\u68C0\u67E5\u3002");
93300
+ const folder2 = authorizedFolder(job.projectDir);
93301
+ if (!folder2) return finish(deps, id, lease, "failed", "\u76EE\u6807\u76EE\u5F55\u6388\u6743\u5DF2\u53D8\u5316\u3002");
93302
+ if (handoff.action === "continue") {
93303
+ const progress = progressFolder(job, folder2);
93304
+ if (!progress || !handoff.recovering && (!handoff.evidence || progressEvidence({ ...job, flow: job.flow ? { ...job.flow, verb: handoff.verb ?? job.flow.verb } : job.flow }, progress) !== handoff.evidence)) {
93305
+ return finish(deps, id, lease, "failed", "\u672C\u5730\u8FDB\u5EA6\u5DF2\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u68C0\u67E5\u3002");
93306
+ }
93307
+ job = { ...job, projectDir: progress };
93308
+ }
93309
+ if (handoff.action === "restart") {
93310
+ try {
93311
+ job = { ...job, projectDir: restartFolder(job, folder2), resume: null, fork: false };
93312
+ } catch {
93313
+ return finish(deps, id, lease, "failed", "\u65E0\u6CD5\u51C6\u5907\u65B0\u9694\u79BB\u76EE\u5F55\uFF0C\u5DF2\u6709\u6587\u4EF6\u5DF2\u4FDD\u7559\u3002");
93314
+ }
93315
+ }
93316
+ }
93039
93317
  if (job.secret) return runSecret(job, deps);
93040
93318
  if (job.test) return runTest(job, deps);
93041
93319
  if (job.agent) return runAgentJob(job, deps, track, keep2, lease, checkpoint, persist);
@@ -93076,7 +93354,7 @@ async function runClaimed(job, deps, track, keep2, lease) {
93076
93354
  discussed = board.board;
93077
93355
  }
93078
93356
  if (job.discussion) {
93079
- const wrote = recovering && fs32.existsSync(ideasFileOf(job)) ? { file: ideasFileOf(job) } : await writeIdeas({ ...job, discussion: job.discussion }, deps.api.listWorkflows);
93357
+ const wrote = recovering && fs34.existsSync(ideasFileOf(job)) ? { file: ideasFileOf(job) } : await writeIdeas({ ...job, discussion: job.discussion }, deps.api.listWorkflows);
93080
93358
  if ("error" in wrote) throw new Error(wrote.error);
93081
93359
  ideas = wrote.file;
93082
93360
  }
@@ -93173,9 +93451,13 @@ ${prompt}` : prompt;
93173
93451
  if (stopped2 && stream.asked()) await stream.halted();
93174
93452
  await stream.end();
93175
93453
  if (stream.lost()) return;
93176
- if (stopped2) return finish(deps, id, lease, "stopped");
93177
- if (!ended3.ok) return finish(deps, id, lease, "failed", ended3.reason);
93178
- return sendBack(deps, id, lease, ws, ended3.report, () => keepChat(job, ended3.report.reply));
93454
+ const boardStopped = await confirmFlowStopped(ws, job, deps);
93455
+ const evidence = progressEvidence(job, ws.cwd);
93456
+ const proof = boardStopped && await stream.confirmed() ? { processesStopped: true, ...evidence ? { evidence } : {} } : {};
93457
+ if (ended3.ok) complete("done", { ...ended3.report, ...proof });
93458
+ if (stopped2) return finish(deps, id, lease, "stopped", "", proof);
93459
+ if (!ended3.ok) return finish(deps, id, lease, "failed", ended3.reason, proof);
93460
+ return sendBack(deps, id, lease, ws, { ...ended3.report, ...proof }, () => keepChat(job, ended3.report.reply));
93179
93461
  }
93180
93462
  checkpoint.started = true;
93181
93463
  checkpoint.opaque = !run2.converse && !run2.renderer?.events;
@@ -93381,8 +93663,8 @@ async function runTest(job, deps) {
93381
93663
  const report2 = (await deps.runtimes()).find((r2) => r2.name === job.runtime);
93382
93664
  if (!report2?.installed) return finish2("failed", "not_installed");
93383
93665
  if (report2.loggedIn === false) return finish2("failed", "signed_out");
93384
- const cwd = path35.join(ownFolder(), "test");
93385
- fs32.mkdirSync(cwd, { recursive: true });
93666
+ const cwd = path36.join(ownFolder(), "test");
93667
+ fs34.mkdirSync(cwd, { recursive: true });
93386
93668
  const run2 = deps.plan(job.runtime, job.prompt, cwd, null, job.model, settingsOf(job));
93387
93669
  const startedAt = Date.now();
93388
93670
  if (run2.converse) {
@@ -93811,7 +94093,7 @@ function startRunner(options) {
93811
94093
 
93812
94094
  // src/signin.ts
93813
94095
  import { spawn as spawn5 } from "node:child_process";
93814
- import crypto5 from "node:crypto";
94096
+ import crypto6 from "node:crypto";
93815
94097
  import http from "node:http";
93816
94098
  var WAIT_MS = 10 * 60 * 1e3;
93817
94099
  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";
@@ -93836,8 +94118,8 @@ var PAGE = (outcome, lang) => {
93836
94118
  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>`;
93837
94119
  };
93838
94120
  async function signIn(options = {}) {
93839
- const verifier = base64url(crypto5.randomBytes(32));
93840
- const challenge = base64url(crypto5.createHash("sha256").update(verifier).digest());
94121
+ const verifier = base64url(crypto6.randomBytes(32));
94122
+ const challenge = base64url(crypto6.createHash("sha256").update(verifier).digest());
93841
94123
  let finish2 = () => {
93842
94124
  };
93843
94125
  const answered = new Promise((resolve2) => finish2 = resolve2);