@defend-tech/opencode-optima 0.1.68 → 0.1.70
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +333 -264
- package/dist/sanitize_cli.js +356 -287
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -108,17 +108,17 @@ var require_visit = __commonJS({
|
|
|
108
108
|
visit.BREAK = BREAK;
|
|
109
109
|
visit.SKIP = SKIP;
|
|
110
110
|
visit.REMOVE = REMOVE;
|
|
111
|
-
function visit_(key, node, visitor,
|
|
112
|
-
const ctrl = callVisitor(key, node, visitor,
|
|
111
|
+
function visit_(key, node, visitor, path7) {
|
|
112
|
+
const ctrl = callVisitor(key, node, visitor, path7);
|
|
113
113
|
if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
|
|
114
|
-
replaceNode(key,
|
|
115
|
-
return visit_(key, ctrl, visitor,
|
|
114
|
+
replaceNode(key, path7, ctrl);
|
|
115
|
+
return visit_(key, ctrl, visitor, path7);
|
|
116
116
|
}
|
|
117
117
|
if (typeof ctrl !== "symbol") {
|
|
118
118
|
if (identity.isCollection(node)) {
|
|
119
|
-
|
|
119
|
+
path7 = Object.freeze(path7.concat(node));
|
|
120
120
|
for (let i = 0; i < node.items.length; ++i) {
|
|
121
|
-
const ci = visit_(i, node.items[i], visitor,
|
|
121
|
+
const ci = visit_(i, node.items[i], visitor, path7);
|
|
122
122
|
if (typeof ci === "number")
|
|
123
123
|
i = ci - 1;
|
|
124
124
|
else if (ci === BREAK)
|
|
@@ -129,13 +129,13 @@ var require_visit = __commonJS({
|
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
131
|
} else if (identity.isPair(node)) {
|
|
132
|
-
|
|
133
|
-
const ck = visit_("key", node.key, visitor,
|
|
132
|
+
path7 = Object.freeze(path7.concat(node));
|
|
133
|
+
const ck = visit_("key", node.key, visitor, path7);
|
|
134
134
|
if (ck === BREAK)
|
|
135
135
|
return BREAK;
|
|
136
136
|
else if (ck === REMOVE)
|
|
137
137
|
node.key = null;
|
|
138
|
-
const cv = visit_("value", node.value, visitor,
|
|
138
|
+
const cv = visit_("value", node.value, visitor, path7);
|
|
139
139
|
if (cv === BREAK)
|
|
140
140
|
return BREAK;
|
|
141
141
|
else if (cv === REMOVE)
|
|
@@ -156,17 +156,17 @@ var require_visit = __commonJS({
|
|
|
156
156
|
visitAsync.BREAK = BREAK;
|
|
157
157
|
visitAsync.SKIP = SKIP;
|
|
158
158
|
visitAsync.REMOVE = REMOVE;
|
|
159
|
-
async function visitAsync_(key, node, visitor,
|
|
160
|
-
const ctrl = await callVisitor(key, node, visitor,
|
|
159
|
+
async function visitAsync_(key, node, visitor, path7) {
|
|
160
|
+
const ctrl = await callVisitor(key, node, visitor, path7);
|
|
161
161
|
if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
|
|
162
|
-
replaceNode(key,
|
|
163
|
-
return visitAsync_(key, ctrl, visitor,
|
|
162
|
+
replaceNode(key, path7, ctrl);
|
|
163
|
+
return visitAsync_(key, ctrl, visitor, path7);
|
|
164
164
|
}
|
|
165
165
|
if (typeof ctrl !== "symbol") {
|
|
166
166
|
if (identity.isCollection(node)) {
|
|
167
|
-
|
|
167
|
+
path7 = Object.freeze(path7.concat(node));
|
|
168
168
|
for (let i = 0; i < node.items.length; ++i) {
|
|
169
|
-
const ci = await visitAsync_(i, node.items[i], visitor,
|
|
169
|
+
const ci = await visitAsync_(i, node.items[i], visitor, path7);
|
|
170
170
|
if (typeof ci === "number")
|
|
171
171
|
i = ci - 1;
|
|
172
172
|
else if (ci === BREAK)
|
|
@@ -177,13 +177,13 @@ var require_visit = __commonJS({
|
|
|
177
177
|
}
|
|
178
178
|
}
|
|
179
179
|
} else if (identity.isPair(node)) {
|
|
180
|
-
|
|
181
|
-
const ck = await visitAsync_("key", node.key, visitor,
|
|
180
|
+
path7 = Object.freeze(path7.concat(node));
|
|
181
|
+
const ck = await visitAsync_("key", node.key, visitor, path7);
|
|
182
182
|
if (ck === BREAK)
|
|
183
183
|
return BREAK;
|
|
184
184
|
else if (ck === REMOVE)
|
|
185
185
|
node.key = null;
|
|
186
|
-
const cv = await visitAsync_("value", node.value, visitor,
|
|
186
|
+
const cv = await visitAsync_("value", node.value, visitor, path7);
|
|
187
187
|
if (cv === BREAK)
|
|
188
188
|
return BREAK;
|
|
189
189
|
else if (cv === REMOVE)
|
|
@@ -210,23 +210,23 @@ var require_visit = __commonJS({
|
|
|
210
210
|
}
|
|
211
211
|
return visitor;
|
|
212
212
|
}
|
|
213
|
-
function callVisitor(key, node, visitor,
|
|
213
|
+
function callVisitor(key, node, visitor, path7) {
|
|
214
214
|
if (typeof visitor === "function")
|
|
215
|
-
return visitor(key, node,
|
|
215
|
+
return visitor(key, node, path7);
|
|
216
216
|
if (identity.isMap(node))
|
|
217
|
-
return visitor.Map?.(key, node,
|
|
217
|
+
return visitor.Map?.(key, node, path7);
|
|
218
218
|
if (identity.isSeq(node))
|
|
219
|
-
return visitor.Seq?.(key, node,
|
|
219
|
+
return visitor.Seq?.(key, node, path7);
|
|
220
220
|
if (identity.isPair(node))
|
|
221
|
-
return visitor.Pair?.(key, node,
|
|
221
|
+
return visitor.Pair?.(key, node, path7);
|
|
222
222
|
if (identity.isScalar(node))
|
|
223
|
-
return visitor.Scalar?.(key, node,
|
|
223
|
+
return visitor.Scalar?.(key, node, path7);
|
|
224
224
|
if (identity.isAlias(node))
|
|
225
|
-
return visitor.Alias?.(key, node,
|
|
225
|
+
return visitor.Alias?.(key, node, path7);
|
|
226
226
|
return void 0;
|
|
227
227
|
}
|
|
228
|
-
function replaceNode(key,
|
|
229
|
-
const parent =
|
|
228
|
+
function replaceNode(key, path7, node) {
|
|
229
|
+
const parent = path7[path7.length - 1];
|
|
230
230
|
if (identity.isCollection(parent)) {
|
|
231
231
|
parent.items[key] = node;
|
|
232
232
|
} else if (identity.isPair(parent)) {
|
|
@@ -834,10 +834,10 @@ var require_Collection = __commonJS({
|
|
|
834
834
|
var createNode = require_createNode();
|
|
835
835
|
var identity = require_identity();
|
|
836
836
|
var Node = require_Node();
|
|
837
|
-
function collectionFromPath(schema,
|
|
837
|
+
function collectionFromPath(schema, path7, value) {
|
|
838
838
|
let v = value;
|
|
839
|
-
for (let i =
|
|
840
|
-
const k =
|
|
839
|
+
for (let i = path7.length - 1; i >= 0; --i) {
|
|
840
|
+
const k = path7[i];
|
|
841
841
|
if (typeof k === "number" && Number.isInteger(k) && k >= 0) {
|
|
842
842
|
const a = [];
|
|
843
843
|
a[k] = v;
|
|
@@ -856,7 +856,7 @@ var require_Collection = __commonJS({
|
|
|
856
856
|
sourceObjects: /* @__PURE__ */ new Map()
|
|
857
857
|
});
|
|
858
858
|
}
|
|
859
|
-
var isEmptyPath = (
|
|
859
|
+
var isEmptyPath = (path7) => path7 == null || typeof path7 === "object" && !!path7[Symbol.iterator]().next().done;
|
|
860
860
|
var Collection = class extends Node.NodeBase {
|
|
861
861
|
constructor(type, schema) {
|
|
862
862
|
super(type);
|
|
@@ -886,11 +886,11 @@ var require_Collection = __commonJS({
|
|
|
886
886
|
* be a Pair instance or a `{ key, value }` object, which may not have a key
|
|
887
887
|
* that already exists in the map.
|
|
888
888
|
*/
|
|
889
|
-
addIn(
|
|
890
|
-
if (isEmptyPath(
|
|
889
|
+
addIn(path7, value) {
|
|
890
|
+
if (isEmptyPath(path7))
|
|
891
891
|
this.add(value);
|
|
892
892
|
else {
|
|
893
|
-
const [key, ...rest] =
|
|
893
|
+
const [key, ...rest] = path7;
|
|
894
894
|
const node = this.get(key, true);
|
|
895
895
|
if (identity.isCollection(node))
|
|
896
896
|
node.addIn(rest, value);
|
|
@@ -904,8 +904,8 @@ var require_Collection = __commonJS({
|
|
|
904
904
|
* Removes a value from the collection.
|
|
905
905
|
* @returns `true` if the item was found and removed.
|
|
906
906
|
*/
|
|
907
|
-
deleteIn(
|
|
908
|
-
const [key, ...rest] =
|
|
907
|
+
deleteIn(path7) {
|
|
908
|
+
const [key, ...rest] = path7;
|
|
909
909
|
if (rest.length === 0)
|
|
910
910
|
return this.delete(key);
|
|
911
911
|
const node = this.get(key, true);
|
|
@@ -919,8 +919,8 @@ var require_Collection = __commonJS({
|
|
|
919
919
|
* scalar values from their surrounding node; to disable set `keepScalar` to
|
|
920
920
|
* `true` (collections are always returned intact).
|
|
921
921
|
*/
|
|
922
|
-
getIn(
|
|
923
|
-
const [key, ...rest] =
|
|
922
|
+
getIn(path7, keepScalar) {
|
|
923
|
+
const [key, ...rest] = path7;
|
|
924
924
|
const node = this.get(key, true);
|
|
925
925
|
if (rest.length === 0)
|
|
926
926
|
return !keepScalar && identity.isScalar(node) ? node.value : node;
|
|
@@ -938,8 +938,8 @@ var require_Collection = __commonJS({
|
|
|
938
938
|
/**
|
|
939
939
|
* Checks if the collection includes a value with the key `key`.
|
|
940
940
|
*/
|
|
941
|
-
hasIn(
|
|
942
|
-
const [key, ...rest] =
|
|
941
|
+
hasIn(path7) {
|
|
942
|
+
const [key, ...rest] = path7;
|
|
943
943
|
if (rest.length === 0)
|
|
944
944
|
return this.has(key);
|
|
945
945
|
const node = this.get(key, true);
|
|
@@ -949,8 +949,8 @@ var require_Collection = __commonJS({
|
|
|
949
949
|
* Sets a value in this collection. For `!!set`, `value` needs to be a
|
|
950
950
|
* boolean to add/remove the item from the set.
|
|
951
951
|
*/
|
|
952
|
-
setIn(
|
|
953
|
-
const [key, ...rest] =
|
|
952
|
+
setIn(path7, value) {
|
|
953
|
+
const [key, ...rest] = path7;
|
|
954
954
|
if (rest.length === 0) {
|
|
955
955
|
this.set(key, value);
|
|
956
956
|
} else {
|
|
@@ -3454,9 +3454,9 @@ var require_Document = __commonJS({
|
|
|
3454
3454
|
this.contents.add(value);
|
|
3455
3455
|
}
|
|
3456
3456
|
/** Adds a value to the document. */
|
|
3457
|
-
addIn(
|
|
3457
|
+
addIn(path7, value) {
|
|
3458
3458
|
if (assertCollection(this.contents))
|
|
3459
|
-
this.contents.addIn(
|
|
3459
|
+
this.contents.addIn(path7, value);
|
|
3460
3460
|
}
|
|
3461
3461
|
/**
|
|
3462
3462
|
* Create a new `Alias` node, ensuring that the target `node` has the required anchor.
|
|
@@ -3531,14 +3531,14 @@ var require_Document = __commonJS({
|
|
|
3531
3531
|
* Removes a value from the document.
|
|
3532
3532
|
* @returns `true` if the item was found and removed.
|
|
3533
3533
|
*/
|
|
3534
|
-
deleteIn(
|
|
3535
|
-
if (Collection.isEmptyPath(
|
|
3534
|
+
deleteIn(path7) {
|
|
3535
|
+
if (Collection.isEmptyPath(path7)) {
|
|
3536
3536
|
if (this.contents == null)
|
|
3537
3537
|
return false;
|
|
3538
3538
|
this.contents = null;
|
|
3539
3539
|
return true;
|
|
3540
3540
|
}
|
|
3541
|
-
return assertCollection(this.contents) ? this.contents.deleteIn(
|
|
3541
|
+
return assertCollection(this.contents) ? this.contents.deleteIn(path7) : false;
|
|
3542
3542
|
}
|
|
3543
3543
|
/**
|
|
3544
3544
|
* Returns item at `key`, or `undefined` if not found. By default unwraps
|
|
@@ -3553,10 +3553,10 @@ var require_Document = __commonJS({
|
|
|
3553
3553
|
* scalar values from their surrounding node; to disable set `keepScalar` to
|
|
3554
3554
|
* `true` (collections are always returned intact).
|
|
3555
3555
|
*/
|
|
3556
|
-
getIn(
|
|
3557
|
-
if (Collection.isEmptyPath(
|
|
3556
|
+
getIn(path7, keepScalar) {
|
|
3557
|
+
if (Collection.isEmptyPath(path7))
|
|
3558
3558
|
return !keepScalar && identity.isScalar(this.contents) ? this.contents.value : this.contents;
|
|
3559
|
-
return identity.isCollection(this.contents) ? this.contents.getIn(
|
|
3559
|
+
return identity.isCollection(this.contents) ? this.contents.getIn(path7, keepScalar) : void 0;
|
|
3560
3560
|
}
|
|
3561
3561
|
/**
|
|
3562
3562
|
* Checks if the document includes a value with the key `key`.
|
|
@@ -3567,10 +3567,10 @@ var require_Document = __commonJS({
|
|
|
3567
3567
|
/**
|
|
3568
3568
|
* Checks if the document includes a value at `path`.
|
|
3569
3569
|
*/
|
|
3570
|
-
hasIn(
|
|
3571
|
-
if (Collection.isEmptyPath(
|
|
3570
|
+
hasIn(path7) {
|
|
3571
|
+
if (Collection.isEmptyPath(path7))
|
|
3572
3572
|
return this.contents !== void 0;
|
|
3573
|
-
return identity.isCollection(this.contents) ? this.contents.hasIn(
|
|
3573
|
+
return identity.isCollection(this.contents) ? this.contents.hasIn(path7) : false;
|
|
3574
3574
|
}
|
|
3575
3575
|
/**
|
|
3576
3576
|
* Sets a value in this document. For `!!set`, `value` needs to be a
|
|
@@ -3587,13 +3587,13 @@ var require_Document = __commonJS({
|
|
|
3587
3587
|
* Sets a value in this document. For `!!set`, `value` needs to be a
|
|
3588
3588
|
* boolean to add/remove the item from the set.
|
|
3589
3589
|
*/
|
|
3590
|
-
setIn(
|
|
3591
|
-
if (Collection.isEmptyPath(
|
|
3590
|
+
setIn(path7, value) {
|
|
3591
|
+
if (Collection.isEmptyPath(path7)) {
|
|
3592
3592
|
this.contents = value;
|
|
3593
3593
|
} else if (this.contents == null) {
|
|
3594
|
-
this.contents = Collection.collectionFromPath(this.schema, Array.from(
|
|
3594
|
+
this.contents = Collection.collectionFromPath(this.schema, Array.from(path7), value);
|
|
3595
3595
|
} else if (assertCollection(this.contents)) {
|
|
3596
|
-
this.contents.setIn(
|
|
3596
|
+
this.contents.setIn(path7, value);
|
|
3597
3597
|
}
|
|
3598
3598
|
}
|
|
3599
3599
|
/**
|
|
@@ -5545,9 +5545,9 @@ var require_cst_visit = __commonJS({
|
|
|
5545
5545
|
visit.BREAK = BREAK;
|
|
5546
5546
|
visit.SKIP = SKIP;
|
|
5547
5547
|
visit.REMOVE = REMOVE;
|
|
5548
|
-
visit.itemAtPath = (cst,
|
|
5548
|
+
visit.itemAtPath = (cst, path7) => {
|
|
5549
5549
|
let item = cst;
|
|
5550
|
-
for (const [field, index] of
|
|
5550
|
+
for (const [field, index] of path7) {
|
|
5551
5551
|
const tok = item?.[field];
|
|
5552
5552
|
if (tok && "items" in tok) {
|
|
5553
5553
|
item = tok.items[index];
|
|
@@ -5556,23 +5556,23 @@ var require_cst_visit = __commonJS({
|
|
|
5556
5556
|
}
|
|
5557
5557
|
return item;
|
|
5558
5558
|
};
|
|
5559
|
-
visit.parentCollection = (cst,
|
|
5560
|
-
const parent = visit.itemAtPath(cst,
|
|
5561
|
-
const field =
|
|
5559
|
+
visit.parentCollection = (cst, path7) => {
|
|
5560
|
+
const parent = visit.itemAtPath(cst, path7.slice(0, -1));
|
|
5561
|
+
const field = path7[path7.length - 1][0];
|
|
5562
5562
|
const coll = parent?.[field];
|
|
5563
5563
|
if (coll && "items" in coll)
|
|
5564
5564
|
return coll;
|
|
5565
5565
|
throw new Error("Parent collection not found");
|
|
5566
5566
|
};
|
|
5567
|
-
function _visit(
|
|
5568
|
-
let ctrl = visitor(item,
|
|
5567
|
+
function _visit(path7, item, visitor) {
|
|
5568
|
+
let ctrl = visitor(item, path7);
|
|
5569
5569
|
if (typeof ctrl === "symbol")
|
|
5570
5570
|
return ctrl;
|
|
5571
5571
|
for (const field of ["key", "value"]) {
|
|
5572
5572
|
const token = item[field];
|
|
5573
5573
|
if (token && "items" in token) {
|
|
5574
5574
|
for (let i = 0; i < token.items.length; ++i) {
|
|
5575
|
-
const ci = _visit(Object.freeze(
|
|
5575
|
+
const ci = _visit(Object.freeze(path7.concat([[field, i]])), token.items[i], visitor);
|
|
5576
5576
|
if (typeof ci === "number")
|
|
5577
5577
|
i = ci - 1;
|
|
5578
5578
|
else if (ci === BREAK)
|
|
@@ -5583,10 +5583,10 @@ var require_cst_visit = __commonJS({
|
|
|
5583
5583
|
}
|
|
5584
5584
|
}
|
|
5585
5585
|
if (typeof ctrl === "function" && field === "key")
|
|
5586
|
-
ctrl = ctrl(item,
|
|
5586
|
+
ctrl = ctrl(item, path7);
|
|
5587
5587
|
}
|
|
5588
5588
|
}
|
|
5589
|
-
return typeof ctrl === "function" ? ctrl(item,
|
|
5589
|
+
return typeof ctrl === "function" ? ctrl(item, path7) : ctrl;
|
|
5590
5590
|
}
|
|
5591
5591
|
exports.visit = visit;
|
|
5592
5592
|
}
|
|
@@ -7550,17 +7550,17 @@ var require_ignore = __commonJS({
|
|
|
7550
7550
|
var throwError = (message, Ctor) => {
|
|
7551
7551
|
throw new Ctor(message);
|
|
7552
7552
|
};
|
|
7553
|
-
var checkPath = (
|
|
7554
|
-
if (!isString(
|
|
7553
|
+
var checkPath = (path7, originalPath, doThrow) => {
|
|
7554
|
+
if (!isString(path7)) {
|
|
7555
7555
|
return doThrow(
|
|
7556
7556
|
`path must be a string, but got \`${originalPath}\``,
|
|
7557
7557
|
TypeError
|
|
7558
7558
|
);
|
|
7559
7559
|
}
|
|
7560
|
-
if (!
|
|
7560
|
+
if (!path7) {
|
|
7561
7561
|
return doThrow(`path must not be empty`, TypeError);
|
|
7562
7562
|
}
|
|
7563
|
-
if (checkPath.isNotRelative(
|
|
7563
|
+
if (checkPath.isNotRelative(path7)) {
|
|
7564
7564
|
const r = "`path.relative()`d";
|
|
7565
7565
|
return doThrow(
|
|
7566
7566
|
`path should be a ${r} string, but got "${originalPath}"`,
|
|
@@ -7569,7 +7569,7 @@ var require_ignore = __commonJS({
|
|
|
7569
7569
|
}
|
|
7570
7570
|
return true;
|
|
7571
7571
|
};
|
|
7572
|
-
var isNotRelative = (
|
|
7572
|
+
var isNotRelative = (path7) => REGEX_TEST_INVALID_PATH.test(path7);
|
|
7573
7573
|
checkPath.isNotRelative = isNotRelative;
|
|
7574
7574
|
checkPath.convert = (p) => p;
|
|
7575
7575
|
var Ignore = class {
|
|
@@ -7628,7 +7628,7 @@ var require_ignore = __commonJS({
|
|
|
7628
7628
|
// setting `checkUnignored` to `false` could reduce additional
|
|
7629
7629
|
// path matching.
|
|
7630
7630
|
// @returns {TestResult} true if a file is ignored
|
|
7631
|
-
_testOne(
|
|
7631
|
+
_testOne(path7, checkUnignored) {
|
|
7632
7632
|
let ignored = false;
|
|
7633
7633
|
let unignored = false;
|
|
7634
7634
|
this._rules.forEach((rule) => {
|
|
@@ -7636,7 +7636,7 @@ var require_ignore = __commonJS({
|
|
|
7636
7636
|
if (unignored === negative && ignored !== unignored || negative && !ignored && !unignored && !checkUnignored) {
|
|
7637
7637
|
return;
|
|
7638
7638
|
}
|
|
7639
|
-
const matched = rule.regex.test(
|
|
7639
|
+
const matched = rule.regex.test(path7);
|
|
7640
7640
|
if (matched) {
|
|
7641
7641
|
ignored = !negative;
|
|
7642
7642
|
unignored = negative;
|
|
@@ -7649,24 +7649,24 @@ var require_ignore = __commonJS({
|
|
|
7649
7649
|
}
|
|
7650
7650
|
// @returns {TestResult}
|
|
7651
7651
|
_test(originalPath, cache, checkUnignored, slices) {
|
|
7652
|
-
const
|
|
7652
|
+
const path7 = originalPath && checkPath.convert(originalPath);
|
|
7653
7653
|
checkPath(
|
|
7654
|
-
|
|
7654
|
+
path7,
|
|
7655
7655
|
originalPath,
|
|
7656
7656
|
this._allowRelativePaths ? RETURN_FALSE : throwError
|
|
7657
7657
|
);
|
|
7658
|
-
return this._t(
|
|
7658
|
+
return this._t(path7, cache, checkUnignored, slices);
|
|
7659
7659
|
}
|
|
7660
|
-
_t(
|
|
7661
|
-
if (
|
|
7662
|
-
return cache[
|
|
7660
|
+
_t(path7, cache, checkUnignored, slices) {
|
|
7661
|
+
if (path7 in cache) {
|
|
7662
|
+
return cache[path7];
|
|
7663
7663
|
}
|
|
7664
7664
|
if (!slices) {
|
|
7665
|
-
slices =
|
|
7665
|
+
slices = path7.split(SLASH);
|
|
7666
7666
|
}
|
|
7667
7667
|
slices.pop();
|
|
7668
7668
|
if (!slices.length) {
|
|
7669
|
-
return cache[
|
|
7669
|
+
return cache[path7] = this._testOne(path7, checkUnignored);
|
|
7670
7670
|
}
|
|
7671
7671
|
const parent = this._t(
|
|
7672
7672
|
slices.join(SLASH) + SLASH,
|
|
@@ -7674,24 +7674,24 @@ var require_ignore = __commonJS({
|
|
|
7674
7674
|
checkUnignored,
|
|
7675
7675
|
slices
|
|
7676
7676
|
);
|
|
7677
|
-
return cache[
|
|
7677
|
+
return cache[path7] = parent.ignored ? parent : this._testOne(path7, checkUnignored);
|
|
7678
7678
|
}
|
|
7679
|
-
ignores(
|
|
7680
|
-
return this._test(
|
|
7679
|
+
ignores(path7) {
|
|
7680
|
+
return this._test(path7, this._ignoreCache, false).ignored;
|
|
7681
7681
|
}
|
|
7682
7682
|
createFilter() {
|
|
7683
|
-
return (
|
|
7683
|
+
return (path7) => !this.ignores(path7);
|
|
7684
7684
|
}
|
|
7685
7685
|
filter(paths) {
|
|
7686
7686
|
return makeArray(paths).filter(this.createFilter());
|
|
7687
7687
|
}
|
|
7688
7688
|
// @returns {TestResult}
|
|
7689
|
-
test(
|
|
7690
|
-
return this._test(
|
|
7689
|
+
test(path7) {
|
|
7690
|
+
return this._test(path7, this._testCache, true);
|
|
7691
7691
|
}
|
|
7692
7692
|
};
|
|
7693
7693
|
var factory = (options) => new Ignore(options);
|
|
7694
|
-
var isPathValid = (
|
|
7694
|
+
var isPathValid = (path7) => checkPath(path7 && checkPath.convert(path7), path7, RETURN_FALSE);
|
|
7695
7695
|
factory.isPathValid = isPathValid;
|
|
7696
7696
|
factory.default = factory;
|
|
7697
7697
|
module.exports = factory;
|
|
@@ -7702,7 +7702,7 @@ var require_ignore = __commonJS({
|
|
|
7702
7702
|
const makePosix = (str) => /^\\\\\?\\/.test(str) || /["<>|\u0000-\u001F]+/u.test(str) ? str : str.replace(/\\/g, "/");
|
|
7703
7703
|
checkPath.convert = makePosix;
|
|
7704
7704
|
const REGIX_IS_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i;
|
|
7705
|
-
checkPath.isNotRelative = (
|
|
7705
|
+
checkPath.isNotRelative = (path7) => REGIX_IS_WINDOWS_PATH_ABSOLUTE.test(path7) || isNotRelative(path7);
|
|
7706
7706
|
}
|
|
7707
7707
|
}
|
|
7708
7708
|
});
|
|
@@ -7714,8 +7714,7 @@ import crypto from "node:crypto";
|
|
|
7714
7714
|
import fs5 from "node:fs";
|
|
7715
7715
|
import http from "node:http";
|
|
7716
7716
|
import os from "node:os";
|
|
7717
|
-
import
|
|
7718
|
-
import { fileURLToPath } from "node:url";
|
|
7717
|
+
import path6 from "node:path";
|
|
7719
7718
|
import { tool } from "@opencode-ai/plugin/tool";
|
|
7720
7719
|
|
|
7721
7720
|
// src/git_utils.js
|
|
@@ -8486,7 +8485,9 @@ async function optima_validate_logic(worktree) {
|
|
|
8486
8485
|
};
|
|
8487
8486
|
}
|
|
8488
8487
|
|
|
8489
|
-
// src/
|
|
8488
|
+
// src/constants.js
|
|
8489
|
+
import path5 from "node:path";
|
|
8490
|
+
import { fileURLToPath } from "node:url";
|
|
8490
8491
|
var PKG_ROOT = path5.resolve(path5.dirname(fileURLToPath(import.meta.url)), "..");
|
|
8491
8492
|
var BUNDLE_ASSETS_DIR = path5.join(PKG_ROOT, "assets");
|
|
8492
8493
|
var BUNDLE_AGENTS_DIR = path5.join(BUNDLE_ASSETS_DIR, "agents");
|
|
@@ -8529,6 +8530,7 @@ var CLICKUP_WEBHOOK_STARTUP_COMMENT_LIMIT = 100;
|
|
|
8529
8530
|
var CLICKUP_WEBHOOK_STARTUP_RECONCILIATION_DELAY_MS = 3e4;
|
|
8530
8531
|
var CLICKUP_WEBHOOK_STARTUP_COMMENT_LOOKBACK_MS = 6 * 60 * 60 * 1e3;
|
|
8531
8532
|
var CLICKUP_ASSIGNMENT_WATCHDOG_INTERVAL_MS = 5 * 60 * 1e3;
|
|
8533
|
+
var CLICKUP_ASSIGNMENT_WATCHDOG_RUNNING_GRACE_MS = 15 * 60 * 1e3;
|
|
8532
8534
|
var CLICKUP_WORKTREE_FAILURE_COMMENT_DEDUPE_MS = 10 * 60 * 1e3;
|
|
8533
8535
|
var CLICKUP_WEBHOOK_LOG_LEVELS = /* @__PURE__ */ new Set(["error", "info", "verbose"]);
|
|
8534
8536
|
var CLICKUP_WEBHOOK_REDACTED = "[REDACTED]";
|
|
@@ -8617,20 +8619,22 @@ var REPO_LOCAL_POLICIES_README = [
|
|
|
8617
8619
|
"Only files in `.optima/policies/` affect runtime prompt behavior.",
|
|
8618
8620
|
""
|
|
8619
8621
|
].join("\n");
|
|
8622
|
+
var CLICKUP_WEBHOOK_CLEANUP_TIMEOUT_MS = 8e3;
|
|
8623
|
+
var CLICKUP_WEBHOOK_SIGNAL_STATE = Symbol.for("opencode-optima.clickup-webhook.signal-state");
|
|
8624
|
+
|
|
8625
|
+
// src/index.js
|
|
8620
8626
|
var activeWorkflows = /* @__PURE__ */ new Map();
|
|
8621
8627
|
var activeClickUpWebhookListeners = /* @__PURE__ */ new Map();
|
|
8622
8628
|
var activeClickUpWebhookLifecycleRegistry = /* @__PURE__ */ new Map();
|
|
8623
|
-
var CLICKUP_WEBHOOK_CLEANUP_TIMEOUT_MS = 8e3;
|
|
8624
|
-
var CLICKUP_WEBHOOK_SIGNAL_STATE = Symbol.for("opencode-optima.clickup-webhook.signal-state");
|
|
8625
8629
|
var activeClickUpTaskRoutes = /* @__PURE__ */ new Map();
|
|
8626
8630
|
function isRootDirectory(candidate) {
|
|
8627
|
-
const resolved =
|
|
8628
|
-
return resolved ===
|
|
8631
|
+
const resolved = path6.resolve(candidate);
|
|
8632
|
+
return resolved === path6.parse(resolved).root;
|
|
8629
8633
|
}
|
|
8630
8634
|
function isSafeWritableDirectory(candidate) {
|
|
8631
8635
|
if (typeof candidate !== "string" || !candidate.trim()) return false;
|
|
8632
|
-
if (!
|
|
8633
|
-
const resolved =
|
|
8636
|
+
if (!path6.isAbsolute(candidate)) return false;
|
|
8637
|
+
const resolved = path6.resolve(candidate);
|
|
8634
8638
|
if (isRootDirectory(resolved)) return false;
|
|
8635
8639
|
try {
|
|
8636
8640
|
const stat = fs5.statSync(resolved);
|
|
@@ -8651,7 +8655,7 @@ function resolveSafeWorktree(context = {}, pluginWorktree = null) {
|
|
|
8651
8655
|
];
|
|
8652
8656
|
for (const candidate of candidates) {
|
|
8653
8657
|
if (typeof candidate !== "string" || !candidate.trim()) continue;
|
|
8654
|
-
const resolved =
|
|
8658
|
+
const resolved = path6.resolve(candidate);
|
|
8655
8659
|
if (isSafeWritableDirectory(resolved)) return resolved;
|
|
8656
8660
|
}
|
|
8657
8661
|
throw new Error(SAFE_WORKTREE_FAILURE);
|
|
@@ -8666,13 +8670,13 @@ function safeWorktreeOrFailure(context, pluginWorktree) {
|
|
|
8666
8670
|
function explicitSafeInputWorktree(input = {}) {
|
|
8667
8671
|
for (const candidate of [input?.worktree, input?.directory]) {
|
|
8668
8672
|
if (typeof candidate !== "string" || !candidate.trim()) continue;
|
|
8669
|
-
const resolved =
|
|
8673
|
+
const resolved = path6.resolve(candidate);
|
|
8670
8674
|
if (isSafeWritableDirectory(resolved)) return resolved;
|
|
8671
8675
|
}
|
|
8672
8676
|
return null;
|
|
8673
8677
|
}
|
|
8674
8678
|
function isGitRepository(worktree) {
|
|
8675
|
-
return fs5.existsSync(
|
|
8679
|
+
return fs5.existsSync(path6.join(worktree, ".git"));
|
|
8676
8680
|
}
|
|
8677
8681
|
function normalizeLooseToken(value) {
|
|
8678
8682
|
return String(value ?? "").trim().normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
@@ -9167,7 +9171,7 @@ function buildClickUpSummaryPayload({ summaryMarkdown = "", summaryPath = "", ta
|
|
|
9167
9171
|
function deriveClickUpWorktree({ baseWorktree = "", taskId, taskType, parentTaskId, subtaskId } = {}) {
|
|
9168
9172
|
const branch = deriveClickUpBranchName({ taskType, parentTaskId, subtaskId, taskId });
|
|
9169
9173
|
const root = baseWorktree || process.cwd();
|
|
9170
|
-
return
|
|
9174
|
+
return path6.join(path6.dirname(root), `${path6.basename(root)}-${branch.replace(/\//g, "-")}`);
|
|
9171
9175
|
}
|
|
9172
9176
|
function clickUpCustomFieldValue(task = {}, names = []) {
|
|
9173
9177
|
const fields = Array.isArray(task.custom_fields) ? task.custom_fields : [];
|
|
@@ -9191,12 +9195,12 @@ function safeExistingClickUpWorktree({ metadata = {}, branch = "" } = {}) {
|
|
|
9191
9195
|
const taskMetadata = metadataTaskRouting(metadata);
|
|
9192
9196
|
const existingWorktree = typeof taskMetadata.worktree === "string" ? taskMetadata.worktree.trim() : "";
|
|
9193
9197
|
const existingBranch = typeof taskMetadata.branch === "string" ? taskMetadata.branch.trim() : "";
|
|
9194
|
-
if (!existingWorktree || !
|
|
9198
|
+
if (!existingWorktree || !path6.isAbsolute(existingWorktree) || !fs5.existsSync(existingWorktree)) return null;
|
|
9195
9199
|
try {
|
|
9196
9200
|
const stat = fs5.statSync(existingWorktree);
|
|
9197
9201
|
if (!stat.isDirectory()) return null;
|
|
9198
9202
|
if (branch && existingBranch && existingBranch !== branch) return null;
|
|
9199
|
-
return { branch: existingBranch || branch, worktree:
|
|
9203
|
+
return { branch: existingBranch || branch, worktree: path6.resolve(existingWorktree), reused: true };
|
|
9200
9204
|
} catch {
|
|
9201
9205
|
return null;
|
|
9202
9206
|
}
|
|
@@ -9282,17 +9286,17 @@ function openChamberEntryBranch(entry) {
|
|
|
9282
9286
|
return String(entry?.branch || entry?.branchName || entry?.branch_name || entry?.worktree?.branch || "").replace(/^refs\/heads\//, "");
|
|
9283
9287
|
}
|
|
9284
9288
|
function openChamberListIncludesDirectory(list, directory) {
|
|
9285
|
-
const resolved =
|
|
9289
|
+
const resolved = path6.resolve(directory);
|
|
9286
9290
|
return normalizeOpenChamberCollection(list).some((entry) => {
|
|
9287
9291
|
const entryDirectory = openChamberEntryDirectory(entry);
|
|
9288
|
-
return entryDirectory &&
|
|
9292
|
+
return entryDirectory && path6.resolve(entryDirectory) === resolved;
|
|
9289
9293
|
});
|
|
9290
9294
|
}
|
|
9291
9295
|
function openChamberListIncludesBranch(list, directory, branch) {
|
|
9292
|
-
const resolved =
|
|
9296
|
+
const resolved = path6.resolve(directory);
|
|
9293
9297
|
return normalizeOpenChamberCollection(list).some((entry) => {
|
|
9294
9298
|
const entryDirectory = openChamberEntryDirectory(entry);
|
|
9295
|
-
if (!entryDirectory ||
|
|
9299
|
+
if (!entryDirectory || path6.resolve(entryDirectory) !== resolved) return false;
|
|
9296
9300
|
const entryBranch = openChamberEntryBranch(entry);
|
|
9297
9301
|
return !entryBranch || entryBranch === branch;
|
|
9298
9302
|
});
|
|
@@ -9300,8 +9304,8 @@ function openChamberListIncludesBranch(list, directory, branch) {
|
|
|
9300
9304
|
async function findOpenChamberProject({ opencodeBaseUrl, baseWorktree, fetchImpl = globalThis.fetch } = {}) {
|
|
9301
9305
|
const projects = await requestOpenCodeJson({ baseUrl: opencodeBaseUrl, endpoint: "/project", directory: baseWorktree, fetchImpl });
|
|
9302
9306
|
if (!Array.isArray(projects)) return null;
|
|
9303
|
-
const resolvedBase =
|
|
9304
|
-
return projects.find((project) =>
|
|
9307
|
+
const resolvedBase = path6.resolve(baseWorktree);
|
|
9308
|
+
return projects.find((project) => path6.resolve(String(project?.worktree || project?.path || "")) === resolvedBase) || null;
|
|
9305
9309
|
}
|
|
9306
9310
|
async function refreshOpenChamberProjectCopy({ opencodeBaseUrl, projectId, fetchImpl = globalThis.fetch } = {}) {
|
|
9307
9311
|
if (!projectId) return { refreshed: false, reason: "project_id_unavailable" };
|
|
@@ -9356,18 +9360,18 @@ async function createOpenChamberClickUpWorktree({ openchamberBaseUrl, baseUrl, b
|
|
|
9356
9360
|
}
|
|
9357
9361
|
const createdDirectory = openChamberEntryDirectory(created);
|
|
9358
9362
|
const createdBranch = openChamberEntryBranch(created);
|
|
9359
|
-
if (!createdDirectory || !
|
|
9363
|
+
if (!createdDirectory || !path6.isAbsolute(createdDirectory)) {
|
|
9360
9364
|
throw new Error(`OpenChamber did not return an absolute worktree path for ${branch}.`);
|
|
9361
9365
|
}
|
|
9362
9366
|
if (createdBranch !== branch) {
|
|
9363
9367
|
throw new Error(`OpenChamber created unexpected branch ${createdBranch || "<unknown>"}; expected ${branch}.`);
|
|
9364
9368
|
}
|
|
9365
9369
|
const verified = await verifyOpenChamberGitWorktree({ openchamberBaseUrl: effectiveOpenChamberBaseUrl, baseWorktree, worktreePath: createdDirectory, branch, fetchImpl });
|
|
9366
|
-
return { created, worktree:
|
|
9370
|
+
return { created, worktree: path6.resolve(createdDirectory), branch: createdBranch, verified };
|
|
9367
9371
|
}
|
|
9368
9372
|
async function registerOpenChamberClickUpWorktree({ openchamberBaseUrl, opencodeBaseUrl, baseUrl, baseWorktree, branch, worktreePath, fetchImpl = globalThis.fetch, source = "reuse" } = {}) {
|
|
9369
9373
|
const visibility = await syncOpenChamberWorktreeVisibility({ openchamberBaseUrl: openchamberBaseUrl || baseUrl, opencodeBaseUrl: opencodeBaseUrl || baseUrl, baseWorktree, worktreePath, branch, fetchImpl });
|
|
9370
|
-
return { branch, worktree:
|
|
9374
|
+
return { branch, worktree: path6.resolve(worktreePath), reused: true, provider: "openchamber", openChamber: { source, visibility } };
|
|
9371
9375
|
}
|
|
9372
9376
|
async function ensureClickUpTaskWorktreeOpenChamber({ baseWorktree = "", taskId, taskType = "Tarea", parentTaskId = "", subtaskId = "", existingMetadata = {}, runGitFn = runGit, openchamberBaseUrl = "", opencodeBaseUrl = "", baseUrl = "", fetchImpl = globalThis.fetch, log = null } = {}) {
|
|
9373
9377
|
const effectiveOpenChamberBaseUrl = openchamberBaseUrl || baseUrl;
|
|
@@ -9430,10 +9434,10 @@ function ensureClickUpTaskWorktree({ baseWorktree = "", taskId, taskType = "Tare
|
|
|
9430
9434
|
const existing = safeExistingClickUpWorktree({ metadata: existingMetadata, branch });
|
|
9431
9435
|
if (existing) return { ...existing, branch, parentBranch: parentBranch || void 0, prTarget: parentBranch || "dev" };
|
|
9432
9436
|
const worktreePath = deriveClickUpWorktree({ baseWorktree, taskId, taskType, parentTaskId: effectiveParent, subtaskId });
|
|
9433
|
-
if (fs5.existsSync(worktreePath)) return { branch, worktree:
|
|
9437
|
+
if (fs5.existsSync(worktreePath)) return { branch, worktree: path6.resolve(worktreePath), reused: true, parentBranch: parentBranch || void 0, prTarget: parentBranch || "dev" };
|
|
9434
9438
|
if (allowNonGitFallback) {
|
|
9435
9439
|
fs5.mkdirSync(worktreePath, { recursive: true });
|
|
9436
|
-
return { branch, worktree:
|
|
9440
|
+
return { branch, worktree: path6.resolve(worktreePath), reused: false, fallback: "non_git", parentBranch: parentBranch || void 0, prTarget: parentBranch || "dev", startPoint: parentBranch || "dev" };
|
|
9437
9441
|
}
|
|
9438
9442
|
let parentBootstrap = null;
|
|
9439
9443
|
if (isSubtask) {
|
|
@@ -9442,14 +9446,14 @@ function ensureClickUpTaskWorktree({ baseWorktree = "", taskId, taskType = "Tare
|
|
|
9442
9446
|
const parentStartPoint = resolveClickUpDevStartPoint(baseWorktree, runGitFn);
|
|
9443
9447
|
const parentBranchExists = clickUpGitRefExists(baseWorktree, parentBranch, runGitFn);
|
|
9444
9448
|
addClickUpWorktreeForBranch({ baseWorktree, branch: parentBranch, worktreePath: parentWorktree, startPoint: parentStartPoint, runGitFn });
|
|
9445
|
-
parentBootstrap = { branch: parentBranch, worktree:
|
|
9449
|
+
parentBootstrap = { branch: parentBranch, worktree: path6.resolve(parentWorktree), startPoint: parentBranchExists ? parentBranch : parentStartPoint, reused: parentBranchExists };
|
|
9446
9450
|
} else {
|
|
9447
|
-
parentBootstrap = { branch: parentBranch, worktree:
|
|
9451
|
+
parentBootstrap = { branch: parentBranch, worktree: path6.resolve(parentWorktree), reused: true };
|
|
9448
9452
|
}
|
|
9449
9453
|
}
|
|
9450
9454
|
const startPoint = isSubtask ? parentBranch : resolveClickUpDevStartPoint(baseWorktree, runGitFn);
|
|
9451
9455
|
addClickUpWorktreeForBranch({ baseWorktree, branch, worktreePath, startPoint, runGitFn });
|
|
9452
|
-
return { branch, worktree:
|
|
9456
|
+
return { branch, worktree: path6.resolve(worktreePath), reused: false, startPoint, parentBranch: parentBranch || void 0, prTarget: parentBranch || "dev", parentBootstrap: parentBootstrap || void 0 };
|
|
9453
9457
|
}
|
|
9454
9458
|
function normalizeClickUpDefinitionDocParent(parent = {}) {
|
|
9455
9459
|
const docId = String(parent.doc_id || parent.docId || CLICKUP_DEFINITION_DOC_PARENT.doc_id).trim();
|
|
@@ -9599,7 +9603,7 @@ function buildClickUpTransitionPayload({ fromStatus, toStatus, validationPassed
|
|
|
9599
9603
|
}
|
|
9600
9604
|
function ensureOptimaGitignoreRules(worktree) {
|
|
9601
9605
|
if (!isGitRepository(worktree)) return { touched: false, added: [] };
|
|
9602
|
-
const gitignorePath =
|
|
9606
|
+
const gitignorePath = path6.join(worktree, ".gitignore");
|
|
9603
9607
|
const existing = fs5.existsSync(gitignorePath) ? fs5.readFileSync(gitignorePath, "utf8") : "";
|
|
9604
9608
|
const existingRules = new Set(existing.split(/\r?\n/).map((line) => line.trim()).filter(Boolean));
|
|
9605
9609
|
const missingRules = OPTIMA_GITIGNORE_RULES.filter((rule) => !existingRules.has(rule));
|
|
@@ -9615,40 +9619,40 @@ function ensureOptimaGitignoreRules(worktree) {
|
|
|
9615
9619
|
return { touched: true, added: missingRules };
|
|
9616
9620
|
}
|
|
9617
9621
|
function optimaDir(worktree) {
|
|
9618
|
-
return
|
|
9622
|
+
return path6.join(worktree, OPTIMA_DIRNAME);
|
|
9619
9623
|
}
|
|
9620
9624
|
function optimaLocalConfigDir(worktree) {
|
|
9621
|
-
return
|
|
9625
|
+
return path6.join(optimaDir(worktree), ".config");
|
|
9622
9626
|
}
|
|
9623
9627
|
function optimaConfigDir(worktree) {
|
|
9624
9628
|
return optimaLocalConfigDir(worktree);
|
|
9625
9629
|
}
|
|
9626
9630
|
function optimaCodemapPath(worktree) {
|
|
9627
|
-
return
|
|
9631
|
+
return path6.join(optimaDir(worktree), "codemap.yml");
|
|
9628
9632
|
}
|
|
9629
9633
|
function optimaTasksDir(worktree) {
|
|
9630
|
-
return
|
|
9634
|
+
return path6.join(optimaDir(worktree), "tasks");
|
|
9631
9635
|
}
|
|
9632
9636
|
function optimaEvidencesDir(worktree) {
|
|
9633
|
-
return
|
|
9637
|
+
return path6.join(optimaDir(worktree), "evidences");
|
|
9634
9638
|
}
|
|
9635
9639
|
function optimaScrsDir(worktree) {
|
|
9636
|
-
return
|
|
9640
|
+
return path6.join(optimaDir(worktree), "docs", "scrs");
|
|
9637
9641
|
}
|
|
9638
9642
|
function legacyNomadworkDir(worktree) {
|
|
9639
|
-
return
|
|
9643
|
+
return path6.join(worktree, LEGACY_NOMADWORK_DIRNAME);
|
|
9640
9644
|
}
|
|
9641
9645
|
function legacyNomadworksDir(worktree) {
|
|
9642
|
-
return
|
|
9646
|
+
return path6.join(worktree, LEGACY_NOMADWORKS_DIRNAME);
|
|
9643
9647
|
}
|
|
9644
9648
|
function legacyOrbitaDir(worktree) {
|
|
9645
|
-
return
|
|
9649
|
+
return path6.join(worktree, LEGACY_ORBITA_DIRNAME);
|
|
9646
9650
|
}
|
|
9647
9651
|
function legacyStaticEngDir(worktree) {
|
|
9648
|
-
return
|
|
9652
|
+
return path6.join(worktree, LEGACY_STATICENG_DIRNAME);
|
|
9649
9653
|
}
|
|
9650
9654
|
function repoConfigPath(worktree) {
|
|
9651
|
-
return
|
|
9655
|
+
return path6.join(optimaConfigDir(worktree), "optima.yaml");
|
|
9652
9656
|
}
|
|
9653
9657
|
function normalizeLegacyDiscussionEntry(entry) {
|
|
9654
9658
|
if (!entry || typeof entry !== "object") return entry;
|
|
@@ -9661,25 +9665,25 @@ function normalizeLegacyDiscussionEntry(entry) {
|
|
|
9661
9665
|
return next;
|
|
9662
9666
|
}
|
|
9663
9667
|
function repoPoliciesDir(worktree) {
|
|
9664
|
-
return
|
|
9668
|
+
return path6.join(optimaDir(worktree), "policies");
|
|
9665
9669
|
}
|
|
9666
9670
|
function generatedPoliciesDir(worktree) {
|
|
9667
|
-
return
|
|
9671
|
+
return path6.join(optimaLocalConfigDir(worktree), "generated", "policies");
|
|
9668
9672
|
}
|
|
9669
9673
|
function generatedAgentsDir(worktree) {
|
|
9670
|
-
return
|
|
9674
|
+
return path6.join(optimaLocalConfigDir(worktree), "generated", "agents");
|
|
9671
9675
|
}
|
|
9672
9676
|
function repoAgentsDir(worktree) {
|
|
9673
|
-
return
|
|
9677
|
+
return path6.join(optimaDir(worktree), "agents");
|
|
9674
9678
|
}
|
|
9675
9679
|
function repoAgentAdditionsDir(worktree) {
|
|
9676
|
-
return
|
|
9680
|
+
return path6.join(optimaDir(worktree), "agent-additions");
|
|
9677
9681
|
}
|
|
9678
9682
|
function legacyRepoAgentsDir(worktree) {
|
|
9679
|
-
return
|
|
9683
|
+
return path6.join(legacyNomadworksDir(worktree), "agents");
|
|
9680
9684
|
}
|
|
9681
9685
|
function runtimeDiscussionRegistryPath(worktree) {
|
|
9682
|
-
return
|
|
9686
|
+
return path6.join(optimaLocalConfigDir(worktree), "runtime", "discussions.json");
|
|
9683
9687
|
}
|
|
9684
9688
|
function resolveConfigPath(worktree) {
|
|
9685
9689
|
return repoConfigPath(worktree);
|
|
@@ -9722,32 +9726,32 @@ function mergeClickUpAgentMetadata(existing, update = {}) {
|
|
|
9722
9726
|
return JSON.stringify(sortJsonValue(merged), null, 2);
|
|
9723
9727
|
}
|
|
9724
9728
|
function optimaRuntimeDir(worktree) {
|
|
9725
|
-
return
|
|
9729
|
+
return path6.join(optimaLocalConfigDir(worktree), "runtime");
|
|
9726
9730
|
}
|
|
9727
9731
|
function clickUpWebhookStatePath(worktree) {
|
|
9728
|
-
return
|
|
9732
|
+
return path6.join(optimaRuntimeDir(worktree), "clickup-webhook.json");
|
|
9729
9733
|
}
|
|
9730
9734
|
function clickUpCommentLedgerPath(worktree) {
|
|
9731
|
-
return
|
|
9735
|
+
return path6.join(optimaRuntimeDir(worktree), "clickup-comment-ledger.jsonl");
|
|
9732
9736
|
}
|
|
9733
9737
|
function clickUpWebhookLogPath(worktree) {
|
|
9734
|
-
return
|
|
9738
|
+
return path6.join(optimaRuntimeDir(worktree), "clickup-webhook.log.jsonl");
|
|
9735
9739
|
}
|
|
9736
9740
|
function normalizeClickUpWebhookLogLevel(value) {
|
|
9737
9741
|
const level = String(value || "info").trim().toLowerCase();
|
|
9738
9742
|
return CLICKUP_WEBHOOK_LOG_LEVELS.has(level) ? level : "info";
|
|
9739
9743
|
}
|
|
9740
9744
|
function clickUpWebhookAuditLogDir() {
|
|
9741
|
-
const dataHome = process.env.XDG_DATA_HOME &&
|
|
9742
|
-
return
|
|
9745
|
+
const dataHome = process.env.XDG_DATA_HOME && path6.isAbsolute(process.env.XDG_DATA_HOME) ? process.env.XDG_DATA_HOME : path6.join(os.homedir(), ".local", "share", "opencode");
|
|
9746
|
+
return path6.join(dataHome, "opencode-optima");
|
|
9743
9747
|
}
|
|
9744
9748
|
function clickUpWebhookAuditLogPath(at = /* @__PURE__ */ new Date(), logDir = clickUpWebhookAuditLogDir()) {
|
|
9745
|
-
return
|
|
9749
|
+
return path6.join(logDir, `clickup-webhook-${at.toISOString().slice(0, 10)}.jsonl`);
|
|
9746
9750
|
}
|
|
9747
9751
|
function clickUpWebhookRequestFilePath(at = /* @__PURE__ */ new Date(), logDir = clickUpWebhookAuditLogDir()) {
|
|
9748
9752
|
const stamp = at.toISOString().replace(/:/g, "-").replace(/\./g, "-");
|
|
9749
9753
|
const shortId = crypto.randomBytes(4).toString("hex");
|
|
9750
|
-
return
|
|
9754
|
+
return path6.join(logDir, "requests", `clickup-webhook-${stamp}-${shortId}.json`);
|
|
9751
9755
|
}
|
|
9752
9756
|
function findOptimaPluginTupleOptions(pluginEntries = []) {
|
|
9753
9757
|
if (!Array.isArray(pluginEntries)) return null;
|
|
@@ -9813,6 +9817,10 @@ function normalizeClickUpWebhookConfig(rawClickUp = null, worktree = process.cwd
|
|
|
9813
9817
|
assignmentWatchdogIntervalMs: normalizeNonNegativeInteger(
|
|
9814
9818
|
opencode.assignment_watchdog_interval_ms ?? opencode.assignmentWatchdogIntervalMs ?? raw.assignment_watchdog_interval_ms ?? raw.assignmentWatchdogIntervalMs,
|
|
9815
9819
|
CLICKUP_ASSIGNMENT_WATCHDOG_INTERVAL_MS
|
|
9820
|
+
),
|
|
9821
|
+
assignmentWatchdogRunningGraceMs: normalizeNonNegativeInteger(
|
|
9822
|
+
opencode.assignment_watchdog_running_grace_ms ?? opencode.assignmentWatchdogRunningGraceMs ?? raw.assignment_watchdog_running_grace_ms ?? raw.assignmentWatchdogRunningGraceMs,
|
|
9823
|
+
CLICKUP_ASSIGNMENT_WATCHDOG_RUNNING_GRACE_MS
|
|
9816
9824
|
)
|
|
9817
9825
|
},
|
|
9818
9826
|
openchamber: {
|
|
@@ -9846,7 +9854,7 @@ function normalizeClickUpWebhookConfig(rawClickUp = null, worktree = process.cwd
|
|
|
9846
9854
|
};
|
|
9847
9855
|
const errors = [];
|
|
9848
9856
|
if (!config.enabled) errors.push("clickup.enabled must be true");
|
|
9849
|
-
if (!config.basePath || !
|
|
9857
|
+
if (!config.basePath || !path6.isAbsolute(config.basePath)) errors.push("clickup.base_path must be an absolute path");
|
|
9850
9858
|
if (!config.teamId) errors.push("clickup.team_id is required");
|
|
9851
9859
|
if (!config.apiToken) errors.push("clickup.api_token is required");
|
|
9852
9860
|
if (!config.webhook.publicUrl) errors.push("clickup.webhook.public_url is required");
|
|
@@ -9904,7 +9912,7 @@ function readClickUpWebhookState(worktree, config = null) {
|
|
|
9904
9912
|
}
|
|
9905
9913
|
function writeClickUpWebhookState(worktree, state, config = null) {
|
|
9906
9914
|
const statePath = clickUpWebhookStatePath(worktree);
|
|
9907
|
-
fs5.mkdirSync(
|
|
9915
|
+
fs5.mkdirSync(path6.dirname(statePath), { recursive: true, mode: 448 });
|
|
9908
9916
|
const next = sanitizeClickUpWebhookState(state, config);
|
|
9909
9917
|
fs5.writeFileSync(statePath, `${JSON.stringify(next, null, 2)}
|
|
9910
9918
|
`, { encoding: "utf8", mode: 384 });
|
|
@@ -9925,7 +9933,7 @@ function isClickUpWebhookStateActive(state, config) {
|
|
|
9925
9933
|
function expandHomePath(value = "") {
|
|
9926
9934
|
const input = String(value || "").trim();
|
|
9927
9935
|
if (input === "~") return os.homedir();
|
|
9928
|
-
if (input.startsWith("~/")) return
|
|
9936
|
+
if (input.startsWith("~/")) return path6.join(os.homedir(), input.slice(2));
|
|
9929
9937
|
return input;
|
|
9930
9938
|
}
|
|
9931
9939
|
function resolveSecretReference(value = "") {
|
|
@@ -10301,7 +10309,7 @@ function readClickUpCommentLedger(ledgerPath) {
|
|
|
10301
10309
|
}
|
|
10302
10310
|
function appendClickUpCommentLedgerEntry(ledgerPath, entry = {}) {
|
|
10303
10311
|
if (!ledgerPath || !entry.key) return;
|
|
10304
|
-
fs5.mkdirSync(
|
|
10312
|
+
fs5.mkdirSync(path6.dirname(ledgerPath), { recursive: true, mode: 448 });
|
|
10305
10313
|
fs5.appendFileSync(ledgerPath, `${JSON.stringify(entry)}
|
|
10306
10314
|
`, { encoding: "utf8", mode: 384 });
|
|
10307
10315
|
try {
|
|
@@ -10768,6 +10776,22 @@ async function readOpenCodeSessionMessages(client, { sessionId, directory, limit
|
|
|
10768
10776
|
if (directory) query.directory = directory;
|
|
10769
10777
|
return normalizeOpenCodeSessionMessages(await client.session.messages({ path: { id: sessionId }, query }));
|
|
10770
10778
|
}
|
|
10779
|
+
async function readOpenCodeChildSessions(client, { sessionId, directory } = {}) {
|
|
10780
|
+
if (typeof client?.session?.children !== "function") return [];
|
|
10781
|
+
const attempts = [
|
|
10782
|
+
{ path: { id: sessionId }, query: directory ? { directory } : {} },
|
|
10783
|
+
{ path: { sessionID: sessionId }, query: directory ? { directory } : {} },
|
|
10784
|
+
{ sessionID: sessionId, ...directory ? { directory } : {} }
|
|
10785
|
+
];
|
|
10786
|
+
for (const attempt of attempts) {
|
|
10787
|
+
try {
|
|
10788
|
+
const result = await client.session.children(attempt);
|
|
10789
|
+
return normalizeOpenCodeSessionCollection(result?.data ?? result);
|
|
10790
|
+
} catch {
|
|
10791
|
+
}
|
|
10792
|
+
}
|
|
10793
|
+
return [];
|
|
10794
|
+
}
|
|
10771
10795
|
function openCodeResultSummary(result) {
|
|
10772
10796
|
const data = result?.data ?? result;
|
|
10773
10797
|
return {
|
|
@@ -10828,13 +10852,28 @@ function openCodeMessageTimestampMs(message = {}, key = "updated") {
|
|
|
10828
10852
|
const number = Number(value);
|
|
10829
10853
|
return Number.isFinite(number) && number > 0 ? number : 0;
|
|
10830
10854
|
}
|
|
10831
|
-
function
|
|
10855
|
+
function openCodeSessionTimestampMs(session = {}, key = "updated") {
|
|
10856
|
+
const time = session?.time || session?.info?.time || {};
|
|
10857
|
+
const value = key === "created" ? session.time_created ?? session.timeCreated ?? time.created : session.time_updated ?? session.timeUpdated ?? time.updated ?? session.time_created ?? session.timeCreated ?? time.created;
|
|
10858
|
+
const number = Number(value);
|
|
10859
|
+
return Number.isFinite(number) && number > 0 ? number : 0;
|
|
10860
|
+
}
|
|
10861
|
+
function openCodeNowMs(now = /* @__PURE__ */ new Date()) {
|
|
10862
|
+
const value = typeof now === "function" ? now() : now;
|
|
10863
|
+
const number = Number(value instanceof Date ? value.getTime() : new Date(value).getTime());
|
|
10864
|
+
return Number.isFinite(number) && number > 0 ? number : 0;
|
|
10865
|
+
}
|
|
10866
|
+
function isOpenCodeAssistantMessageRunning(message = {}, { latestActivityAt = 0, now = /* @__PURE__ */ new Date(), runningGraceMs = CLICKUP_ASSIGNMENT_WATCHDOG_RUNNING_GRACE_MS } = {}) {
|
|
10832
10867
|
if (normalizeLooseToken(normalizeOpenCodeMessageRole(message)) !== "assistant") return false;
|
|
10833
10868
|
const started = openCodeMessageTimestampMs(message, "created") > 0;
|
|
10834
10869
|
if (!started) return false;
|
|
10835
|
-
|
|
10870
|
+
if (openCodeMessageTimestampMs(message, "completed") !== 0) return false;
|
|
10871
|
+
const nowMs = openCodeNowMs(now);
|
|
10872
|
+
const activityAt = Number(latestActivityAt) || openCodeMessageTimestampMs(message, "updated") || openCodeMessageTimestampMs(message, "created");
|
|
10873
|
+
if (!Number.isFinite(nowMs) || nowMs <= 0 || !Number.isFinite(activityAt) || activityAt <= 0) return false;
|
|
10874
|
+
return nowMs - activityAt <= Math.max(0, Number(runningGraceMs) || 0);
|
|
10836
10875
|
}
|
|
10837
|
-
async function inspectOpenCodeSessionActivity(client, { sessionId, directory, limit = 10 } = {}) {
|
|
10876
|
+
async function inspectOpenCodeSessionActivity(client, { sessionId, directory, limit = 10, now = /* @__PURE__ */ new Date(), runningGraceMs = CLICKUP_ASSIGNMENT_WATCHDOG_RUNNING_GRACE_MS } = {}) {
|
|
10838
10877
|
const messages = await readOpenCodeSessionMessages(client, { sessionId, directory, limit });
|
|
10839
10878
|
if (!messages) return { ok: false, reason: "message_inspection_unavailable", sessionId, directory };
|
|
10840
10879
|
const enriched = messages.map((message, index) => ({
|
|
@@ -10844,20 +10883,45 @@ async function inspectOpenCodeSessionActivity(client, { sessionId, directory, li
|
|
|
10844
10883
|
createdAt: openCodeMessageTimestampMs(message, "created"),
|
|
10845
10884
|
completedAt: openCodeMessageTimestampMs(message, "completed")
|
|
10846
10885
|
})).sort((a, b) => a.sortTime - b.sortTime || a.index - b.index);
|
|
10886
|
+
const childSessions = await readOpenCodeChildSessions(client, { sessionId, directory });
|
|
10887
|
+
const childActivities = childSessions.map((session, index) => ({
|
|
10888
|
+
session,
|
|
10889
|
+
index,
|
|
10890
|
+
id: session.id || session.sessionID || session.sessionId || null,
|
|
10891
|
+
agent: session.agent || session.mode?.agent || session.metadata?.agent || "",
|
|
10892
|
+
updatedAt: openCodeSessionTimestampMs(session, "updated")
|
|
10893
|
+
})).filter((entry) => entry.updatedAt > 0).sort((a, b) => a.updatedAt - b.updatedAt || a.index - b.index);
|
|
10847
10894
|
const assistantMessages = enriched.filter((entry) => normalizeLooseToken(normalizeOpenCodeMessageRole(entry.message)) === "assistant");
|
|
10848
10895
|
const latestAssistant = assistantMessages.at(-1) || null;
|
|
10849
10896
|
const latest = enriched.at(-1) || null;
|
|
10850
|
-
const
|
|
10897
|
+
const latestChild = childActivities.at(-1) || null;
|
|
10898
|
+
const latestMessageActivityAt = latest?.sortTime || 0;
|
|
10899
|
+
const latestChildActivityAt = latestChild?.updatedAt || 0;
|
|
10900
|
+
const latestActivityAt = Math.max(latestMessageActivityAt, latestChildActivityAt);
|
|
10901
|
+
const nowMs = openCodeNowMs(now);
|
|
10902
|
+
const latestActivityAgeMs = Number.isFinite(nowMs) && latestActivityAt > 0 ? Math.max(0, nowMs - latestActivityAt) : null;
|
|
10903
|
+
const assistantRunning = latestAssistant ? isOpenCodeAssistantMessageRunning(latestAssistant.message, { latestActivityAt, now, runningGraceMs }) : false;
|
|
10904
|
+
const childRunning = latestChildActivityAt > 0 && latestActivityAgeMs !== null && latestActivityAgeMs <= Math.max(0, Number(runningGraceMs) || 0);
|
|
10905
|
+
const running = assistantRunning || childRunning;
|
|
10906
|
+
const runningReason = running ? childRunning && latestChildActivityAt >= latestMessageActivityAt ? "recent_child_session_activity" : "recent_incomplete_assistant" : latestAssistant && latestAssistant.completedAt === 0 ? "stale_incomplete_assistant" : "not_running";
|
|
10851
10907
|
return {
|
|
10852
10908
|
ok: true,
|
|
10853
10909
|
sessionId,
|
|
10854
10910
|
directory,
|
|
10855
10911
|
count: messages.length,
|
|
10856
10912
|
running,
|
|
10913
|
+
runningReason,
|
|
10914
|
+
runningGraceMs,
|
|
10915
|
+
latestActivityAt,
|
|
10916
|
+
latestActivityAgeMs,
|
|
10857
10917
|
latestMessageId: latest ? normalizeOpenCodeMessageId(latest.message) : null,
|
|
10858
10918
|
latestAssistantMessageId: latestAssistant ? normalizeOpenCodeMessageId(latestAssistant.message) : null,
|
|
10859
10919
|
latestAssistantCreatedAt: latestAssistant?.createdAt || 0,
|
|
10860
|
-
latestAssistantCompletedAt: latestAssistant?.completedAt || 0
|
|
10920
|
+
latestAssistantCompletedAt: latestAssistant?.completedAt || 0,
|
|
10921
|
+
latestChildSessionId: latestChild?.id || null,
|
|
10922
|
+
latestChildAgent: latestChild?.agent || null,
|
|
10923
|
+
latestChildUpdatedAt: latestChild?.updatedAt || 0,
|
|
10924
|
+
childSessionCount: childSessions.length
|
|
10861
10925
|
};
|
|
10862
10926
|
}
|
|
10863
10927
|
function summarizeOpenCodeMessages(messages = [], { snippetLength = 160, maxMessages = 50 } = {}) {
|
|
@@ -11164,7 +11228,7 @@ function formatClickUpWebhookPrompt({ eventType, taskId, payload, branch = "", w
|
|
|
11164
11228
|
}
|
|
11165
11229
|
function appendClickUpWebhookLocalLog(worktree, entry) {
|
|
11166
11230
|
const logPath = clickUpWebhookLogPath(worktree);
|
|
11167
|
-
fs5.mkdirSync(
|
|
11231
|
+
fs5.mkdirSync(path6.dirname(logPath), { recursive: true });
|
|
11168
11232
|
const safeEntry = { ...entry, at: entry.at || (/* @__PURE__ */ new Date()).toISOString() };
|
|
11169
11233
|
fs5.appendFileSync(logPath, `${JSON.stringify(safeEntry)}
|
|
11170
11234
|
`, "utf8");
|
|
@@ -11195,7 +11259,7 @@ function closeClickUpWebhookServer(server) {
|
|
|
11195
11259
|
});
|
|
11196
11260
|
}
|
|
11197
11261
|
function managedClickUpWebhookKey({ worktree, state, config } = {}) {
|
|
11198
|
-
return [
|
|
11262
|
+
return [path6.resolve(worktree || process.cwd()), state?.webhookId || "", config?.webhook?.publicUrl || ""].join("|");
|
|
11199
11263
|
}
|
|
11200
11264
|
async function deleteClickUpWebhookBestEffort({ webhookId, clickupClient, worktree, reason = "cleanup" } = {}) {
|
|
11201
11265
|
const id = String(webhookId || "").trim();
|
|
@@ -11300,8 +11364,8 @@ function writeClickUpWebhookAuditLog({ method, url, headers = {}, rawBody = "",
|
|
|
11300
11364
|
let requestFile;
|
|
11301
11365
|
if (level === "verbose") {
|
|
11302
11366
|
const absoluteRequestFile = clickUpWebhookRequestFilePath(at, logDir);
|
|
11303
|
-
fs5.mkdirSync(
|
|
11304
|
-
requestFile =
|
|
11367
|
+
fs5.mkdirSync(path6.dirname(absoluteRequestFile), { recursive: true });
|
|
11368
|
+
requestFile = path6.relative(logDir, absoluteRequestFile).split(path6.sep).join("/");
|
|
11305
11369
|
const parsedBody = payload || (() => {
|
|
11306
11370
|
try {
|
|
11307
11371
|
return JSON.parse(Buffer.isBuffer(rawBody) ? rawBody.toString("utf8") : String(rawBody || ""));
|
|
@@ -11617,7 +11681,12 @@ async function reconcileClickUpStartup({ config, state = {}, worktree = process.
|
|
|
11617
11681
|
const directory = String(getNestedMetadataValue(metadata, "task.worktree") || "").trim();
|
|
11618
11682
|
if (sessionId) {
|
|
11619
11683
|
try {
|
|
11620
|
-
const activity = await inspectOpenCodeSessionActivity(openCodeClient, {
|
|
11684
|
+
const activity = await inspectOpenCodeSessionActivity(openCodeClient, {
|
|
11685
|
+
sessionId,
|
|
11686
|
+
directory,
|
|
11687
|
+
now,
|
|
11688
|
+
runningGraceMs: config.opencode.assignmentWatchdogRunningGraceMs
|
|
11689
|
+
});
|
|
11621
11690
|
appendClickUpWebhookLocalLog(worktree, { type: "assignment_watchdog_session_activity", taskId, sessionId, directory: directory || null, ...activity });
|
|
11622
11691
|
if (activity.running) {
|
|
11623
11692
|
routed.ignored += 1;
|
|
@@ -11912,17 +11981,17 @@ function startClickUpWebhookListener({ config, state, worktree, clickupClient, o
|
|
|
11912
11981
|
return result;
|
|
11913
11982
|
}
|
|
11914
11983
|
function legacyVariantPath(destinationPath) {
|
|
11915
|
-
const parsed =
|
|
11984
|
+
const parsed = path6.parse(destinationPath);
|
|
11916
11985
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:TZ.]/g, "").slice(0, 14);
|
|
11917
|
-
if (parsed.ext) return
|
|
11918
|
-
return
|
|
11986
|
+
if (parsed.ext) return path6.join(parsed.dir, `${parsed.name}.legacy-${stamp}${parsed.ext}`);
|
|
11987
|
+
return path6.join(parsed.dir, `${parsed.base}.legacy-${stamp}`);
|
|
11919
11988
|
}
|
|
11920
11989
|
function normalizeWorkflowTaskPath(taskPath) {
|
|
11921
11990
|
if (typeof taskPath !== "string") return { ok: false, message: "Error: task_path is required." };
|
|
11922
11991
|
const trimmed = taskPath.trim();
|
|
11923
11992
|
if (!trimmed) return { ok: false, message: "Error: task_path is required." };
|
|
11924
11993
|
const normalized = trimmed.replace(/\\/g, "/");
|
|
11925
|
-
if (
|
|
11994
|
+
if (path6.isAbsolute(trimmed)) return { ok: true, taskPath: trimmed };
|
|
11926
11995
|
if (normalized === "tasks" || normalized.startsWith("tasks/")) {
|
|
11927
11996
|
return {
|
|
11928
11997
|
ok: false,
|
|
@@ -11941,12 +12010,12 @@ function mergeFileIntoDestination(sourcePath, destinationPath, relativeSource, g
|
|
|
11941
12010
|
const sourceWasTracked = isGitTracked(gitState, sourcePath);
|
|
11942
12011
|
if (gitAwareMoveIfTracked(sourcePath, destinationPath, gitState)) return;
|
|
11943
12012
|
if (!fs5.existsSync(destinationPath)) {
|
|
11944
|
-
fs5.mkdirSync(
|
|
12013
|
+
fs5.mkdirSync(path6.dirname(destinationPath), { recursive: true });
|
|
11945
12014
|
fs5.renameSync(sourcePath, destinationPath);
|
|
11946
12015
|
if (sourceWasTracked) stageGitAwareMerge(sourcePath, destinationPath, gitState);
|
|
11947
12016
|
return;
|
|
11948
12017
|
}
|
|
11949
|
-
const ext =
|
|
12018
|
+
const ext = path6.extname(destinationPath).toLowerCase();
|
|
11950
12019
|
if ([".yaml", ".yml", ".json"].includes(ext)) {
|
|
11951
12020
|
const sourceRaw = fs5.readFileSync(sourcePath, "utf8");
|
|
11952
12021
|
const destRaw = fs5.readFileSync(destinationPath, "utf8");
|
|
@@ -11981,14 +12050,14 @@ ${sourceRaw}
|
|
|
11981
12050
|
fs5.renameSync(sourcePath, preservedPath);
|
|
11982
12051
|
stageGitAwareMerge(sourcePath, preservedPath, gitState);
|
|
11983
12052
|
}
|
|
11984
|
-
function mergePathIntoDestination(sourcePath, destinationPath, relativeSource =
|
|
12053
|
+
function mergePathIntoDestination(sourcePath, destinationPath, relativeSource = path6.basename(sourcePath), gitState = null) {
|
|
11985
12054
|
if (!fs5.existsSync(sourcePath)) return;
|
|
11986
12055
|
const stat = fs5.statSync(sourcePath);
|
|
11987
12056
|
if (stat.isDirectory()) {
|
|
11988
12057
|
const sourceWasTracked = isGitTracked(gitState, sourcePath) || hasGitTrackedChildren(gitState, sourcePath);
|
|
11989
12058
|
if (gitAwareMoveIfTracked(sourcePath, destinationPath, gitState)) return;
|
|
11990
12059
|
if (!fs5.existsSync(destinationPath)) {
|
|
11991
|
-
fs5.mkdirSync(
|
|
12060
|
+
fs5.mkdirSync(path6.dirname(destinationPath), { recursive: true });
|
|
11992
12061
|
fs5.renameSync(sourcePath, destinationPath);
|
|
11993
12062
|
if (sourceWasTracked) stageGitAwareMerge(sourcePath, destinationPath, gitState);
|
|
11994
12063
|
return;
|
|
@@ -11996,9 +12065,9 @@ function mergePathIntoDestination(sourcePath, destinationPath, relativeSource =
|
|
|
11996
12065
|
fs5.mkdirSync(destinationPath, { recursive: true });
|
|
11997
12066
|
for (const entry of fs5.readdirSync(sourcePath)) {
|
|
11998
12067
|
mergePathIntoDestination(
|
|
11999
|
-
|
|
12000
|
-
|
|
12001
|
-
|
|
12068
|
+
path6.join(sourcePath, entry),
|
|
12069
|
+
path6.join(destinationPath, entry),
|
|
12070
|
+
path6.join(relativeSource, entry),
|
|
12002
12071
|
gitState
|
|
12003
12072
|
);
|
|
12004
12073
|
}
|
|
@@ -12008,7 +12077,7 @@ function mergePathIntoDestination(sourcePath, destinationPath, relativeSource =
|
|
|
12008
12077
|
mergeFileIntoDestination(sourcePath, destinationPath, relativeSource, gitState);
|
|
12009
12078
|
}
|
|
12010
12079
|
function isOptimaPluginPackageWorktree(worktree) {
|
|
12011
|
-
const packageJsonPath =
|
|
12080
|
+
const packageJsonPath = path6.join(worktree, "package.json");
|
|
12012
12081
|
if (!fs5.existsSync(packageJsonPath)) return false;
|
|
12013
12082
|
try {
|
|
12014
12083
|
const pkg = JSON.parse(fs5.readFileSync(packageJsonPath, "utf8"));
|
|
@@ -12020,51 +12089,51 @@ function isOptimaPluginPackageWorktree(worktree) {
|
|
|
12020
12089
|
function migrateLegacyOptimaLayout(worktree) {
|
|
12021
12090
|
const gitState = gitMigrationState(worktree);
|
|
12022
12091
|
const migrations = [
|
|
12023
|
-
[
|
|
12024
|
-
[
|
|
12025
|
-
[
|
|
12026
|
-
[
|
|
12027
|
-
[
|
|
12028
|
-
[
|
|
12092
|
+
[path6.join(legacyOrbitaDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path6.join(".orbita", "orbita.yaml")],
|
|
12093
|
+
[path6.join(legacyOrbitaDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path6.join(".orbita", "staticeng.yaml")],
|
|
12094
|
+
[path6.join(legacyOrbitaDir(worktree), ".config"), optimaLocalConfigDir(worktree), path6.join(".orbita", ".config")],
|
|
12095
|
+
[path6.join(legacyOrbitaDir(worktree), "config"), optimaLocalConfigDir(worktree), path6.join(".orbita", "config")],
|
|
12096
|
+
[path6.join(legacyOrbitaDir(worktree), "runtime"), path6.join(optimaLocalConfigDir(worktree), "runtime"), path6.join(".orbita", "runtime")],
|
|
12097
|
+
[path6.join(legacyOrbitaDir(worktree), "generated"), path6.join(optimaLocalConfigDir(worktree), "generated"), path6.join(".orbita", "generated")],
|
|
12029
12098
|
[legacyOrbitaDir(worktree), optimaDir(worktree), ".orbita"],
|
|
12030
|
-
[
|
|
12031
|
-
[
|
|
12032
|
-
[
|
|
12033
|
-
[
|
|
12034
|
-
[
|
|
12035
|
-
[
|
|
12099
|
+
[path6.join(legacyStaticEngDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path6.join(".staticeng", "staticeng.yaml")],
|
|
12100
|
+
[path6.join(legacyStaticEngDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path6.join(".staticeng", "orbita.yaml")],
|
|
12101
|
+
[path6.join(legacyStaticEngDir(worktree), ".config"), optimaLocalConfigDir(worktree), path6.join(".staticeng", ".config")],
|
|
12102
|
+
[path6.join(legacyStaticEngDir(worktree), "config"), optimaLocalConfigDir(worktree), path6.join(".staticeng", "config")],
|
|
12103
|
+
[path6.join(legacyStaticEngDir(worktree), "runtime"), path6.join(optimaLocalConfigDir(worktree), "runtime"), path6.join(".staticeng", "runtime")],
|
|
12104
|
+
[path6.join(legacyStaticEngDir(worktree), "generated"), path6.join(optimaLocalConfigDir(worktree), "generated"), path6.join(".staticeng", "generated")],
|
|
12036
12105
|
[legacyStaticEngDir(worktree), optimaDir(worktree), ".staticeng"],
|
|
12037
|
-
[
|
|
12038
|
-
[
|
|
12039
|
-
[
|
|
12040
|
-
[
|
|
12041
|
-
[
|
|
12042
|
-
[
|
|
12043
|
-
[
|
|
12044
|
-
[
|
|
12045
|
-
[
|
|
12046
|
-
[
|
|
12047
|
-
[
|
|
12048
|
-
[
|
|
12106
|
+
[path6.join(legacyNomadworkDir(worktree), "nomadworks.yaml"), repoConfigPath(worktree), path6.join(".nomadwork", "nomadworks.yaml")],
|
|
12107
|
+
[path6.join(legacyNomadworksDir(worktree), "nomadworks.yaml"), repoConfigPath(worktree), path6.join(".nomadworks", "nomadworks.yaml")],
|
|
12108
|
+
[path6.join(legacyNomadworkDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path6.join(".nomadwork", "staticeng.yaml")],
|
|
12109
|
+
[path6.join(legacyNomadworksDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path6.join(".nomadworks", "staticeng.yaml")],
|
|
12110
|
+
[path6.join(legacyNomadworkDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path6.join(".nomadwork", "orbita.yaml")],
|
|
12111
|
+
[path6.join(legacyNomadworksDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path6.join(".nomadworks", "orbita.yaml")],
|
|
12112
|
+
[path6.join(legacyNomadworkDir(worktree), "runtime"), path6.join(optimaLocalConfigDir(worktree), "runtime"), path6.join(".nomadwork", "runtime")],
|
|
12113
|
+
[path6.join(legacyNomadworksDir(worktree), "runtime"), path6.join(optimaLocalConfigDir(worktree), "runtime"), path6.join(".nomadworks", "runtime")],
|
|
12114
|
+
[path6.join(legacyNomadworkDir(worktree), "generated"), path6.join(optimaLocalConfigDir(worktree), "generated"), path6.join(".nomadwork", "generated")],
|
|
12115
|
+
[path6.join(legacyNomadworksDir(worktree), "generated"), path6.join(optimaLocalConfigDir(worktree), "generated"), path6.join(".nomadworks", "generated")],
|
|
12116
|
+
[path6.join(legacyNomadworkDir(worktree), "config"), optimaLocalConfigDir(worktree), path6.join(".nomadwork", "config")],
|
|
12117
|
+
[path6.join(legacyNomadworksDir(worktree), "config"), optimaLocalConfigDir(worktree), path6.join(".nomadworks", "config")],
|
|
12049
12118
|
[legacyNomadworkDir(worktree), optimaDir(worktree), ".nomadwork"],
|
|
12050
12119
|
[legacyNomadworksDir(worktree), optimaDir(worktree), ".nomadworks"],
|
|
12051
|
-
[
|
|
12052
|
-
[
|
|
12053
|
-
[
|
|
12054
|
-
[
|
|
12055
|
-
[
|
|
12120
|
+
[path6.join(worktree, "tasks"), optimaTasksDir(worktree), "tasks"],
|
|
12121
|
+
[path6.join(worktree, "evidences"), optimaEvidencesDir(worktree), "evidences"],
|
|
12122
|
+
[path6.join(worktree, "docs", "scrs"), optimaScrsDir(worktree), path6.join("docs", "scrs")],
|
|
12123
|
+
[path6.join(worktree, "codemap.yml"), optimaCodemapPath(worktree), "codemap.yml"],
|
|
12124
|
+
[path6.join(worktree, "codemap.yaml"), optimaCodemapPath(worktree), "codemap.yaml"]
|
|
12056
12125
|
];
|
|
12057
12126
|
if (!isOptimaPluginPackageWorktree(worktree)) {
|
|
12058
|
-
migrations.push([
|
|
12127
|
+
migrations.push([path6.join(worktree, "policies"), repoPoliciesDir(worktree), "policies"]);
|
|
12059
12128
|
}
|
|
12060
12129
|
for (const [source, destination, relativeSource] of migrations) {
|
|
12061
12130
|
if (fs5.existsSync(source)) mergePathIntoDestination(source, destination, relativeSource, gitState);
|
|
12062
12131
|
}
|
|
12063
12132
|
for (const [source, destination, relativeSource] of [
|
|
12064
|
-
[
|
|
12065
|
-
[
|
|
12066
|
-
[
|
|
12067
|
-
[
|
|
12133
|
+
[path6.join(optimaDir(worktree), "optima.yaml"), repoConfigPath(worktree), path6.join(".optima", "optima.yaml")],
|
|
12134
|
+
[path6.join(optimaDir(worktree), "config"), optimaLocalConfigDir(worktree), path6.join(".optima", "config")],
|
|
12135
|
+
[path6.join(optimaDir(worktree), "runtime"), path6.join(optimaLocalConfigDir(worktree), "runtime"), path6.join(".optima", "runtime")],
|
|
12136
|
+
[path6.join(optimaDir(worktree), "generated"), path6.join(optimaLocalConfigDir(worktree), "generated"), path6.join(".optima", "generated")]
|
|
12068
12137
|
]) {
|
|
12069
12138
|
if (fs5.existsSync(source)) mergePathIntoDestination(source, destination, relativeSource, gitState);
|
|
12070
12139
|
}
|
|
@@ -12113,7 +12182,7 @@ function toModelString(provider, model) {
|
|
|
12113
12182
|
}
|
|
12114
12183
|
function readTaskMetadata(taskPath, worktree) {
|
|
12115
12184
|
if (!taskPath) return {};
|
|
12116
|
-
const absoluteTaskPath =
|
|
12185
|
+
const absoluteTaskPath = path6.isAbsolute(taskPath) ? taskPath : path6.join(worktree, taskPath);
|
|
12117
12186
|
if (!fs5.existsSync(absoluteTaskPath)) return {};
|
|
12118
12187
|
try {
|
|
12119
12188
|
const raw = fs5.readFileSync(absoluteTaskPath, "utf8");
|
|
@@ -12158,18 +12227,18 @@ function loadDiscussionRegistry(worktree) {
|
|
|
12158
12227
|
}
|
|
12159
12228
|
function saveDiscussionRegistry(worktree, registry) {
|
|
12160
12229
|
const registryPath = runtimeDiscussionRegistryPath(worktree);
|
|
12161
|
-
const runtimeDir =
|
|
12230
|
+
const runtimeDir = path6.dirname(registryPath);
|
|
12162
12231
|
if (!fs5.existsSync(runtimeDir)) fs5.mkdirSync(runtimeDir, { recursive: true });
|
|
12163
12232
|
fs5.writeFileSync(registryPath, JSON.stringify(registry, null, 2), "utf8");
|
|
12164
12233
|
}
|
|
12165
12234
|
function runtimeDiscussionsDir(worktree) {
|
|
12166
|
-
return
|
|
12235
|
+
return path6.join(optimaLocalConfigDir(worktree), "runtime", "discussions");
|
|
12167
12236
|
}
|
|
12168
12237
|
function archivedRuntimeDiscussionsDir(worktree) {
|
|
12169
|
-
return
|
|
12238
|
+
return path6.join(runtimeDiscussionsDir(worktree), "archive");
|
|
12170
12239
|
}
|
|
12171
12240
|
function finalDiscussionsDir(worktree) {
|
|
12172
|
-
return
|
|
12241
|
+
return path6.join(optimaTasksDir(worktree), "discussions");
|
|
12173
12242
|
}
|
|
12174
12243
|
function nextDiscussionIdentity(worktree, title) {
|
|
12175
12244
|
const discussionsDir = finalDiscussionsDir(worktree);
|
|
@@ -12180,11 +12249,11 @@ function nextDiscussionIdentity(worktree, title) {
|
|
|
12180
12249
|
while (true) {
|
|
12181
12250
|
const id = `DISCUSSION-${String(sequence).padStart(3, "0")}`;
|
|
12182
12251
|
const filename = `${id}-${slugifyTitle(title)}.md`;
|
|
12183
|
-
const summaryRelativePath =
|
|
12184
|
-
const summaryAbsolutePath =
|
|
12252
|
+
const summaryRelativePath = path6.join(".optima", "tasks", "discussions", filename);
|
|
12253
|
+
const summaryAbsolutePath = path6.join(worktree, summaryRelativePath);
|
|
12185
12254
|
const transcriptFilename = `${id}-transcript.md`;
|
|
12186
|
-
const transcriptRelativePath =
|
|
12187
|
-
const transcriptAbsolutePath =
|
|
12255
|
+
const transcriptRelativePath = path6.join(".optima", ".config", "runtime", "discussions", transcriptFilename);
|
|
12256
|
+
const transcriptAbsolutePath = path6.join(worktree, transcriptRelativePath);
|
|
12188
12257
|
if (!fs5.existsSync(summaryAbsolutePath) && !fs5.existsSync(transcriptAbsolutePath)) {
|
|
12189
12258
|
return {
|
|
12190
12259
|
id,
|
|
@@ -12209,11 +12278,11 @@ function findDiscussionById(worktree, discussionID) {
|
|
|
12209
12278
|
return {
|
|
12210
12279
|
id: discussionID,
|
|
12211
12280
|
filename,
|
|
12212
|
-
summaryRelativePath:
|
|
12213
|
-
summaryAbsolutePath:
|
|
12281
|
+
summaryRelativePath: path6.join(".optima", "tasks", "discussions", filename),
|
|
12282
|
+
summaryAbsolutePath: path6.join(discussionsDir, filename),
|
|
12214
12283
|
transcriptFilename,
|
|
12215
|
-
transcriptRelativePath:
|
|
12216
|
-
transcriptAbsolutePath:
|
|
12284
|
+
transcriptRelativePath: path6.join(".optima", ".config", "runtime", "discussions", transcriptFilename),
|
|
12285
|
+
transcriptAbsolutePath: path6.join(runtimeDiscussionsDir(worktree), transcriptFilename)
|
|
12217
12286
|
};
|
|
12218
12287
|
}
|
|
12219
12288
|
function parseDiscussionFile(filePath) {
|
|
@@ -12296,15 +12365,15 @@ async function appendMessageIfNeeded(client, worktree, registry, sessionID, mess
|
|
|
12296
12365
|
});
|
|
12297
12366
|
const text = extractTextParts(response.data.parts || []);
|
|
12298
12367
|
if (!text) return;
|
|
12299
|
-
appendDiscussionMessage(
|
|
12368
|
+
appendDiscussionMessage(path6.join(worktree, discussion.transcriptPath), speaker, text, messageID);
|
|
12300
12369
|
discussion.appendedMessageIDs ??= [];
|
|
12301
12370
|
discussion.appendedMessageIDs.push(messageID);
|
|
12302
12371
|
saveDiscussionRegistry(worktree, registry);
|
|
12303
12372
|
}
|
|
12304
12373
|
async function summarizeDiscussionWithBA(client, worktree, discussion) {
|
|
12305
|
-
const transcriptPath =
|
|
12306
|
-
const summaryPath =
|
|
12307
|
-
const summaryDir =
|
|
12374
|
+
const transcriptPath = path6.join(worktree, discussion.transcriptPath);
|
|
12375
|
+
const summaryPath = path6.join(worktree, discussion.summaryPath);
|
|
12376
|
+
const summaryDir = path6.dirname(summaryPath);
|
|
12308
12377
|
if (!fs5.existsSync(summaryDir)) fs5.mkdirSync(summaryDir, { recursive: true });
|
|
12309
12378
|
const hasExistingSummary = fs5.existsSync(summaryPath);
|
|
12310
12379
|
const priorMtimeMs = hasExistingSummary ? fs5.statSync(summaryPath).mtimeMs : null;
|
|
@@ -12407,11 +12476,11 @@ async function summarizeDiscussionWithBA(client, worktree, discussion) {
|
|
|
12407
12476
|
return { confirmation, summaryPath, transcriptPath, hasExistingSummary, priorMtimeMs };
|
|
12408
12477
|
}
|
|
12409
12478
|
function archiveDiscussionTranscript(worktree, transcriptRelativePath) {
|
|
12410
|
-
const sourcePath =
|
|
12479
|
+
const sourcePath = path6.join(worktree, transcriptRelativePath);
|
|
12411
12480
|
if (!fs5.existsSync(sourcePath)) return null;
|
|
12412
12481
|
const archiveDir = archivedRuntimeDiscussionsDir(worktree);
|
|
12413
12482
|
if (!fs5.existsSync(archiveDir)) fs5.mkdirSync(archiveDir, { recursive: true });
|
|
12414
|
-
const targetPath =
|
|
12483
|
+
const targetPath = path6.join(archiveDir, path6.basename(sourcePath));
|
|
12415
12484
|
fs5.renameSync(sourcePath, targetPath);
|
|
12416
12485
|
return targetPath;
|
|
12417
12486
|
}
|
|
@@ -12430,7 +12499,7 @@ async function finalizeClosingDiscussion(client, worktree, registry, sessionID,
|
|
|
12430
12499
|
if (!summaryContent) {
|
|
12431
12500
|
throw new Error(`Discussion summary file is empty at ${discussion.summaryPath}`);
|
|
12432
12501
|
}
|
|
12433
|
-
const transcriptPath =
|
|
12502
|
+
const transcriptPath = path6.join(worktree, discussion.transcriptPath);
|
|
12434
12503
|
setDiscussionStatus(transcriptPath, "closed");
|
|
12435
12504
|
const archivedTranscriptPath = archiveDiscussionTranscript(worktree, discussion.transcriptPath);
|
|
12436
12505
|
delete registry.active[sessionID];
|
|
@@ -12438,7 +12507,7 @@ async function finalizeClosingDiscussion(client, worktree, registry, sessionID,
|
|
|
12438
12507
|
return {
|
|
12439
12508
|
confirmation,
|
|
12440
12509
|
summaryPath: discussion.summaryPath,
|
|
12441
|
-
archivedTranscriptPath: archivedTranscriptPath ?
|
|
12510
|
+
archivedTranscriptPath: archivedTranscriptPath ? path6.relative(worktree, archivedTranscriptPath) : path6.join(".optima", ".config", "runtime", "discussions", "archive", path6.basename(discussion.transcriptPath))
|
|
12442
12511
|
};
|
|
12443
12512
|
}
|
|
12444
12513
|
function normalizeTeamMode(value) {
|
|
@@ -12510,7 +12579,7 @@ function syncGeneratedPolicies(worktree, repoCfg) {
|
|
|
12510
12579
|
if (!fs5.existsSync(generatedDir)) fs5.mkdirSync(generatedDir, { recursive: true });
|
|
12511
12580
|
const policyFiles = fs5.readdirSync(BUNDLE_POLICIES_DIR).filter((file) => file.endsWith(".md") && file !== "README.md");
|
|
12512
12581
|
for (const file of policyFiles) {
|
|
12513
|
-
const sourcePath =
|
|
12582
|
+
const sourcePath = path6.join(BUNDLE_POLICIES_DIR, file);
|
|
12514
12583
|
const source = fs5.readFileSync(sourcePath, "utf8").trimEnd();
|
|
12515
12584
|
const generated = [
|
|
12516
12585
|
"<!--",
|
|
@@ -12522,18 +12591,18 @@ function syncGeneratedPolicies(worktree, repoCfg) {
|
|
|
12522
12591
|
source,
|
|
12523
12592
|
""
|
|
12524
12593
|
].join("\n");
|
|
12525
|
-
fs5.writeFileSync(
|
|
12594
|
+
fs5.writeFileSync(path6.join(generatedDir, file), generated, "utf8");
|
|
12526
12595
|
}
|
|
12527
12596
|
}
|
|
12528
12597
|
function ensureReadmeFile(dirPath, content) {
|
|
12529
12598
|
if (!fs5.existsSync(dirPath)) fs5.mkdirSync(dirPath, { recursive: true });
|
|
12530
|
-
const readmePath =
|
|
12599
|
+
const readmePath = path6.join(dirPath, "README.md");
|
|
12531
12600
|
if (!fs5.existsSync(readmePath)) {
|
|
12532
12601
|
fs5.writeFileSync(readmePath, content, "utf8");
|
|
12533
12602
|
}
|
|
12534
12603
|
}
|
|
12535
12604
|
function ensureFileIfMissing(filePath, content) {
|
|
12536
|
-
if (!fs5.existsSync(
|
|
12605
|
+
if (!fs5.existsSync(path6.dirname(filePath))) fs5.mkdirSync(path6.dirname(filePath), { recursive: true });
|
|
12537
12606
|
if (!fs5.existsSync(filePath)) fs5.writeFileSync(filePath, content, "utf8");
|
|
12538
12607
|
}
|
|
12539
12608
|
function currentTasksRegistryContent() {
|
|
@@ -12620,13 +12689,13 @@ Never place implementation evidence under root \`evidences/\`.
|
|
|
12620
12689
|
}
|
|
12621
12690
|
function ensureOptimaTaskTemplates(worktree) {
|
|
12622
12691
|
const tasksDir = optimaTasksDir(worktree);
|
|
12623
|
-
ensureFileIfMissing(
|
|
12624
|
-
ensureFileIfMissing(
|
|
12692
|
+
ensureFileIfMissing(path6.join(tasksDir, "task-template.md"), taskTemplateContent());
|
|
12693
|
+
ensureFileIfMissing(path6.join(tasksDir, "subtask-template.md"), subtaskTemplateContent());
|
|
12625
12694
|
}
|
|
12626
12695
|
function scaffoldOptimaConfig(worktree, teamMode = "full") {
|
|
12627
12696
|
const configPath = repoConfigPath(worktree);
|
|
12628
12697
|
if (fs5.existsSync(configPath)) return false;
|
|
12629
|
-
const templatePath =
|
|
12698
|
+
const templatePath = path6.join(TEMPLATES_DIR, "optima.yaml.template");
|
|
12630
12699
|
if (!fs5.existsSync(templatePath)) return false;
|
|
12631
12700
|
const agentIds = fs5.existsSync(BUNDLE_AGENTS_DIR) ? fs5.readdirSync(BUNDLE_AGENTS_DIR).filter((f) => f.endsWith(".md")).map((f) => f.replace(".md", "")) : [];
|
|
12632
12701
|
let optimaConfig = fs5.readFileSync(templatePath, "utf8");
|
|
@@ -12645,9 +12714,9 @@ function scaffoldOptimaConfig(worktree, teamMode = "full") {
|
|
|
12645
12714
|
function scaffoldOptimaRootCodemap(worktree) {
|
|
12646
12715
|
const rootCodemapPath = optimaCodemapPath(worktree);
|
|
12647
12716
|
if (fs5.existsSync(rootCodemapPath)) return false;
|
|
12648
|
-
const templatePath =
|
|
12717
|
+
const templatePath = path6.join(TEMPLATES_DIR, "codemap.yml.template");
|
|
12649
12718
|
if (!fs5.existsSync(templatePath)) return false;
|
|
12650
|
-
const codemapConfig = fs5.readFileSync(templatePath, "utf8").replace("{{projectName}}",
|
|
12719
|
+
const codemapConfig = fs5.readFileSync(templatePath, "utf8").replace("{{projectName}}", path6.basename(worktree));
|
|
12651
12720
|
ensureFileIfMissing(rootCodemapPath, codemapConfig);
|
|
12652
12721
|
return fs5.existsSync(rootCodemapPath);
|
|
12653
12722
|
}
|
|
@@ -12656,10 +12725,10 @@ function ensureOptimaRegistries(worktree) {
|
|
|
12656
12725
|
const scrsDir = optimaScrsDir(worktree);
|
|
12657
12726
|
if (!fs5.existsSync(tasksDir)) fs5.mkdirSync(tasksDir, { recursive: true });
|
|
12658
12727
|
if (!fs5.existsSync(scrsDir)) fs5.mkdirSync(scrsDir, { recursive: true });
|
|
12659
|
-
ensureFileIfMissing(
|
|
12660
|
-
ensureFileIfMissing(
|
|
12661
|
-
ensureFileIfMissing(
|
|
12662
|
-
ensureFileIfMissing(
|
|
12728
|
+
ensureFileIfMissing(path6.join(tasksDir, "current.md"), currentTasksRegistryContent());
|
|
12729
|
+
ensureFileIfMissing(path6.join(tasksDir, "done.md"), doneTasksRegistryContent());
|
|
12730
|
+
ensureFileIfMissing(path6.join(scrsDir, "current.md"), currentScrRegistryContent());
|
|
12731
|
+
ensureFileIfMissing(path6.join(scrsDir, "done.md"), doneScrRegistryContent());
|
|
12663
12732
|
}
|
|
12664
12733
|
function scaffoldOptimaReadmes(worktree) {
|
|
12665
12734
|
ensureReadmeFile(repoPoliciesDir(worktree), REPO_LOCAL_POLICIES_README);
|
|
@@ -12821,12 +12890,12 @@ function shouldRegisterWorkflowProductManager(options = {}, worktree = process.c
|
|
|
12821
12890
|
}
|
|
12822
12891
|
function isClickUpDerivedWorktreeSibling(candidate, basePath) {
|
|
12823
12892
|
if (typeof candidate !== "string" || typeof basePath !== "string" || !candidate.trim() || !basePath.trim()) return false;
|
|
12824
|
-
const resolvedCandidate =
|
|
12825
|
-
const resolvedBase =
|
|
12826
|
-
const baseParent =
|
|
12827
|
-
if (
|
|
12828
|
-
const baseName =
|
|
12829
|
-
const candidateName =
|
|
12893
|
+
const resolvedCandidate = path6.resolve(candidate);
|
|
12894
|
+
const resolvedBase = path6.resolve(basePath);
|
|
12895
|
+
const baseParent = path6.dirname(resolvedBase);
|
|
12896
|
+
if (path6.dirname(resolvedCandidate) !== baseParent) return false;
|
|
12897
|
+
const baseName = path6.basename(resolvedBase);
|
|
12898
|
+
const candidateName = path6.basename(resolvedCandidate);
|
|
12830
12899
|
if (!candidateName.startsWith(`${baseName}-`)) return false;
|
|
12831
12900
|
const branchSlug = candidateName.slice(baseName.length + 1);
|
|
12832
12901
|
const parts = branchSlug.split("-").filter(Boolean);
|
|
@@ -12838,7 +12907,7 @@ function isClickUpDerivedWorktreeSibling(candidate, basePath) {
|
|
|
12838
12907
|
if (!candidateStat.isDirectory() || candidateStat.isSymbolicLink()) return false;
|
|
12839
12908
|
const realCandidate = fs5.realpathSync.native(resolvedCandidate);
|
|
12840
12909
|
const realBaseParent = fs5.realpathSync.native(baseParent);
|
|
12841
|
-
return
|
|
12910
|
+
return path6.dirname(realCandidate) === realBaseParent && path6.basename(realCandidate) === candidateName;
|
|
12842
12911
|
} catch {
|
|
12843
12912
|
return false;
|
|
12844
12913
|
}
|
|
@@ -12846,15 +12915,15 @@ function isClickUpDerivedWorktreeSibling(candidate, basePath) {
|
|
|
12846
12915
|
function resolveSessionToolDirectory({ requestedDirectory, context, pluginWorktree, clickUpWebhookValidation } = {}) {
|
|
12847
12916
|
const safe = safeWorktreeOrFailure(context, pluginWorktree);
|
|
12848
12917
|
if (!safe.ok) return { ok: false, error: safe.message };
|
|
12849
|
-
const requested = String(requestedDirectory || "").trim() ?
|
|
12918
|
+
const requested = String(requestedDirectory || "").trim() ? path6.resolve(safe.worktree, String(requestedDirectory).trim()) : safe.worktree;
|
|
12850
12919
|
if (!isSafeWritableDirectory(requested)) return { ok: false, error: `Directory is not a safe writable directory: ${requested}` };
|
|
12851
12920
|
if (isSameOrNestedPath(requested, safe.worktree)) return { ok: true, directory: requested, safeWorktree: safe.worktree, scope: "context_worktree" };
|
|
12852
12921
|
const clickUpBasePath = clickUpWebhookValidation?.complete === true && clickUpWebhookValidation?.ok !== false ? clickUpWebhookValidation.config?.basePath : "";
|
|
12853
12922
|
if (clickUpBasePath && isSameOrNestedPath(requested, clickUpBasePath)) {
|
|
12854
|
-
return { ok: true, directory: requested, safeWorktree: safe.worktree, scope: "clickup_base_path", clickupBasePath:
|
|
12923
|
+
return { ok: true, directory: requested, safeWorktree: safe.worktree, scope: "clickup_base_path", clickupBasePath: path6.resolve(clickUpBasePath) };
|
|
12855
12924
|
}
|
|
12856
12925
|
if (clickUpBasePath && isClickUpDerivedWorktreeSibling(requested, clickUpBasePath)) {
|
|
12857
|
-
return { ok: true, directory: requested, safeWorktree: safe.worktree, scope: "clickup_derived_worktree", clickupBasePath:
|
|
12926
|
+
return { ok: true, directory: requested, safeWorktree: safe.worktree, scope: "clickup_derived_worktree", clickupBasePath: path6.resolve(clickUpBasePath) };
|
|
12858
12927
|
}
|
|
12859
12928
|
return {
|
|
12860
12929
|
ok: false,
|
|
@@ -12888,8 +12957,8 @@ function buildOptimaAgents(repoCfg, operatingTeamMode, worktree, debugDir, optio
|
|
|
12888
12957
|
if (!enabled) continue;
|
|
12889
12958
|
}
|
|
12890
12959
|
const promptOptions = { preferCompactPromptDocs: repoCfg.features?.compact_prompt_docs !== false };
|
|
12891
|
-
const bundledDefinition = loadAgentDefinition(
|
|
12892
|
-
const repoDefinition = loadAgentDefinition(
|
|
12960
|
+
const bundledDefinition = loadAgentDefinition(path6.join(BUNDLE_AGENTS_DIR, file), worktree, promptOptions);
|
|
12961
|
+
const repoDefinition = loadAgentDefinition(path6.join(repoAgentDefinitions, file), worktree, promptOptions) || loadAgentDefinition(path6.join(legacyAgentsDir, file), worktree, promptOptions);
|
|
12893
12962
|
const activeDefinition = repoDefinition || bundledDefinition;
|
|
12894
12963
|
if (!activeDefinition) continue;
|
|
12895
12964
|
const { data } = activeDefinition;
|
|
@@ -12898,7 +12967,7 @@ function buildOptimaAgents(repoCfg, operatingTeamMode, worktree, debugDir, optio
|
|
|
12898
12967
|
if (modePromptFragment) finalPrompt = `${finalPrompt}
|
|
12899
12968
|
|
|
12900
12969
|
${modePromptFragment}`;
|
|
12901
|
-
const additionFragment = loadMarkdownFragment(
|
|
12970
|
+
const additionFragment = loadMarkdownFragment(path6.join(repoAgentAdditions, file), worktree);
|
|
12902
12971
|
if (additionFragment) {
|
|
12903
12972
|
finalPrompt = `${finalPrompt}
|
|
12904
12973
|
|
|
@@ -12951,7 +13020,7 @@ Use this Optima-provided fallback when the current task worktree lacks docs/core
|
|
|
12951
13020
|
}
|
|
12952
13021
|
ourAgents[id] = agentConfig;
|
|
12953
13022
|
if (repoCfg.features?.debug_dumps !== false) {
|
|
12954
|
-
const debugPath =
|
|
13023
|
+
const debugPath = path6.join(debugDir, `${id}.md`);
|
|
12955
13024
|
const { prompt, ...dumpConfig } = agentConfig;
|
|
12956
13025
|
const debugHeader = `---
|
|
12957
13026
|
${import_yaml3.default.stringify(dumpConfig).trim()}
|
|
@@ -13103,8 +13172,8 @@ async function OptimaPlugin(input = {}, pluginOptions = {}) {
|
|
|
13103
13172
|
migrateLegacyOptimaLayout(toolWorktree);
|
|
13104
13173
|
const cfgDir = optimaConfigDir(toolWorktree);
|
|
13105
13174
|
if (!fs5.existsSync(cfgDir)) fs5.mkdirSync(cfgDir, { recursive: true });
|
|
13106
|
-
const optimaTmplPath =
|
|
13107
|
-
const codemapTmplPath =
|
|
13175
|
+
const optimaTmplPath = path6.join(TEMPLATES_DIR, "optima.yaml.template");
|
|
13176
|
+
const codemapTmplPath = path6.join(TEMPLATES_DIR, "codemap.yml.template");
|
|
13108
13177
|
if (!fs5.existsSync(optimaTmplPath) || !fs5.existsSync(codemapTmplPath)) {
|
|
13109
13178
|
return "Error: Initialization templates not found in plugin.";
|
|
13110
13179
|
}
|
|
@@ -13226,14 +13295,14 @@ Restart or reload OpenCode manually if the newly scaffolded config or agents are
|
|
|
13226
13295
|
async execute(args, context) {
|
|
13227
13296
|
const safe = safeWorktreeOrFailure(context, worktree);
|
|
13228
13297
|
if (!safe.ok) return safe.message;
|
|
13229
|
-
const summaryPath =
|
|
13298
|
+
const summaryPath = path6.resolve(safe.worktree, args.summary_path || "");
|
|
13230
13299
|
if (!fs5.existsSync(summaryPath)) return `FAIL: summary_path not found: ${summaryPath}`;
|
|
13231
|
-
const taskPath = args.task_path ?
|
|
13300
|
+
const taskPath = args.task_path ? path6.resolve(safe.worktree, args.task_path) : "";
|
|
13232
13301
|
const payload = buildClickUpSummaryPayload({
|
|
13233
13302
|
summaryMarkdown: fs5.readFileSync(summaryPath, "utf8"),
|
|
13234
|
-
summaryPath:
|
|
13303
|
+
summaryPath: path6.relative(safe.worktree, summaryPath),
|
|
13235
13304
|
taskMarkdown: taskPath && fs5.existsSync(taskPath) ? fs5.readFileSync(taskPath, "utf8") : "",
|
|
13236
|
-
taskPath: taskPath ?
|
|
13305
|
+
taskPath: taskPath ? path6.relative(safe.worktree, taskPath) : "",
|
|
13237
13306
|
branch: args.branch,
|
|
13238
13307
|
worktree: args.worktree,
|
|
13239
13308
|
pr: args.pr
|
|
@@ -13312,12 +13381,12 @@ Restart or reload OpenCode manually if the newly scaffolded config or agents are
|
|
|
13312
13381
|
async execute(args, context) {
|
|
13313
13382
|
const safe = safeWorktreeOrFailure(context, worktree);
|
|
13314
13383
|
if (!safe.ok) return safe.message;
|
|
13315
|
-
const markdownPath =
|
|
13384
|
+
const markdownPath = path6.resolve(safe.worktree, args.markdown_path || "");
|
|
13316
13385
|
if (!fs5.existsSync(markdownPath)) return `FAIL: markdown_path not found: ${markdownPath}`;
|
|
13317
13386
|
const payload = buildClickUpCreateSubtasksPayload({
|
|
13318
13387
|
parentTaskId: args.parent_task_id,
|
|
13319
13388
|
markdown: fs5.readFileSync(markdownPath, "utf8"),
|
|
13320
|
-
sourcePath:
|
|
13389
|
+
sourcePath: path6.relative(safe.worktree, markdownPath),
|
|
13321
13390
|
parentBranch: args.parent_branch,
|
|
13322
13391
|
parentTaskType: args.parent_task_type || "Tarea",
|
|
13323
13392
|
apply: String(args.apply || "").toLowerCase() === "true"
|
|
@@ -13516,7 +13585,7 @@ Backfilled messages: ${backfilled}`;
|
|
|
13516
13585
|
if (!existing) {
|
|
13517
13586
|
return "FAIL: No active discussion exists for this session.";
|
|
13518
13587
|
}
|
|
13519
|
-
const discussionPath =
|
|
13588
|
+
const discussionPath = path6.join(toolWorktree, existing.transcriptPath);
|
|
13520
13589
|
setDiscussionStatus(discussionPath, "summarizing");
|
|
13521
13590
|
existing.status = "summarizing";
|
|
13522
13591
|
saveDiscussionRegistry(toolWorktree, toolRegistry);
|
|
@@ -13568,7 +13637,7 @@ Reason: ${err.message}`;
|
|
|
13568
13637
|
try {
|
|
13569
13638
|
const sessionResult = await client.session.create({
|
|
13570
13639
|
query: { directory: workflowDirectory },
|
|
13571
|
-
body: { title: `Workflow Run: ${
|
|
13640
|
+
body: { title: `Workflow Run: ${path6.basename(workflowTaskPath)}` }
|
|
13572
13641
|
});
|
|
13573
13642
|
const sessionId = sessionResult.data.id;
|
|
13574
13643
|
activeWorkflows.set(sessionId, { pmaSessionId, taskPath: workflowTaskPath, track: workflowTrack, directory: workflowDirectory });
|