opencode-hive 1.3.4 → 1.3.6

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/index.js CHANGED
@@ -45,7 +45,7 @@ var __export = (target, all) => {
45
45
  };
46
46
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
47
47
 
48
- // ../../node_modules/.bun/ms@2.1.3/node_modules/ms/index.js
48
+ // ../../node_modules/ms/index.js
49
49
  var require_ms = __commonJS((exports, module) => {
50
50
  var s = 1000;
51
51
  var m = s * 60;
@@ -155,7 +155,7 @@ var require_ms = __commonJS((exports, module) => {
155
155
  }
156
156
  });
157
157
 
158
- // ../../node_modules/.bun/debug@4.4.3/node_modules/debug/src/common.js
158
+ // ../../node_modules/debug/src/common.js
159
159
  var require_common = __commonJS((exports, module) => {
160
160
  function setup(env) {
161
161
  createDebug.debug = createDebug;
@@ -330,7 +330,7 @@ var require_common = __commonJS((exports, module) => {
330
330
  module.exports = setup;
331
331
  });
332
332
 
333
- // ../../node_modules/.bun/debug@4.4.3/node_modules/debug/src/browser.js
333
+ // ../../node_modules/debug/src/browser.js
334
334
  var require_browser = __commonJS((exports, module) => {
335
335
  exports.formatArgs = formatArgs;
336
336
  exports.save = save;
@@ -490,7 +490,7 @@ var require_browser = __commonJS((exports, module) => {
490
490
  };
491
491
  });
492
492
 
493
- // ../../node_modules/.bun/has-flag@4.0.0/node_modules/has-flag/index.js
493
+ // ../../node_modules/has-flag/index.js
494
494
  var require_has_flag = __commonJS((exports, module) => {
495
495
  module.exports = (flag, argv = process.argv) => {
496
496
  const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
@@ -500,7 +500,7 @@ var require_has_flag = __commonJS((exports, module) => {
500
500
  };
501
501
  });
502
502
 
503
- // ../../node_modules/.bun/supports-color@7.2.0/node_modules/supports-color/index.js
503
+ // ../../node_modules/supports-color/index.js
504
504
  var require_supports_color = __commonJS((exports, module) => {
505
505
  var os = __require("os");
506
506
  var tty = __require("tty");
@@ -599,7 +599,7 @@ var require_supports_color = __commonJS((exports, module) => {
599
599
  };
600
600
  });
601
601
 
602
- // ../../node_modules/.bun/debug@4.4.3/node_modules/debug/src/node.js
602
+ // ../../node_modules/debug/src/node.js
603
603
  var require_node = __commonJS((exports, module) => {
604
604
  var tty = __require("tty");
605
605
  var util = __require("util");
@@ -770,7 +770,7 @@ var require_node = __commonJS((exports, module) => {
770
770
  };
771
771
  });
772
772
 
773
- // ../../node_modules/.bun/debug@4.4.3/node_modules/debug/src/index.js
773
+ // ../../node_modules/debug/src/index.js
774
774
  var require_src = __commonJS((exports, module) => {
775
775
  if (typeof process === "undefined" || process.type === "renderer" || false || process.__nwjs) {
776
776
  module.exports = require_browser();
@@ -779,7 +779,7 @@ var require_src = __commonJS((exports, module) => {
779
779
  }
780
780
  });
781
781
 
782
- // ../../node_modules/.bun/@kwsites+file-exists@1.1.1/node_modules/@kwsites/file-exists/dist/src/index.js
782
+ // ../../node_modules/@kwsites/file-exists/dist/src/index.js
783
783
  var require_src2 = __commonJS((exports) => {
784
784
  var __importDefault = exports && exports.__importDefault || function(mod) {
785
785
  return mod && mod.__esModule ? mod : { default: mod };
@@ -820,7 +820,7 @@ var require_src2 = __commonJS((exports) => {
820
820
  exports.READABLE = exports.FILE + exports.FOLDER;
821
821
  });
822
822
 
823
- // ../../node_modules/.bun/@kwsites+file-exists@1.1.1/node_modules/@kwsites/file-exists/dist/index.js
823
+ // ../../node_modules/@kwsites/file-exists/dist/index.js
824
824
  var require_dist = __commonJS((exports) => {
825
825
  function __export2(m) {
826
826
  for (var p in m)
@@ -831,7 +831,7 @@ var require_dist = __commonJS((exports) => {
831
831
  __export2(require_src2());
832
832
  });
833
833
 
834
- // ../../node_modules/.bun/@kwsites+promise-deferred@1.1.1/node_modules/@kwsites/promise-deferred/dist/index.js
834
+ // ../../node_modules/@kwsites/promise-deferred/dist/index.js
835
835
  var require_dist2 = __commonJS((exports) => {
836
836
  Object.defineProperty(exports, "__esModule", { value: true });
837
837
  exports.createDeferred = exports.deferred = undefined;
@@ -871,11 +871,11 @@ var require_dist2 = __commonJS((exports) => {
871
871
  });
872
872
 
873
873
  // src/index.ts
874
- import * as path10 from "path";
875
- import * as fs12 from "fs";
874
+ import * as path11 from "path";
875
+ import * as fs13 from "fs";
876
876
  import * as os from "os";
877
877
 
878
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/classic/external.js
878
+ // ../../node_modules/zod/v4/classic/external.js
879
879
  var exports_external = {};
880
880
  __export(exports_external, {
881
881
  xid: () => xid2,
@@ -1105,7 +1105,7 @@ __export(exports_external, {
1105
1105
  $brand: () => $brand
1106
1106
  });
1107
1107
 
1108
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/core/index.js
1108
+ // ../../node_modules/zod/v4/core/index.js
1109
1109
  var exports_core2 = {};
1110
1110
  __export(exports_core2, {
1111
1111
  version: () => version,
@@ -1369,7 +1369,7 @@ __export(exports_core2, {
1369
1369
  $ZodAny: () => $ZodAny
1370
1370
  });
1371
1371
 
1372
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/core/core.js
1372
+ // ../../node_modules/zod/v4/core/core.js
1373
1373
  var NEVER = Object.freeze({
1374
1374
  status: "aborted"
1375
1375
  });
@@ -1436,7 +1436,7 @@ function config(newConfig) {
1436
1436
  Object.assign(globalConfig, newConfig);
1437
1437
  return globalConfig;
1438
1438
  }
1439
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/core/util.js
1439
+ // ../../node_modules/zod/v4/core/util.js
1440
1440
  var exports_util = {};
1441
1441
  __export(exports_util, {
1442
1442
  unwrapMessage: () => unwrapMessage,
@@ -2065,7 +2065,7 @@ class Class {
2065
2065
  constructor(..._args) {}
2066
2066
  }
2067
2067
 
2068
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/core/errors.js
2068
+ // ../../node_modules/zod/v4/core/errors.js
2069
2069
  var initializer = (inst, def) => {
2070
2070
  inst.name = "$ZodError";
2071
2071
  Object.defineProperty(inst, "_zod", {
@@ -2208,7 +2208,7 @@ function prettifyError(error) {
2208
2208
  `);
2209
2209
  }
2210
2210
 
2211
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/core/parse.js
2211
+ // ../../node_modules/zod/v4/core/parse.js
2212
2212
  var _parse = (_Err) => (schema, value, _ctx, _params) => {
2213
2213
  const ctx = _ctx ? Object.assign(_ctx, { async: false }) : { async: false };
2214
2214
  const result = schema._zod.run({ value, issues: [] }, ctx);
@@ -2295,7 +2295,7 @@ var _safeDecodeAsync = (_Err) => async (schema, value, _ctx) => {
2295
2295
  return _safeParseAsync(_Err)(schema, value, _ctx);
2296
2296
  };
2297
2297
  var safeDecodeAsync = /* @__PURE__ */ _safeDecodeAsync($ZodRealError);
2298
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/core/regexes.js
2298
+ // ../../node_modules/zod/v4/core/regexes.js
2299
2299
  var exports_regexes = {};
2300
2300
  __export(exports_regexes, {
2301
2301
  xid: () => xid,
@@ -2447,7 +2447,7 @@ var sha512_hex = /^[0-9a-fA-F]{128}$/;
2447
2447
  var sha512_base64 = /* @__PURE__ */ fixedBase64(86, "==");
2448
2448
  var sha512_base64url = /* @__PURE__ */ fixedBase64url(86);
2449
2449
 
2450
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/core/checks.js
2450
+ // ../../node_modules/zod/v4/core/checks.js
2451
2451
  var $ZodCheck = /* @__PURE__ */ $constructor("$ZodCheck", (inst, def) => {
2452
2452
  var _a;
2453
2453
  inst._zod ?? (inst._zod = {});
@@ -2988,7 +2988,7 @@ var $ZodCheckOverwrite = /* @__PURE__ */ $constructor("$ZodCheckOverwrite", (ins
2988
2988
  };
2989
2989
  });
2990
2990
 
2991
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/core/doc.js
2991
+ // ../../node_modules/zod/v4/core/doc.js
2992
2992
  class Doc {
2993
2993
  constructor(args = []) {
2994
2994
  this.content = [];
@@ -3026,14 +3026,14 @@ class Doc {
3026
3026
  }
3027
3027
  }
3028
3028
 
3029
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/core/versions.js
3029
+ // ../../node_modules/zod/v4/core/versions.js
3030
3030
  var version = {
3031
3031
  major: 4,
3032
3032
  minor: 1,
3033
3033
  patch: 8
3034
3034
  };
3035
3035
 
3036
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/core/schemas.js
3036
+ // ../../node_modules/zod/v4/core/schemas.js
3037
3037
  var $ZodType = /* @__PURE__ */ $constructor("$ZodType", (inst, def) => {
3038
3038
  var _a;
3039
3039
  inst ?? (inst = {});
@@ -4856,7 +4856,7 @@ function handleRefineResult(result, payload, input, inst) {
4856
4856
  payload.issues.push(issue(_iss));
4857
4857
  }
4858
4858
  }
4859
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/index.js
4859
+ // ../../node_modules/zod/v4/locales/index.js
4860
4860
  var exports_locales = {};
4861
4861
  __export(exports_locales, {
4862
4862
  zhTW: () => zh_TW_default,
@@ -4907,7 +4907,7 @@ __export(exports_locales, {
4907
4907
  ar: () => ar_default
4908
4908
  });
4909
4909
 
4910
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/ar.js
4910
+ // ../../node_modules/zod/v4/locales/ar.js
4911
4911
  var error = () => {
4912
4912
  const Sizable = {
4913
4913
  string: { unit: "حرف", verb: "أن يحوي" },
@@ -5023,7 +5023,7 @@ function ar_default() {
5023
5023
  localeError: error()
5024
5024
  };
5025
5025
  }
5026
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/az.js
5026
+ // ../../node_modules/zod/v4/locales/az.js
5027
5027
  var error2 = () => {
5028
5028
  const Sizable = {
5029
5029
  string: { unit: "simvol", verb: "olmalıdır" },
@@ -5138,7 +5138,7 @@ function az_default() {
5138
5138
  localeError: error2()
5139
5139
  };
5140
5140
  }
5141
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/be.js
5141
+ // ../../node_modules/zod/v4/locales/be.js
5142
5142
  function getBelarusianPlural(count, one, few, many) {
5143
5143
  const absCount = Math.abs(count);
5144
5144
  const lastDigit = absCount % 10;
@@ -5302,7 +5302,7 @@ function be_default() {
5302
5302
  localeError: error3()
5303
5303
  };
5304
5304
  }
5305
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/ca.js
5305
+ // ../../node_modules/zod/v4/locales/ca.js
5306
5306
  var error4 = () => {
5307
5307
  const Sizable = {
5308
5308
  string: { unit: "caràcters", verb: "contenir" },
@@ -5419,7 +5419,7 @@ function ca_default() {
5419
5419
  localeError: error4()
5420
5420
  };
5421
5421
  }
5422
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/cs.js
5422
+ // ../../node_modules/zod/v4/locales/cs.js
5423
5423
  var error5 = () => {
5424
5424
  const Sizable = {
5425
5425
  string: { unit: "znaků", verb: "mít" },
@@ -5554,7 +5554,7 @@ function cs_default() {
5554
5554
  localeError: error5()
5555
5555
  };
5556
5556
  }
5557
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/da.js
5557
+ // ../../node_modules/zod/v4/locales/da.js
5558
5558
  var error6 = () => {
5559
5559
  const Sizable = {
5560
5560
  string: { unit: "tegn", verb: "havde" },
@@ -5685,7 +5685,7 @@ function da_default() {
5685
5685
  localeError: error6()
5686
5686
  };
5687
5687
  }
5688
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/de.js
5688
+ // ../../node_modules/zod/v4/locales/de.js
5689
5689
  var error7 = () => {
5690
5690
  const Sizable = {
5691
5691
  string: { unit: "Zeichen", verb: "zu haben" },
@@ -5801,7 +5801,7 @@ function de_default() {
5801
5801
  localeError: error7()
5802
5802
  };
5803
5803
  }
5804
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/en.js
5804
+ // ../../node_modules/zod/v4/locales/en.js
5805
5805
  var parsedType = (data) => {
5806
5806
  const t = typeof data;
5807
5807
  switch (t) {
@@ -5918,7 +5918,7 @@ function en_default() {
5918
5918
  localeError: error8()
5919
5919
  };
5920
5920
  }
5921
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/eo.js
5921
+ // ../../node_modules/zod/v4/locales/eo.js
5922
5922
  var parsedType2 = (data) => {
5923
5923
  const t = typeof data;
5924
5924
  switch (t) {
@@ -6034,7 +6034,7 @@ function eo_default() {
6034
6034
  localeError: error9()
6035
6035
  };
6036
6036
  }
6037
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/es.js
6037
+ // ../../node_modules/zod/v4/locales/es.js
6038
6038
  var error10 = () => {
6039
6039
  const Sizable = {
6040
6040
  string: { unit: "caracteres", verb: "tener" },
@@ -6182,7 +6182,7 @@ function es_default() {
6182
6182
  localeError: error10()
6183
6183
  };
6184
6184
  }
6185
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/fa.js
6185
+ // ../../node_modules/zod/v4/locales/fa.js
6186
6186
  var error11 = () => {
6187
6187
  const Sizable = {
6188
6188
  string: { unit: "کاراکتر", verb: "داشته باشد" },
@@ -6304,7 +6304,7 @@ function fa_default() {
6304
6304
  localeError: error11()
6305
6305
  };
6306
6306
  }
6307
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/fi.js
6307
+ // ../../node_modules/zod/v4/locales/fi.js
6308
6308
  var error12 = () => {
6309
6309
  const Sizable = {
6310
6310
  string: { unit: "merkkiä", subject: "merkkijonon" },
@@ -6426,7 +6426,7 @@ function fi_default() {
6426
6426
  localeError: error12()
6427
6427
  };
6428
6428
  }
6429
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/fr.js
6429
+ // ../../node_modules/zod/v4/locales/fr.js
6430
6430
  var error13 = () => {
6431
6431
  const Sizable = {
6432
6432
  string: { unit: "caractères", verb: "avoir" },
@@ -6542,7 +6542,7 @@ function fr_default() {
6542
6542
  localeError: error13()
6543
6543
  };
6544
6544
  }
6545
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/fr-CA.js
6545
+ // ../../node_modules/zod/v4/locales/fr-CA.js
6546
6546
  var error14 = () => {
6547
6547
  const Sizable = {
6548
6548
  string: { unit: "caractères", verb: "avoir" },
@@ -6659,7 +6659,7 @@ function fr_CA_default() {
6659
6659
  localeError: error14()
6660
6660
  };
6661
6661
  }
6662
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/he.js
6662
+ // ../../node_modules/zod/v4/locales/he.js
6663
6663
  var error15 = () => {
6664
6664
  const Sizable = {
6665
6665
  string: { unit: "אותיות", verb: "לכלול" },
@@ -6775,7 +6775,7 @@ function he_default() {
6775
6775
  localeError: error15()
6776
6776
  };
6777
6777
  }
6778
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/hu.js
6778
+ // ../../node_modules/zod/v4/locales/hu.js
6779
6779
  var error16 = () => {
6780
6780
  const Sizable = {
6781
6781
  string: { unit: "karakter", verb: "legyen" },
@@ -6891,7 +6891,7 @@ function hu_default() {
6891
6891
  localeError: error16()
6892
6892
  };
6893
6893
  }
6894
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/id.js
6894
+ // ../../node_modules/zod/v4/locales/id.js
6895
6895
  var error17 = () => {
6896
6896
  const Sizable = {
6897
6897
  string: { unit: "karakter", verb: "memiliki" },
@@ -7007,7 +7007,7 @@ function id_default() {
7007
7007
  localeError: error17()
7008
7008
  };
7009
7009
  }
7010
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/is.js
7010
+ // ../../node_modules/zod/v4/locales/is.js
7011
7011
  var parsedType3 = (data) => {
7012
7012
  const t = typeof data;
7013
7013
  switch (t) {
@@ -7124,7 +7124,7 @@ function is_default() {
7124
7124
  localeError: error18()
7125
7125
  };
7126
7126
  }
7127
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/it.js
7127
+ // ../../node_modules/zod/v4/locales/it.js
7128
7128
  var error19 = () => {
7129
7129
  const Sizable = {
7130
7130
  string: { unit: "caratteri", verb: "avere" },
@@ -7240,7 +7240,7 @@ function it_default() {
7240
7240
  localeError: error19()
7241
7241
  };
7242
7242
  }
7243
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/ja.js
7243
+ // ../../node_modules/zod/v4/locales/ja.js
7244
7244
  var error20 = () => {
7245
7245
  const Sizable = {
7246
7246
  string: { unit: "文字", verb: "である" },
@@ -7355,7 +7355,7 @@ function ja_default() {
7355
7355
  localeError: error20()
7356
7356
  };
7357
7357
  }
7358
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/ka.js
7358
+ // ../../node_modules/zod/v4/locales/ka.js
7359
7359
  var parsedType4 = (data) => {
7360
7360
  const t = typeof data;
7361
7361
  switch (t) {
@@ -7480,7 +7480,7 @@ function ka_default() {
7480
7480
  localeError: error21()
7481
7481
  };
7482
7482
  }
7483
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/km.js
7483
+ // ../../node_modules/zod/v4/locales/km.js
7484
7484
  var error22 = () => {
7485
7485
  const Sizable = {
7486
7486
  string: { unit: "តួអក្សរ", verb: "គួរមាន" },
@@ -7598,11 +7598,11 @@ function km_default() {
7598
7598
  };
7599
7599
  }
7600
7600
 
7601
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/kh.js
7601
+ // ../../node_modules/zod/v4/locales/kh.js
7602
7602
  function kh_default() {
7603
7603
  return km_default();
7604
7604
  }
7605
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/ko.js
7605
+ // ../../node_modules/zod/v4/locales/ko.js
7606
7606
  var error23 = () => {
7607
7607
  const Sizable = {
7608
7608
  string: { unit: "문자", verb: "to have" },
@@ -7723,7 +7723,7 @@ function ko_default() {
7723
7723
  localeError: error23()
7724
7724
  };
7725
7725
  }
7726
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/lt.js
7726
+ // ../../node_modules/zod/v4/locales/lt.js
7727
7727
  var parsedType5 = (data) => {
7728
7728
  const t = typeof data;
7729
7729
  return parsedTypeFromType(t, data);
@@ -7952,7 +7952,7 @@ function lt_default() {
7952
7952
  localeError: error24()
7953
7953
  };
7954
7954
  }
7955
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/mk.js
7955
+ // ../../node_modules/zod/v4/locales/mk.js
7956
7956
  var error25 = () => {
7957
7957
  const Sizable = {
7958
7958
  string: { unit: "знаци", verb: "да имаат" },
@@ -8069,7 +8069,7 @@ function mk_default() {
8069
8069
  localeError: error25()
8070
8070
  };
8071
8071
  }
8072
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/ms.js
8072
+ // ../../node_modules/zod/v4/locales/ms.js
8073
8073
  var error26 = () => {
8074
8074
  const Sizable = {
8075
8075
  string: { unit: "aksara", verb: "mempunyai" },
@@ -8185,7 +8185,7 @@ function ms_default() {
8185
8185
  localeError: error26()
8186
8186
  };
8187
8187
  }
8188
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/nl.js
8188
+ // ../../node_modules/zod/v4/locales/nl.js
8189
8189
  var error27 = () => {
8190
8190
  const Sizable = {
8191
8191
  string: { unit: "tekens" },
@@ -8302,7 +8302,7 @@ function nl_default() {
8302
8302
  localeError: error27()
8303
8303
  };
8304
8304
  }
8305
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/no.js
8305
+ // ../../node_modules/zod/v4/locales/no.js
8306
8306
  var error28 = () => {
8307
8307
  const Sizable = {
8308
8308
  string: { unit: "tegn", verb: "å ha" },
@@ -8418,7 +8418,7 @@ function no_default() {
8418
8418
  localeError: error28()
8419
8419
  };
8420
8420
  }
8421
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/ota.js
8421
+ // ../../node_modules/zod/v4/locales/ota.js
8422
8422
  var error29 = () => {
8423
8423
  const Sizable = {
8424
8424
  string: { unit: "harf", verb: "olmalıdır" },
@@ -8534,7 +8534,7 @@ function ota_default() {
8534
8534
  localeError: error29()
8535
8535
  };
8536
8536
  }
8537
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/ps.js
8537
+ // ../../node_modules/zod/v4/locales/ps.js
8538
8538
  var error30 = () => {
8539
8539
  const Sizable = {
8540
8540
  string: { unit: "توکي", verb: "ولري" },
@@ -8656,7 +8656,7 @@ function ps_default() {
8656
8656
  localeError: error30()
8657
8657
  };
8658
8658
  }
8659
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/pl.js
8659
+ // ../../node_modules/zod/v4/locales/pl.js
8660
8660
  var error31 = () => {
8661
8661
  const Sizable = {
8662
8662
  string: { unit: "znaków", verb: "mieć" },
@@ -8773,7 +8773,7 @@ function pl_default() {
8773
8773
  localeError: error31()
8774
8774
  };
8775
8775
  }
8776
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/pt.js
8776
+ // ../../node_modules/zod/v4/locales/pt.js
8777
8777
  var error32 = () => {
8778
8778
  const Sizable = {
8779
8779
  string: { unit: "caracteres", verb: "ter" },
@@ -8889,7 +8889,7 @@ function pt_default() {
8889
8889
  localeError: error32()
8890
8890
  };
8891
8891
  }
8892
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/ru.js
8892
+ // ../../node_modules/zod/v4/locales/ru.js
8893
8893
  function getRussianPlural(count, one, few, many) {
8894
8894
  const absCount = Math.abs(count);
8895
8895
  const lastDigit = absCount % 10;
@@ -9053,7 +9053,7 @@ function ru_default() {
9053
9053
  localeError: error33()
9054
9054
  };
9055
9055
  }
9056
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/sl.js
9056
+ // ../../node_modules/zod/v4/locales/sl.js
9057
9057
  var error34 = () => {
9058
9058
  const Sizable = {
9059
9059
  string: { unit: "znakov", verb: "imeti" },
@@ -9170,7 +9170,7 @@ function sl_default() {
9170
9170
  localeError: error34()
9171
9171
  };
9172
9172
  }
9173
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/sv.js
9173
+ // ../../node_modules/zod/v4/locales/sv.js
9174
9174
  var error35 = () => {
9175
9175
  const Sizable = {
9176
9176
  string: { unit: "tecken", verb: "att ha" },
@@ -9288,7 +9288,7 @@ function sv_default() {
9288
9288
  localeError: error35()
9289
9289
  };
9290
9290
  }
9291
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/ta.js
9291
+ // ../../node_modules/zod/v4/locales/ta.js
9292
9292
  var error36 = () => {
9293
9293
  const Sizable = {
9294
9294
  string: { unit: "எழுத்துக்கள்", verb: "கொண்டிருக்க வேண்டும்" },
@@ -9405,7 +9405,7 @@ function ta_default() {
9405
9405
  localeError: error36()
9406
9406
  };
9407
9407
  }
9408
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/th.js
9408
+ // ../../node_modules/zod/v4/locales/th.js
9409
9409
  var error37 = () => {
9410
9410
  const Sizable = {
9411
9411
  string: { unit: "ตัวอักษร", verb: "ควรมี" },
@@ -9522,7 +9522,7 @@ function th_default() {
9522
9522
  localeError: error37()
9523
9523
  };
9524
9524
  }
9525
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/tr.js
9525
+ // ../../node_modules/zod/v4/locales/tr.js
9526
9526
  var parsedType6 = (data) => {
9527
9527
  const t = typeof data;
9528
9528
  switch (t) {
@@ -9637,7 +9637,7 @@ function tr_default() {
9637
9637
  localeError: error38()
9638
9638
  };
9639
9639
  }
9640
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/uk.js
9640
+ // ../../node_modules/zod/v4/locales/uk.js
9641
9641
  var error39 = () => {
9642
9642
  const Sizable = {
9643
9643
  string: { unit: "символів", verb: "матиме" },
@@ -9754,11 +9754,11 @@ function uk_default() {
9754
9754
  };
9755
9755
  }
9756
9756
 
9757
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/ua.js
9757
+ // ../../node_modules/zod/v4/locales/ua.js
9758
9758
  function ua_default() {
9759
9759
  return uk_default();
9760
9760
  }
9761
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/ur.js
9761
+ // ../../node_modules/zod/v4/locales/ur.js
9762
9762
  var error40 = () => {
9763
9763
  const Sizable = {
9764
9764
  string: { unit: "حروف", verb: "ہونا" },
@@ -9875,7 +9875,7 @@ function ur_default() {
9875
9875
  localeError: error40()
9876
9876
  };
9877
9877
  }
9878
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/vi.js
9878
+ // ../../node_modules/zod/v4/locales/vi.js
9879
9879
  var error41 = () => {
9880
9880
  const Sizable = {
9881
9881
  string: { unit: "ký tự", verb: "có" },
@@ -9991,7 +9991,7 @@ function vi_default() {
9991
9991
  localeError: error41()
9992
9992
  };
9993
9993
  }
9994
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/zh-CN.js
9994
+ // ../../node_modules/zod/v4/locales/zh-CN.js
9995
9995
  var error42 = () => {
9996
9996
  const Sizable = {
9997
9997
  string: { unit: "字符", verb: "包含" },
@@ -10107,7 +10107,7 @@ function zh_CN_default() {
10107
10107
  localeError: error42()
10108
10108
  };
10109
10109
  }
10110
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/zh-TW.js
10110
+ // ../../node_modules/zod/v4/locales/zh-TW.js
10111
10111
  var error43 = () => {
10112
10112
  const Sizable = {
10113
10113
  string: { unit: "字元", verb: "擁有" },
@@ -10224,7 +10224,7 @@ function zh_TW_default() {
10224
10224
  localeError: error43()
10225
10225
  };
10226
10226
  }
10227
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/locales/yo.js
10227
+ // ../../node_modules/zod/v4/locales/yo.js
10228
10228
  var error44 = () => {
10229
10229
  const Sizable = {
10230
10230
  string: { unit: "àmi", verb: "ní" },
@@ -10339,7 +10339,7 @@ function yo_default() {
10339
10339
  localeError: error44()
10340
10340
  };
10341
10341
  }
10342
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/core/registries.js
10342
+ // ../../node_modules/zod/v4/core/registries.js
10343
10343
  var $output = Symbol("ZodOutput");
10344
10344
  var $input = Symbol("ZodInput");
10345
10345
 
@@ -10390,7 +10390,7 @@ function registry() {
10390
10390
  return new $ZodRegistry;
10391
10391
  }
10392
10392
  var globalRegistry = /* @__PURE__ */ registry();
10393
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/core/api.js
10393
+ // ../../node_modules/zod/v4/core/api.js
10394
10394
  function _string(Class2, params) {
10395
10395
  return new Class2({
10396
10396
  type: "string",
@@ -11268,7 +11268,7 @@ function _stringFormat(Class2, format, fnOrRegex, _params = {}) {
11268
11268
  const inst = new Class2(def);
11269
11269
  return inst;
11270
11270
  }
11271
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/core/to-json-schema.js
11271
+ // ../../node_modules/zod/v4/core/to-json-schema.js
11272
11272
  class JSONSchemaGenerator {
11273
11273
  constructor(params) {
11274
11274
  this.counter = 0;
@@ -12072,9 +12072,9 @@ function isTransforming(_schema, _ctx) {
12072
12072
  }
12073
12073
  throw new Error(`Unknown schema type: ${def.type}`);
12074
12074
  }
12075
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/core/json-schema.js
12075
+ // ../../node_modules/zod/v4/core/json-schema.js
12076
12076
  var exports_json_schema = {};
12077
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/classic/iso.js
12077
+ // ../../node_modules/zod/v4/classic/iso.js
12078
12078
  var exports_iso = {};
12079
12079
  __export(exports_iso, {
12080
12080
  time: () => time2,
@@ -12115,7 +12115,7 @@ function duration2(params) {
12115
12115
  return _isoDuration(ZodISODuration, params);
12116
12116
  }
12117
12117
 
12118
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/classic/errors.js
12118
+ // ../../node_modules/zod/v4/classic/errors.js
12119
12119
  var initializer2 = (inst, issues) => {
12120
12120
  $ZodError.init(inst, issues);
12121
12121
  inst.name = "ZodError";
@@ -12150,7 +12150,7 @@ var ZodRealError = $constructor("ZodError", initializer2, {
12150
12150
  Parent: Error
12151
12151
  });
12152
12152
 
12153
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/classic/parse.js
12153
+ // ../../node_modules/zod/v4/classic/parse.js
12154
12154
  var parse3 = /* @__PURE__ */ _parse(ZodRealError);
12155
12155
  var parseAsync2 = /* @__PURE__ */ _parseAsync(ZodRealError);
12156
12156
  var safeParse2 = /* @__PURE__ */ _safeParse(ZodRealError);
@@ -12164,7 +12164,7 @@ var safeDecode2 = /* @__PURE__ */ _safeDecode(ZodRealError);
12164
12164
  var safeEncodeAsync2 = /* @__PURE__ */ _safeEncodeAsync(ZodRealError);
12165
12165
  var safeDecodeAsync2 = /* @__PURE__ */ _safeDecodeAsync(ZodRealError);
12166
12166
 
12167
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/classic/schemas.js
12167
+ // ../../node_modules/zod/v4/classic/schemas.js
12168
12168
  var ZodType = /* @__PURE__ */ $constructor("ZodType", (inst, def) => {
12169
12169
  $ZodType.init(inst, def);
12170
12170
  inst.def = def;
@@ -13139,7 +13139,7 @@ function json(params) {
13139
13139
  function preprocess(fn, schema) {
13140
13140
  return pipe(transform(fn), schema);
13141
13141
  }
13142
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/classic/compat.js
13142
+ // ../../node_modules/zod/v4/classic/compat.js
13143
13143
  var ZodIssueCode = {
13144
13144
  invalid_type: "invalid_type",
13145
13145
  too_big: "too_big",
@@ -13163,7 +13163,7 @@ function getErrorMap() {
13163
13163
  }
13164
13164
  var ZodFirstPartyTypeKind;
13165
13165
  (function(ZodFirstPartyTypeKind2) {})(ZodFirstPartyTypeKind || (ZodFirstPartyTypeKind = {}));
13166
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/classic/coerce.js
13166
+ // ../../node_modules/zod/v4/classic/coerce.js
13167
13167
  var exports_coerce = {};
13168
13168
  __export(exports_coerce, {
13169
13169
  string: () => string3,
@@ -13188,9 +13188,9 @@ function date4(params) {
13188
13188
  return _coercedDate(ZodDate, params);
13189
13189
  }
13190
13190
 
13191
- // ../../node_modules/.bun/zod@4.1.8/node_modules/zod/v4/classic/external.js
13191
+ // ../../node_modules/zod/v4/classic/external.js
13192
13192
  config(en_default());
13193
- // ../../node_modules/.bun/@opencode-ai+plugin@1.3.2/node_modules/@opencode-ai/plugin/dist/tool.js
13193
+ // ../../node_modules/@opencode-ai/plugin/dist/tool.js
13194
13194
  function tool(input) {
13195
13195
  return input;
13196
13196
  }
@@ -14303,12 +14303,22 @@ When batch complete:
14303
14303
  ### Step 4.5: Post-Batch Hygienic Review
14304
14304
 
14305
14305
  After the batch report, ask the operator if they want a Hygienic code review for the batch.
14306
- If yes, run \`task({ subagent_type: "hygienic", prompt: "Review implementation changes from the latest batch." })\` and apply feedback before starting the next batch.
14306
+ If yes, run \`task({ subagent_type: "hygienic", prompt: "Review implementation changes from the latest batch." })\`.
14307
+ Route review feedback through this decision tree before continuing:
14308
+
14309
+ | Feedback type | Action |
14310
+ |---------------|--------|
14311
+ | Minor / local to the completed batch | **Inline fix** — apply directly, no new task |
14312
+ | New isolated work that does not affect downstream sequencing | **Manual task** — \`hive_task_create()\` for non-blocking ad-hoc work |
14313
+ | Changes downstream sequencing, dependencies, or scope | **Plan amendment** — update \`plan.md\`, then \`hive_tasks_sync({ refreshPending: true })\` to rewrite pending tasks from the amended plan |
14314
+
14315
+ When amending the plan: append new task numbers at the end (do not renumber), update \`Depends on:\` entries to express the new DAG order, then sync.
14307
14316
 
14308
14317
  ### Step 5: Continue
14309
- Based on feedback:
14310
- - Apply changes if needed
14311
- - Execute next batch
14318
+ After applying review feedback (or if none):
14319
+ - Re-check \`hive_status()\` for the updated **runnable** set — tasks whose dependencies are all satisfied
14320
+ - Tasks blocked by unmet dependencies stay blocked until predecessors complete
14321
+ - Execute the next batch of runnable tasks
14312
14322
  - Repeat until complete
14313
14323
 
14314
14324
  ### Step 6: Complete Development
@@ -15890,7 +15900,18 @@ After completing and merging a batch:
15890
15900
  1. Ask the user via \`question()\` if they want a Hygienic code review for the batch.
15891
15901
  2. If yes → default to built-in \`hygienic-reviewer\`; choose a configured hygienic-derived reviewer only when its description in \`Configured Custom Subagents\` is a better match.
15892
15902
  3. Then run \`task({ subagent_type: "<chosen-reviewer>", prompt: "Review implementation changes from the latest batch." })\`.
15893
- 4. Apply feedback before starting the next batch.
15903
+ 4. Route review feedback through this decision tree before starting the next batch:
15904
+
15905
+ #### Review Follow-Up Routing
15906
+
15907
+ | Feedback type | Action |
15908
+ |---------------|--------|
15909
+ | Minor / local to the completed batch | **Inline fix** — apply directly, no new task |
15910
+ | New isolated work that does not affect downstream sequencing | **Manual task** — \`hive_task_create()\` for non-blocking ad-hoc work |
15911
+ | Changes downstream sequencing, dependencies, or scope | **Plan amendment** — update \`plan.md\`, then \`hive_tasks_sync({ refreshPending: true })\` to rewrite pending tasks from the amended plan |
15912
+
15913
+ When amending the plan: append new task numbers at the end (do not renumber), update \`Depends on:\` entries to express the new DAG order, then sync.
15914
+ After sync, re-check \`hive_status()\` for the updated **runnable** set before dispatching.
15894
15915
 
15895
15916
  ### AGENTS.md Maintenance
15896
15917
  After feature completion (all tasks merged):
@@ -16169,7 +16190,19 @@ Merge after batch completes, then verify the merged result.
16169
16190
 
16170
16191
  After completing and merging a batch: ask via \`question()\` if they want a Hygienic review.
16171
16192
  If yes, default to built-in \`hygienic-reviewer\`; choose a configured hygienic-derived reviewer only when its description in \`Configured Custom Subagents\` is a better match.
16172
- Then run \`task({ subagent_type: "<chosen-reviewer>", prompt: "Review implementation changes from the latest batch." })\` and apply feedback before the next batch.
16193
+ Then run \`task({ subagent_type: "<chosen-reviewer>", prompt: "Review implementation changes from the latest batch." })\`.
16194
+ Route review feedback through this decision tree before starting the next batch:
16195
+
16196
+ #### Review Follow-Up Routing
16197
+
16198
+ | Feedback type | Action |
16199
+ |---------------|--------|
16200
+ | Minor / local to the completed batch | **Inline fix** — apply directly, no new task |
16201
+ | New isolated work that does not affect downstream sequencing | **Manual task** — \`hive_task_create()\` for non-blocking ad-hoc work |
16202
+ | Changes downstream sequencing, dependencies, or scope | **Plan amendment** — update \`plan.md\`, then \`hive_tasks_sync({ refreshPending: true })\` to rewrite pending tasks from the amended plan |
16203
+
16204
+ When amending the plan: append new task numbers at the end (do not renumber), update \`Depends on:\` entries to express the new DAG order, then sync.
16205
+ After sync, re-check \`hive_status()\` for the updated **runnable** set before dispatching.
16173
16206
 
16174
16207
  ### AGENTS.md Maintenance
16175
16208
 
@@ -16738,6 +16771,9 @@ function getFeaturesPath(projectRoot) {
16738
16771
  function getActiveFeaturePath(projectRoot) {
16739
16772
  return path2.join(getHivePath(projectRoot), ACTIVE_FEATURE_FILE);
16740
16773
  }
16774
+ function getGlobalSessionsPath(projectRoot) {
16775
+ return path2.join(getHivePath(projectRoot), "sessions.json");
16776
+ }
16741
16777
  function parseIndexedFeatureDirectoryName(directoryName) {
16742
16778
  const match = directoryName.match(/^(\d+)[_-](.+)$/);
16743
16779
  if (!match) {
@@ -17313,13 +17349,20 @@ class PlanService {
17313
17349
  // ../hive-core/src/services/taskService.ts
17314
17350
  import * as fs6 from "fs";
17315
17351
  var TASK_STATUS_SCHEMA_VERSION = 1;
17352
+ var EXECUTION_HISTORY_STATUSES = new Set([
17353
+ "in_progress",
17354
+ "done",
17355
+ "blocked",
17356
+ "failed",
17357
+ "partial"
17358
+ ]);
17316
17359
 
17317
17360
  class TaskService {
17318
17361
  projectRoot;
17319
17362
  constructor(projectRoot) {
17320
17363
  this.projectRoot = projectRoot;
17321
17364
  }
17322
- sync(featureName) {
17365
+ sync(featureName, options) {
17323
17366
  const planPath = getPlanPath(this.projectRoot, featureName);
17324
17367
  const planContent = readText(planPath);
17325
17368
  if (!planContent) {
@@ -17335,12 +17378,13 @@ class TaskService {
17335
17378
  manual: []
17336
17379
  };
17337
17380
  const existingByName = new Map(existingTasks.map((t) => [t.folder, t]));
17381
+ const refreshPending = options?.refreshPending === true;
17338
17382
  for (const existing of existingTasks) {
17339
17383
  if (existing.origin === "manual") {
17340
17384
  result.manual.push(existing.folder);
17341
17385
  continue;
17342
17386
  }
17343
- if (existing.status === "done" || existing.status === "in_progress") {
17387
+ if (EXECUTION_HISTORY_STATUSES.has(existing.status)) {
17344
17388
  result.kept.push(existing.folder);
17345
17389
  continue;
17346
17390
  }
@@ -17353,6 +17397,12 @@ class TaskService {
17353
17397
  if (!stillInPlan) {
17354
17398
  this.deleteTask(featureName, existing.folder);
17355
17399
  result.removed.push(existing.folder);
17400
+ } else if (refreshPending && existing.status === "pending") {
17401
+ const planTask = planTasks.find((p) => p.folder === existing.folder);
17402
+ if (planTask) {
17403
+ this.refreshPendingTask(featureName, planTask, planTasks, planContent);
17404
+ }
17405
+ result.kept.push(existing.folder);
17356
17406
  } else {
17357
17407
  result.kept.push(existing.folder);
17358
17408
  }
@@ -17365,19 +17415,34 @@ class TaskService {
17365
17415
  }
17366
17416
  return result;
17367
17417
  }
17368
- create(featureName, name, order) {
17418
+ create(featureName, name, order, metadata) {
17369
17419
  const tasksPath = getTasksPath(this.projectRoot, featureName);
17370
17420
  const existingFolders = this.listFolders(featureName);
17421
+ if (metadata?.source === "review" && metadata.dependsOn && metadata.dependsOn.length > 0) {
17422
+ throw new Error(`Review-sourced manual tasks cannot have explicit dependsOn. ` + `Cross-task dependencies require a plan amendment. ` + `Either remove the dependsOn field or amend the plan to express the dependency.`);
17423
+ }
17371
17424
  const nextOrder = order ?? this.getNextOrder(existingFolders);
17372
17425
  const folder = `${String(nextOrder).padStart(2, "0")}-${name}`;
17426
+ const collision = existingFolders.find((f) => {
17427
+ const match = f.match(/^(\d+)-/);
17428
+ return match && parseInt(match[1], 10) === nextOrder;
17429
+ });
17430
+ if (collision) {
17431
+ throw new Error(`Task folder collision: order ${nextOrder} already exists as "${collision}". ` + `Choose a different order number or omit to auto-increment.`);
17432
+ }
17373
17433
  const taskPath = getTaskPath(this.projectRoot, featureName, folder);
17374
17434
  ensureDir(taskPath);
17435
+ const dependsOn = metadata?.dependsOn ?? [];
17375
17436
  const status = {
17376
17437
  status: "pending",
17377
17438
  origin: "manual",
17378
- planTitle: name
17439
+ planTitle: name,
17440
+ dependsOn,
17441
+ ...metadata ? { metadata: { ...metadata, dependsOn: undefined } } : {}
17379
17442
  };
17380
17443
  writeJson(getTaskStatusPath(this.projectRoot, featureName, folder), status);
17444
+ const specContent = this.buildManualTaskSpec(featureName, folder, name, dependsOn, metadata);
17445
+ writeText(getTaskSpecPath(this.projectRoot, featureName, folder), specContent);
17381
17446
  return folder;
17382
17447
  }
17383
17448
  createFromPlan(featureName, task, allTasks, planContent) {
@@ -17400,6 +17465,27 @@ class TaskService {
17400
17465
  });
17401
17466
  writeText(getTaskSpecPath(this.projectRoot, featureName, task.folder), specContent);
17402
17467
  }
17468
+ refreshPendingTask(featureName, task, allTasks, planContent) {
17469
+ const dependsOn = this.resolveDependencies(task, allTasks);
17470
+ const statusPath = getTaskStatusPath(this.projectRoot, featureName, task.folder);
17471
+ const current = readJson(statusPath);
17472
+ if (current) {
17473
+ const updated = {
17474
+ ...current,
17475
+ planTitle: task.name,
17476
+ dependsOn
17477
+ };
17478
+ writeJson(statusPath, updated);
17479
+ }
17480
+ const specContent = this.buildSpecContent({
17481
+ featureName,
17482
+ task,
17483
+ dependsOn,
17484
+ allTasks,
17485
+ planContent
17486
+ });
17487
+ writeText(getTaskSpecPath(this.projectRoot, featureName, task.folder), specContent);
17488
+ }
17403
17489
  buildSpecContent(params) {
17404
17490
  const { featureName, task, dependsOn, allTasks, planContent, contextFiles = [], completedTasks = [] } = params;
17405
17491
  const getTaskType = (planSection2, taskName) => {
@@ -17561,6 +17647,10 @@ ${f.content}`).join(`
17561
17647
  writeText(specPath, content);
17562
17648
  return specPath;
17563
17649
  }
17650
+ readSpec(featureName, taskFolder) {
17651
+ const specPath = getTaskSpecPath(this.projectRoot, featureName, taskFolder);
17652
+ return readText(specPath);
17653
+ }
17564
17654
  update(featureName, taskFolder, updates, lockOptions) {
17565
17655
  const statusPath = getTaskStatusPath(this.projectRoot, featureName, taskFolder);
17566
17656
  if (!fileExists(statusPath)) {
@@ -17857,6 +17947,63 @@ _Add detailed instructions here_
17857
17947
  const subtaskOrder = subtaskId.split(".")[1];
17858
17948
  return folders.find((f) => f.startsWith(`${subtaskOrder}-`)) || null;
17859
17949
  }
17950
+ buildManualTaskSpec(featureName, folder, name, dependsOn, metadata) {
17951
+ const lines = [
17952
+ `# Task: ${folder}`,
17953
+ "",
17954
+ `## Feature: ${featureName}`,
17955
+ "",
17956
+ "## Dependencies",
17957
+ ""
17958
+ ];
17959
+ if (dependsOn.length > 0) {
17960
+ for (const dep of dependsOn) {
17961
+ lines.push(`- ${dep}`);
17962
+ }
17963
+ } else {
17964
+ lines.push("_None_");
17965
+ }
17966
+ lines.push("");
17967
+ if (metadata?.goal) {
17968
+ lines.push("## Goal", "", metadata.goal, "");
17969
+ }
17970
+ if (metadata?.description) {
17971
+ lines.push("## Description", "", metadata.description, "");
17972
+ }
17973
+ if (metadata?.acceptanceCriteria && metadata.acceptanceCriteria.length > 0) {
17974
+ lines.push("## Acceptance Criteria", "");
17975
+ for (const criterion of metadata.acceptanceCriteria) {
17976
+ lines.push(`- ${criterion}`);
17977
+ }
17978
+ lines.push("");
17979
+ }
17980
+ if (metadata?.files && metadata.files.length > 0) {
17981
+ lines.push("## Files", "");
17982
+ for (const file2 of metadata.files) {
17983
+ lines.push(`- ${file2}`);
17984
+ }
17985
+ lines.push("");
17986
+ }
17987
+ if (metadata?.references && metadata.references.length > 0) {
17988
+ lines.push("## References", "");
17989
+ for (const ref of metadata.references) {
17990
+ lines.push(`- ${ref}`);
17991
+ }
17992
+ lines.push("");
17993
+ }
17994
+ if (metadata?.source || metadata?.reason) {
17995
+ lines.push("## Origin", "");
17996
+ if (metadata?.source) {
17997
+ lines.push(`**Source:** ${metadata.source}`);
17998
+ }
17999
+ if (metadata?.reason) {
18000
+ lines.push(`**Reason:** ${metadata.reason}`);
18001
+ }
18002
+ lines.push("");
18003
+ }
18004
+ return lines.join(`
18005
+ `);
18006
+ }
17860
18007
  slugify(name) {
17861
18008
  return name.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "");
17862
18009
  }
@@ -17865,7 +18012,7 @@ _Add detailed instructions here_
17865
18012
  import * as fs7 from "fs/promises";
17866
18013
  import * as path5 from "path";
17867
18014
 
17868
- // ../../node_modules/.bun/simple-git@3.33.0/node_modules/simple-git/dist/esm/index.js
18015
+ // ../../node_modules/simple-git/dist/esm/index.js
17869
18016
  var import_file_exists = __toESM(require_dist(), 1);
17870
18017
  var import_debug = __toESM(require_src(), 1);
17871
18018
  var import_promise_deferred = __toESM(require_dist2(), 1);
@@ -18110,7 +18257,7 @@ var init_argument_filters = __esm({
18110
18257
  return typeof input === "number";
18111
18258
  };
18112
18259
  filterString = (input) => {
18113
- return typeof input === "string" || isPathSpec(input);
18260
+ return typeof input === "string";
18114
18261
  };
18115
18262
  filterStringOrStringArray = (input) => {
18116
18263
  return filterString(input) || Array.isArray(input) && input.every(filterString);
@@ -20251,15 +20398,15 @@ function parser3(indexX, indexY, handler) {
20251
20398
  return [`${indexX}${indexY}`, handler];
20252
20399
  }
20253
20400
  function conflicts(indexX, ...indexY) {
20254
- return indexY.map((y) => parser3(indexX, y, (result, file2) => result.conflicted.push(file2)));
20401
+ return indexY.map((y) => parser3(indexX, y, (result, file2) => append(result.conflicted, file2)));
20255
20402
  }
20256
20403
  function splitLine(result, lineStr) {
20257
20404
  const trimmed2 = lineStr.trim();
20258
20405
  switch (" ") {
20259
20406
  case trimmed2.charAt(2):
20260
- return data(trimmed2.charAt(0), trimmed2.charAt(1), trimmed2.slice(3));
20407
+ return data(trimmed2.charAt(0), trimmed2.charAt(1), trimmed2.substr(3));
20261
20408
  case trimmed2.charAt(1):
20262
- return data(" ", trimmed2.charAt(0), trimmed2.slice(2));
20409
+ return data(" ", trimmed2.charAt(0), trimmed2.substr(2));
20263
20410
  default:
20264
20411
  return;
20265
20412
  }
@@ -20303,42 +20450,26 @@ var init_StatusSummary = __esm({
20303
20450
  }
20304
20451
  };
20305
20452
  parsers6 = new Map([
20306
- parser3(" ", "A", (result, file2) => result.created.push(file2)),
20307
- parser3(" ", "D", (result, file2) => result.deleted.push(file2)),
20308
- parser3(" ", "M", (result, file2) => result.modified.push(file2)),
20309
- parser3("A", " ", (result, file2) => {
20310
- result.created.push(file2);
20311
- result.staged.push(file2);
20312
- }),
20313
- parser3("A", "M", (result, file2) => {
20314
- result.created.push(file2);
20315
- result.staged.push(file2);
20316
- result.modified.push(file2);
20317
- }),
20318
- parser3("D", " ", (result, file2) => {
20319
- result.deleted.push(file2);
20320
- result.staged.push(file2);
20321
- }),
20322
- parser3("M", " ", (result, file2) => {
20323
- result.modified.push(file2);
20324
- result.staged.push(file2);
20325
- }),
20326
- parser3("M", "M", (result, file2) => {
20327
- result.modified.push(file2);
20328
- result.staged.push(file2);
20329
- }),
20453
+ parser3(" ", "A", (result, file2) => append(result.created, file2)),
20454
+ parser3(" ", "D", (result, file2) => append(result.deleted, file2)),
20455
+ parser3(" ", "M", (result, file2) => append(result.modified, file2)),
20456
+ parser3("A", " ", (result, file2) => append(result.created, file2) && append(result.staged, file2)),
20457
+ parser3("A", "M", (result, file2) => append(result.created, file2) && append(result.staged, file2) && append(result.modified, file2)),
20458
+ parser3("D", " ", (result, file2) => append(result.deleted, file2) && append(result.staged, file2)),
20459
+ parser3("M", " ", (result, file2) => append(result.modified, file2) && append(result.staged, file2)),
20460
+ parser3("M", "M", (result, file2) => append(result.modified, file2) && append(result.staged, file2)),
20330
20461
  parser3("R", " ", (result, file2) => {
20331
- result.renamed.push(renamedFile(file2));
20462
+ append(result.renamed, renamedFile(file2));
20332
20463
  }),
20333
20464
  parser3("R", "M", (result, file2) => {
20334
20465
  const renamed = renamedFile(file2);
20335
- result.renamed.push(renamed);
20336
- result.modified.push(renamed.to);
20466
+ append(result.renamed, renamed);
20467
+ append(result.modified, renamed.to);
20337
20468
  }),
20338
20469
  parser3("!", "!", (_result, _file2) => {
20339
- (_result.ignored = _result.ignored || []).push(_file2);
20470
+ append(_result.ignored = _result.ignored || [], _file2);
20340
20471
  }),
20341
- parser3("?", "?", (result, file2) => result.not_added.push(file2)),
20472
+ parser3("?", "?", (result, file2) => append(result.not_added, file2)),
20342
20473
  ...conflicts("A", "A", "U"),
20343
20474
  ...conflicts("D", "D", "U"),
20344
20475
  ...conflicts("U", "A", "D", "U"),
@@ -20464,41 +20595,6 @@ var init_version = __esm({
20464
20595
  ];
20465
20596
  }
20466
20597
  });
20467
- function createCloneTask(api2, task, repoPath, ...args) {
20468
- if (!filterString(repoPath)) {
20469
- return configurationErrorTask(`git.${api2}() requires a string 'repoPath'`);
20470
- }
20471
- return task(repoPath, filterType(args[0], filterString), getTrailingOptions(arguments));
20472
- }
20473
- function clone_default() {
20474
- return {
20475
- clone(repo, ...rest) {
20476
- return this._runTask(createCloneTask("clone", cloneTask, filterType(repo, filterString), ...rest), trailingFunctionArgument(arguments));
20477
- },
20478
- mirror(repo, ...rest) {
20479
- return this._runTask(createCloneTask("mirror", cloneMirrorTask, filterType(repo, filterString), ...rest), trailingFunctionArgument(arguments));
20480
- }
20481
- };
20482
- }
20483
- var cloneTask;
20484
- var cloneMirrorTask;
20485
- var init_clone = __esm({
20486
- "src/lib/tasks/clone.ts"() {
20487
- init_task();
20488
- init_utils();
20489
- init_pathspec();
20490
- cloneTask = (repo, directory, customArgs) => {
20491
- const commands = ["clone", ...customArgs];
20492
- filterString(repo) && commands.push(pathspec(repo));
20493
- filterString(directory) && commands.push(pathspec(directory));
20494
- return straightThroughStringTask(commands);
20495
- };
20496
- cloneMirrorTask = (repo, directory, customArgs) => {
20497
- append(customArgs, "--mirror");
20498
- return cloneTask(repo, directory, customArgs);
20499
- };
20500
- }
20501
- });
20502
20598
  var simple_git_api_exports = {};
20503
20599
  __export2(simple_git_api_exports, {
20504
20600
  SimpleGitApi: () => SimpleGitApi
@@ -20524,7 +20620,6 @@ var init_simple_git_api = __esm({
20524
20620
  init_task();
20525
20621
  init_version();
20526
20622
  init_utils();
20527
- init_clone();
20528
20623
  SimpleGitApi = class {
20529
20624
  constructor(_executor) {
20530
20625
  this._executor = _executor;
@@ -20587,7 +20682,7 @@ var init_simple_git_api = __esm({
20587
20682
  return this._runTask(statusTask(getTrailingOptions(arguments)), trailingFunctionArgument(arguments));
20588
20683
  }
20589
20684
  };
20590
- Object.assign(SimpleGitApi.prototype, checkout_default(), clone_default(), commit_default(), config_default(), count_objects_default(), first_commit_default(), grep_default(), log_default(), show_default(), version_default());
20685
+ Object.assign(SimpleGitApi.prototype, checkout_default(), commit_default(), config_default(), count_objects_default(), first_commit_default(), grep_default(), log_default(), show_default(), version_default());
20591
20686
  }
20592
20687
  });
20593
20688
  var scheduler_exports = {};
@@ -20875,6 +20970,34 @@ var init_check_ignore = __esm({
20875
20970
  init_CheckIgnore();
20876
20971
  }
20877
20972
  });
20973
+ var clone_exports = {};
20974
+ __export2(clone_exports, {
20975
+ cloneMirrorTask: () => cloneMirrorTask,
20976
+ cloneTask: () => cloneTask
20977
+ });
20978
+ function disallowedCommand(command) {
20979
+ return /^--upload-pack(=|$)/.test(command);
20980
+ }
20981
+ function cloneTask(repo, directory, customArgs) {
20982
+ const commands = ["clone", ...customArgs];
20983
+ filterString(repo) && commands.push(repo);
20984
+ filterString(directory) && commands.push(directory);
20985
+ const banned = commands.find(disallowedCommand);
20986
+ if (banned) {
20987
+ return configurationErrorTask(`git.fetch: potential exploit argument blocked.`);
20988
+ }
20989
+ return straightThroughStringTask(commands);
20990
+ }
20991
+ function cloneMirrorTask(repo, directory, customArgs) {
20992
+ append(customArgs, "--mirror");
20993
+ return cloneTask(repo, directory, customArgs);
20994
+ }
20995
+ var init_clone = __esm({
20996
+ "src/lib/tasks/clone.ts"() {
20997
+ init_task();
20998
+ init_utils();
20999
+ }
21000
+ });
20878
21001
  function parseFetchResult(stdOut, stdErr) {
20879
21002
  const result = {
20880
21003
  raw: stdOut,
@@ -20926,7 +21049,7 @@ var fetch_exports = {};
20926
21049
  __export2(fetch_exports, {
20927
21050
  fetchTask: () => fetchTask
20928
21051
  });
20929
- function disallowedCommand(command) {
21052
+ function disallowedCommand2(command) {
20930
21053
  return /^--upload-pack(=|$)/.test(command);
20931
21054
  }
20932
21055
  function fetchTask(remote, branch, customArgs) {
@@ -20934,7 +21057,7 @@ function fetchTask(remote, branch, customArgs) {
20934
21057
  if (remote && branch) {
20935
21058
  commands.push(remote, branch);
20936
21059
  }
20937
- const banned = commands.find(disallowedCommand);
21060
+ const banned = commands.find(disallowedCommand2);
20938
21061
  if (banned) {
20939
21062
  return configurationErrorTask(`git.fetch: potential exploit argument blocked.`);
20940
21063
  }
@@ -21233,7 +21356,7 @@ var require_git = __commonJS2({
21233
21356
  var { GitExecutor: GitExecutor2 } = (init_git_executor(), __toCommonJS(git_executor_exports));
21234
21357
  var { SimpleGitApi: SimpleGitApi2 } = (init_simple_git_api(), __toCommonJS(simple_git_api_exports));
21235
21358
  var { Scheduler: Scheduler2 } = (init_scheduler(), __toCommonJS(scheduler_exports));
21236
- var { adhocExecTask: adhocExecTask2, configurationErrorTask: configurationErrorTask2 } = (init_task(), __toCommonJS(task_exports));
21359
+ var { configurationErrorTask: configurationErrorTask2 } = (init_task(), __toCommonJS(task_exports));
21237
21360
  var {
21238
21361
  asArray: asArray2,
21239
21362
  filterArray: filterArray2,
@@ -21254,6 +21377,7 @@ var require_git = __commonJS2({
21254
21377
  } = (init_branch(), __toCommonJS(branch_exports));
21255
21378
  var { checkIgnoreTask: checkIgnoreTask2 } = (init_check_ignore(), __toCommonJS(check_ignore_exports));
21256
21379
  var { checkIsRepoTask: checkIsRepoTask2 } = (init_check_is_repo(), __toCommonJS(check_is_repo_exports));
21380
+ var { cloneTask: cloneTask2, cloneMirrorTask: cloneMirrorTask2 } = (init_clone(), __toCommonJS(clone_exports));
21257
21381
  var { cleanWithOptionsTask: cleanWithOptionsTask2, isCleanOptionsArray: isCleanOptionsArray2 } = (init_clean(), __toCommonJS(clean_exports));
21258
21382
  var { diffSummaryTask: diffSummaryTask2 } = (init_diff(), __toCommonJS(diff_exports));
21259
21383
  var { fetchTask: fetchTask2 } = (init_fetch(), __toCommonJS(fetch_exports));
@@ -21298,6 +21422,18 @@ var require_git = __commonJS2({
21298
21422
  Git2.prototype.stashList = function(options) {
21299
21423
  return this._runTask(stashListTask2(trailingOptionsArgument2(arguments) || {}, filterArray2(options) && options || []), trailingFunctionArgument2(arguments));
21300
21424
  };
21425
+ function createCloneTask(api2, task, repoPath, localPath) {
21426
+ if (typeof repoPath !== "string") {
21427
+ return configurationErrorTask2(`git.${api2}() requires a string 'repoPath'`);
21428
+ }
21429
+ return task(repoPath, filterType2(localPath, filterString2), getTrailingOptions2(arguments));
21430
+ }
21431
+ Git2.prototype.clone = function() {
21432
+ return this._runTask(createCloneTask("clone", cloneTask2, ...arguments), trailingFunctionArgument2(arguments));
21433
+ };
21434
+ Git2.prototype.mirror = function() {
21435
+ return this._runTask(createCloneTask("mirror", cloneMirrorTask2, ...arguments), trailingFunctionArgument2(arguments));
21436
+ };
21301
21437
  Git2.prototype.mv = function(from, to) {
21302
21438
  return this._runTask(moveTask2(from, to), trailingFunctionArgument2(arguments));
21303
21439
  };
@@ -21316,7 +21452,8 @@ var require_git = __commonJS2({
21316
21452
  return this._runTask(fetchTask2(filterType2(remote, filterString2), filterType2(branch, filterString2), getTrailingOptions2(arguments)), trailingFunctionArgument2(arguments));
21317
21453
  };
21318
21454
  Git2.prototype.silent = function(silence) {
21319
- return this._runTask(adhocExecTask2(() => console.warn("simple-git deprecation notice: git.silent: logging should be configured using the `debug` library / `DEBUG` environment variable, this method will be removed.")));
21455
+ console.warn("simple-git deprecation notice: git.silent: logging should be configured using the `debug` library / `DEBUG` environment variable, this will be an error in version 3");
21456
+ return this;
21320
21457
  };
21321
21458
  Git2.prototype.tags = function(options, then) {
21322
21459
  return this._runTask(tagListTask2(getTrailingOptions2(arguments)), trailingFunctionArgument2(arguments));
@@ -21469,7 +21606,7 @@ var require_git = __commonJS2({
21469
21606
  return this._runTask(task);
21470
21607
  };
21471
21608
  Git2.prototype.clearQueue = function() {
21472
- return this._runTask(adhocExecTask2(() => console.warn("simple-git deprecation notice: clearQueue() is deprecated and will be removed, switch to using the abortPlugin instead.")));
21609
+ return this;
21473
21610
  };
21474
21611
  Git2.prototype.checkIgnore = function(pathnames, then) {
21475
21612
  return this._runTask(checkIgnoreTask2(asArray2(filterType2(pathnames, filterStringOrStringArray2, []))), trailingFunctionArgument2(arguments));
@@ -21533,33 +21670,20 @@ function abortPlugin(signal) {
21533
21670
  function isConfigSwitch(arg) {
21534
21671
  return typeof arg === "string" && arg.trim().toLowerCase() === "-c";
21535
21672
  }
21536
- function isCloneUploadPackSwitch(char, arg) {
21537
- if (typeof arg !== "string" || !arg.includes(char)) {
21538
- return false;
21673
+ function preventProtocolOverride(arg, next) {
21674
+ if (!isConfigSwitch(arg)) {
21675
+ return;
21539
21676
  }
21540
- const cleaned = arg.trim().replace(/\0/g, "");
21541
- return /^(--no)?-{1,2}[\dlsqvnobucj]+(\s|$)/.test(cleaned);
21542
- }
21543
- function preventConfigBuilder(config2, setting, message = String(config2)) {
21544
- const regex = typeof config2 === "string" ? new RegExp(`\\s*${config2}`, "i") : config2;
21545
- return function preventCommand(options, arg, next) {
21546
- if (options[setting] !== true && isConfigSwitch(arg) && regex.test(next)) {
21547
- throw new GitPluginError(undefined, "unsafe", `Configuring ${message} is not permitted without enabling ${setting}`);
21548
- }
21549
- };
21677
+ if (!/^\s*protocol(.[a-z]+)?.allow/.test(next)) {
21678
+ return;
21679
+ }
21680
+ throw new GitPluginError(undefined, "unsafe", "Configuring protocol.allow is not permitted without enabling allowUnsafeExtProtocol");
21550
21681
  }
21551
- var preventUnsafeConfig = [
21552
- preventConfigBuilder(/^\s*protocol(.[a-z]+)?.allow/i, "allowUnsafeProtocolOverride", "protocol.allow"),
21553
- preventConfigBuilder("core.sshCommand", "allowUnsafeSshCommand"),
21554
- preventConfigBuilder("core.gitProxy", "allowUnsafeGitProxy"),
21555
- preventConfigBuilder("core.hooksPath", "allowUnsafeHooksPath"),
21556
- preventConfigBuilder("diff.external", "allowUnsafeDiffExternal")
21557
- ];
21558
21682
  function preventUploadPack(arg, method) {
21559
21683
  if (/^\s*--(upload|receive)-pack/.test(arg)) {
21560
21684
  throw new GitPluginError(undefined, "unsafe", `Use of --upload-pack or --receive-pack is not permitted without enabling allowUnsafePack`);
21561
21685
  }
21562
- if (method === "clone" && isCloneUploadPackSwitch("u", arg)) {
21686
+ if (method === "clone" && /^\s*-u\b/.test(arg)) {
21563
21687
  throw new GitPluginError(undefined, "unsafe", `Use of clone with option -u is not permitted without enabling allowUnsafePack`);
21564
21688
  }
21565
21689
  if (method === "push" && /^\s*--exec\b/.test(arg)) {
@@ -21567,16 +21691,16 @@ function preventUploadPack(arg, method) {
21567
21691
  }
21568
21692
  }
21569
21693
  function blockUnsafeOperationsPlugin({
21570
- allowUnsafePack = false,
21571
- ...options
21694
+ allowUnsafeProtocolOverride = false,
21695
+ allowUnsafePack = false
21572
21696
  } = {}) {
21573
21697
  return {
21574
21698
  type: "spawn.args",
21575
21699
  action(args, context) {
21576
21700
  args.forEach((current, index) => {
21577
21701
  const next = index < args.length ? args[index + 1] : "";
21702
+ allowUnsafeProtocolOverride || preventProtocolOverride(current, next);
21578
21703
  allowUnsafePack || preventUploadPack(current, context.method);
21579
- preventUnsafeConfig.forEach((helper) => helper(options, current, next));
21580
21704
  });
21581
21705
  return args;
21582
21706
  }
@@ -21660,7 +21784,7 @@ init_utils();
21660
21784
  var WRONG_NUMBER_ERR = `Invalid value supplied for custom binary, requires a single string or an array containing either one or two strings`;
21661
21785
  var WRONG_CHARS_ERR = `Invalid value supplied for custom binary, restricted characters must be removed or supply the unsafe.allowUnsafeCustomBinary option`;
21662
21786
  function isBadArgument(arg) {
21663
- return !arg || !/^([a-z]:)?([a-z0-9/.\\_~-]+)$/i.test(arg);
21787
+ return !arg || !/^([a-z]:)?([a-z0-9/.\\_-]+)$/i.test(arg);
21664
21788
  }
21665
21789
  function toBinaryConfig(input, allowUnsafe) {
21666
21790
  if (input.length < 1 || input.length > 2) {
@@ -21880,12 +22004,12 @@ function gitInstanceFactory(baseDir, options) {
21880
22004
  plugins.add(commandConfigPrefixingPlugin(config2.config));
21881
22005
  }
21882
22006
  plugins.add(blockUnsafeOperationsPlugin(config2.unsafe));
22007
+ plugins.add(suffixPathsPlugin());
21883
22008
  plugins.add(completionDetectionPlugin(config2.completion));
21884
22009
  config2.abort && plugins.add(abortPlugin(config2.abort));
21885
22010
  config2.progress && plugins.add(progressMonitorPlugin(config2.progress));
21886
22011
  config2.timeout && plugins.add(timeoutPlugin(config2.timeout));
21887
22012
  config2.spawnOptions && plugins.add(spawnOptionsPlugin(config2.spawnOptions));
21888
- plugins.add(suffixPathsPlugin());
21889
22013
  plugins.add(errorDetectionPlugin(errorDetectionHandler(true)));
21890
22014
  config2.errors && plugins.add(errorDetectionPlugin(config2.errors));
21891
22015
  customBinaryPlugin(plugins, config2.binary, config2.unsafe?.allowUnsafeCustomBinary);
@@ -22454,17 +22578,217 @@ ${f.content}`);
22454
22578
  return `${normalized}.md`;
22455
22579
  }
22456
22580
  }
22457
- // ../hive-core/src/services/configService.ts
22581
+ // ../hive-core/src/services/sessionService.ts
22458
22582
  import * as fs9 from "fs";
22459
22583
  import * as path7 from "path";
22584
+ class SessionService {
22585
+ projectRoot;
22586
+ constructor(projectRoot) {
22587
+ this.projectRoot = projectRoot;
22588
+ }
22589
+ applySessionPatch(target, patch) {
22590
+ if (!patch) {
22591
+ return;
22592
+ }
22593
+ const { sessionId: _sessionId, ...rest } = patch;
22594
+ Object.assign(target, rest);
22595
+ }
22596
+ getSessionsPath(featureName) {
22597
+ return path7.join(getFeaturePath(this.projectRoot, featureName), "sessions.json");
22598
+ }
22599
+ getSessions(featureName) {
22600
+ const sessionsPath = this.getSessionsPath(featureName);
22601
+ return readJson(sessionsPath) || { sessions: [] };
22602
+ }
22603
+ saveSessions(featureName, data) {
22604
+ const sessionsPath = this.getSessionsPath(featureName);
22605
+ ensureDir(path7.dirname(sessionsPath));
22606
+ writeJson(sessionsPath, data);
22607
+ }
22608
+ getGlobalSessions() {
22609
+ const globalPath = getGlobalSessionsPath(this.projectRoot);
22610
+ return readJson(globalPath) || { sessions: [] };
22611
+ }
22612
+ saveGlobalSessions(data) {
22613
+ const globalPath = getGlobalSessionsPath(this.projectRoot);
22614
+ ensureDir(path7.dirname(globalPath));
22615
+ writeJson(globalPath, data);
22616
+ }
22617
+ updateGlobalSessions(mutator) {
22618
+ const globalPath = getGlobalSessionsPath(this.projectRoot);
22619
+ ensureDir(path7.dirname(globalPath));
22620
+ const release = acquireLockSync(globalPath);
22621
+ try {
22622
+ const data = readJson(globalPath) || { sessions: [] };
22623
+ const session = mutator(data);
22624
+ writeJsonAtomic(globalPath, data);
22625
+ return session;
22626
+ } finally {
22627
+ release();
22628
+ }
22629
+ }
22630
+ trackGlobal(sessionId, patch) {
22631
+ return this.updateGlobalSessions((data) => {
22632
+ const now = new Date().toISOString();
22633
+ let session = data.sessions.find((s) => s.sessionId === sessionId);
22634
+ if (session) {
22635
+ session.lastActiveAt = now;
22636
+ this.applySessionPatch(session, patch);
22637
+ } else {
22638
+ session = {
22639
+ sessionId,
22640
+ startedAt: now,
22641
+ lastActiveAt: now
22642
+ };
22643
+ this.applySessionPatch(session, patch);
22644
+ data.sessions.push(session);
22645
+ }
22646
+ return session;
22647
+ });
22648
+ }
22649
+ bindFeature(sessionId, featureName, patch) {
22650
+ const session = this.updateGlobalSessions((data) => {
22651
+ let current = data.sessions.find((s) => s.sessionId === sessionId);
22652
+ const now = new Date().toISOString();
22653
+ if (!current) {
22654
+ current = {
22655
+ sessionId,
22656
+ startedAt: now,
22657
+ lastActiveAt: now
22658
+ };
22659
+ data.sessions.push(current);
22660
+ }
22661
+ current.featureName = featureName;
22662
+ current.lastActiveAt = now;
22663
+ this.applySessionPatch(current, patch);
22664
+ return current;
22665
+ });
22666
+ const featureData = this.getSessions(featureName);
22667
+ let featureSession = featureData.sessions.find((s) => s.sessionId === sessionId);
22668
+ if (featureSession) {
22669
+ Object.assign(featureSession, session);
22670
+ } else {
22671
+ featureData.sessions.push({ ...session });
22672
+ }
22673
+ this.saveSessions(featureName, featureData);
22674
+ return session;
22675
+ }
22676
+ getGlobal(sessionId) {
22677
+ const data = this.getGlobalSessions();
22678
+ return data.sessions.find((s) => s.sessionId === sessionId);
22679
+ }
22680
+ track(featureName, sessionId, taskFolder) {
22681
+ const data = this.getSessions(featureName);
22682
+ const now = new Date().toISOString();
22683
+ let session = data.sessions.find((s) => s.sessionId === sessionId);
22684
+ if (session) {
22685
+ session.lastActiveAt = now;
22686
+ if (taskFolder)
22687
+ session.taskFolder = taskFolder;
22688
+ } else {
22689
+ session = {
22690
+ sessionId,
22691
+ taskFolder,
22692
+ startedAt: now,
22693
+ lastActiveAt: now
22694
+ };
22695
+ data.sessions.push(session);
22696
+ }
22697
+ if (!data.master) {
22698
+ data.master = sessionId;
22699
+ }
22700
+ this.saveSessions(featureName, data);
22701
+ return session;
22702
+ }
22703
+ setMaster(featureName, sessionId) {
22704
+ const data = this.getSessions(featureName);
22705
+ data.master = sessionId;
22706
+ this.saveSessions(featureName, data);
22707
+ }
22708
+ getMaster(featureName) {
22709
+ return this.getSessions(featureName).master;
22710
+ }
22711
+ list(featureName) {
22712
+ return this.getSessions(featureName).sessions;
22713
+ }
22714
+ get(featureName, sessionId) {
22715
+ return this.getSessions(featureName).sessions.find((s) => s.sessionId === sessionId);
22716
+ }
22717
+ getByTask(featureName, taskFolder) {
22718
+ return this.getSessions(featureName).sessions.find((s) => s.taskFolder === taskFolder);
22719
+ }
22720
+ remove(featureName, sessionId) {
22721
+ const data = this.getSessions(featureName);
22722
+ const index = data.sessions.findIndex((s) => s.sessionId === sessionId);
22723
+ if (index === -1)
22724
+ return false;
22725
+ data.sessions.splice(index, 1);
22726
+ if (data.master === sessionId) {
22727
+ data.master = data.sessions[0]?.sessionId;
22728
+ }
22729
+ this.saveSessions(featureName, data);
22730
+ return true;
22731
+ }
22732
+ findFeatureBySession(sessionId) {
22733
+ const globalSession = this.getGlobal(sessionId);
22734
+ if (globalSession?.featureName) {
22735
+ return globalSession.featureName;
22736
+ }
22737
+ const featuresPath = path7.join(this.projectRoot, ".hive", "features");
22738
+ if (!fs9.existsSync(featuresPath))
22739
+ return null;
22740
+ const features = fs9.readdirSync(featuresPath, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
22741
+ for (const feature of features) {
22742
+ const sessions = this.getSessions(feature);
22743
+ if (sessions.sessions.some((s) => s.sessionId === sessionId)) {
22744
+ return feature;
22745
+ }
22746
+ if (sessions.master === sessionId) {
22747
+ return feature;
22748
+ }
22749
+ }
22750
+ return null;
22751
+ }
22752
+ fork(featureName, fromSessionId) {
22753
+ const data = this.getSessions(featureName);
22754
+ const now = new Date().toISOString();
22755
+ const sourceSession = fromSessionId ? data.sessions.find((s) => s.sessionId === fromSessionId) : data.sessions.find((s) => s.sessionId === data.master);
22756
+ const newSessionId = `ses_fork_${Date.now()}`;
22757
+ const newSession = {
22758
+ sessionId: newSessionId,
22759
+ taskFolder: sourceSession?.taskFolder,
22760
+ startedAt: now,
22761
+ lastActiveAt: now
22762
+ };
22763
+ data.sessions.push(newSession);
22764
+ this.saveSessions(featureName, data);
22765
+ return newSession;
22766
+ }
22767
+ fresh(featureName, title) {
22768
+ const data = this.getSessions(featureName);
22769
+ const now = new Date().toISOString();
22770
+ const newSessionId = `ses_${title ? title.replace(/\s+/g, "_").toLowerCase() : Date.now()}`;
22771
+ const newSession = {
22772
+ sessionId: newSessionId,
22773
+ startedAt: now,
22774
+ lastActiveAt: now
22775
+ };
22776
+ data.sessions.push(newSession);
22777
+ this.saveSessions(featureName, data);
22778
+ return newSession;
22779
+ }
22780
+ }
22781
+ // ../hive-core/src/services/configService.ts
22782
+ import * as fs10 from "fs";
22783
+ import * as path8 from "path";
22460
22784
  class ConfigService {
22461
22785
  configPath;
22462
22786
  cachedConfig = null;
22463
22787
  cachedCustomAgentConfigs = null;
22464
22788
  constructor() {
22465
22789
  const homeDir = process.env.HOME || process.env.USERPROFILE || "";
22466
- const configDir = path7.join(homeDir, ".config", "opencode");
22467
- this.configPath = path7.join(configDir, "agent_hive.json");
22790
+ const configDir = path8.join(homeDir, ".config", "opencode");
22791
+ this.configPath = path8.join(configDir, "agent_hive.json");
22468
22792
  }
22469
22793
  getPath() {
22470
22794
  return this.configPath;
@@ -22474,12 +22798,12 @@ class ConfigService {
22474
22798
  return this.cachedConfig;
22475
22799
  }
22476
22800
  try {
22477
- if (!fs9.existsSync(this.configPath)) {
22801
+ if (!fs10.existsSync(this.configPath)) {
22478
22802
  this.cachedConfig = { ...DEFAULT_HIVE_CONFIG };
22479
22803
  this.cachedCustomAgentConfigs = null;
22480
22804
  return this.cachedConfig;
22481
22805
  }
22482
- const raw = fs9.readFileSync(this.configPath, "utf-8");
22806
+ const raw = fs10.readFileSync(this.configPath, "utf-8");
22483
22807
  const stored = JSON.parse(raw);
22484
22808
  const storedCustomAgents = this.isObjectRecord(stored.customAgents) ? stored.customAgents : {};
22485
22809
  const mergedBuiltInAgents = BUILT_IN_AGENT_NAMES.reduce((acc, agentName) => {
@@ -22527,17 +22851,17 @@ class ConfigService {
22527
22851
  ...updates.customAgents
22528
22852
  } : current.customAgents
22529
22853
  };
22530
- const configDir = path7.dirname(this.configPath);
22531
- if (!fs9.existsSync(configDir)) {
22532
- fs9.mkdirSync(configDir, { recursive: true });
22854
+ const configDir = path8.dirname(this.configPath);
22855
+ if (!fs10.existsSync(configDir)) {
22856
+ fs10.mkdirSync(configDir, { recursive: true });
22533
22857
  }
22534
- fs9.writeFileSync(this.configPath, JSON.stringify(merged, null, 2));
22858
+ fs10.writeFileSync(this.configPath, JSON.stringify(merged, null, 2));
22535
22859
  this.cachedConfig = merged;
22536
22860
  this.cachedCustomAgentConfigs = null;
22537
22861
  return merged;
22538
22862
  }
22539
22863
  exists() {
22540
- return fs9.existsSync(this.configPath);
22864
+ return fs10.existsSync(this.configPath);
22541
22865
  }
22542
22866
  init() {
22543
22867
  if (!this.exists()) {
@@ -22673,8 +22997,8 @@ class ConfigService {
22673
22997
  }
22674
22998
  }
22675
22999
  // ../hive-core/src/services/agentsMdService.ts
22676
- import * as fs10 from "fs";
22677
- import * as path8 from "path";
23000
+ import * as fs11 from "fs";
23001
+ import * as path9 from "path";
22678
23002
  class AgentsMdService {
22679
23003
  rootDir;
22680
23004
  contextService;
@@ -22683,7 +23007,7 @@ class AgentsMdService {
22683
23007
  this.contextService = contextService;
22684
23008
  }
22685
23009
  async init() {
22686
- const agentsMdPath = path8.join(this.rootDir, "AGENTS.md");
23010
+ const agentsMdPath = path9.join(this.rootDir, "AGENTS.md");
22687
23011
  const existed = fileExists(agentsMdPath);
22688
23012
  if (existed) {
22689
23013
  const existing = readText(agentsMdPath);
@@ -22694,14 +23018,14 @@ class AgentsMdService {
22694
23018
  }
22695
23019
  async sync(featureName) {
22696
23020
  const contexts = this.contextService.list(featureName);
22697
- const agentsMdPath = path8.join(this.rootDir, "AGENTS.md");
22698
- const current = await fs10.promises.readFile(agentsMdPath, "utf-8").catch(() => "");
23021
+ const agentsMdPath = path9.join(this.rootDir, "AGENTS.md");
23022
+ const current = await fs11.promises.readFile(agentsMdPath, "utf-8").catch(() => "");
22699
23023
  const findings = this.extractFindings(contexts);
22700
23024
  const proposals = this.generateProposals(findings, current);
22701
23025
  return { proposals, diff: this.formatDiff(current, proposals) };
22702
23026
  }
22703
23027
  apply(content) {
22704
- const agentsMdPath = path8.join(this.rootDir, "AGENTS.md");
23028
+ const agentsMdPath = path9.join(this.rootDir, "AGENTS.md");
22705
23029
  const isNew = !fileExists(agentsMdPath);
22706
23030
  writeText(agentsMdPath, content);
22707
23031
  return { path: agentsMdPath, chars: content.length, isNew };
@@ -22761,7 +23085,7 @@ class AgentsMdService {
22761
23085
  return this.generateTemplate(detections);
22762
23086
  }
22763
23087
  async detectProjectInfo() {
22764
- const packageJsonPath = path8.join(this.rootDir, "package.json");
23088
+ const packageJsonPath = path9.join(this.rootDir, "package.json");
22765
23089
  let packageJson = null;
22766
23090
  if (fileExists(packageJsonPath)) {
22767
23091
  try {
@@ -22781,26 +23105,26 @@ class AgentsMdService {
22781
23105
  return info;
22782
23106
  }
22783
23107
  detectPackageManager() {
22784
- if (fileExists(path8.join(this.rootDir, "bun.lockb")))
23108
+ if (fileExists(path9.join(this.rootDir, "bun.lockb")))
22785
23109
  return "bun";
22786
- if (fileExists(path8.join(this.rootDir, "pnpm-lock.yaml")))
23110
+ if (fileExists(path9.join(this.rootDir, "pnpm-lock.yaml")))
22787
23111
  return "pnpm";
22788
- if (fileExists(path8.join(this.rootDir, "yarn.lock")))
23112
+ if (fileExists(path9.join(this.rootDir, "yarn.lock")))
22789
23113
  return "yarn";
22790
- if (fileExists(path8.join(this.rootDir, "package-lock.json")))
23114
+ if (fileExists(path9.join(this.rootDir, "package-lock.json")))
22791
23115
  return "npm";
22792
23116
  return "npm";
22793
23117
  }
22794
23118
  detectLanguage() {
22795
- if (fileExists(path8.join(this.rootDir, "tsconfig.json")))
23119
+ if (fileExists(path9.join(this.rootDir, "tsconfig.json")))
22796
23120
  return "TypeScript";
22797
- if (fileExists(path8.join(this.rootDir, "package.json")))
23121
+ if (fileExists(path9.join(this.rootDir, "package.json")))
22798
23122
  return "JavaScript";
22799
- if (fileExists(path8.join(this.rootDir, "requirements.txt")))
23123
+ if (fileExists(path9.join(this.rootDir, "requirements.txt")))
22800
23124
  return "Python";
22801
- if (fileExists(path8.join(this.rootDir, "go.mod")))
23125
+ if (fileExists(path9.join(this.rootDir, "go.mod")))
22802
23126
  return "Go";
22803
- if (fileExists(path8.join(this.rootDir, "Cargo.toml")))
23127
+ if (fileExists(path9.join(this.rootDir, "Cargo.toml")))
22804
23128
  return "Rust";
22805
23129
  return "Unknown";
22806
23130
  }
@@ -22879,25 +23203,25 @@ class AgentsMdService {
22879
23203
  }
22880
23204
  }
22881
23205
  // ../hive-core/src/services/dockerSandboxService.ts
22882
- import { existsSync as existsSync4 } from "fs";
22883
- import { join as join9, sep } from "path";
23206
+ import { existsSync as existsSync5 } from "fs";
23207
+ import { join as join10, sep } from "path";
22884
23208
  import { execSync } from "child_process";
22885
23209
 
22886
23210
  class DockerSandboxService {
22887
23211
  static detectImage(worktreePath) {
22888
- if (existsSync4(join9(worktreePath, "Dockerfile"))) {
23212
+ if (existsSync5(join10(worktreePath, "Dockerfile"))) {
22889
23213
  return null;
22890
23214
  }
22891
- if (existsSync4(join9(worktreePath, "package.json"))) {
23215
+ if (existsSync5(join10(worktreePath, "package.json"))) {
22892
23216
  return "node:22-slim";
22893
23217
  }
22894
- if (existsSync4(join9(worktreePath, "requirements.txt")) || existsSync4(join9(worktreePath, "pyproject.toml"))) {
23218
+ if (existsSync5(join10(worktreePath, "requirements.txt")) || existsSync5(join10(worktreePath, "pyproject.toml"))) {
22895
23219
  return "python:3.12-slim";
22896
23220
  }
22897
- if (existsSync4(join9(worktreePath, "go.mod"))) {
23221
+ if (existsSync5(join10(worktreePath, "go.mod"))) {
22898
23222
  return "golang:1.22-slim";
22899
23223
  }
22900
- if (existsSync4(join9(worktreePath, "Cargo.toml"))) {
23224
+ if (existsSync5(join10(worktreePath, "Cargo.toml"))) {
22901
23225
  return "rust:1.77-slim";
22902
23226
  }
22903
23227
  return "ubuntu:24.04";
@@ -23467,17 +23791,17 @@ function applyContextBudget(files, config2 = {}) {
23467
23791
  }
23468
23792
 
23469
23793
  // src/utils/prompt-file.ts
23470
- import * as fs11 from "fs";
23471
- import * as path9 from "path";
23794
+ import * as fs12 from "fs";
23795
+ import * as path10 from "path";
23472
23796
  function writeWorkerPromptFile(feature, task, prompt, hiveDir) {
23473
- const projectRoot = path9.dirname(hiveDir);
23797
+ const projectRoot = path10.dirname(hiveDir);
23474
23798
  const featureDir = resolveFeatureDirectoryName(projectRoot, feature);
23475
- const promptDir = path9.join(hiveDir, "features", featureDir, "tasks", task);
23476
- const promptPath = path9.join(promptDir, "worker-prompt.md");
23477
- if (!fs11.existsSync(promptDir)) {
23478
- fs11.mkdirSync(promptDir, { recursive: true });
23799
+ const promptDir = path10.join(hiveDir, "features", featureDir, "tasks", task);
23800
+ const promptPath = path10.join(promptDir, "worker-prompt.md");
23801
+ if (!fs12.existsSync(promptDir)) {
23802
+ fs12.mkdirSync(promptDir, { recursive: true });
23479
23803
  }
23480
- fs11.writeFileSync(promptPath, prompt, "utf-8");
23804
+ fs12.writeFileSync(promptPath, prompt, "utf-8");
23481
23805
  return promptPath;
23482
23806
  }
23483
23807
 
@@ -23488,9 +23812,48 @@ function normalizeVariant(variant) {
23488
23812
  const trimmed2 = variant.trim();
23489
23813
  return trimmed2.length > 0 ? trimmed2 : undefined;
23490
23814
  }
23491
- function createVariantHook(configService) {
23815
+ var BUILT_IN_AGENTS = {
23816
+ "hive-master": { sessionKind: "primary", baseAgent: "hive-master" },
23817
+ "architect-planner": { sessionKind: "primary", baseAgent: "architect-planner" },
23818
+ "swarm-orchestrator": { sessionKind: "primary", baseAgent: "swarm-orchestrator" },
23819
+ "forager-worker": { sessionKind: "task-worker", baseAgent: "forager-worker" },
23820
+ "scout-researcher": { sessionKind: "subagent", baseAgent: "scout-researcher" },
23821
+ "hygienic-reviewer": { sessionKind: "subagent", baseAgent: "hygienic-reviewer" }
23822
+ };
23823
+ var BASE_AGENT_KIND = {
23824
+ "forager-worker": "task-worker",
23825
+ "hygienic-reviewer": "subagent"
23826
+ };
23827
+ function classifySession(agent, customAgents = {}) {
23828
+ const builtIn = BUILT_IN_AGENTS[agent];
23829
+ if (builtIn) {
23830
+ return { sessionKind: builtIn.sessionKind, baseAgent: builtIn.baseAgent };
23831
+ }
23832
+ const custom2 = customAgents[agent];
23833
+ if (custom2) {
23834
+ const kind = BASE_AGENT_KIND[custom2.baseAgent];
23835
+ if (kind) {
23836
+ return { sessionKind: kind, baseAgent: custom2.baseAgent };
23837
+ }
23838
+ }
23839
+ return { sessionKind: "unknown", baseAgent: undefined };
23840
+ }
23841
+ function createVariantHook(configService, sessionService, customAgents, taskWorkerRecovery) {
23492
23842
  return async (input, output) => {
23493
23843
  const { agent } = input;
23844
+ if (agent && sessionService) {
23845
+ const { sessionKind, baseAgent } = classifySession(agent, customAgents);
23846
+ const patch = { agent, sessionKind };
23847
+ if (baseAgent) {
23848
+ patch.baseAgent = baseAgent;
23849
+ }
23850
+ if (sessionKind === "task-worker" && taskWorkerRecovery) {
23851
+ patch.featureName = taskWorkerRecovery.featureName;
23852
+ patch.taskFolder = taskWorkerRecovery.taskFolder;
23853
+ patch.workerPromptPath = taskWorkerRecovery.workerPromptPath;
23854
+ }
23855
+ sessionService.trackGlobal(input.sessionID, patch);
23856
+ }
23494
23857
  if (!agent)
23495
23858
  return;
23496
23859
  if (!configService.hasConfiguredAgent(agent))
@@ -23524,10 +23887,69 @@ var HIVE_SYSTEM_PROMPT = `
23524
23887
  Use hive_merge to integrate changes into the current branch.
23525
23888
  `;
23526
23889
 
23527
- // src/utils/compaction-prompt.ts
23528
- var COMPACTION_RESUME_PROMPT = "You were compacted mid-task. " + "Resume by reading your worker-prompt.md (in the task worktree root) to recall your assignment. " + "Do not call status tools or re-read the full codebase. " + "Locate your last commit message or notes, then continue from where you left off.";
23529
- function buildCompactionPrompt() {
23530
- return COMPACTION_RESUME_PROMPT;
23890
+ // src/utils/compaction-anchor.ts
23891
+ var AGENT_ROLE_MAP = {
23892
+ "hive-master": "Hive",
23893
+ "architect-planner": "Architect",
23894
+ "swarm-orchestrator": "Swarm",
23895
+ "forager-worker": "Forager",
23896
+ "scout-researcher": "Scout",
23897
+ "hygienic-reviewer": "Hygienic"
23898
+ };
23899
+ var BASE_AGENT_ROLE_MAP = {
23900
+ "forager-worker": "Forager",
23901
+ "hygienic-reviewer": "Hygienic",
23902
+ "scout-researcher": "Scout"
23903
+ };
23904
+ function resolveRole(ctx) {
23905
+ if (ctx.agent && AGENT_ROLE_MAP[ctx.agent]) {
23906
+ return AGENT_ROLE_MAP[ctx.agent];
23907
+ }
23908
+ if (ctx.baseAgent && BASE_AGENT_ROLE_MAP[ctx.baseAgent]) {
23909
+ return BASE_AGENT_ROLE_MAP[ctx.baseAgent];
23910
+ }
23911
+ return;
23912
+ }
23913
+ function resolveWorkerPromptPath(ctx) {
23914
+ if (ctx.workerPromptPath) {
23915
+ return ctx.workerPromptPath;
23916
+ }
23917
+ if (ctx.featureName && ctx.taskFolder) {
23918
+ return `.hive/features/${ctx.featureName}/tasks/${ctx.taskFolder}/worker-prompt.md`;
23919
+ }
23920
+ return;
23921
+ }
23922
+ function buildCompactionReanchor(ctx) {
23923
+ const role = resolveRole(ctx);
23924
+ const kind = ctx.sessionKind ?? "unknown";
23925
+ const workerPromptPath = resolveWorkerPromptPath(ctx);
23926
+ const lines = [];
23927
+ const context = [];
23928
+ lines.push("Compaction recovery — you were compacted mid-session.");
23929
+ if (role) {
23930
+ lines.push(`Role: ${role}`);
23931
+ }
23932
+ lines.push("Do not switch roles.");
23933
+ lines.push("Do not call status tools to rediscover state.");
23934
+ lines.push("Do not re-read the full codebase.");
23935
+ if (kind === "task-worker") {
23936
+ lines.push("Do not delegate.");
23937
+ if (workerPromptPath) {
23938
+ lines.push("Re-read worker-prompt.md now to recall your assignment.");
23939
+ context.push(workerPromptPath);
23940
+ } else {
23941
+ lines.push("Re-read worker-prompt.md from the Hive task metadata to recall your assignment.");
23942
+ }
23943
+ }
23944
+ if ((kind === "primary" || kind === "subagent") && ctx.directivePrompt) {
23945
+ lines.push("Original directive survives via post-compaction replay.");
23946
+ }
23947
+ lines.push("Next action: resume from where you left off.");
23948
+ return {
23949
+ prompt: lines.join(`
23950
+ `),
23951
+ context
23952
+ };
23531
23953
  }
23532
23954
 
23533
23955
  // src/index.ts
@@ -23642,13 +24064,14 @@ No Hive skills available.` : base + formatSkillsXml(filteredSkills);
23642
24064
  });
23643
24065
  }
23644
24066
  var plugin = async (ctx) => {
23645
- const { directory, client } = ctx;
24067
+ const { directory, client, worktree } = ctx;
23646
24068
  const featureService = new FeatureService(directory);
23647
24069
  const planService = new PlanService(directory);
23648
24070
  const taskService = new TaskService(directory);
23649
24071
  const contextService = new ContextService(directory);
23650
24072
  const agentsMdService = new AgentsMdService(directory, contextService);
23651
24073
  const configService = new ConfigService;
24074
+ const sessionService = new SessionService(directory);
23652
24075
  const disabledMcps = configService.getDisabledMcps();
23653
24076
  const disabledSkills = configService.getDisabledSkills();
23654
24077
  const builtinMcps = createBuiltinMcps(disabledMcps);
@@ -23656,8 +24079,15 @@ var plugin = async (ctx) => {
23656
24079
  const effectiveAutoLoadSkills = configService.getAgentConfig("hive-master").autoLoadSkills ?? [];
23657
24080
  const worktreeService = new WorktreeService({
23658
24081
  baseDir: directory,
23659
- hiveDir: path10.join(directory, ".hive")
24082
+ hiveDir: path11.join(directory, ".hive")
23660
24083
  });
24084
+ const customAgentConfigsForClassification = getCustomAgentConfigsCompat(configService);
24085
+ const runtimeContext = detectContext(worktree || directory);
24086
+ const taskWorkerRecovery = runtimeContext.isWorktree && runtimeContext.feature && runtimeContext.task ? {
24087
+ featureName: runtimeContext.feature,
24088
+ taskFolder: runtimeContext.task,
24089
+ workerPromptPath: path11.posix.join(".hive", "features", resolveFeatureDirectoryName(directory, runtimeContext.feature), "tasks", runtimeContext.task, "worker-prompt.md")
24090
+ } : undefined;
23661
24091
  const isOmoSlimEnabled = () => {
23662
24092
  return configService.isOmoSlimEnabled();
23663
24093
  };
@@ -23678,12 +24108,65 @@ var plugin = async (ctx) => {
23678
24108
  }
23679
24109
  }
23680
24110
  };
24111
+ const bindFeatureSession = (feature, toolContext, patch) => {
24112
+ const ctx2 = toolContext;
24113
+ if (!ctx2?.sessionID)
24114
+ return;
24115
+ sessionService.bindFeature(ctx2.sessionID, feature, patch);
24116
+ };
24117
+ const extractTextParts = (parts) => {
24118
+ if (!Array.isArray(parts))
24119
+ return [];
24120
+ return parts.filter((part) => {
24121
+ return !!part && typeof part === "object" && part.type === "text" && typeof part.text === "string";
24122
+ }).map((part) => part.text.trim()).filter(Boolean);
24123
+ };
24124
+ const shouldCaptureDirective = (info, parts) => {
24125
+ if (info.role !== "user")
24126
+ return false;
24127
+ const textParts = parts.filter((part) => {
24128
+ return !!part && typeof part === "object" && part.type === "text";
24129
+ });
24130
+ if (textParts.length === 0)
24131
+ return false;
24132
+ return !textParts.every((part) => part.synthetic === true);
24133
+ };
24134
+ const buildDirectiveReplayText = (session) => {
24135
+ if (!session.directivePrompt)
24136
+ return null;
24137
+ const role = session.agent === "scout-researcher" || session.baseAgent === "scout-researcher" ? "Scout" : session.agent === "hygienic-reviewer" || session.baseAgent === "hygienic-reviewer" ? "Hygienic" : session.agent === "architect-planner" || session.baseAgent === "architect-planner" ? "Architect" : session.agent === "swarm-orchestrator" || session.baseAgent === "swarm-orchestrator" ? "Swarm" : session.agent === "hive-master" || session.baseAgent === "hive-master" ? "Hive" : "current role";
24138
+ return [
24139
+ `Post-compaction recovery: You are still ${role}.`,
24140
+ "Resume the original assignment below. Do not replace it with a new goal.",
24141
+ "",
24142
+ session.directivePrompt
24143
+ ].join(`
24144
+ `);
24145
+ };
24146
+ const shouldUseDirectiveReplay = (session) => {
24147
+ return session?.sessionKind === "primary" || session?.sessionKind === "subagent";
24148
+ };
24149
+ const shouldUseWorkerReplay = (session) => {
24150
+ return session?.sessionKind === "task-worker" && !!session.featureName && !!session.taskFolder && !!session.workerPromptPath;
24151
+ };
24152
+ const buildWorkerReplayText = (session) => {
24153
+ if (!session.featureName || !session.taskFolder || !session.workerPromptPath)
24154
+ return null;
24155
+ const role = "Forager";
24156
+ return [
24157
+ `Post-compaction recovery: You are still the ${role} worker for task ${session.taskFolder}.`,
24158
+ `Resume only this task. Do not merge, do not start the next task, and do not replace this assignment with a new goal.`,
24159
+ `Do not call orchestration tools unless the worker prompt explicitly says so.`,
24160
+ `Re-read @${session.workerPromptPath} and continue from the existing worktree state.`
24161
+ ].join(`
24162
+ `);
24163
+ };
23681
24164
  const checkBlocked = (feature) => {
23682
- const fs13 = __require("fs");
24165
+ const fs14 = __require("fs");
23683
24166
  const featureDir = resolveFeatureDirectoryName(directory, feature);
23684
- const blockedPath = path10.join(directory, ".hive", "features", featureDir, "BLOCKED");
23685
- if (fs13.existsSync(blockedPath)) {
23686
- const reason = fs13.readFileSync(blockedPath, "utf-8").trim();
24167
+ const blockedPath = path11.join(directory, ".hive", "features", featureDir, "BLOCKED");
24168
+ if (fs14.existsSync(blockedPath)) {
24169
+ const reason = fs14.readFileSync(blockedPath, "utf-8").trim();
23687
24170
  return `⛔ BLOCKED by Beekeeper
23688
24171
 
23689
24172
  ${reason || "(No reason provided)"}
@@ -23736,13 +24219,13 @@ To unblock: Remove .hive/features/${featureDir}/BLOCKED`;
23736
24219
  feature,
23737
24220
  task,
23738
24221
  taskInfo,
23739
- worktree,
24222
+ worktree: worktree2,
23740
24223
  continueFrom,
23741
24224
  decision
23742
24225
  }) => {
23743
24226
  taskService.update(feature, task, {
23744
24227
  status: "in_progress",
23745
- baseCommit: worktree.commit
24228
+ baseCommit: worktree2.commit
23746
24229
  });
23747
24230
  const planResult = planService.read(feature);
23748
24231
  const allTasks = taskService.list(feature);
@@ -23770,31 +24253,37 @@ To unblock: Remove .hive/features/${featureDir}/BLOCKED`;
23770
24253
  const taskOrder = parseInt(taskInfo.folder.match(/^(\d+)/)?.[1] || "0", 10);
23771
24254
  const status = taskService.getRawStatus(feature, task);
23772
24255
  const dependsOn = status?.dependsOn ?? [];
23773
- const specContent = taskService.buildSpecContent({
23774
- featureName: feature,
23775
- task: {
23776
- folder: task,
23777
- name: taskInfo.planTitle ?? taskInfo.name,
23778
- order: taskOrder,
23779
- description: undefined
23780
- },
23781
- dependsOn,
23782
- allTasks: allTasks.map((t) => ({
23783
- folder: t.folder,
23784
- name: t.name,
23785
- order: parseInt(t.folder.match(/^(\d+)/)?.[1] || "0", 10)
23786
- })),
23787
- planContent: planResult?.content ?? null,
23788
- contextFiles,
23789
- completedTasks: previousTasks
23790
- });
23791
- taskService.writeSpec(feature, task, specContent);
24256
+ let specContent;
24257
+ const existingManualSpec = status?.origin === "manual" ? taskService.readSpec(feature, task) : null;
24258
+ if (existingManualSpec) {
24259
+ specContent = existingManualSpec;
24260
+ } else {
24261
+ specContent = taskService.buildSpecContent({
24262
+ featureName: feature,
24263
+ task: {
24264
+ folder: task,
24265
+ name: taskInfo.planTitle ?? taskInfo.name,
24266
+ order: taskOrder,
24267
+ description: undefined
24268
+ },
24269
+ dependsOn,
24270
+ allTasks: allTasks.map((t) => ({
24271
+ folder: t.folder,
24272
+ name: t.name,
24273
+ order: parseInt(t.folder.match(/^(\d+)/)?.[1] || "0", 10)
24274
+ })),
24275
+ planContent: planResult?.content ?? null,
24276
+ contextFiles,
24277
+ completedTasks: previousTasks
24278
+ });
24279
+ taskService.writeSpec(feature, task, specContent);
24280
+ }
23792
24281
  const workerPrompt = buildWorkerPrompt({
23793
24282
  feature,
23794
24283
  task,
23795
24284
  taskOrder,
23796
- worktreePath: worktree.path,
23797
- branch: worktree.branch,
24285
+ worktreePath: worktree2.path,
24286
+ branch: worktree2.branch,
23798
24287
  plan: planResult?.content || "No plan available",
23799
24288
  contextFiles,
23800
24289
  spec: specContent,
@@ -23836,9 +24325,9 @@ To unblock: Remove .hive/features/${featureDir}/BLOCKED`;
23836
24325
  spec: specContent,
23837
24326
  workerPrompt
23838
24327
  });
23839
- const hiveDir = path10.join(directory, ".hive");
24328
+ const hiveDir = path11.join(directory, ".hive");
23840
24329
  const workerPromptPath = writeWorkerPromptFile(feature, task, workerPrompt, hiveDir);
23841
- const relativePromptPath = normalizePath(path10.relative(directory, workerPromptPath));
24330
+ const relativePromptPath = normalizePath(path11.relative(directory, workerPromptPath));
23842
24331
  const PREVIEW_MAX_LENGTH = 200;
23843
24332
  const workerPromptPreview = workerPrompt.length > PREVIEW_MAX_LENGTH ? workerPrompt.slice(0, PREVIEW_MAX_LENGTH) + "..." : workerPrompt;
23844
24333
  const taskToolPrompt = `Follow instructions in @${relativePromptPath}`;
@@ -23867,8 +24356,8 @@ Use the \`@path\` attachment syntax in the prompt to reference the file. Do not
23867
24356
  const responseBase = {
23868
24357
  success: true,
23869
24358
  terminal: false,
23870
- worktreePath: worktree.path,
23871
- branch: worktree.branch,
24359
+ worktreePath: worktree2.path,
24360
+ branch: worktree2.branch,
23872
24361
  mode: "delegate",
23873
24362
  agent,
23874
24363
  defaultAgent,
@@ -24004,8 +24493,8 @@ Use the \`@path\` attachment syntax in the prompt to reference the file. Do not
24004
24493
  ]
24005
24494
  });
24006
24495
  }
24007
- const worktree = await worktreeService.create(feature, task);
24008
- return buildWorktreeLaunchResponse({ feature, task, taskInfo, worktree });
24496
+ const worktree2 = await worktreeService.create(feature, task);
24497
+ return buildWorktreeLaunchResponse({ feature, task, taskInfo, worktree: worktree2 });
24009
24498
  };
24010
24499
  const executeBlockedResume = async ({
24011
24500
  task,
@@ -24096,8 +24585,8 @@ Use the \`@path\` attachment syntax in the prompt to reference the file. Do not
24096
24585
  ]
24097
24586
  });
24098
24587
  }
24099
- const worktree = await worktreeService.get(feature, task);
24100
- if (!worktree) {
24588
+ const worktree2 = await worktreeService.get(feature, task);
24589
+ if (!worktree2) {
24101
24590
  return respond({
24102
24591
  success: false,
24103
24592
  terminal: true,
@@ -24113,12 +24602,27 @@ Use the \`@path\` attachment syntax in the prompt to reference the file. Do not
24113
24602
  feature,
24114
24603
  task,
24115
24604
  taskInfo,
24116
- worktree,
24605
+ worktree: worktree2,
24117
24606
  continueFrom,
24118
24607
  decision
24119
24608
  });
24120
24609
  };
24121
24610
  return {
24611
+ event: async (input) => {
24612
+ if (input.event.type !== "session.compacted") {
24613
+ return;
24614
+ }
24615
+ const sessionID = input.event.properties.sessionID;
24616
+ const existing = sessionService.getGlobal(sessionID);
24617
+ if (existing?.directivePrompt && shouldUseDirectiveReplay(existing)) {
24618
+ sessionService.trackGlobal(sessionID, { replayDirectivePending: true });
24619
+ return;
24620
+ }
24621
+ if (shouldUseWorkerReplay(existing)) {
24622
+ sessionService.trackGlobal(sessionID, { replayDirectivePending: true });
24623
+ return;
24624
+ }
24625
+ },
24122
24626
  "experimental.chat.system.transform": async (input, output) => {
24123
24627
  if (!shouldExecuteHook("experimental.chat.system.transform", configService, turnCounters)) {
24124
24628
  return;
@@ -24152,9 +24656,110 @@ Use the \`@path\` attachment syntax in the prompt to reference the file. Do not
24152
24656
  }
24153
24657
  },
24154
24658
  "experimental.session.compacting": async (_input, output) => {
24155
- output.context.push(buildCompactionPrompt());
24659
+ const session = sessionService.getGlobal(_input.sessionID);
24660
+ if (session) {
24661
+ const ctx2 = {
24662
+ agent: session.agent,
24663
+ baseAgent: session.baseAgent,
24664
+ sessionKind: session.sessionKind,
24665
+ featureName: session.featureName,
24666
+ taskFolder: session.taskFolder,
24667
+ workerPromptPath: session.workerPromptPath,
24668
+ directivePrompt: session.directivePrompt
24669
+ };
24670
+ const reanchor = buildCompactionReanchor(ctx2);
24671
+ output.prompt = reanchor.prompt;
24672
+ output.context.push(...reanchor.context);
24673
+ } else {
24674
+ const reanchor = buildCompactionReanchor({});
24675
+ output.prompt = reanchor.prompt;
24676
+ output.context.push(...reanchor.context);
24677
+ }
24678
+ },
24679
+ "chat.message": createVariantHook(configService, sessionService, customAgentConfigsForClassification, taskWorkerRecovery),
24680
+ "experimental.chat.messages.transform": async (_input, output) => {
24681
+ if (!Array.isArray(output.messages) || output.messages.length === 0) {
24682
+ return;
24683
+ }
24684
+ const firstMessage = output.messages[0];
24685
+ const sessionID = firstMessage?.info?.sessionID;
24686
+ if (!sessionID) {
24687
+ return;
24688
+ }
24689
+ const session = sessionService.getGlobal(sessionID);
24690
+ const captureCandidates = output.messages.filter(({ info, parts }) => info.sessionID === sessionID && shouldCaptureDirective(info, parts));
24691
+ const latestDirective = captureCandidates.at(-1);
24692
+ if (latestDirective) {
24693
+ const directiveText = extractTextParts(latestDirective.parts).join(`
24694
+
24695
+ `);
24696
+ const existingDirective = session?.directivePrompt;
24697
+ if (directiveText && directiveText !== existingDirective && shouldUseDirectiveReplay(session ?? { sessionKind: "subagent" })) {
24698
+ sessionService.trackGlobal(sessionID, { directivePrompt: directiveText });
24699
+ }
24700
+ }
24701
+ const refreshed = sessionService.getGlobal(sessionID);
24702
+ if (!refreshed?.replayDirectivePending) {
24703
+ return;
24704
+ }
24705
+ if (shouldUseWorkerReplay(refreshed)) {
24706
+ const workerText = buildWorkerReplayText(refreshed);
24707
+ if (!workerText) {
24708
+ sessionService.trackGlobal(sessionID, { replayDirectivePending: false });
24709
+ return;
24710
+ }
24711
+ const now2 = Date.now();
24712
+ output.messages.push({
24713
+ info: {
24714
+ id: `msg_replay_${sessionID}`,
24715
+ sessionID,
24716
+ role: "user",
24717
+ time: { created: now2 }
24718
+ },
24719
+ parts: [
24720
+ {
24721
+ id: `prt_replay_${sessionID}`,
24722
+ sessionID,
24723
+ messageID: `msg_replay_${sessionID}`,
24724
+ type: "text",
24725
+ text: workerText,
24726
+ synthetic: true
24727
+ }
24728
+ ]
24729
+ });
24730
+ sessionService.trackGlobal(sessionID, { replayDirectivePending: false });
24731
+ return;
24732
+ }
24733
+ if (!shouldUseDirectiveReplay(refreshed)) {
24734
+ sessionService.trackGlobal(sessionID, { replayDirectivePending: false });
24735
+ return;
24736
+ }
24737
+ const replayText = buildDirectiveReplayText(refreshed);
24738
+ if (!replayText) {
24739
+ sessionService.trackGlobal(sessionID, { replayDirectivePending: false });
24740
+ return;
24741
+ }
24742
+ const now = Date.now();
24743
+ output.messages.push({
24744
+ info: {
24745
+ id: `msg_replay_${sessionID}`,
24746
+ sessionID,
24747
+ role: "user",
24748
+ time: { created: now }
24749
+ },
24750
+ parts: [
24751
+ {
24752
+ id: `prt_replay_${sessionID}`,
24753
+ sessionID,
24754
+ messageID: `msg_replay_${sessionID}`,
24755
+ type: "text",
24756
+ text: replayText,
24757
+ synthetic: true
24758
+ }
24759
+ ]
24760
+ });
24761
+ sessionService.trackGlobal(sessionID, { replayDirectivePending: false });
24156
24762
  },
24157
- "chat.message": createVariantHook(configService),
24158
24763
  "tool.execute.before": async (input, output) => {
24159
24764
  if (!shouldExecuteHook("tool.execute.before", configService, turnCounters, { safetyCritical: true })) {
24160
24765
  return;
@@ -24176,7 +24781,7 @@ Use the \`@path\` attachment syntax in the prompt to reference the file. Do not
24176
24781
  const workdir = output.args?.workdir;
24177
24782
  if (!workdir)
24178
24783
  return;
24179
- const hiveWorktreeBase = path10.join(directory, ".hive", ".worktrees");
24784
+ const hiveWorktreeBase = path11.join(directory, ".hive", ".worktrees");
24180
24785
  if (!workdir.startsWith(hiveWorktreeBase))
24181
24786
  return;
24182
24787
  const wrapped = DockerSandboxService.wrapCommand(workdir, command, sandboxConfig);
@@ -24290,6 +24895,7 @@ Expand your Discovery section and try again.`;
24290
24895
  if (!feature)
24291
24896
  return "Error: No feature specified. Create a feature or provide feature param.";
24292
24897
  captureSession(feature, toolContext);
24898
+ bindFeatureSession(feature, toolContext);
24293
24899
  const result = planService.read(feature);
24294
24900
  if (!result)
24295
24901
  return "Error: No plan.md found";
@@ -24322,11 +24928,12 @@ Expand your Discovery section and try again.`;
24322
24928
  }
24323
24929
  }),
24324
24930
  hive_tasks_sync: tool({
24325
- description: "Generate tasks from approved plan",
24931
+ description: "Generate tasks from approved plan. When refreshPending is true, refresh pending plan tasks from current plan.md and delete removed pending tasks. Manual tasks and tasks with execution history are preserved.",
24326
24932
  args: {
24327
- feature: tool.schema.string().optional().describe("Feature name (defaults to detection or single feature)")
24933
+ feature: tool.schema.string().optional().describe("Feature name (defaults to detection or single feature)"),
24934
+ refreshPending: tool.schema.boolean().optional().describe("When true, refresh pending plan tasks from current plan.md (rewrite dependsOn, planTitle, spec.md) and delete pending tasks removed from plan")
24328
24935
  },
24329
- async execute({ feature: explicitFeature }) {
24936
+ async execute({ feature: explicitFeature, refreshPending }) {
24330
24937
  const feature = resolveFeature(explicitFeature);
24331
24938
  if (!feature)
24332
24939
  return "Error: No feature specified. Create a feature or provide feature param.";
@@ -24334,26 +24941,52 @@ Expand your Discovery section and try again.`;
24334
24941
  if (!featureData || featureData.status === "planning") {
24335
24942
  return "Error: Plan must be approved first";
24336
24943
  }
24337
- const result = taskService.sync(feature);
24944
+ const result = taskService.sync(feature, { refreshPending });
24338
24945
  if (featureData.status === "approved") {
24339
24946
  featureService.updateStatus(feature, "executing");
24340
24947
  }
24341
- return `Tasks synced: ${result.created.length} created, ${result.removed.length} removed, ${result.kept.length} kept`;
24948
+ return `Tasks synced: ${result.created.length} created, ${result.removed.length} removed, ${result.kept.length} kept, ${result.manual.length} manual`;
24342
24949
  }
24343
24950
  }),
24344
24951
  hive_task_create: tool({
24345
- description: "Create manual task (not from plan)",
24952
+ description: "Create manual task (not from plan). Manual tasks always have explicit dependsOn (default: []). Provide structured metadata for useful spec.md and worker prompt.",
24346
24953
  args: {
24347
24954
  name: tool.schema.string().describe("Task name"),
24348
24955
  order: tool.schema.number().optional().describe("Task order"),
24349
- feature: tool.schema.string().optional().describe("Feature name (defaults to detection or single feature)")
24956
+ feature: tool.schema.string().optional().describe("Feature name (defaults to detection or single feature)"),
24957
+ description: tool.schema.string().optional().describe("What the worker needs to achieve"),
24958
+ goal: tool.schema.string().optional().describe("Why this task exists and what done means"),
24959
+ acceptanceCriteria: tool.schema.array(tool.schema.string()).optional().describe("Specific observable outcomes"),
24960
+ references: tool.schema.array(tool.schema.string()).optional().describe("File paths or line ranges relevant to this task"),
24961
+ files: tool.schema.array(tool.schema.string()).optional().describe("Files likely to be modified"),
24962
+ dependsOn: tool.schema.array(tool.schema.string()).optional().describe("Task folder names this task depends on (default: [] for no dependencies)"),
24963
+ reason: tool.schema.string().optional().describe("Why this task was created"),
24964
+ source: tool.schema.string().optional().describe("Origin: review, operator, or ad_hoc")
24350
24965
  },
24351
- async execute({ name, order, feature: explicitFeature }) {
24966
+ async execute({ name, order, feature: explicitFeature, description, goal, acceptanceCriteria, references, files, dependsOn, reason, source }) {
24352
24967
  const feature = resolveFeature(explicitFeature);
24353
24968
  if (!feature)
24354
24969
  return "Error: No feature specified. Create a feature or provide feature param.";
24355
- const folder = taskService.create(feature, name, order);
24970
+ const metadata = {};
24971
+ if (description)
24972
+ metadata.description = description;
24973
+ if (goal)
24974
+ metadata.goal = goal;
24975
+ if (acceptanceCriteria)
24976
+ metadata.acceptanceCriteria = acceptanceCriteria;
24977
+ if (references)
24978
+ metadata.references = references;
24979
+ if (files)
24980
+ metadata.files = files;
24981
+ if (dependsOn)
24982
+ metadata.dependsOn = dependsOn;
24983
+ if (reason)
24984
+ metadata.reason = reason;
24985
+ if (source)
24986
+ metadata.source = source;
24987
+ const folder = taskService.create(feature, name, order, Object.keys(metadata).length > 0 ? metadata : undefined);
24356
24988
  return `Manual task created: ${folder}
24989
+ Dependencies: [${(dependsOn ?? []).join(", ")}]
24357
24990
  Reminder: start work with hive_worktree_start to use its worktree, and ensure any subagents work in that worktree too.`;
24358
24991
  }
24359
24992
  }),
@@ -24413,7 +25046,7 @@ Reminder: start work with hive_worktree_start to use its worktree, and ensure an
24413
25046
  }).optional().describe("Blocker info when status is blocked"),
24414
25047
  feature: tool.schema.string().optional().describe("Feature name (defaults to detection or single feature)")
24415
25048
  },
24416
- async execute({ task, summary, message, status = "completed", blocker, feature: explicitFeature }) {
25049
+ async execute({ task, summary, message, status = "completed", blocker, feature: explicitFeature }, toolContext) {
24417
25050
  const respond2 = (payload) => JSON.stringify(payload, null, 2);
24418
25051
  const feature = resolveFeature(explicitFeature);
24419
25052
  if (!feature) {
@@ -24455,6 +25088,9 @@ Reminder: start work with hive_worktree_start to use its worktree, and ensure an
24455
25088
  nextAction: "Only in_progress or blocked tasks can be committed. Start/resume the task first."
24456
25089
  });
24457
25090
  }
25091
+ const featureDir = resolveFeatureDirectoryName(directory, feature);
25092
+ const workerPromptPath = path11.posix.join(".hive", "features", featureDir, "tasks", task, "worker-prompt.md");
25093
+ bindFeatureSession(feature, toolContext, { taskFolder: task, workerPromptPath });
24458
25094
  let verificationNote;
24459
25095
  if (status === "completed") {
24460
25096
  const verificationKeywords = ["test", "build", "lint", "vitest", "jest", "npm run", "pnpm", "cargo", "pytest", "verified", "passes", "succeeds", "ast-grep", "scan"];
@@ -24470,7 +25106,7 @@ Reminder: start work with hive_worktree_start to use its worktree, and ensure an
24470
25106
  summary,
24471
25107
  blocker
24472
25108
  });
24473
- const worktree2 = await worktreeService.get(feature, task);
25109
+ const worktree3 = await worktreeService.get(feature, task);
24474
25110
  return respond2({
24475
25111
  ok: true,
24476
25112
  terminal: true,
@@ -24481,8 +25117,8 @@ Reminder: start work with hive_worktree_start to use its worktree, and ensure an
24481
25117
  taskState: "blocked",
24482
25118
  summary,
24483
25119
  blocker,
24484
- worktreePath: worktree2?.path,
24485
- branch: worktree2?.branch,
25120
+ worktreePath: worktree3?.path,
25121
+ branch: worktree3?.branch,
24486
25122
  message: 'Task blocked. Hive Master will ask user and resume with hive_worktree_create(continueFrom: "blocked", decision: answer)',
24487
25123
  nextAction: 'Wait for orchestrator to collect user decision and resume with continueFrom: "blocked".'
24488
25124
  });
@@ -24541,7 +25177,7 @@ Reminder: start work with hive_worktree_start to use its worktree, and ensure an
24541
25177
  `));
24542
25178
  const finalStatus = status === "completed" ? "done" : status;
24543
25179
  taskService.update(feature, task, { status: finalStatus, summary });
24544
- const worktree = await worktreeService.get(feature, task);
25180
+ const worktree2 = await worktreeService.get(feature, task);
24545
25181
  return respond2({
24546
25182
  ok: true,
24547
25183
  terminal: true,
@@ -24556,8 +25192,8 @@ Reminder: start work with hive_worktree_start to use its worktree, and ensure an
24556
25192
  sha: commitResult.sha,
24557
25193
  message: commitResult.message
24558
25194
  },
24559
- worktreePath: worktree?.path,
24560
- branch: worktree?.branch,
25195
+ worktreePath: worktree2?.path,
25196
+ branch: worktree2?.branch,
24561
25197
  reportPath,
24562
25198
  message: `Task "${task}" ${status}.`,
24563
25199
  nextAction: "Use hive_merge to integrate changes. Worktree is preserved for review."
@@ -24619,10 +25255,11 @@ Files changed: ${result.filesChanged?.length || 0}`;
24619
25255
  content: tool.schema.string().describe("Markdown content to write"),
24620
25256
  feature: tool.schema.string().optional().describe("Feature name (defaults to active)")
24621
25257
  },
24622
- async execute({ name, content, feature: explicitFeature }) {
25258
+ async execute({ name, content, feature: explicitFeature }, toolContext) {
24623
25259
  const feature = resolveFeature(explicitFeature);
24624
25260
  if (!feature)
24625
25261
  return "Error: No feature specified. Create a feature or provide feature param.";
25262
+ bindFeatureSession(feature, toolContext);
24626
25263
  const filePath = contextService.write(feature, name, content);
24627
25264
  return `Context file written: ${filePath}`;
24628
25265
  }
@@ -24672,36 +25309,36 @@ Files changed: ${result.filesChanged?.length || 0}`;
24672
25309
  const contextFiles = contextService.list(feature);
24673
25310
  const overview = contextFiles.find((file2) => file2.name === "overview") ?? null;
24674
25311
  const readThreads = (filePath) => {
24675
- if (!fs12.existsSync(filePath)) {
25312
+ if (!fs13.existsSync(filePath)) {
24676
25313
  return null;
24677
25314
  }
24678
25315
  try {
24679
- const data = JSON.parse(fs12.readFileSync(filePath, "utf-8"));
25316
+ const data = JSON.parse(fs13.readFileSync(filePath, "utf-8"));
24680
25317
  return data.threads ?? [];
24681
25318
  } catch {
24682
25319
  return [];
24683
25320
  }
24684
25321
  };
24685
- const featurePath = path10.join(directory, ".hive", "features", resolveFeatureDirectoryName(directory, feature));
24686
- const reviewDir = path10.join(featurePath, "comments");
24687
- const planThreads = readThreads(path10.join(reviewDir, "plan.json")) ?? readThreads(path10.join(featurePath, "comments.json"));
24688
- const overviewThreads = readThreads(path10.join(reviewDir, "overview.json"));
25322
+ const featurePath = path11.join(directory, ".hive", "features", resolveFeatureDirectoryName(directory, feature));
25323
+ const reviewDir = path11.join(featurePath, "comments");
25324
+ const planThreads = readThreads(path11.join(reviewDir, "plan.json")) ?? readThreads(path11.join(featurePath, "comments.json"));
25325
+ const overviewThreads = readThreads(path11.join(reviewDir, "overview.json"));
24689
25326
  const reviewCounts = {
24690
25327
  plan: planThreads?.length ?? 0,
24691
25328
  overview: overviewThreads?.length ?? 0
24692
25329
  };
24693
25330
  const tasksSummary = await Promise.all(tasks.map(async (t) => {
24694
25331
  const rawStatus = taskService.getRawStatus(feature, t.folder);
24695
- const worktree = await worktreeService.get(feature, t.folder);
24696
- const hasChanges = worktree ? await worktreeService.hasUncommittedChanges(worktree.feature, worktree.step) : null;
25332
+ const worktree2 = await worktreeService.get(feature, t.folder);
25333
+ const hasChanges = worktree2 ? await worktreeService.hasUncommittedChanges(worktree2.feature, worktree2.step) : null;
24697
25334
  return {
24698
25335
  folder: t.folder,
24699
25336
  name: t.name,
24700
25337
  status: t.status,
24701
25338
  origin: t.origin || "plan",
24702
25339
  dependsOn: rawStatus?.dependsOn ?? null,
24703
- worktree: worktree ? {
24704
- branch: worktree.branch,
25340
+ worktree: worktree2 ? {
25341
+ branch: worktree2.branch,
24705
25342
  hasChanges
24706
25343
  } : null
24707
25344
  };