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/README.md +48 -2
- package/dist/hive-core/src/services/index.d.ts +1 -0
- package/dist/hive-core/src/services/sessionService.d.ts +8 -1
- package/dist/hive-core/src/services/taskService.d.ts +9 -3
- package/dist/hive-core/src/types.d.ts +20 -0
- package/dist/hive-core/src/utils/paths.d.ts +1 -0
- package/dist/index.js +945 -308
- package/dist/opencode-hive/src/agents/hive.d.ts +1 -1
- package/dist/opencode-hive/src/agents/swarm.d.ts +1 -1
- package/dist/opencode-hive/src/hooks/variant-hook.d.ts +14 -2
- package/dist/opencode-hive/src/utils/compaction-anchor.d.ts +14 -0
- package/package.json +4 -4
- package/skills/executing-plans/SKILL.md +14 -4
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
875
|
-
import * as
|
|
874
|
+
import * as path11 from "path";
|
|
875
|
+
import * as fs13 from "fs";
|
|
876
876
|
import * as os from "os";
|
|
877
877
|
|
|
878
|
-
// ../../node_modules
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
7601
|
+
// ../../node_modules/zod/v4/locales/kh.js
|
|
7602
7602
|
function kh_default() {
|
|
7603
7603
|
return km_default();
|
|
7604
7604
|
}
|
|
7605
|
-
// ../../node_modules
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
9757
|
+
// ../../node_modules/zod/v4/locales/ua.js
|
|
9758
9758
|
function ua_default() {
|
|
9759
9759
|
return uk_default();
|
|
9760
9760
|
}
|
|
9761
|
-
// ../../node_modules
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
12075
|
+
// ../../node_modules/zod/v4/core/json-schema.js
|
|
12076
12076
|
var exports_json_schema = {};
|
|
12077
|
-
// ../../node_modules
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
13191
|
+
// ../../node_modules/zod/v4/classic/external.js
|
|
13192
13192
|
config(en_default());
|
|
13193
|
-
// ../../node_modules
|
|
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." })
|
|
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
|
-
|
|
14310
|
-
-
|
|
14311
|
-
-
|
|
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.
|
|
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." })
|
|
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 (
|
|
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
|
|
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"
|
|
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
|
|
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.
|
|
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.
|
|
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
|
|
20307
|
-
parser3(" ", "D", (result, file2) => result.deleted
|
|
20308
|
-
parser3(" ", "M", (result, file2) => result.modified
|
|
20309
|
-
parser3("A", " ", (result, file2) =>
|
|
20310
|
-
|
|
20311
|
-
|
|
20312
|
-
|
|
20313
|
-
parser3("
|
|
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
|
|
20462
|
+
append(result.renamed, renamedFile(file2));
|
|
20332
20463
|
}),
|
|
20333
20464
|
parser3("R", "M", (result, file2) => {
|
|
20334
20465
|
const renamed = renamedFile(file2);
|
|
20335
|
-
result.renamed
|
|
20336
|
-
result.modified
|
|
20466
|
+
append(result.renamed, renamed);
|
|
20467
|
+
append(result.modified, renamed.to);
|
|
20337
20468
|
}),
|
|
20338
20469
|
parser3("!", "!", (_result, _file2) => {
|
|
20339
|
-
(_result.ignored = _result.ignored || []
|
|
20470
|
+
append(_result.ignored = _result.ignored || [], _file2);
|
|
20340
20471
|
}),
|
|
20341
|
-
parser3("?", "?", (result, file2) => result.not_added
|
|
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(),
|
|
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
|
|
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(
|
|
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 {
|
|
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
|
-
|
|
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
|
|
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
|
|
21537
|
-
if (
|
|
21538
|
-
return
|
|
21673
|
+
function preventProtocolOverride(arg, next) {
|
|
21674
|
+
if (!isConfigSwitch(arg)) {
|
|
21675
|
+
return;
|
|
21539
21676
|
}
|
|
21540
|
-
|
|
21541
|
-
|
|
21542
|
-
}
|
|
21543
|
-
|
|
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" &&
|
|
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
|
-
|
|
21571
|
-
|
|
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/.\\_
|
|
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/
|
|
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 =
|
|
22467
|
-
this.configPath =
|
|
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 (!
|
|
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 =
|
|
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 =
|
|
22531
|
-
if (!
|
|
22532
|
-
|
|
22854
|
+
const configDir = path8.dirname(this.configPath);
|
|
22855
|
+
if (!fs10.existsSync(configDir)) {
|
|
22856
|
+
fs10.mkdirSync(configDir, { recursive: true });
|
|
22533
22857
|
}
|
|
22534
|
-
|
|
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
|
|
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
|
|
22677
|
-
import * as
|
|
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 =
|
|
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 =
|
|
22698
|
-
const current = await
|
|
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 =
|
|
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 =
|
|
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(
|
|
23108
|
+
if (fileExists(path9.join(this.rootDir, "bun.lockb")))
|
|
22785
23109
|
return "bun";
|
|
22786
|
-
if (fileExists(
|
|
23110
|
+
if (fileExists(path9.join(this.rootDir, "pnpm-lock.yaml")))
|
|
22787
23111
|
return "pnpm";
|
|
22788
|
-
if (fileExists(
|
|
23112
|
+
if (fileExists(path9.join(this.rootDir, "yarn.lock")))
|
|
22789
23113
|
return "yarn";
|
|
22790
|
-
if (fileExists(
|
|
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(
|
|
23119
|
+
if (fileExists(path9.join(this.rootDir, "tsconfig.json")))
|
|
22796
23120
|
return "TypeScript";
|
|
22797
|
-
if (fileExists(
|
|
23121
|
+
if (fileExists(path9.join(this.rootDir, "package.json")))
|
|
22798
23122
|
return "JavaScript";
|
|
22799
|
-
if (fileExists(
|
|
23123
|
+
if (fileExists(path9.join(this.rootDir, "requirements.txt")))
|
|
22800
23124
|
return "Python";
|
|
22801
|
-
if (fileExists(
|
|
23125
|
+
if (fileExists(path9.join(this.rootDir, "go.mod")))
|
|
22802
23126
|
return "Go";
|
|
22803
|
-
if (fileExists(
|
|
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
|
|
22883
|
-
import { join as
|
|
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 (
|
|
23212
|
+
if (existsSync5(join10(worktreePath, "Dockerfile"))) {
|
|
22889
23213
|
return null;
|
|
22890
23214
|
}
|
|
22891
|
-
if (
|
|
23215
|
+
if (existsSync5(join10(worktreePath, "package.json"))) {
|
|
22892
23216
|
return "node:22-slim";
|
|
22893
23217
|
}
|
|
22894
|
-
if (
|
|
23218
|
+
if (existsSync5(join10(worktreePath, "requirements.txt")) || existsSync5(join10(worktreePath, "pyproject.toml"))) {
|
|
22895
23219
|
return "python:3.12-slim";
|
|
22896
23220
|
}
|
|
22897
|
-
if (
|
|
23221
|
+
if (existsSync5(join10(worktreePath, "go.mod"))) {
|
|
22898
23222
|
return "golang:1.22-slim";
|
|
22899
23223
|
}
|
|
22900
|
-
if (
|
|
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
|
|
23471
|
-
import * as
|
|
23794
|
+
import * as fs12 from "fs";
|
|
23795
|
+
import * as path10 from "path";
|
|
23472
23796
|
function writeWorkerPromptFile(feature, task, prompt, hiveDir) {
|
|
23473
|
-
const projectRoot =
|
|
23797
|
+
const projectRoot = path10.dirname(hiveDir);
|
|
23474
23798
|
const featureDir = resolveFeatureDirectoryName(projectRoot, feature);
|
|
23475
|
-
const promptDir =
|
|
23476
|
-
const promptPath =
|
|
23477
|
-
if (!
|
|
23478
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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-
|
|
23528
|
-
var
|
|
23529
|
-
|
|
23530
|
-
|
|
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:
|
|
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
|
|
24165
|
+
const fs14 = __require("fs");
|
|
23683
24166
|
const featureDir = resolveFeatureDirectoryName(directory, feature);
|
|
23684
|
-
const blockedPath =
|
|
23685
|
-
if (
|
|
23686
|
-
const reason =
|
|
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:
|
|
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
|
-
|
|
23774
|
-
|
|
23775
|
-
|
|
23776
|
-
|
|
23777
|
-
|
|
23778
|
-
|
|
23779
|
-
|
|
23780
|
-
|
|
23781
|
-
|
|
23782
|
-
|
|
23783
|
-
|
|
23784
|
-
|
|
23785
|
-
|
|
23786
|
-
|
|
23787
|
-
|
|
23788
|
-
|
|
23789
|
-
|
|
23790
|
-
|
|
23791
|
-
|
|
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:
|
|
23797
|
-
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 =
|
|
24328
|
+
const hiveDir = path11.join(directory, ".hive");
|
|
23840
24329
|
const workerPromptPath = writeWorkerPromptFile(feature, task, workerPrompt, hiveDir);
|
|
23841
|
-
const relativePromptPath = normalizePath(
|
|
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:
|
|
23871
|
-
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
|
|
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
|
|
24100
|
-
if (!
|
|
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
|
-
|
|
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 =
|
|
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
|
|
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
|
|
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:
|
|
24485
|
-
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
|
|
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:
|
|
24560
|
-
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 (!
|
|
25312
|
+
if (!fs13.existsSync(filePath)) {
|
|
24676
25313
|
return null;
|
|
24677
25314
|
}
|
|
24678
25315
|
try {
|
|
24679
|
-
const data = JSON.parse(
|
|
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 =
|
|
24686
|
-
const reviewDir =
|
|
24687
|
-
const planThreads = readThreads(
|
|
24688
|
-
const overviewThreads = readThreads(
|
|
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
|
|
24696
|
-
const hasChanges =
|
|
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:
|
|
24704
|
-
branch:
|
|
25340
|
+
worktree: worktree2 ? {
|
|
25341
|
+
branch: worktree2.branch,
|
|
24705
25342
|
hasChanges
|
|
24706
25343
|
} : null
|
|
24707
25344
|
};
|