@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/sanitize_cli.js
CHANGED
|
@@ -109,17 +109,17 @@ var require_visit = __commonJS({
|
|
|
109
109
|
visit.BREAK = BREAK;
|
|
110
110
|
visit.SKIP = SKIP;
|
|
111
111
|
visit.REMOVE = REMOVE;
|
|
112
|
-
function visit_(key, node, visitor,
|
|
113
|
-
const ctrl = callVisitor(key, node, visitor,
|
|
112
|
+
function visit_(key, node, visitor, path8) {
|
|
113
|
+
const ctrl = callVisitor(key, node, visitor, path8);
|
|
114
114
|
if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
|
|
115
|
-
replaceNode(key,
|
|
116
|
-
return visit_(key, ctrl, visitor,
|
|
115
|
+
replaceNode(key, path8, ctrl);
|
|
116
|
+
return visit_(key, ctrl, visitor, path8);
|
|
117
117
|
}
|
|
118
118
|
if (typeof ctrl !== "symbol") {
|
|
119
119
|
if (identity.isCollection(node)) {
|
|
120
|
-
|
|
120
|
+
path8 = Object.freeze(path8.concat(node));
|
|
121
121
|
for (let i = 0; i < node.items.length; ++i) {
|
|
122
|
-
const ci = visit_(i, node.items[i], visitor,
|
|
122
|
+
const ci = visit_(i, node.items[i], visitor, path8);
|
|
123
123
|
if (typeof ci === "number")
|
|
124
124
|
i = ci - 1;
|
|
125
125
|
else if (ci === BREAK)
|
|
@@ -130,13 +130,13 @@ var require_visit = __commonJS({
|
|
|
130
130
|
}
|
|
131
131
|
}
|
|
132
132
|
} else if (identity.isPair(node)) {
|
|
133
|
-
|
|
134
|
-
const ck = visit_("key", node.key, visitor,
|
|
133
|
+
path8 = Object.freeze(path8.concat(node));
|
|
134
|
+
const ck = visit_("key", node.key, visitor, path8);
|
|
135
135
|
if (ck === BREAK)
|
|
136
136
|
return BREAK;
|
|
137
137
|
else if (ck === REMOVE)
|
|
138
138
|
node.key = null;
|
|
139
|
-
const cv = visit_("value", node.value, visitor,
|
|
139
|
+
const cv = visit_("value", node.value, visitor, path8);
|
|
140
140
|
if (cv === BREAK)
|
|
141
141
|
return BREAK;
|
|
142
142
|
else if (cv === REMOVE)
|
|
@@ -157,17 +157,17 @@ var require_visit = __commonJS({
|
|
|
157
157
|
visitAsync.BREAK = BREAK;
|
|
158
158
|
visitAsync.SKIP = SKIP;
|
|
159
159
|
visitAsync.REMOVE = REMOVE;
|
|
160
|
-
async function visitAsync_(key, node, visitor,
|
|
161
|
-
const ctrl = await callVisitor(key, node, visitor,
|
|
160
|
+
async function visitAsync_(key, node, visitor, path8) {
|
|
161
|
+
const ctrl = await callVisitor(key, node, visitor, path8);
|
|
162
162
|
if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
|
|
163
|
-
replaceNode(key,
|
|
164
|
-
return visitAsync_(key, ctrl, visitor,
|
|
163
|
+
replaceNode(key, path8, ctrl);
|
|
164
|
+
return visitAsync_(key, ctrl, visitor, path8);
|
|
165
165
|
}
|
|
166
166
|
if (typeof ctrl !== "symbol") {
|
|
167
167
|
if (identity.isCollection(node)) {
|
|
168
|
-
|
|
168
|
+
path8 = Object.freeze(path8.concat(node));
|
|
169
169
|
for (let i = 0; i < node.items.length; ++i) {
|
|
170
|
-
const ci = await visitAsync_(i, node.items[i], visitor,
|
|
170
|
+
const ci = await visitAsync_(i, node.items[i], visitor, path8);
|
|
171
171
|
if (typeof ci === "number")
|
|
172
172
|
i = ci - 1;
|
|
173
173
|
else if (ci === BREAK)
|
|
@@ -178,13 +178,13 @@ var require_visit = __commonJS({
|
|
|
178
178
|
}
|
|
179
179
|
}
|
|
180
180
|
} else if (identity.isPair(node)) {
|
|
181
|
-
|
|
182
|
-
const ck = await visitAsync_("key", node.key, visitor,
|
|
181
|
+
path8 = Object.freeze(path8.concat(node));
|
|
182
|
+
const ck = await visitAsync_("key", node.key, visitor, path8);
|
|
183
183
|
if (ck === BREAK)
|
|
184
184
|
return BREAK;
|
|
185
185
|
else if (ck === REMOVE)
|
|
186
186
|
node.key = null;
|
|
187
|
-
const cv = await visitAsync_("value", node.value, visitor,
|
|
187
|
+
const cv = await visitAsync_("value", node.value, visitor, path8);
|
|
188
188
|
if (cv === BREAK)
|
|
189
189
|
return BREAK;
|
|
190
190
|
else if (cv === REMOVE)
|
|
@@ -211,23 +211,23 @@ var require_visit = __commonJS({
|
|
|
211
211
|
}
|
|
212
212
|
return visitor;
|
|
213
213
|
}
|
|
214
|
-
function callVisitor(key, node, visitor,
|
|
214
|
+
function callVisitor(key, node, visitor, path8) {
|
|
215
215
|
if (typeof visitor === "function")
|
|
216
|
-
return visitor(key, node,
|
|
216
|
+
return visitor(key, node, path8);
|
|
217
217
|
if (identity.isMap(node))
|
|
218
|
-
return visitor.Map?.(key, node,
|
|
218
|
+
return visitor.Map?.(key, node, path8);
|
|
219
219
|
if (identity.isSeq(node))
|
|
220
|
-
return visitor.Seq?.(key, node,
|
|
220
|
+
return visitor.Seq?.(key, node, path8);
|
|
221
221
|
if (identity.isPair(node))
|
|
222
|
-
return visitor.Pair?.(key, node,
|
|
222
|
+
return visitor.Pair?.(key, node, path8);
|
|
223
223
|
if (identity.isScalar(node))
|
|
224
|
-
return visitor.Scalar?.(key, node,
|
|
224
|
+
return visitor.Scalar?.(key, node, path8);
|
|
225
225
|
if (identity.isAlias(node))
|
|
226
|
-
return visitor.Alias?.(key, node,
|
|
226
|
+
return visitor.Alias?.(key, node, path8);
|
|
227
227
|
return void 0;
|
|
228
228
|
}
|
|
229
|
-
function replaceNode(key,
|
|
230
|
-
const parent =
|
|
229
|
+
function replaceNode(key, path8, node) {
|
|
230
|
+
const parent = path8[path8.length - 1];
|
|
231
231
|
if (identity.isCollection(parent)) {
|
|
232
232
|
parent.items[key] = node;
|
|
233
233
|
} else if (identity.isPair(parent)) {
|
|
@@ -835,10 +835,10 @@ var require_Collection = __commonJS({
|
|
|
835
835
|
var createNode = require_createNode();
|
|
836
836
|
var identity = require_identity();
|
|
837
837
|
var Node = require_Node();
|
|
838
|
-
function collectionFromPath(schema,
|
|
838
|
+
function collectionFromPath(schema, path8, value) {
|
|
839
839
|
let v = value;
|
|
840
|
-
for (let i =
|
|
841
|
-
const k =
|
|
840
|
+
for (let i = path8.length - 1; i >= 0; --i) {
|
|
841
|
+
const k = path8[i];
|
|
842
842
|
if (typeof k === "number" && Number.isInteger(k) && k >= 0) {
|
|
843
843
|
const a = [];
|
|
844
844
|
a[k] = v;
|
|
@@ -857,7 +857,7 @@ var require_Collection = __commonJS({
|
|
|
857
857
|
sourceObjects: /* @__PURE__ */ new Map()
|
|
858
858
|
});
|
|
859
859
|
}
|
|
860
|
-
var isEmptyPath = (
|
|
860
|
+
var isEmptyPath = (path8) => path8 == null || typeof path8 === "object" && !!path8[Symbol.iterator]().next().done;
|
|
861
861
|
var Collection = class extends Node.NodeBase {
|
|
862
862
|
constructor(type, schema) {
|
|
863
863
|
super(type);
|
|
@@ -887,11 +887,11 @@ var require_Collection = __commonJS({
|
|
|
887
887
|
* be a Pair instance or a `{ key, value }` object, which may not have a key
|
|
888
888
|
* that already exists in the map.
|
|
889
889
|
*/
|
|
890
|
-
addIn(
|
|
891
|
-
if (isEmptyPath(
|
|
890
|
+
addIn(path8, value) {
|
|
891
|
+
if (isEmptyPath(path8))
|
|
892
892
|
this.add(value);
|
|
893
893
|
else {
|
|
894
|
-
const [key, ...rest] =
|
|
894
|
+
const [key, ...rest] = path8;
|
|
895
895
|
const node = this.get(key, true);
|
|
896
896
|
if (identity.isCollection(node))
|
|
897
897
|
node.addIn(rest, value);
|
|
@@ -905,8 +905,8 @@ var require_Collection = __commonJS({
|
|
|
905
905
|
* Removes a value from the collection.
|
|
906
906
|
* @returns `true` if the item was found and removed.
|
|
907
907
|
*/
|
|
908
|
-
deleteIn(
|
|
909
|
-
const [key, ...rest] =
|
|
908
|
+
deleteIn(path8) {
|
|
909
|
+
const [key, ...rest] = path8;
|
|
910
910
|
if (rest.length === 0)
|
|
911
911
|
return this.delete(key);
|
|
912
912
|
const node = this.get(key, true);
|
|
@@ -920,8 +920,8 @@ var require_Collection = __commonJS({
|
|
|
920
920
|
* scalar values from their surrounding node; to disable set `keepScalar` to
|
|
921
921
|
* `true` (collections are always returned intact).
|
|
922
922
|
*/
|
|
923
|
-
getIn(
|
|
924
|
-
const [key, ...rest] =
|
|
923
|
+
getIn(path8, keepScalar) {
|
|
924
|
+
const [key, ...rest] = path8;
|
|
925
925
|
const node = this.get(key, true);
|
|
926
926
|
if (rest.length === 0)
|
|
927
927
|
return !keepScalar && identity.isScalar(node) ? node.value : node;
|
|
@@ -939,8 +939,8 @@ var require_Collection = __commonJS({
|
|
|
939
939
|
/**
|
|
940
940
|
* Checks if the collection includes a value with the key `key`.
|
|
941
941
|
*/
|
|
942
|
-
hasIn(
|
|
943
|
-
const [key, ...rest] =
|
|
942
|
+
hasIn(path8) {
|
|
943
|
+
const [key, ...rest] = path8;
|
|
944
944
|
if (rest.length === 0)
|
|
945
945
|
return this.has(key);
|
|
946
946
|
const node = this.get(key, true);
|
|
@@ -950,8 +950,8 @@ var require_Collection = __commonJS({
|
|
|
950
950
|
* Sets a value in this collection. For `!!set`, `value` needs to be a
|
|
951
951
|
* boolean to add/remove the item from the set.
|
|
952
952
|
*/
|
|
953
|
-
setIn(
|
|
954
|
-
const [key, ...rest] =
|
|
953
|
+
setIn(path8, value) {
|
|
954
|
+
const [key, ...rest] = path8;
|
|
955
955
|
if (rest.length === 0) {
|
|
956
956
|
this.set(key, value);
|
|
957
957
|
} else {
|
|
@@ -3455,9 +3455,9 @@ var require_Document = __commonJS({
|
|
|
3455
3455
|
this.contents.add(value);
|
|
3456
3456
|
}
|
|
3457
3457
|
/** Adds a value to the document. */
|
|
3458
|
-
addIn(
|
|
3458
|
+
addIn(path8, value) {
|
|
3459
3459
|
if (assertCollection(this.contents))
|
|
3460
|
-
this.contents.addIn(
|
|
3460
|
+
this.contents.addIn(path8, value);
|
|
3461
3461
|
}
|
|
3462
3462
|
/**
|
|
3463
3463
|
* Create a new `Alias` node, ensuring that the target `node` has the required anchor.
|
|
@@ -3532,14 +3532,14 @@ var require_Document = __commonJS({
|
|
|
3532
3532
|
* Removes a value from the document.
|
|
3533
3533
|
* @returns `true` if the item was found and removed.
|
|
3534
3534
|
*/
|
|
3535
|
-
deleteIn(
|
|
3536
|
-
if (Collection.isEmptyPath(
|
|
3535
|
+
deleteIn(path8) {
|
|
3536
|
+
if (Collection.isEmptyPath(path8)) {
|
|
3537
3537
|
if (this.contents == null)
|
|
3538
3538
|
return false;
|
|
3539
3539
|
this.contents = null;
|
|
3540
3540
|
return true;
|
|
3541
3541
|
}
|
|
3542
|
-
return assertCollection(this.contents) ? this.contents.deleteIn(
|
|
3542
|
+
return assertCollection(this.contents) ? this.contents.deleteIn(path8) : false;
|
|
3543
3543
|
}
|
|
3544
3544
|
/**
|
|
3545
3545
|
* Returns item at `key`, or `undefined` if not found. By default unwraps
|
|
@@ -3554,10 +3554,10 @@ var require_Document = __commonJS({
|
|
|
3554
3554
|
* scalar values from their surrounding node; to disable set `keepScalar` to
|
|
3555
3555
|
* `true` (collections are always returned intact).
|
|
3556
3556
|
*/
|
|
3557
|
-
getIn(
|
|
3558
|
-
if (Collection.isEmptyPath(
|
|
3557
|
+
getIn(path8, keepScalar) {
|
|
3558
|
+
if (Collection.isEmptyPath(path8))
|
|
3559
3559
|
return !keepScalar && identity.isScalar(this.contents) ? this.contents.value : this.contents;
|
|
3560
|
-
return identity.isCollection(this.contents) ? this.contents.getIn(
|
|
3560
|
+
return identity.isCollection(this.contents) ? this.contents.getIn(path8, keepScalar) : void 0;
|
|
3561
3561
|
}
|
|
3562
3562
|
/**
|
|
3563
3563
|
* Checks if the document includes a value with the key `key`.
|
|
@@ -3568,10 +3568,10 @@ var require_Document = __commonJS({
|
|
|
3568
3568
|
/**
|
|
3569
3569
|
* Checks if the document includes a value at `path`.
|
|
3570
3570
|
*/
|
|
3571
|
-
hasIn(
|
|
3572
|
-
if (Collection.isEmptyPath(
|
|
3571
|
+
hasIn(path8) {
|
|
3572
|
+
if (Collection.isEmptyPath(path8))
|
|
3573
3573
|
return this.contents !== void 0;
|
|
3574
|
-
return identity.isCollection(this.contents) ? this.contents.hasIn(
|
|
3574
|
+
return identity.isCollection(this.contents) ? this.contents.hasIn(path8) : false;
|
|
3575
3575
|
}
|
|
3576
3576
|
/**
|
|
3577
3577
|
* Sets a value in this document. For `!!set`, `value` needs to be a
|
|
@@ -3588,13 +3588,13 @@ var require_Document = __commonJS({
|
|
|
3588
3588
|
* Sets a value in this document. For `!!set`, `value` needs to be a
|
|
3589
3589
|
* boolean to add/remove the item from the set.
|
|
3590
3590
|
*/
|
|
3591
|
-
setIn(
|
|
3592
|
-
if (Collection.isEmptyPath(
|
|
3591
|
+
setIn(path8, value) {
|
|
3592
|
+
if (Collection.isEmptyPath(path8)) {
|
|
3593
3593
|
this.contents = value;
|
|
3594
3594
|
} else if (this.contents == null) {
|
|
3595
|
-
this.contents = Collection.collectionFromPath(this.schema, Array.from(
|
|
3595
|
+
this.contents = Collection.collectionFromPath(this.schema, Array.from(path8), value);
|
|
3596
3596
|
} else if (assertCollection(this.contents)) {
|
|
3597
|
-
this.contents.setIn(
|
|
3597
|
+
this.contents.setIn(path8, value);
|
|
3598
3598
|
}
|
|
3599
3599
|
}
|
|
3600
3600
|
/**
|
|
@@ -5546,9 +5546,9 @@ var require_cst_visit = __commonJS({
|
|
|
5546
5546
|
visit.BREAK = BREAK;
|
|
5547
5547
|
visit.SKIP = SKIP;
|
|
5548
5548
|
visit.REMOVE = REMOVE;
|
|
5549
|
-
visit.itemAtPath = (cst,
|
|
5549
|
+
visit.itemAtPath = (cst, path8) => {
|
|
5550
5550
|
let item = cst;
|
|
5551
|
-
for (const [field, index] of
|
|
5551
|
+
for (const [field, index] of path8) {
|
|
5552
5552
|
const tok = item?.[field];
|
|
5553
5553
|
if (tok && "items" in tok) {
|
|
5554
5554
|
item = tok.items[index];
|
|
@@ -5557,23 +5557,23 @@ var require_cst_visit = __commonJS({
|
|
|
5557
5557
|
}
|
|
5558
5558
|
return item;
|
|
5559
5559
|
};
|
|
5560
|
-
visit.parentCollection = (cst,
|
|
5561
|
-
const parent = visit.itemAtPath(cst,
|
|
5562
|
-
const field =
|
|
5560
|
+
visit.parentCollection = (cst, path8) => {
|
|
5561
|
+
const parent = visit.itemAtPath(cst, path8.slice(0, -1));
|
|
5562
|
+
const field = path8[path8.length - 1][0];
|
|
5563
5563
|
const coll = parent?.[field];
|
|
5564
5564
|
if (coll && "items" in coll)
|
|
5565
5565
|
return coll;
|
|
5566
5566
|
throw new Error("Parent collection not found");
|
|
5567
5567
|
};
|
|
5568
|
-
function _visit(
|
|
5569
|
-
let ctrl = visitor(item,
|
|
5568
|
+
function _visit(path8, item, visitor) {
|
|
5569
|
+
let ctrl = visitor(item, path8);
|
|
5570
5570
|
if (typeof ctrl === "symbol")
|
|
5571
5571
|
return ctrl;
|
|
5572
5572
|
for (const field of ["key", "value"]) {
|
|
5573
5573
|
const token = item[field];
|
|
5574
5574
|
if (token && "items" in token) {
|
|
5575
5575
|
for (let i = 0; i < token.items.length; ++i) {
|
|
5576
|
-
const ci = _visit(Object.freeze(
|
|
5576
|
+
const ci = _visit(Object.freeze(path8.concat([[field, i]])), token.items[i], visitor);
|
|
5577
5577
|
if (typeof ci === "number")
|
|
5578
5578
|
i = ci - 1;
|
|
5579
5579
|
else if (ci === BREAK)
|
|
@@ -5584,10 +5584,10 @@ var require_cst_visit = __commonJS({
|
|
|
5584
5584
|
}
|
|
5585
5585
|
}
|
|
5586
5586
|
if (typeof ctrl === "function" && field === "key")
|
|
5587
|
-
ctrl = ctrl(item,
|
|
5587
|
+
ctrl = ctrl(item, path8);
|
|
5588
5588
|
}
|
|
5589
5589
|
}
|
|
5590
|
-
return typeof ctrl === "function" ? ctrl(item,
|
|
5590
|
+
return typeof ctrl === "function" ? ctrl(item, path8) : ctrl;
|
|
5591
5591
|
}
|
|
5592
5592
|
exports.visit = visit;
|
|
5593
5593
|
}
|
|
@@ -7551,17 +7551,17 @@ var require_ignore = __commonJS({
|
|
|
7551
7551
|
var throwError = (message, Ctor) => {
|
|
7552
7552
|
throw new Ctor(message);
|
|
7553
7553
|
};
|
|
7554
|
-
var checkPath = (
|
|
7555
|
-
if (!isString(
|
|
7554
|
+
var checkPath = (path8, originalPath, doThrow) => {
|
|
7555
|
+
if (!isString(path8)) {
|
|
7556
7556
|
return doThrow(
|
|
7557
7557
|
`path must be a string, but got \`${originalPath}\``,
|
|
7558
7558
|
TypeError
|
|
7559
7559
|
);
|
|
7560
7560
|
}
|
|
7561
|
-
if (!
|
|
7561
|
+
if (!path8) {
|
|
7562
7562
|
return doThrow(`path must not be empty`, TypeError);
|
|
7563
7563
|
}
|
|
7564
|
-
if (checkPath.isNotRelative(
|
|
7564
|
+
if (checkPath.isNotRelative(path8)) {
|
|
7565
7565
|
const r = "`path.relative()`d";
|
|
7566
7566
|
return doThrow(
|
|
7567
7567
|
`path should be a ${r} string, but got "${originalPath}"`,
|
|
@@ -7570,7 +7570,7 @@ var require_ignore = __commonJS({
|
|
|
7570
7570
|
}
|
|
7571
7571
|
return true;
|
|
7572
7572
|
};
|
|
7573
|
-
var isNotRelative = (
|
|
7573
|
+
var isNotRelative = (path8) => REGEX_TEST_INVALID_PATH.test(path8);
|
|
7574
7574
|
checkPath.isNotRelative = isNotRelative;
|
|
7575
7575
|
checkPath.convert = (p) => p;
|
|
7576
7576
|
var Ignore = class {
|
|
@@ -7629,7 +7629,7 @@ var require_ignore = __commonJS({
|
|
|
7629
7629
|
// setting `checkUnignored` to `false` could reduce additional
|
|
7630
7630
|
// path matching.
|
|
7631
7631
|
// @returns {TestResult} true if a file is ignored
|
|
7632
|
-
_testOne(
|
|
7632
|
+
_testOne(path8, checkUnignored) {
|
|
7633
7633
|
let ignored = false;
|
|
7634
7634
|
let unignored = false;
|
|
7635
7635
|
this._rules.forEach((rule) => {
|
|
@@ -7637,7 +7637,7 @@ var require_ignore = __commonJS({
|
|
|
7637
7637
|
if (unignored === negative && ignored !== unignored || negative && !ignored && !unignored && !checkUnignored) {
|
|
7638
7638
|
return;
|
|
7639
7639
|
}
|
|
7640
|
-
const matched = rule.regex.test(
|
|
7640
|
+
const matched = rule.regex.test(path8);
|
|
7641
7641
|
if (matched) {
|
|
7642
7642
|
ignored = !negative;
|
|
7643
7643
|
unignored = negative;
|
|
@@ -7650,24 +7650,24 @@ var require_ignore = __commonJS({
|
|
|
7650
7650
|
}
|
|
7651
7651
|
// @returns {TestResult}
|
|
7652
7652
|
_test(originalPath, cache, checkUnignored, slices) {
|
|
7653
|
-
const
|
|
7653
|
+
const path8 = originalPath && checkPath.convert(originalPath);
|
|
7654
7654
|
checkPath(
|
|
7655
|
-
|
|
7655
|
+
path8,
|
|
7656
7656
|
originalPath,
|
|
7657
7657
|
this._allowRelativePaths ? RETURN_FALSE : throwError
|
|
7658
7658
|
);
|
|
7659
|
-
return this._t(
|
|
7659
|
+
return this._t(path8, cache, checkUnignored, slices);
|
|
7660
7660
|
}
|
|
7661
|
-
_t(
|
|
7662
|
-
if (
|
|
7663
|
-
return cache[
|
|
7661
|
+
_t(path8, cache, checkUnignored, slices) {
|
|
7662
|
+
if (path8 in cache) {
|
|
7663
|
+
return cache[path8];
|
|
7664
7664
|
}
|
|
7665
7665
|
if (!slices) {
|
|
7666
|
-
slices =
|
|
7666
|
+
slices = path8.split(SLASH);
|
|
7667
7667
|
}
|
|
7668
7668
|
slices.pop();
|
|
7669
7669
|
if (!slices.length) {
|
|
7670
|
-
return cache[
|
|
7670
|
+
return cache[path8] = this._testOne(path8, checkUnignored);
|
|
7671
7671
|
}
|
|
7672
7672
|
const parent = this._t(
|
|
7673
7673
|
slices.join(SLASH) + SLASH,
|
|
@@ -7675,24 +7675,24 @@ var require_ignore = __commonJS({
|
|
|
7675
7675
|
checkUnignored,
|
|
7676
7676
|
slices
|
|
7677
7677
|
);
|
|
7678
|
-
return cache[
|
|
7678
|
+
return cache[path8] = parent.ignored ? parent : this._testOne(path8, checkUnignored);
|
|
7679
7679
|
}
|
|
7680
|
-
ignores(
|
|
7681
|
-
return this._test(
|
|
7680
|
+
ignores(path8) {
|
|
7681
|
+
return this._test(path8, this._ignoreCache, false).ignored;
|
|
7682
7682
|
}
|
|
7683
7683
|
createFilter() {
|
|
7684
|
-
return (
|
|
7684
|
+
return (path8) => !this.ignores(path8);
|
|
7685
7685
|
}
|
|
7686
7686
|
filter(paths) {
|
|
7687
7687
|
return makeArray(paths).filter(this.createFilter());
|
|
7688
7688
|
}
|
|
7689
7689
|
// @returns {TestResult}
|
|
7690
|
-
test(
|
|
7691
|
-
return this._test(
|
|
7690
|
+
test(path8) {
|
|
7691
|
+
return this._test(path8, this._testCache, true);
|
|
7692
7692
|
}
|
|
7693
7693
|
};
|
|
7694
7694
|
var factory = (options) => new Ignore(options);
|
|
7695
|
-
var isPathValid = (
|
|
7695
|
+
var isPathValid = (path8) => checkPath(path8 && checkPath.convert(path8), path8, RETURN_FALSE);
|
|
7696
7696
|
factory.isPathValid = isPathValid;
|
|
7697
7697
|
factory.default = factory;
|
|
7698
7698
|
module.exports = factory;
|
|
@@ -7703,7 +7703,7 @@ var require_ignore = __commonJS({
|
|
|
7703
7703
|
const makePosix = (str) => /^\\\\\?\\/.test(str) || /["<>|\u0000-\u001F]+/u.test(str) ? str : str.replace(/\\/g, "/");
|
|
7704
7704
|
checkPath.convert = makePosix;
|
|
7705
7705
|
const REGIX_IS_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i;
|
|
7706
|
-
checkPath.isNotRelative = (
|
|
7706
|
+
checkPath.isNotRelative = (path8) => REGIX_IS_WINDOWS_PATH_ABSOLUTE.test(path8) || isNotRelative(path8);
|
|
7707
7707
|
}
|
|
7708
7708
|
}
|
|
7709
7709
|
});
|
|
@@ -7711,7 +7711,7 @@ var require_ignore = __commonJS({
|
|
|
7711
7711
|
// src/sanitize_cli.js
|
|
7712
7712
|
import fs6 from "node:fs";
|
|
7713
7713
|
import os2 from "node:os";
|
|
7714
|
-
import
|
|
7714
|
+
import path7 from "node:path";
|
|
7715
7715
|
import { execFileSync as execFileSync2, spawnSync } from "node:child_process";
|
|
7716
7716
|
|
|
7717
7717
|
// src/index.js
|
|
@@ -7721,8 +7721,7 @@ import crypto from "node:crypto";
|
|
|
7721
7721
|
import fs5 from "node:fs";
|
|
7722
7722
|
import http from "node:http";
|
|
7723
7723
|
import os from "node:os";
|
|
7724
|
-
import
|
|
7725
|
-
import { fileURLToPath } from "node:url";
|
|
7724
|
+
import path6 from "node:path";
|
|
7726
7725
|
import { tool } from "@opencode-ai/plugin/tool";
|
|
7727
7726
|
|
|
7728
7727
|
// src/git_utils.js
|
|
@@ -8493,7 +8492,9 @@ async function optima_validate_logic(worktree) {
|
|
|
8493
8492
|
};
|
|
8494
8493
|
}
|
|
8495
8494
|
|
|
8496
|
-
// src/
|
|
8495
|
+
// src/constants.js
|
|
8496
|
+
import path5 from "node:path";
|
|
8497
|
+
import { fileURLToPath } from "node:url";
|
|
8497
8498
|
var PKG_ROOT = path5.resolve(path5.dirname(fileURLToPath(import.meta.url)), "..");
|
|
8498
8499
|
var BUNDLE_ASSETS_DIR = path5.join(PKG_ROOT, "assets");
|
|
8499
8500
|
var BUNDLE_AGENTS_DIR = path5.join(BUNDLE_ASSETS_DIR, "agents");
|
|
@@ -8536,6 +8537,7 @@ var CLICKUP_WEBHOOK_STARTUP_COMMENT_LIMIT = 100;
|
|
|
8536
8537
|
var CLICKUP_WEBHOOK_STARTUP_RECONCILIATION_DELAY_MS = 3e4;
|
|
8537
8538
|
var CLICKUP_WEBHOOK_STARTUP_COMMENT_LOOKBACK_MS = 6 * 60 * 60 * 1e3;
|
|
8538
8539
|
var CLICKUP_ASSIGNMENT_WATCHDOG_INTERVAL_MS = 5 * 60 * 1e3;
|
|
8540
|
+
var CLICKUP_ASSIGNMENT_WATCHDOG_RUNNING_GRACE_MS = 15 * 60 * 1e3;
|
|
8539
8541
|
var CLICKUP_WORKTREE_FAILURE_COMMENT_DEDUPE_MS = 10 * 60 * 1e3;
|
|
8540
8542
|
var CLICKUP_WEBHOOK_LOG_LEVELS = /* @__PURE__ */ new Set(["error", "info", "verbose"]);
|
|
8541
8543
|
var CLICKUP_WEBHOOK_REDACTED = "[REDACTED]";
|
|
@@ -8624,20 +8626,22 @@ var REPO_LOCAL_POLICIES_README = [
|
|
|
8624
8626
|
"Only files in `.optima/policies/` affect runtime prompt behavior.",
|
|
8625
8627
|
""
|
|
8626
8628
|
].join("\n");
|
|
8629
|
+
var CLICKUP_WEBHOOK_CLEANUP_TIMEOUT_MS = 8e3;
|
|
8630
|
+
var CLICKUP_WEBHOOK_SIGNAL_STATE = Symbol.for("opencode-optima.clickup-webhook.signal-state");
|
|
8631
|
+
|
|
8632
|
+
// src/index.js
|
|
8627
8633
|
var activeWorkflows = /* @__PURE__ */ new Map();
|
|
8628
8634
|
var activeClickUpWebhookListeners = /* @__PURE__ */ new Map();
|
|
8629
8635
|
var activeClickUpWebhookLifecycleRegistry = /* @__PURE__ */ new Map();
|
|
8630
|
-
var CLICKUP_WEBHOOK_CLEANUP_TIMEOUT_MS = 8e3;
|
|
8631
|
-
var CLICKUP_WEBHOOK_SIGNAL_STATE = Symbol.for("opencode-optima.clickup-webhook.signal-state");
|
|
8632
8636
|
var activeClickUpTaskRoutes = /* @__PURE__ */ new Map();
|
|
8633
8637
|
function isRootDirectory(candidate) {
|
|
8634
|
-
const resolved =
|
|
8635
|
-
return resolved ===
|
|
8638
|
+
const resolved = path6.resolve(candidate);
|
|
8639
|
+
return resolved === path6.parse(resolved).root;
|
|
8636
8640
|
}
|
|
8637
8641
|
function isSafeWritableDirectory(candidate) {
|
|
8638
8642
|
if (typeof candidate !== "string" || !candidate.trim()) return false;
|
|
8639
|
-
if (!
|
|
8640
|
-
const resolved =
|
|
8643
|
+
if (!path6.isAbsolute(candidate)) return false;
|
|
8644
|
+
const resolved = path6.resolve(candidate);
|
|
8641
8645
|
if (isRootDirectory(resolved)) return false;
|
|
8642
8646
|
try {
|
|
8643
8647
|
const stat = fs5.statSync(resolved);
|
|
@@ -8658,7 +8662,7 @@ function resolveSafeWorktree(context = {}, pluginWorktree = null) {
|
|
|
8658
8662
|
];
|
|
8659
8663
|
for (const candidate of candidates) {
|
|
8660
8664
|
if (typeof candidate !== "string" || !candidate.trim()) continue;
|
|
8661
|
-
const resolved =
|
|
8665
|
+
const resolved = path6.resolve(candidate);
|
|
8662
8666
|
if (isSafeWritableDirectory(resolved)) return resolved;
|
|
8663
8667
|
}
|
|
8664
8668
|
throw new Error(SAFE_WORKTREE_FAILURE);
|
|
@@ -8673,13 +8677,13 @@ function safeWorktreeOrFailure(context, pluginWorktree) {
|
|
|
8673
8677
|
function explicitSafeInputWorktree(input = {}) {
|
|
8674
8678
|
for (const candidate of [input?.worktree, input?.directory]) {
|
|
8675
8679
|
if (typeof candidate !== "string" || !candidate.trim()) continue;
|
|
8676
|
-
const resolved =
|
|
8680
|
+
const resolved = path6.resolve(candidate);
|
|
8677
8681
|
if (isSafeWritableDirectory(resolved)) return resolved;
|
|
8678
8682
|
}
|
|
8679
8683
|
return null;
|
|
8680
8684
|
}
|
|
8681
8685
|
function isGitRepository(worktree) {
|
|
8682
|
-
return fs5.existsSync(
|
|
8686
|
+
return fs5.existsSync(path6.join(worktree, ".git"));
|
|
8683
8687
|
}
|
|
8684
8688
|
function normalizeLooseToken(value) {
|
|
8685
8689
|
return String(value ?? "").trim().normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
@@ -9174,7 +9178,7 @@ function buildClickUpSummaryPayload({ summaryMarkdown = "", summaryPath = "", ta
|
|
|
9174
9178
|
function deriveClickUpWorktree({ baseWorktree = "", taskId, taskType, parentTaskId, subtaskId } = {}) {
|
|
9175
9179
|
const branch = deriveClickUpBranchName({ taskType, parentTaskId, subtaskId, taskId });
|
|
9176
9180
|
const root = baseWorktree || process.cwd();
|
|
9177
|
-
return
|
|
9181
|
+
return path6.join(path6.dirname(root), `${path6.basename(root)}-${branch.replace(/\//g, "-")}`);
|
|
9178
9182
|
}
|
|
9179
9183
|
function clickUpCustomFieldValue(task = {}, names = []) {
|
|
9180
9184
|
const fields = Array.isArray(task.custom_fields) ? task.custom_fields : [];
|
|
@@ -9198,12 +9202,12 @@ function safeExistingClickUpWorktree({ metadata = {}, branch = "" } = {}) {
|
|
|
9198
9202
|
const taskMetadata = metadataTaskRouting(metadata);
|
|
9199
9203
|
const existingWorktree = typeof taskMetadata.worktree === "string" ? taskMetadata.worktree.trim() : "";
|
|
9200
9204
|
const existingBranch = typeof taskMetadata.branch === "string" ? taskMetadata.branch.trim() : "";
|
|
9201
|
-
if (!existingWorktree || !
|
|
9205
|
+
if (!existingWorktree || !path6.isAbsolute(existingWorktree) || !fs5.existsSync(existingWorktree)) return null;
|
|
9202
9206
|
try {
|
|
9203
9207
|
const stat = fs5.statSync(existingWorktree);
|
|
9204
9208
|
if (!stat.isDirectory()) return null;
|
|
9205
9209
|
if (branch && existingBranch && existingBranch !== branch) return null;
|
|
9206
|
-
return { branch: existingBranch || branch, worktree:
|
|
9210
|
+
return { branch: existingBranch || branch, worktree: path6.resolve(existingWorktree), reused: true };
|
|
9207
9211
|
} catch {
|
|
9208
9212
|
return null;
|
|
9209
9213
|
}
|
|
@@ -9289,17 +9293,17 @@ function openChamberEntryBranch(entry) {
|
|
|
9289
9293
|
return String(entry?.branch || entry?.branchName || entry?.branch_name || entry?.worktree?.branch || "").replace(/^refs\/heads\//, "");
|
|
9290
9294
|
}
|
|
9291
9295
|
function openChamberListIncludesDirectory(list, directory) {
|
|
9292
|
-
const resolved =
|
|
9296
|
+
const resolved = path6.resolve(directory);
|
|
9293
9297
|
return normalizeOpenChamberCollection(list).some((entry) => {
|
|
9294
9298
|
const entryDirectory = openChamberEntryDirectory(entry);
|
|
9295
|
-
return entryDirectory &&
|
|
9299
|
+
return entryDirectory && path6.resolve(entryDirectory) === resolved;
|
|
9296
9300
|
});
|
|
9297
9301
|
}
|
|
9298
9302
|
function openChamberListIncludesBranch(list, directory, branch) {
|
|
9299
|
-
const resolved =
|
|
9303
|
+
const resolved = path6.resolve(directory);
|
|
9300
9304
|
return normalizeOpenChamberCollection(list).some((entry) => {
|
|
9301
9305
|
const entryDirectory = openChamberEntryDirectory(entry);
|
|
9302
|
-
if (!entryDirectory ||
|
|
9306
|
+
if (!entryDirectory || path6.resolve(entryDirectory) !== resolved) return false;
|
|
9303
9307
|
const entryBranch = openChamberEntryBranch(entry);
|
|
9304
9308
|
return !entryBranch || entryBranch === branch;
|
|
9305
9309
|
});
|
|
@@ -9307,8 +9311,8 @@ function openChamberListIncludesBranch(list, directory, branch) {
|
|
|
9307
9311
|
async function findOpenChamberProject({ opencodeBaseUrl, baseWorktree, fetchImpl = globalThis.fetch } = {}) {
|
|
9308
9312
|
const projects = await requestOpenCodeJson({ baseUrl: opencodeBaseUrl, endpoint: "/project", directory: baseWorktree, fetchImpl });
|
|
9309
9313
|
if (!Array.isArray(projects)) return null;
|
|
9310
|
-
const resolvedBase =
|
|
9311
|
-
return projects.find((project) =>
|
|
9314
|
+
const resolvedBase = path6.resolve(baseWorktree);
|
|
9315
|
+
return projects.find((project) => path6.resolve(String(project?.worktree || project?.path || "")) === resolvedBase) || null;
|
|
9312
9316
|
}
|
|
9313
9317
|
async function refreshOpenChamberProjectCopy({ opencodeBaseUrl, projectId, fetchImpl = globalThis.fetch } = {}) {
|
|
9314
9318
|
if (!projectId) return { refreshed: false, reason: "project_id_unavailable" };
|
|
@@ -9363,18 +9367,18 @@ async function createOpenChamberClickUpWorktree({ openchamberBaseUrl, baseUrl, b
|
|
|
9363
9367
|
}
|
|
9364
9368
|
const createdDirectory = openChamberEntryDirectory(created);
|
|
9365
9369
|
const createdBranch = openChamberEntryBranch(created);
|
|
9366
|
-
if (!createdDirectory || !
|
|
9370
|
+
if (!createdDirectory || !path6.isAbsolute(createdDirectory)) {
|
|
9367
9371
|
throw new Error(`OpenChamber did not return an absolute worktree path for ${branch}.`);
|
|
9368
9372
|
}
|
|
9369
9373
|
if (createdBranch !== branch) {
|
|
9370
9374
|
throw new Error(`OpenChamber created unexpected branch ${createdBranch || "<unknown>"}; expected ${branch}.`);
|
|
9371
9375
|
}
|
|
9372
9376
|
const verified = await verifyOpenChamberGitWorktree({ openchamberBaseUrl: effectiveOpenChamberBaseUrl, baseWorktree, worktreePath: createdDirectory, branch, fetchImpl });
|
|
9373
|
-
return { created, worktree:
|
|
9377
|
+
return { created, worktree: path6.resolve(createdDirectory), branch: createdBranch, verified };
|
|
9374
9378
|
}
|
|
9375
9379
|
async function registerOpenChamberClickUpWorktree({ openchamberBaseUrl, opencodeBaseUrl, baseUrl, baseWorktree, branch, worktreePath, fetchImpl = globalThis.fetch, source = "reuse" } = {}) {
|
|
9376
9380
|
const visibility = await syncOpenChamberWorktreeVisibility({ openchamberBaseUrl: openchamberBaseUrl || baseUrl, opencodeBaseUrl: opencodeBaseUrl || baseUrl, baseWorktree, worktreePath, branch, fetchImpl });
|
|
9377
|
-
return { branch, worktree:
|
|
9381
|
+
return { branch, worktree: path6.resolve(worktreePath), reused: true, provider: "openchamber", openChamber: { source, visibility } };
|
|
9378
9382
|
}
|
|
9379
9383
|
async function ensureClickUpTaskWorktreeOpenChamber({ baseWorktree = "", taskId, taskType = "Tarea", parentTaskId = "", subtaskId = "", existingMetadata = {}, runGitFn = runGit, openchamberBaseUrl = "", opencodeBaseUrl = "", baseUrl = "", fetchImpl = globalThis.fetch, log = null } = {}) {
|
|
9380
9384
|
const effectiveOpenChamberBaseUrl = openchamberBaseUrl || baseUrl;
|
|
@@ -9437,10 +9441,10 @@ function ensureClickUpTaskWorktree({ baseWorktree = "", taskId, taskType = "Tare
|
|
|
9437
9441
|
const existing = safeExistingClickUpWorktree({ metadata: existingMetadata, branch });
|
|
9438
9442
|
if (existing) return { ...existing, branch, parentBranch: parentBranch || void 0, prTarget: parentBranch || "dev" };
|
|
9439
9443
|
const worktreePath = deriveClickUpWorktree({ baseWorktree, taskId, taskType, parentTaskId: effectiveParent, subtaskId });
|
|
9440
|
-
if (fs5.existsSync(worktreePath)) return { branch, worktree:
|
|
9444
|
+
if (fs5.existsSync(worktreePath)) return { branch, worktree: path6.resolve(worktreePath), reused: true, parentBranch: parentBranch || void 0, prTarget: parentBranch || "dev" };
|
|
9441
9445
|
if (allowNonGitFallback) {
|
|
9442
9446
|
fs5.mkdirSync(worktreePath, { recursive: true });
|
|
9443
|
-
return { branch, worktree:
|
|
9447
|
+
return { branch, worktree: path6.resolve(worktreePath), reused: false, fallback: "non_git", parentBranch: parentBranch || void 0, prTarget: parentBranch || "dev", startPoint: parentBranch || "dev" };
|
|
9444
9448
|
}
|
|
9445
9449
|
let parentBootstrap = null;
|
|
9446
9450
|
if (isSubtask) {
|
|
@@ -9449,14 +9453,14 @@ function ensureClickUpTaskWorktree({ baseWorktree = "", taskId, taskType = "Tare
|
|
|
9449
9453
|
const parentStartPoint = resolveClickUpDevStartPoint(baseWorktree, runGitFn);
|
|
9450
9454
|
const parentBranchExists = clickUpGitRefExists(baseWorktree, parentBranch, runGitFn);
|
|
9451
9455
|
addClickUpWorktreeForBranch({ baseWorktree, branch: parentBranch, worktreePath: parentWorktree, startPoint: parentStartPoint, runGitFn });
|
|
9452
|
-
parentBootstrap = { branch: parentBranch, worktree:
|
|
9456
|
+
parentBootstrap = { branch: parentBranch, worktree: path6.resolve(parentWorktree), startPoint: parentBranchExists ? parentBranch : parentStartPoint, reused: parentBranchExists };
|
|
9453
9457
|
} else {
|
|
9454
|
-
parentBootstrap = { branch: parentBranch, worktree:
|
|
9458
|
+
parentBootstrap = { branch: parentBranch, worktree: path6.resolve(parentWorktree), reused: true };
|
|
9455
9459
|
}
|
|
9456
9460
|
}
|
|
9457
9461
|
const startPoint = isSubtask ? parentBranch : resolveClickUpDevStartPoint(baseWorktree, runGitFn);
|
|
9458
9462
|
addClickUpWorktreeForBranch({ baseWorktree, branch, worktreePath, startPoint, runGitFn });
|
|
9459
|
-
return { branch, worktree:
|
|
9463
|
+
return { branch, worktree: path6.resolve(worktreePath), reused: false, startPoint, parentBranch: parentBranch || void 0, prTarget: parentBranch || "dev", parentBootstrap: parentBootstrap || void 0 };
|
|
9460
9464
|
}
|
|
9461
9465
|
function normalizeClickUpDefinitionDocParent(parent = {}) {
|
|
9462
9466
|
const docId = String(parent.doc_id || parent.docId || CLICKUP_DEFINITION_DOC_PARENT.doc_id).trim();
|
|
@@ -9606,7 +9610,7 @@ function buildClickUpTransitionPayload({ fromStatus, toStatus, validationPassed
|
|
|
9606
9610
|
}
|
|
9607
9611
|
function ensureOptimaGitignoreRules(worktree) {
|
|
9608
9612
|
if (!isGitRepository(worktree)) return { touched: false, added: [] };
|
|
9609
|
-
const gitignorePath =
|
|
9613
|
+
const gitignorePath = path6.join(worktree, ".gitignore");
|
|
9610
9614
|
const existing = fs5.existsSync(gitignorePath) ? fs5.readFileSync(gitignorePath, "utf8") : "";
|
|
9611
9615
|
const existingRules = new Set(existing.split(/\r?\n/).map((line) => line.trim()).filter(Boolean));
|
|
9612
9616
|
const missingRules = OPTIMA_GITIGNORE_RULES.filter((rule) => !existingRules.has(rule));
|
|
@@ -9622,40 +9626,40 @@ function ensureOptimaGitignoreRules(worktree) {
|
|
|
9622
9626
|
return { touched: true, added: missingRules };
|
|
9623
9627
|
}
|
|
9624
9628
|
function optimaDir(worktree) {
|
|
9625
|
-
return
|
|
9629
|
+
return path6.join(worktree, OPTIMA_DIRNAME);
|
|
9626
9630
|
}
|
|
9627
9631
|
function optimaLocalConfigDir(worktree) {
|
|
9628
|
-
return
|
|
9632
|
+
return path6.join(optimaDir(worktree), ".config");
|
|
9629
9633
|
}
|
|
9630
9634
|
function optimaConfigDir(worktree) {
|
|
9631
9635
|
return optimaLocalConfigDir(worktree);
|
|
9632
9636
|
}
|
|
9633
9637
|
function optimaCodemapPath(worktree) {
|
|
9634
|
-
return
|
|
9638
|
+
return path6.join(optimaDir(worktree), "codemap.yml");
|
|
9635
9639
|
}
|
|
9636
9640
|
function optimaTasksDir(worktree) {
|
|
9637
|
-
return
|
|
9641
|
+
return path6.join(optimaDir(worktree), "tasks");
|
|
9638
9642
|
}
|
|
9639
9643
|
function optimaEvidencesDir(worktree) {
|
|
9640
|
-
return
|
|
9644
|
+
return path6.join(optimaDir(worktree), "evidences");
|
|
9641
9645
|
}
|
|
9642
9646
|
function optimaScrsDir(worktree) {
|
|
9643
|
-
return
|
|
9647
|
+
return path6.join(optimaDir(worktree), "docs", "scrs");
|
|
9644
9648
|
}
|
|
9645
9649
|
function legacyNomadworkDir(worktree) {
|
|
9646
|
-
return
|
|
9650
|
+
return path6.join(worktree, LEGACY_NOMADWORK_DIRNAME);
|
|
9647
9651
|
}
|
|
9648
9652
|
function legacyNomadworksDir(worktree) {
|
|
9649
|
-
return
|
|
9653
|
+
return path6.join(worktree, LEGACY_NOMADWORKS_DIRNAME);
|
|
9650
9654
|
}
|
|
9651
9655
|
function legacyOrbitaDir(worktree) {
|
|
9652
|
-
return
|
|
9656
|
+
return path6.join(worktree, LEGACY_ORBITA_DIRNAME);
|
|
9653
9657
|
}
|
|
9654
9658
|
function legacyStaticEngDir(worktree) {
|
|
9655
|
-
return
|
|
9659
|
+
return path6.join(worktree, LEGACY_STATICENG_DIRNAME);
|
|
9656
9660
|
}
|
|
9657
9661
|
function repoConfigPath(worktree) {
|
|
9658
|
-
return
|
|
9662
|
+
return path6.join(optimaConfigDir(worktree), "optima.yaml");
|
|
9659
9663
|
}
|
|
9660
9664
|
function normalizeLegacyDiscussionEntry(entry) {
|
|
9661
9665
|
if (!entry || typeof entry !== "object") return entry;
|
|
@@ -9668,25 +9672,25 @@ function normalizeLegacyDiscussionEntry(entry) {
|
|
|
9668
9672
|
return next;
|
|
9669
9673
|
}
|
|
9670
9674
|
function repoPoliciesDir(worktree) {
|
|
9671
|
-
return
|
|
9675
|
+
return path6.join(optimaDir(worktree), "policies");
|
|
9672
9676
|
}
|
|
9673
9677
|
function generatedPoliciesDir(worktree) {
|
|
9674
|
-
return
|
|
9678
|
+
return path6.join(optimaLocalConfigDir(worktree), "generated", "policies");
|
|
9675
9679
|
}
|
|
9676
9680
|
function generatedAgentsDir(worktree) {
|
|
9677
|
-
return
|
|
9681
|
+
return path6.join(optimaLocalConfigDir(worktree), "generated", "agents");
|
|
9678
9682
|
}
|
|
9679
9683
|
function repoAgentsDir(worktree) {
|
|
9680
|
-
return
|
|
9684
|
+
return path6.join(optimaDir(worktree), "agents");
|
|
9681
9685
|
}
|
|
9682
9686
|
function repoAgentAdditionsDir(worktree) {
|
|
9683
|
-
return
|
|
9687
|
+
return path6.join(optimaDir(worktree), "agent-additions");
|
|
9684
9688
|
}
|
|
9685
9689
|
function legacyRepoAgentsDir(worktree) {
|
|
9686
|
-
return
|
|
9690
|
+
return path6.join(legacyNomadworksDir(worktree), "agents");
|
|
9687
9691
|
}
|
|
9688
9692
|
function runtimeDiscussionRegistryPath(worktree) {
|
|
9689
|
-
return
|
|
9693
|
+
return path6.join(optimaLocalConfigDir(worktree), "runtime", "discussions.json");
|
|
9690
9694
|
}
|
|
9691
9695
|
function resolveConfigPath(worktree) {
|
|
9692
9696
|
return repoConfigPath(worktree);
|
|
@@ -9729,32 +9733,32 @@ function mergeClickUpAgentMetadata(existing, update = {}) {
|
|
|
9729
9733
|
return JSON.stringify(sortJsonValue(merged), null, 2);
|
|
9730
9734
|
}
|
|
9731
9735
|
function optimaRuntimeDir(worktree) {
|
|
9732
|
-
return
|
|
9736
|
+
return path6.join(optimaLocalConfigDir(worktree), "runtime");
|
|
9733
9737
|
}
|
|
9734
9738
|
function clickUpWebhookStatePath(worktree) {
|
|
9735
|
-
return
|
|
9739
|
+
return path6.join(optimaRuntimeDir(worktree), "clickup-webhook.json");
|
|
9736
9740
|
}
|
|
9737
9741
|
function clickUpCommentLedgerPath(worktree) {
|
|
9738
|
-
return
|
|
9742
|
+
return path6.join(optimaRuntimeDir(worktree), "clickup-comment-ledger.jsonl");
|
|
9739
9743
|
}
|
|
9740
9744
|
function clickUpWebhookLogPath(worktree) {
|
|
9741
|
-
return
|
|
9745
|
+
return path6.join(optimaRuntimeDir(worktree), "clickup-webhook.log.jsonl");
|
|
9742
9746
|
}
|
|
9743
9747
|
function normalizeClickUpWebhookLogLevel(value) {
|
|
9744
9748
|
const level = String(value || "info").trim().toLowerCase();
|
|
9745
9749
|
return CLICKUP_WEBHOOK_LOG_LEVELS.has(level) ? level : "info";
|
|
9746
9750
|
}
|
|
9747
9751
|
function clickUpWebhookAuditLogDir() {
|
|
9748
|
-
const dataHome = process.env.XDG_DATA_HOME &&
|
|
9749
|
-
return
|
|
9752
|
+
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");
|
|
9753
|
+
return path6.join(dataHome, "opencode-optima");
|
|
9750
9754
|
}
|
|
9751
9755
|
function clickUpWebhookAuditLogPath(at = /* @__PURE__ */ new Date(), logDir = clickUpWebhookAuditLogDir()) {
|
|
9752
|
-
return
|
|
9756
|
+
return path6.join(logDir, `clickup-webhook-${at.toISOString().slice(0, 10)}.jsonl`);
|
|
9753
9757
|
}
|
|
9754
9758
|
function clickUpWebhookRequestFilePath(at = /* @__PURE__ */ new Date(), logDir = clickUpWebhookAuditLogDir()) {
|
|
9755
9759
|
const stamp = at.toISOString().replace(/:/g, "-").replace(/\./g, "-");
|
|
9756
9760
|
const shortId = crypto.randomBytes(4).toString("hex");
|
|
9757
|
-
return
|
|
9761
|
+
return path6.join(logDir, "requests", `clickup-webhook-${stamp}-${shortId}.json`);
|
|
9758
9762
|
}
|
|
9759
9763
|
function findOptimaPluginTupleOptions(pluginEntries = []) {
|
|
9760
9764
|
if (!Array.isArray(pluginEntries)) return null;
|
|
@@ -9820,6 +9824,10 @@ function normalizeClickUpWebhookConfig(rawClickUp = null, worktree = process.cwd
|
|
|
9820
9824
|
assignmentWatchdogIntervalMs: normalizeNonNegativeInteger(
|
|
9821
9825
|
opencode.assignment_watchdog_interval_ms ?? opencode.assignmentWatchdogIntervalMs ?? raw.assignment_watchdog_interval_ms ?? raw.assignmentWatchdogIntervalMs,
|
|
9822
9826
|
CLICKUP_ASSIGNMENT_WATCHDOG_INTERVAL_MS
|
|
9827
|
+
),
|
|
9828
|
+
assignmentWatchdogRunningGraceMs: normalizeNonNegativeInteger(
|
|
9829
|
+
opencode.assignment_watchdog_running_grace_ms ?? opencode.assignmentWatchdogRunningGraceMs ?? raw.assignment_watchdog_running_grace_ms ?? raw.assignmentWatchdogRunningGraceMs,
|
|
9830
|
+
CLICKUP_ASSIGNMENT_WATCHDOG_RUNNING_GRACE_MS
|
|
9823
9831
|
)
|
|
9824
9832
|
},
|
|
9825
9833
|
openchamber: {
|
|
@@ -9853,7 +9861,7 @@ function normalizeClickUpWebhookConfig(rawClickUp = null, worktree = process.cwd
|
|
|
9853
9861
|
};
|
|
9854
9862
|
const errors = [];
|
|
9855
9863
|
if (!config.enabled) errors.push("clickup.enabled must be true");
|
|
9856
|
-
if (!config.basePath || !
|
|
9864
|
+
if (!config.basePath || !path6.isAbsolute(config.basePath)) errors.push("clickup.base_path must be an absolute path");
|
|
9857
9865
|
if (!config.teamId) errors.push("clickup.team_id is required");
|
|
9858
9866
|
if (!config.apiToken) errors.push("clickup.api_token is required");
|
|
9859
9867
|
if (!config.webhook.publicUrl) errors.push("clickup.webhook.public_url is required");
|
|
@@ -9911,7 +9919,7 @@ function readClickUpWebhookState(worktree, config = null) {
|
|
|
9911
9919
|
}
|
|
9912
9920
|
function writeClickUpWebhookState(worktree, state, config = null) {
|
|
9913
9921
|
const statePath = clickUpWebhookStatePath(worktree);
|
|
9914
|
-
fs5.mkdirSync(
|
|
9922
|
+
fs5.mkdirSync(path6.dirname(statePath), { recursive: true, mode: 448 });
|
|
9915
9923
|
const next = sanitizeClickUpWebhookState(state, config);
|
|
9916
9924
|
fs5.writeFileSync(statePath, `${JSON.stringify(next, null, 2)}
|
|
9917
9925
|
`, { encoding: "utf8", mode: 384 });
|
|
@@ -9932,7 +9940,7 @@ function isClickUpWebhookStateActive(state, config) {
|
|
|
9932
9940
|
function expandHomePath(value = "") {
|
|
9933
9941
|
const input = String(value || "").trim();
|
|
9934
9942
|
if (input === "~") return os.homedir();
|
|
9935
|
-
if (input.startsWith("~/")) return
|
|
9943
|
+
if (input.startsWith("~/")) return path6.join(os.homedir(), input.slice(2));
|
|
9936
9944
|
return input;
|
|
9937
9945
|
}
|
|
9938
9946
|
function resolveSecretReference(value = "") {
|
|
@@ -10308,7 +10316,7 @@ function readClickUpCommentLedger(ledgerPath) {
|
|
|
10308
10316
|
}
|
|
10309
10317
|
function appendClickUpCommentLedgerEntry(ledgerPath, entry = {}) {
|
|
10310
10318
|
if (!ledgerPath || !entry.key) return;
|
|
10311
|
-
fs5.mkdirSync(
|
|
10319
|
+
fs5.mkdirSync(path6.dirname(ledgerPath), { recursive: true, mode: 448 });
|
|
10312
10320
|
fs5.appendFileSync(ledgerPath, `${JSON.stringify(entry)}
|
|
10313
10321
|
`, { encoding: "utf8", mode: 384 });
|
|
10314
10322
|
try {
|
|
@@ -10775,6 +10783,22 @@ async function readOpenCodeSessionMessages(client, { sessionId, directory, limit
|
|
|
10775
10783
|
if (directory) query.directory = directory;
|
|
10776
10784
|
return normalizeOpenCodeSessionMessages(await client.session.messages({ path: { id: sessionId }, query }));
|
|
10777
10785
|
}
|
|
10786
|
+
async function readOpenCodeChildSessions(client, { sessionId, directory } = {}) {
|
|
10787
|
+
if (typeof client?.session?.children !== "function") return [];
|
|
10788
|
+
const attempts = [
|
|
10789
|
+
{ path: { id: sessionId }, query: directory ? { directory } : {} },
|
|
10790
|
+
{ path: { sessionID: sessionId }, query: directory ? { directory } : {} },
|
|
10791
|
+
{ sessionID: sessionId, ...directory ? { directory } : {} }
|
|
10792
|
+
];
|
|
10793
|
+
for (const attempt of attempts) {
|
|
10794
|
+
try {
|
|
10795
|
+
const result = await client.session.children(attempt);
|
|
10796
|
+
return normalizeOpenCodeSessionCollection(result?.data ?? result);
|
|
10797
|
+
} catch {
|
|
10798
|
+
}
|
|
10799
|
+
}
|
|
10800
|
+
return [];
|
|
10801
|
+
}
|
|
10778
10802
|
function openCodeResultSummary(result) {
|
|
10779
10803
|
const data = result?.data ?? result;
|
|
10780
10804
|
return {
|
|
@@ -10835,13 +10859,28 @@ function openCodeMessageTimestampMs(message = {}, key = "updated") {
|
|
|
10835
10859
|
const number = Number(value);
|
|
10836
10860
|
return Number.isFinite(number) && number > 0 ? number : 0;
|
|
10837
10861
|
}
|
|
10838
|
-
function
|
|
10862
|
+
function openCodeSessionTimestampMs(session = {}, key = "updated") {
|
|
10863
|
+
const time = session?.time || session?.info?.time || {};
|
|
10864
|
+
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;
|
|
10865
|
+
const number = Number(value);
|
|
10866
|
+
return Number.isFinite(number) && number > 0 ? number : 0;
|
|
10867
|
+
}
|
|
10868
|
+
function openCodeNowMs(now = /* @__PURE__ */ new Date()) {
|
|
10869
|
+
const value = typeof now === "function" ? now() : now;
|
|
10870
|
+
const number = Number(value instanceof Date ? value.getTime() : new Date(value).getTime());
|
|
10871
|
+
return Number.isFinite(number) && number > 0 ? number : 0;
|
|
10872
|
+
}
|
|
10873
|
+
function isOpenCodeAssistantMessageRunning(message = {}, { latestActivityAt = 0, now = /* @__PURE__ */ new Date(), runningGraceMs = CLICKUP_ASSIGNMENT_WATCHDOG_RUNNING_GRACE_MS } = {}) {
|
|
10839
10874
|
if (normalizeLooseToken(normalizeOpenCodeMessageRole(message)) !== "assistant") return false;
|
|
10840
10875
|
const started = openCodeMessageTimestampMs(message, "created") > 0;
|
|
10841
10876
|
if (!started) return false;
|
|
10842
|
-
|
|
10877
|
+
if (openCodeMessageTimestampMs(message, "completed") !== 0) return false;
|
|
10878
|
+
const nowMs = openCodeNowMs(now);
|
|
10879
|
+
const activityAt = Number(latestActivityAt) || openCodeMessageTimestampMs(message, "updated") || openCodeMessageTimestampMs(message, "created");
|
|
10880
|
+
if (!Number.isFinite(nowMs) || nowMs <= 0 || !Number.isFinite(activityAt) || activityAt <= 0) return false;
|
|
10881
|
+
return nowMs - activityAt <= Math.max(0, Number(runningGraceMs) || 0);
|
|
10843
10882
|
}
|
|
10844
|
-
async function inspectOpenCodeSessionActivity(client, { sessionId, directory, limit = 10 } = {}) {
|
|
10883
|
+
async function inspectOpenCodeSessionActivity(client, { sessionId, directory, limit = 10, now = /* @__PURE__ */ new Date(), runningGraceMs = CLICKUP_ASSIGNMENT_WATCHDOG_RUNNING_GRACE_MS } = {}) {
|
|
10845
10884
|
const messages = await readOpenCodeSessionMessages(client, { sessionId, directory, limit });
|
|
10846
10885
|
if (!messages) return { ok: false, reason: "message_inspection_unavailable", sessionId, directory };
|
|
10847
10886
|
const enriched = messages.map((message, index) => ({
|
|
@@ -10851,20 +10890,45 @@ async function inspectOpenCodeSessionActivity(client, { sessionId, directory, li
|
|
|
10851
10890
|
createdAt: openCodeMessageTimestampMs(message, "created"),
|
|
10852
10891
|
completedAt: openCodeMessageTimestampMs(message, "completed")
|
|
10853
10892
|
})).sort((a, b) => a.sortTime - b.sortTime || a.index - b.index);
|
|
10893
|
+
const childSessions = await readOpenCodeChildSessions(client, { sessionId, directory });
|
|
10894
|
+
const childActivities = childSessions.map((session, index) => ({
|
|
10895
|
+
session,
|
|
10896
|
+
index,
|
|
10897
|
+
id: session.id || session.sessionID || session.sessionId || null,
|
|
10898
|
+
agent: session.agent || session.mode?.agent || session.metadata?.agent || "",
|
|
10899
|
+
updatedAt: openCodeSessionTimestampMs(session, "updated")
|
|
10900
|
+
})).filter((entry) => entry.updatedAt > 0).sort((a, b) => a.updatedAt - b.updatedAt || a.index - b.index);
|
|
10854
10901
|
const assistantMessages = enriched.filter((entry) => normalizeLooseToken(normalizeOpenCodeMessageRole(entry.message)) === "assistant");
|
|
10855
10902
|
const latestAssistant = assistantMessages.at(-1) || null;
|
|
10856
10903
|
const latest = enriched.at(-1) || null;
|
|
10857
|
-
const
|
|
10904
|
+
const latestChild = childActivities.at(-1) || null;
|
|
10905
|
+
const latestMessageActivityAt = latest?.sortTime || 0;
|
|
10906
|
+
const latestChildActivityAt = latestChild?.updatedAt || 0;
|
|
10907
|
+
const latestActivityAt = Math.max(latestMessageActivityAt, latestChildActivityAt);
|
|
10908
|
+
const nowMs = openCodeNowMs(now);
|
|
10909
|
+
const latestActivityAgeMs = Number.isFinite(nowMs) && latestActivityAt > 0 ? Math.max(0, nowMs - latestActivityAt) : null;
|
|
10910
|
+
const assistantRunning = latestAssistant ? isOpenCodeAssistantMessageRunning(latestAssistant.message, { latestActivityAt, now, runningGraceMs }) : false;
|
|
10911
|
+
const childRunning = latestChildActivityAt > 0 && latestActivityAgeMs !== null && latestActivityAgeMs <= Math.max(0, Number(runningGraceMs) || 0);
|
|
10912
|
+
const running = assistantRunning || childRunning;
|
|
10913
|
+
const runningReason = running ? childRunning && latestChildActivityAt >= latestMessageActivityAt ? "recent_child_session_activity" : "recent_incomplete_assistant" : latestAssistant && latestAssistant.completedAt === 0 ? "stale_incomplete_assistant" : "not_running";
|
|
10858
10914
|
return {
|
|
10859
10915
|
ok: true,
|
|
10860
10916
|
sessionId,
|
|
10861
10917
|
directory,
|
|
10862
10918
|
count: messages.length,
|
|
10863
10919
|
running,
|
|
10920
|
+
runningReason,
|
|
10921
|
+
runningGraceMs,
|
|
10922
|
+
latestActivityAt,
|
|
10923
|
+
latestActivityAgeMs,
|
|
10864
10924
|
latestMessageId: latest ? normalizeOpenCodeMessageId(latest.message) : null,
|
|
10865
10925
|
latestAssistantMessageId: latestAssistant ? normalizeOpenCodeMessageId(latestAssistant.message) : null,
|
|
10866
10926
|
latestAssistantCreatedAt: latestAssistant?.createdAt || 0,
|
|
10867
|
-
latestAssistantCompletedAt: latestAssistant?.completedAt || 0
|
|
10927
|
+
latestAssistantCompletedAt: latestAssistant?.completedAt || 0,
|
|
10928
|
+
latestChildSessionId: latestChild?.id || null,
|
|
10929
|
+
latestChildAgent: latestChild?.agent || null,
|
|
10930
|
+
latestChildUpdatedAt: latestChild?.updatedAt || 0,
|
|
10931
|
+
childSessionCount: childSessions.length
|
|
10868
10932
|
};
|
|
10869
10933
|
}
|
|
10870
10934
|
function summarizeOpenCodeMessages(messages = [], { snippetLength = 160, maxMessages = 50 } = {}) {
|
|
@@ -11171,7 +11235,7 @@ function formatClickUpWebhookPrompt({ eventType, taskId, payload, branch = "", w
|
|
|
11171
11235
|
}
|
|
11172
11236
|
function appendClickUpWebhookLocalLog(worktree, entry) {
|
|
11173
11237
|
const logPath = clickUpWebhookLogPath(worktree);
|
|
11174
|
-
fs5.mkdirSync(
|
|
11238
|
+
fs5.mkdirSync(path6.dirname(logPath), { recursive: true });
|
|
11175
11239
|
const safeEntry = { ...entry, at: entry.at || (/* @__PURE__ */ new Date()).toISOString() };
|
|
11176
11240
|
fs5.appendFileSync(logPath, `${JSON.stringify(safeEntry)}
|
|
11177
11241
|
`, "utf8");
|
|
@@ -11202,7 +11266,7 @@ function closeClickUpWebhookServer(server) {
|
|
|
11202
11266
|
});
|
|
11203
11267
|
}
|
|
11204
11268
|
function managedClickUpWebhookKey({ worktree, state, config } = {}) {
|
|
11205
|
-
return [
|
|
11269
|
+
return [path6.resolve(worktree || process.cwd()), state?.webhookId || "", config?.webhook?.publicUrl || ""].join("|");
|
|
11206
11270
|
}
|
|
11207
11271
|
async function deleteClickUpWebhookBestEffort({ webhookId, clickupClient, worktree, reason = "cleanup" } = {}) {
|
|
11208
11272
|
const id = String(webhookId || "").trim();
|
|
@@ -11307,8 +11371,8 @@ function writeClickUpWebhookAuditLog({ method, url, headers = {}, rawBody = "",
|
|
|
11307
11371
|
let requestFile;
|
|
11308
11372
|
if (level === "verbose") {
|
|
11309
11373
|
const absoluteRequestFile = clickUpWebhookRequestFilePath(at, logDir);
|
|
11310
|
-
fs5.mkdirSync(
|
|
11311
|
-
requestFile =
|
|
11374
|
+
fs5.mkdirSync(path6.dirname(absoluteRequestFile), { recursive: true });
|
|
11375
|
+
requestFile = path6.relative(logDir, absoluteRequestFile).split(path6.sep).join("/");
|
|
11312
11376
|
const parsedBody = payload || (() => {
|
|
11313
11377
|
try {
|
|
11314
11378
|
return JSON.parse(Buffer.isBuffer(rawBody) ? rawBody.toString("utf8") : String(rawBody || ""));
|
|
@@ -11624,7 +11688,12 @@ async function reconcileClickUpStartup({ config, state = {}, worktree = process.
|
|
|
11624
11688
|
const directory = String(getNestedMetadataValue(metadata, "task.worktree") || "").trim();
|
|
11625
11689
|
if (sessionId) {
|
|
11626
11690
|
try {
|
|
11627
|
-
const activity = await inspectOpenCodeSessionActivity(openCodeClient, {
|
|
11691
|
+
const activity = await inspectOpenCodeSessionActivity(openCodeClient, {
|
|
11692
|
+
sessionId,
|
|
11693
|
+
directory,
|
|
11694
|
+
now,
|
|
11695
|
+
runningGraceMs: config.opencode.assignmentWatchdogRunningGraceMs
|
|
11696
|
+
});
|
|
11628
11697
|
appendClickUpWebhookLocalLog(worktree, { type: "assignment_watchdog_session_activity", taskId, sessionId, directory: directory || null, ...activity });
|
|
11629
11698
|
if (activity.running) {
|
|
11630
11699
|
routed.ignored += 1;
|
|
@@ -11919,17 +11988,17 @@ function startClickUpWebhookListener({ config, state, worktree, clickupClient, o
|
|
|
11919
11988
|
return result;
|
|
11920
11989
|
}
|
|
11921
11990
|
function legacyVariantPath(destinationPath) {
|
|
11922
|
-
const parsed =
|
|
11991
|
+
const parsed = path6.parse(destinationPath);
|
|
11923
11992
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:TZ.]/g, "").slice(0, 14);
|
|
11924
|
-
if (parsed.ext) return
|
|
11925
|
-
return
|
|
11993
|
+
if (parsed.ext) return path6.join(parsed.dir, `${parsed.name}.legacy-${stamp}${parsed.ext}`);
|
|
11994
|
+
return path6.join(parsed.dir, `${parsed.base}.legacy-${stamp}`);
|
|
11926
11995
|
}
|
|
11927
11996
|
function normalizeWorkflowTaskPath(taskPath) {
|
|
11928
11997
|
if (typeof taskPath !== "string") return { ok: false, message: "Error: task_path is required." };
|
|
11929
11998
|
const trimmed = taskPath.trim();
|
|
11930
11999
|
if (!trimmed) return { ok: false, message: "Error: task_path is required." };
|
|
11931
12000
|
const normalized = trimmed.replace(/\\/g, "/");
|
|
11932
|
-
if (
|
|
12001
|
+
if (path6.isAbsolute(trimmed)) return { ok: true, taskPath: trimmed };
|
|
11933
12002
|
if (normalized === "tasks" || normalized.startsWith("tasks/")) {
|
|
11934
12003
|
return {
|
|
11935
12004
|
ok: false,
|
|
@@ -11948,12 +12017,12 @@ function mergeFileIntoDestination(sourcePath, destinationPath, relativeSource, g
|
|
|
11948
12017
|
const sourceWasTracked = isGitTracked(gitState, sourcePath);
|
|
11949
12018
|
if (gitAwareMoveIfTracked(sourcePath, destinationPath, gitState)) return;
|
|
11950
12019
|
if (!fs5.existsSync(destinationPath)) {
|
|
11951
|
-
fs5.mkdirSync(
|
|
12020
|
+
fs5.mkdirSync(path6.dirname(destinationPath), { recursive: true });
|
|
11952
12021
|
fs5.renameSync(sourcePath, destinationPath);
|
|
11953
12022
|
if (sourceWasTracked) stageGitAwareMerge(sourcePath, destinationPath, gitState);
|
|
11954
12023
|
return;
|
|
11955
12024
|
}
|
|
11956
|
-
const ext =
|
|
12025
|
+
const ext = path6.extname(destinationPath).toLowerCase();
|
|
11957
12026
|
if ([".yaml", ".yml", ".json"].includes(ext)) {
|
|
11958
12027
|
const sourceRaw = fs5.readFileSync(sourcePath, "utf8");
|
|
11959
12028
|
const destRaw = fs5.readFileSync(destinationPath, "utf8");
|
|
@@ -11988,14 +12057,14 @@ ${sourceRaw}
|
|
|
11988
12057
|
fs5.renameSync(sourcePath, preservedPath);
|
|
11989
12058
|
stageGitAwareMerge(sourcePath, preservedPath, gitState);
|
|
11990
12059
|
}
|
|
11991
|
-
function mergePathIntoDestination(sourcePath, destinationPath, relativeSource =
|
|
12060
|
+
function mergePathIntoDestination(sourcePath, destinationPath, relativeSource = path6.basename(sourcePath), gitState = null) {
|
|
11992
12061
|
if (!fs5.existsSync(sourcePath)) return;
|
|
11993
12062
|
const stat = fs5.statSync(sourcePath);
|
|
11994
12063
|
if (stat.isDirectory()) {
|
|
11995
12064
|
const sourceWasTracked = isGitTracked(gitState, sourcePath) || hasGitTrackedChildren(gitState, sourcePath);
|
|
11996
12065
|
if (gitAwareMoveIfTracked(sourcePath, destinationPath, gitState)) return;
|
|
11997
12066
|
if (!fs5.existsSync(destinationPath)) {
|
|
11998
|
-
fs5.mkdirSync(
|
|
12067
|
+
fs5.mkdirSync(path6.dirname(destinationPath), { recursive: true });
|
|
11999
12068
|
fs5.renameSync(sourcePath, destinationPath);
|
|
12000
12069
|
if (sourceWasTracked) stageGitAwareMerge(sourcePath, destinationPath, gitState);
|
|
12001
12070
|
return;
|
|
@@ -12003,9 +12072,9 @@ function mergePathIntoDestination(sourcePath, destinationPath, relativeSource =
|
|
|
12003
12072
|
fs5.mkdirSync(destinationPath, { recursive: true });
|
|
12004
12073
|
for (const entry of fs5.readdirSync(sourcePath)) {
|
|
12005
12074
|
mergePathIntoDestination(
|
|
12006
|
-
|
|
12007
|
-
|
|
12008
|
-
|
|
12075
|
+
path6.join(sourcePath, entry),
|
|
12076
|
+
path6.join(destinationPath, entry),
|
|
12077
|
+
path6.join(relativeSource, entry),
|
|
12009
12078
|
gitState
|
|
12010
12079
|
);
|
|
12011
12080
|
}
|
|
@@ -12015,7 +12084,7 @@ function mergePathIntoDestination(sourcePath, destinationPath, relativeSource =
|
|
|
12015
12084
|
mergeFileIntoDestination(sourcePath, destinationPath, relativeSource, gitState);
|
|
12016
12085
|
}
|
|
12017
12086
|
function isOptimaPluginPackageWorktree(worktree) {
|
|
12018
|
-
const packageJsonPath =
|
|
12087
|
+
const packageJsonPath = path6.join(worktree, "package.json");
|
|
12019
12088
|
if (!fs5.existsSync(packageJsonPath)) return false;
|
|
12020
12089
|
try {
|
|
12021
12090
|
const pkg = JSON.parse(fs5.readFileSync(packageJsonPath, "utf8"));
|
|
@@ -12027,51 +12096,51 @@ function isOptimaPluginPackageWorktree(worktree) {
|
|
|
12027
12096
|
function migrateLegacyOptimaLayout(worktree) {
|
|
12028
12097
|
const gitState = gitMigrationState(worktree);
|
|
12029
12098
|
const migrations = [
|
|
12030
|
-
[
|
|
12031
|
-
[
|
|
12032
|
-
[
|
|
12033
|
-
[
|
|
12034
|
-
[
|
|
12035
|
-
[
|
|
12099
|
+
[path6.join(legacyOrbitaDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path6.join(".orbita", "orbita.yaml")],
|
|
12100
|
+
[path6.join(legacyOrbitaDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path6.join(".orbita", "staticeng.yaml")],
|
|
12101
|
+
[path6.join(legacyOrbitaDir(worktree), ".config"), optimaLocalConfigDir(worktree), path6.join(".orbita", ".config")],
|
|
12102
|
+
[path6.join(legacyOrbitaDir(worktree), "config"), optimaLocalConfigDir(worktree), path6.join(".orbita", "config")],
|
|
12103
|
+
[path6.join(legacyOrbitaDir(worktree), "runtime"), path6.join(optimaLocalConfigDir(worktree), "runtime"), path6.join(".orbita", "runtime")],
|
|
12104
|
+
[path6.join(legacyOrbitaDir(worktree), "generated"), path6.join(optimaLocalConfigDir(worktree), "generated"), path6.join(".orbita", "generated")],
|
|
12036
12105
|
[legacyOrbitaDir(worktree), optimaDir(worktree), ".orbita"],
|
|
12037
|
-
[
|
|
12038
|
-
[
|
|
12039
|
-
[
|
|
12040
|
-
[
|
|
12041
|
-
[
|
|
12042
|
-
[
|
|
12106
|
+
[path6.join(legacyStaticEngDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path6.join(".staticeng", "staticeng.yaml")],
|
|
12107
|
+
[path6.join(legacyStaticEngDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path6.join(".staticeng", "orbita.yaml")],
|
|
12108
|
+
[path6.join(legacyStaticEngDir(worktree), ".config"), optimaLocalConfigDir(worktree), path6.join(".staticeng", ".config")],
|
|
12109
|
+
[path6.join(legacyStaticEngDir(worktree), "config"), optimaLocalConfigDir(worktree), path6.join(".staticeng", "config")],
|
|
12110
|
+
[path6.join(legacyStaticEngDir(worktree), "runtime"), path6.join(optimaLocalConfigDir(worktree), "runtime"), path6.join(".staticeng", "runtime")],
|
|
12111
|
+
[path6.join(legacyStaticEngDir(worktree), "generated"), path6.join(optimaLocalConfigDir(worktree), "generated"), path6.join(".staticeng", "generated")],
|
|
12043
12112
|
[legacyStaticEngDir(worktree), optimaDir(worktree), ".staticeng"],
|
|
12044
|
-
[
|
|
12045
|
-
[
|
|
12046
|
-
[
|
|
12047
|
-
[
|
|
12048
|
-
[
|
|
12049
|
-
[
|
|
12050
|
-
[
|
|
12051
|
-
[
|
|
12052
|
-
[
|
|
12053
|
-
[
|
|
12054
|
-
[
|
|
12055
|
-
[
|
|
12113
|
+
[path6.join(legacyNomadworkDir(worktree), "nomadworks.yaml"), repoConfigPath(worktree), path6.join(".nomadwork", "nomadworks.yaml")],
|
|
12114
|
+
[path6.join(legacyNomadworksDir(worktree), "nomadworks.yaml"), repoConfigPath(worktree), path6.join(".nomadworks", "nomadworks.yaml")],
|
|
12115
|
+
[path6.join(legacyNomadworkDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path6.join(".nomadwork", "staticeng.yaml")],
|
|
12116
|
+
[path6.join(legacyNomadworksDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path6.join(".nomadworks", "staticeng.yaml")],
|
|
12117
|
+
[path6.join(legacyNomadworkDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path6.join(".nomadwork", "orbita.yaml")],
|
|
12118
|
+
[path6.join(legacyNomadworksDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path6.join(".nomadworks", "orbita.yaml")],
|
|
12119
|
+
[path6.join(legacyNomadworkDir(worktree), "runtime"), path6.join(optimaLocalConfigDir(worktree), "runtime"), path6.join(".nomadwork", "runtime")],
|
|
12120
|
+
[path6.join(legacyNomadworksDir(worktree), "runtime"), path6.join(optimaLocalConfigDir(worktree), "runtime"), path6.join(".nomadworks", "runtime")],
|
|
12121
|
+
[path6.join(legacyNomadworkDir(worktree), "generated"), path6.join(optimaLocalConfigDir(worktree), "generated"), path6.join(".nomadwork", "generated")],
|
|
12122
|
+
[path6.join(legacyNomadworksDir(worktree), "generated"), path6.join(optimaLocalConfigDir(worktree), "generated"), path6.join(".nomadworks", "generated")],
|
|
12123
|
+
[path6.join(legacyNomadworkDir(worktree), "config"), optimaLocalConfigDir(worktree), path6.join(".nomadwork", "config")],
|
|
12124
|
+
[path6.join(legacyNomadworksDir(worktree), "config"), optimaLocalConfigDir(worktree), path6.join(".nomadworks", "config")],
|
|
12056
12125
|
[legacyNomadworkDir(worktree), optimaDir(worktree), ".nomadwork"],
|
|
12057
12126
|
[legacyNomadworksDir(worktree), optimaDir(worktree), ".nomadworks"],
|
|
12058
|
-
[
|
|
12059
|
-
[
|
|
12060
|
-
[
|
|
12061
|
-
[
|
|
12062
|
-
[
|
|
12127
|
+
[path6.join(worktree, "tasks"), optimaTasksDir(worktree), "tasks"],
|
|
12128
|
+
[path6.join(worktree, "evidences"), optimaEvidencesDir(worktree), "evidences"],
|
|
12129
|
+
[path6.join(worktree, "docs", "scrs"), optimaScrsDir(worktree), path6.join("docs", "scrs")],
|
|
12130
|
+
[path6.join(worktree, "codemap.yml"), optimaCodemapPath(worktree), "codemap.yml"],
|
|
12131
|
+
[path6.join(worktree, "codemap.yaml"), optimaCodemapPath(worktree), "codemap.yaml"]
|
|
12063
12132
|
];
|
|
12064
12133
|
if (!isOptimaPluginPackageWorktree(worktree)) {
|
|
12065
|
-
migrations.push([
|
|
12134
|
+
migrations.push([path6.join(worktree, "policies"), repoPoliciesDir(worktree), "policies"]);
|
|
12066
12135
|
}
|
|
12067
12136
|
for (const [source, destination, relativeSource] of migrations) {
|
|
12068
12137
|
if (fs5.existsSync(source)) mergePathIntoDestination(source, destination, relativeSource, gitState);
|
|
12069
12138
|
}
|
|
12070
12139
|
for (const [source, destination, relativeSource] of [
|
|
12071
|
-
[
|
|
12072
|
-
[
|
|
12073
|
-
[
|
|
12074
|
-
[
|
|
12140
|
+
[path6.join(optimaDir(worktree), "optima.yaml"), repoConfigPath(worktree), path6.join(".optima", "optima.yaml")],
|
|
12141
|
+
[path6.join(optimaDir(worktree), "config"), optimaLocalConfigDir(worktree), path6.join(".optima", "config")],
|
|
12142
|
+
[path6.join(optimaDir(worktree), "runtime"), path6.join(optimaLocalConfigDir(worktree), "runtime"), path6.join(".optima", "runtime")],
|
|
12143
|
+
[path6.join(optimaDir(worktree), "generated"), path6.join(optimaLocalConfigDir(worktree), "generated"), path6.join(".optima", "generated")]
|
|
12075
12144
|
]) {
|
|
12076
12145
|
if (fs5.existsSync(source)) mergePathIntoDestination(source, destination, relativeSource, gitState);
|
|
12077
12146
|
}
|
|
@@ -12120,7 +12189,7 @@ function toModelString(provider, model) {
|
|
|
12120
12189
|
}
|
|
12121
12190
|
function readTaskMetadata(taskPath, worktree) {
|
|
12122
12191
|
if (!taskPath) return {};
|
|
12123
|
-
const absoluteTaskPath =
|
|
12192
|
+
const absoluteTaskPath = path6.isAbsolute(taskPath) ? taskPath : path6.join(worktree, taskPath);
|
|
12124
12193
|
if (!fs5.existsSync(absoluteTaskPath)) return {};
|
|
12125
12194
|
try {
|
|
12126
12195
|
const raw = fs5.readFileSync(absoluteTaskPath, "utf8");
|
|
@@ -12165,18 +12234,18 @@ function loadDiscussionRegistry(worktree) {
|
|
|
12165
12234
|
}
|
|
12166
12235
|
function saveDiscussionRegistry(worktree, registry) {
|
|
12167
12236
|
const registryPath = runtimeDiscussionRegistryPath(worktree);
|
|
12168
|
-
const runtimeDir =
|
|
12237
|
+
const runtimeDir = path6.dirname(registryPath);
|
|
12169
12238
|
if (!fs5.existsSync(runtimeDir)) fs5.mkdirSync(runtimeDir, { recursive: true });
|
|
12170
12239
|
fs5.writeFileSync(registryPath, JSON.stringify(registry, null, 2), "utf8");
|
|
12171
12240
|
}
|
|
12172
12241
|
function runtimeDiscussionsDir(worktree) {
|
|
12173
|
-
return
|
|
12242
|
+
return path6.join(optimaLocalConfigDir(worktree), "runtime", "discussions");
|
|
12174
12243
|
}
|
|
12175
12244
|
function archivedRuntimeDiscussionsDir(worktree) {
|
|
12176
|
-
return
|
|
12245
|
+
return path6.join(runtimeDiscussionsDir(worktree), "archive");
|
|
12177
12246
|
}
|
|
12178
12247
|
function finalDiscussionsDir(worktree) {
|
|
12179
|
-
return
|
|
12248
|
+
return path6.join(optimaTasksDir(worktree), "discussions");
|
|
12180
12249
|
}
|
|
12181
12250
|
function nextDiscussionIdentity(worktree, title) {
|
|
12182
12251
|
const discussionsDir = finalDiscussionsDir(worktree);
|
|
@@ -12187,11 +12256,11 @@ function nextDiscussionIdentity(worktree, title) {
|
|
|
12187
12256
|
while (true) {
|
|
12188
12257
|
const id = `DISCUSSION-${String(sequence).padStart(3, "0")}`;
|
|
12189
12258
|
const filename = `${id}-${slugifyTitle(title)}.md`;
|
|
12190
|
-
const summaryRelativePath =
|
|
12191
|
-
const summaryAbsolutePath =
|
|
12259
|
+
const summaryRelativePath = path6.join(".optima", "tasks", "discussions", filename);
|
|
12260
|
+
const summaryAbsolutePath = path6.join(worktree, summaryRelativePath);
|
|
12192
12261
|
const transcriptFilename = `${id}-transcript.md`;
|
|
12193
|
-
const transcriptRelativePath =
|
|
12194
|
-
const transcriptAbsolutePath =
|
|
12262
|
+
const transcriptRelativePath = path6.join(".optima", ".config", "runtime", "discussions", transcriptFilename);
|
|
12263
|
+
const transcriptAbsolutePath = path6.join(worktree, transcriptRelativePath);
|
|
12195
12264
|
if (!fs5.existsSync(summaryAbsolutePath) && !fs5.existsSync(transcriptAbsolutePath)) {
|
|
12196
12265
|
return {
|
|
12197
12266
|
id,
|
|
@@ -12216,11 +12285,11 @@ function findDiscussionById(worktree, discussionID) {
|
|
|
12216
12285
|
return {
|
|
12217
12286
|
id: discussionID,
|
|
12218
12287
|
filename,
|
|
12219
|
-
summaryRelativePath:
|
|
12220
|
-
summaryAbsolutePath:
|
|
12288
|
+
summaryRelativePath: path6.join(".optima", "tasks", "discussions", filename),
|
|
12289
|
+
summaryAbsolutePath: path6.join(discussionsDir, filename),
|
|
12221
12290
|
transcriptFilename,
|
|
12222
|
-
transcriptRelativePath:
|
|
12223
|
-
transcriptAbsolutePath:
|
|
12291
|
+
transcriptRelativePath: path6.join(".optima", ".config", "runtime", "discussions", transcriptFilename),
|
|
12292
|
+
transcriptAbsolutePath: path6.join(runtimeDiscussionsDir(worktree), transcriptFilename)
|
|
12224
12293
|
};
|
|
12225
12294
|
}
|
|
12226
12295
|
function parseDiscussionFile(filePath) {
|
|
@@ -12303,15 +12372,15 @@ async function appendMessageIfNeeded(client, worktree, registry, sessionID, mess
|
|
|
12303
12372
|
});
|
|
12304
12373
|
const text = extractTextParts(response.data.parts || []);
|
|
12305
12374
|
if (!text) return;
|
|
12306
|
-
appendDiscussionMessage(
|
|
12375
|
+
appendDiscussionMessage(path6.join(worktree, discussion.transcriptPath), speaker, text, messageID);
|
|
12307
12376
|
discussion.appendedMessageIDs ??= [];
|
|
12308
12377
|
discussion.appendedMessageIDs.push(messageID);
|
|
12309
12378
|
saveDiscussionRegistry(worktree, registry);
|
|
12310
12379
|
}
|
|
12311
12380
|
async function summarizeDiscussionWithBA(client, worktree, discussion) {
|
|
12312
|
-
const transcriptPath =
|
|
12313
|
-
const summaryPath =
|
|
12314
|
-
const summaryDir =
|
|
12381
|
+
const transcriptPath = path6.join(worktree, discussion.transcriptPath);
|
|
12382
|
+
const summaryPath = path6.join(worktree, discussion.summaryPath);
|
|
12383
|
+
const summaryDir = path6.dirname(summaryPath);
|
|
12315
12384
|
if (!fs5.existsSync(summaryDir)) fs5.mkdirSync(summaryDir, { recursive: true });
|
|
12316
12385
|
const hasExistingSummary = fs5.existsSync(summaryPath);
|
|
12317
12386
|
const priorMtimeMs = hasExistingSummary ? fs5.statSync(summaryPath).mtimeMs : null;
|
|
@@ -12414,11 +12483,11 @@ async function summarizeDiscussionWithBA(client, worktree, discussion) {
|
|
|
12414
12483
|
return { confirmation, summaryPath, transcriptPath, hasExistingSummary, priorMtimeMs };
|
|
12415
12484
|
}
|
|
12416
12485
|
function archiveDiscussionTranscript(worktree, transcriptRelativePath) {
|
|
12417
|
-
const sourcePath =
|
|
12486
|
+
const sourcePath = path6.join(worktree, transcriptRelativePath);
|
|
12418
12487
|
if (!fs5.existsSync(sourcePath)) return null;
|
|
12419
12488
|
const archiveDir = archivedRuntimeDiscussionsDir(worktree);
|
|
12420
12489
|
if (!fs5.existsSync(archiveDir)) fs5.mkdirSync(archiveDir, { recursive: true });
|
|
12421
|
-
const targetPath =
|
|
12490
|
+
const targetPath = path6.join(archiveDir, path6.basename(sourcePath));
|
|
12422
12491
|
fs5.renameSync(sourcePath, targetPath);
|
|
12423
12492
|
return targetPath;
|
|
12424
12493
|
}
|
|
@@ -12437,7 +12506,7 @@ async function finalizeClosingDiscussion(client, worktree, registry, sessionID,
|
|
|
12437
12506
|
if (!summaryContent) {
|
|
12438
12507
|
throw new Error(`Discussion summary file is empty at ${discussion.summaryPath}`);
|
|
12439
12508
|
}
|
|
12440
|
-
const transcriptPath =
|
|
12509
|
+
const transcriptPath = path6.join(worktree, discussion.transcriptPath);
|
|
12441
12510
|
setDiscussionStatus(transcriptPath, "closed");
|
|
12442
12511
|
const archivedTranscriptPath = archiveDiscussionTranscript(worktree, discussion.transcriptPath);
|
|
12443
12512
|
delete registry.active[sessionID];
|
|
@@ -12445,7 +12514,7 @@ async function finalizeClosingDiscussion(client, worktree, registry, sessionID,
|
|
|
12445
12514
|
return {
|
|
12446
12515
|
confirmation,
|
|
12447
12516
|
summaryPath: discussion.summaryPath,
|
|
12448
|
-
archivedTranscriptPath: archivedTranscriptPath ?
|
|
12517
|
+
archivedTranscriptPath: archivedTranscriptPath ? path6.relative(worktree, archivedTranscriptPath) : path6.join(".optima", ".config", "runtime", "discussions", "archive", path6.basename(discussion.transcriptPath))
|
|
12449
12518
|
};
|
|
12450
12519
|
}
|
|
12451
12520
|
function normalizeTeamMode(value) {
|
|
@@ -12517,7 +12586,7 @@ function syncGeneratedPolicies(worktree, repoCfg) {
|
|
|
12517
12586
|
if (!fs5.existsSync(generatedDir)) fs5.mkdirSync(generatedDir, { recursive: true });
|
|
12518
12587
|
const policyFiles = fs5.readdirSync(BUNDLE_POLICIES_DIR).filter((file) => file.endsWith(".md") && file !== "README.md");
|
|
12519
12588
|
for (const file of policyFiles) {
|
|
12520
|
-
const sourcePath =
|
|
12589
|
+
const sourcePath = path6.join(BUNDLE_POLICIES_DIR, file);
|
|
12521
12590
|
const source = fs5.readFileSync(sourcePath, "utf8").trimEnd();
|
|
12522
12591
|
const generated = [
|
|
12523
12592
|
"<!--",
|
|
@@ -12529,18 +12598,18 @@ function syncGeneratedPolicies(worktree, repoCfg) {
|
|
|
12529
12598
|
source,
|
|
12530
12599
|
""
|
|
12531
12600
|
].join("\n");
|
|
12532
|
-
fs5.writeFileSync(
|
|
12601
|
+
fs5.writeFileSync(path6.join(generatedDir, file), generated, "utf8");
|
|
12533
12602
|
}
|
|
12534
12603
|
}
|
|
12535
12604
|
function ensureReadmeFile(dirPath, content) {
|
|
12536
12605
|
if (!fs5.existsSync(dirPath)) fs5.mkdirSync(dirPath, { recursive: true });
|
|
12537
|
-
const readmePath =
|
|
12606
|
+
const readmePath = path6.join(dirPath, "README.md");
|
|
12538
12607
|
if (!fs5.existsSync(readmePath)) {
|
|
12539
12608
|
fs5.writeFileSync(readmePath, content, "utf8");
|
|
12540
12609
|
}
|
|
12541
12610
|
}
|
|
12542
12611
|
function ensureFileIfMissing(filePath, content) {
|
|
12543
|
-
if (!fs5.existsSync(
|
|
12612
|
+
if (!fs5.existsSync(path6.dirname(filePath))) fs5.mkdirSync(path6.dirname(filePath), { recursive: true });
|
|
12544
12613
|
if (!fs5.existsSync(filePath)) fs5.writeFileSync(filePath, content, "utf8");
|
|
12545
12614
|
}
|
|
12546
12615
|
function currentTasksRegistryContent() {
|
|
@@ -12627,13 +12696,13 @@ Never place implementation evidence under root \`evidences/\`.
|
|
|
12627
12696
|
}
|
|
12628
12697
|
function ensureOptimaTaskTemplates(worktree) {
|
|
12629
12698
|
const tasksDir = optimaTasksDir(worktree);
|
|
12630
|
-
ensureFileIfMissing(
|
|
12631
|
-
ensureFileIfMissing(
|
|
12699
|
+
ensureFileIfMissing(path6.join(tasksDir, "task-template.md"), taskTemplateContent());
|
|
12700
|
+
ensureFileIfMissing(path6.join(tasksDir, "subtask-template.md"), subtaskTemplateContent());
|
|
12632
12701
|
}
|
|
12633
12702
|
function scaffoldOptimaConfig(worktree, teamMode = "full") {
|
|
12634
12703
|
const configPath = repoConfigPath(worktree);
|
|
12635
12704
|
if (fs5.existsSync(configPath)) return false;
|
|
12636
|
-
const templatePath =
|
|
12705
|
+
const templatePath = path6.join(TEMPLATES_DIR, "optima.yaml.template");
|
|
12637
12706
|
if (!fs5.existsSync(templatePath)) return false;
|
|
12638
12707
|
const agentIds = fs5.existsSync(BUNDLE_AGENTS_DIR) ? fs5.readdirSync(BUNDLE_AGENTS_DIR).filter((f) => f.endsWith(".md")).map((f) => f.replace(".md", "")) : [];
|
|
12639
12708
|
let optimaConfig = fs5.readFileSync(templatePath, "utf8");
|
|
@@ -12652,9 +12721,9 @@ function scaffoldOptimaConfig(worktree, teamMode = "full") {
|
|
|
12652
12721
|
function scaffoldOptimaRootCodemap(worktree) {
|
|
12653
12722
|
const rootCodemapPath = optimaCodemapPath(worktree);
|
|
12654
12723
|
if (fs5.existsSync(rootCodemapPath)) return false;
|
|
12655
|
-
const templatePath =
|
|
12724
|
+
const templatePath = path6.join(TEMPLATES_DIR, "codemap.yml.template");
|
|
12656
12725
|
if (!fs5.existsSync(templatePath)) return false;
|
|
12657
|
-
const codemapConfig = fs5.readFileSync(templatePath, "utf8").replace("{{projectName}}",
|
|
12726
|
+
const codemapConfig = fs5.readFileSync(templatePath, "utf8").replace("{{projectName}}", path6.basename(worktree));
|
|
12658
12727
|
ensureFileIfMissing(rootCodemapPath, codemapConfig);
|
|
12659
12728
|
return fs5.existsSync(rootCodemapPath);
|
|
12660
12729
|
}
|
|
@@ -12663,10 +12732,10 @@ function ensureOptimaRegistries(worktree) {
|
|
|
12663
12732
|
const scrsDir = optimaScrsDir(worktree);
|
|
12664
12733
|
if (!fs5.existsSync(tasksDir)) fs5.mkdirSync(tasksDir, { recursive: true });
|
|
12665
12734
|
if (!fs5.existsSync(scrsDir)) fs5.mkdirSync(scrsDir, { recursive: true });
|
|
12666
|
-
ensureFileIfMissing(
|
|
12667
|
-
ensureFileIfMissing(
|
|
12668
|
-
ensureFileIfMissing(
|
|
12669
|
-
ensureFileIfMissing(
|
|
12735
|
+
ensureFileIfMissing(path6.join(tasksDir, "current.md"), currentTasksRegistryContent());
|
|
12736
|
+
ensureFileIfMissing(path6.join(tasksDir, "done.md"), doneTasksRegistryContent());
|
|
12737
|
+
ensureFileIfMissing(path6.join(scrsDir, "current.md"), currentScrRegistryContent());
|
|
12738
|
+
ensureFileIfMissing(path6.join(scrsDir, "done.md"), doneScrRegistryContent());
|
|
12670
12739
|
}
|
|
12671
12740
|
function scaffoldOptimaReadmes(worktree) {
|
|
12672
12741
|
ensureReadmeFile(repoPoliciesDir(worktree), REPO_LOCAL_POLICIES_README);
|
|
@@ -12828,12 +12897,12 @@ function shouldRegisterWorkflowProductManager(options = {}, worktree = process.c
|
|
|
12828
12897
|
}
|
|
12829
12898
|
function isClickUpDerivedWorktreeSibling(candidate, basePath) {
|
|
12830
12899
|
if (typeof candidate !== "string" || typeof basePath !== "string" || !candidate.trim() || !basePath.trim()) return false;
|
|
12831
|
-
const resolvedCandidate =
|
|
12832
|
-
const resolvedBase =
|
|
12833
|
-
const baseParent =
|
|
12834
|
-
if (
|
|
12835
|
-
const baseName =
|
|
12836
|
-
const candidateName =
|
|
12900
|
+
const resolvedCandidate = path6.resolve(candidate);
|
|
12901
|
+
const resolvedBase = path6.resolve(basePath);
|
|
12902
|
+
const baseParent = path6.dirname(resolvedBase);
|
|
12903
|
+
if (path6.dirname(resolvedCandidate) !== baseParent) return false;
|
|
12904
|
+
const baseName = path6.basename(resolvedBase);
|
|
12905
|
+
const candidateName = path6.basename(resolvedCandidate);
|
|
12837
12906
|
if (!candidateName.startsWith(`${baseName}-`)) return false;
|
|
12838
12907
|
const branchSlug = candidateName.slice(baseName.length + 1);
|
|
12839
12908
|
const parts = branchSlug.split("-").filter(Boolean);
|
|
@@ -12845,7 +12914,7 @@ function isClickUpDerivedWorktreeSibling(candidate, basePath) {
|
|
|
12845
12914
|
if (!candidateStat.isDirectory() || candidateStat.isSymbolicLink()) return false;
|
|
12846
12915
|
const realCandidate = fs5.realpathSync.native(resolvedCandidate);
|
|
12847
12916
|
const realBaseParent = fs5.realpathSync.native(baseParent);
|
|
12848
|
-
return
|
|
12917
|
+
return path6.dirname(realCandidate) === realBaseParent && path6.basename(realCandidate) === candidateName;
|
|
12849
12918
|
} catch {
|
|
12850
12919
|
return false;
|
|
12851
12920
|
}
|
|
@@ -12853,15 +12922,15 @@ function isClickUpDerivedWorktreeSibling(candidate, basePath) {
|
|
|
12853
12922
|
function resolveSessionToolDirectory({ requestedDirectory, context, pluginWorktree, clickUpWebhookValidation } = {}) {
|
|
12854
12923
|
const safe = safeWorktreeOrFailure(context, pluginWorktree);
|
|
12855
12924
|
if (!safe.ok) return { ok: false, error: safe.message };
|
|
12856
|
-
const requested = String(requestedDirectory || "").trim() ?
|
|
12925
|
+
const requested = String(requestedDirectory || "").trim() ? path6.resolve(safe.worktree, String(requestedDirectory).trim()) : safe.worktree;
|
|
12857
12926
|
if (!isSafeWritableDirectory(requested)) return { ok: false, error: `Directory is not a safe writable directory: ${requested}` };
|
|
12858
12927
|
if (isSameOrNestedPath(requested, safe.worktree)) return { ok: true, directory: requested, safeWorktree: safe.worktree, scope: "context_worktree" };
|
|
12859
12928
|
const clickUpBasePath = clickUpWebhookValidation?.complete === true && clickUpWebhookValidation?.ok !== false ? clickUpWebhookValidation.config?.basePath : "";
|
|
12860
12929
|
if (clickUpBasePath && isSameOrNestedPath(requested, clickUpBasePath)) {
|
|
12861
|
-
return { ok: true, directory: requested, safeWorktree: safe.worktree, scope: "clickup_base_path", clickupBasePath:
|
|
12930
|
+
return { ok: true, directory: requested, safeWorktree: safe.worktree, scope: "clickup_base_path", clickupBasePath: path6.resolve(clickUpBasePath) };
|
|
12862
12931
|
}
|
|
12863
12932
|
if (clickUpBasePath && isClickUpDerivedWorktreeSibling(requested, clickUpBasePath)) {
|
|
12864
|
-
return { ok: true, directory: requested, safeWorktree: safe.worktree, scope: "clickup_derived_worktree", clickupBasePath:
|
|
12933
|
+
return { ok: true, directory: requested, safeWorktree: safe.worktree, scope: "clickup_derived_worktree", clickupBasePath: path6.resolve(clickUpBasePath) };
|
|
12865
12934
|
}
|
|
12866
12935
|
return {
|
|
12867
12936
|
ok: false,
|
|
@@ -12895,8 +12964,8 @@ function buildOptimaAgents(repoCfg, operatingTeamMode, worktree, debugDir, optio
|
|
|
12895
12964
|
if (!enabled) continue;
|
|
12896
12965
|
}
|
|
12897
12966
|
const promptOptions = { preferCompactPromptDocs: repoCfg.features?.compact_prompt_docs !== false };
|
|
12898
|
-
const bundledDefinition = loadAgentDefinition(
|
|
12899
|
-
const repoDefinition = loadAgentDefinition(
|
|
12967
|
+
const bundledDefinition = loadAgentDefinition(path6.join(BUNDLE_AGENTS_DIR, file), worktree, promptOptions);
|
|
12968
|
+
const repoDefinition = loadAgentDefinition(path6.join(repoAgentDefinitions, file), worktree, promptOptions) || loadAgentDefinition(path6.join(legacyAgentsDir, file), worktree, promptOptions);
|
|
12900
12969
|
const activeDefinition = repoDefinition || bundledDefinition;
|
|
12901
12970
|
if (!activeDefinition) continue;
|
|
12902
12971
|
const { data } = activeDefinition;
|
|
@@ -12905,7 +12974,7 @@ function buildOptimaAgents(repoCfg, operatingTeamMode, worktree, debugDir, optio
|
|
|
12905
12974
|
if (modePromptFragment) finalPrompt = `${finalPrompt}
|
|
12906
12975
|
|
|
12907
12976
|
${modePromptFragment}`;
|
|
12908
|
-
const additionFragment = loadMarkdownFragment(
|
|
12977
|
+
const additionFragment = loadMarkdownFragment(path6.join(repoAgentAdditions, file), worktree);
|
|
12909
12978
|
if (additionFragment) {
|
|
12910
12979
|
finalPrompt = `${finalPrompt}
|
|
12911
12980
|
|
|
@@ -12958,7 +13027,7 @@ Use this Optima-provided fallback when the current task worktree lacks docs/core
|
|
|
12958
13027
|
}
|
|
12959
13028
|
ourAgents[id] = agentConfig;
|
|
12960
13029
|
if (repoCfg.features?.debug_dumps !== false) {
|
|
12961
|
-
const debugPath =
|
|
13030
|
+
const debugPath = path6.join(debugDir, `${id}.md`);
|
|
12962
13031
|
const { prompt, ...dumpConfig } = agentConfig;
|
|
12963
13032
|
const debugHeader = `---
|
|
12964
13033
|
${import_yaml3.default.stringify(dumpConfig).trim()}
|
|
@@ -13110,8 +13179,8 @@ async function OptimaPlugin(input = {}, pluginOptions = {}) {
|
|
|
13110
13179
|
migrateLegacyOptimaLayout(toolWorktree);
|
|
13111
13180
|
const cfgDir = optimaConfigDir(toolWorktree);
|
|
13112
13181
|
if (!fs5.existsSync(cfgDir)) fs5.mkdirSync(cfgDir, { recursive: true });
|
|
13113
|
-
const optimaTmplPath =
|
|
13114
|
-
const codemapTmplPath =
|
|
13182
|
+
const optimaTmplPath = path6.join(TEMPLATES_DIR, "optima.yaml.template");
|
|
13183
|
+
const codemapTmplPath = path6.join(TEMPLATES_DIR, "codemap.yml.template");
|
|
13115
13184
|
if (!fs5.existsSync(optimaTmplPath) || !fs5.existsSync(codemapTmplPath)) {
|
|
13116
13185
|
return "Error: Initialization templates not found in plugin.";
|
|
13117
13186
|
}
|
|
@@ -13233,14 +13302,14 @@ Restart or reload OpenCode manually if the newly scaffolded config or agents are
|
|
|
13233
13302
|
async execute(args, context) {
|
|
13234
13303
|
const safe = safeWorktreeOrFailure(context, worktree);
|
|
13235
13304
|
if (!safe.ok) return safe.message;
|
|
13236
|
-
const summaryPath =
|
|
13305
|
+
const summaryPath = path6.resolve(safe.worktree, args.summary_path || "");
|
|
13237
13306
|
if (!fs5.existsSync(summaryPath)) return `FAIL: summary_path not found: ${summaryPath}`;
|
|
13238
|
-
const taskPath = args.task_path ?
|
|
13307
|
+
const taskPath = args.task_path ? path6.resolve(safe.worktree, args.task_path) : "";
|
|
13239
13308
|
const payload = buildClickUpSummaryPayload({
|
|
13240
13309
|
summaryMarkdown: fs5.readFileSync(summaryPath, "utf8"),
|
|
13241
|
-
summaryPath:
|
|
13310
|
+
summaryPath: path6.relative(safe.worktree, summaryPath),
|
|
13242
13311
|
taskMarkdown: taskPath && fs5.existsSync(taskPath) ? fs5.readFileSync(taskPath, "utf8") : "",
|
|
13243
|
-
taskPath: taskPath ?
|
|
13312
|
+
taskPath: taskPath ? path6.relative(safe.worktree, taskPath) : "",
|
|
13244
13313
|
branch: args.branch,
|
|
13245
13314
|
worktree: args.worktree,
|
|
13246
13315
|
pr: args.pr
|
|
@@ -13319,12 +13388,12 @@ Restart or reload OpenCode manually if the newly scaffolded config or agents are
|
|
|
13319
13388
|
async execute(args, context) {
|
|
13320
13389
|
const safe = safeWorktreeOrFailure(context, worktree);
|
|
13321
13390
|
if (!safe.ok) return safe.message;
|
|
13322
|
-
const markdownPath =
|
|
13391
|
+
const markdownPath = path6.resolve(safe.worktree, args.markdown_path || "");
|
|
13323
13392
|
if (!fs5.existsSync(markdownPath)) return `FAIL: markdown_path not found: ${markdownPath}`;
|
|
13324
13393
|
const payload = buildClickUpCreateSubtasksPayload({
|
|
13325
13394
|
parentTaskId: args.parent_task_id,
|
|
13326
13395
|
markdown: fs5.readFileSync(markdownPath, "utf8"),
|
|
13327
|
-
sourcePath:
|
|
13396
|
+
sourcePath: path6.relative(safe.worktree, markdownPath),
|
|
13328
13397
|
parentBranch: args.parent_branch,
|
|
13329
13398
|
parentTaskType: args.parent_task_type || "Tarea",
|
|
13330
13399
|
apply: String(args.apply || "").toLowerCase() === "true"
|
|
@@ -13523,7 +13592,7 @@ Backfilled messages: ${backfilled}`;
|
|
|
13523
13592
|
if (!existing) {
|
|
13524
13593
|
return "FAIL: No active discussion exists for this session.";
|
|
13525
13594
|
}
|
|
13526
|
-
const discussionPath =
|
|
13595
|
+
const discussionPath = path6.join(toolWorktree, existing.transcriptPath);
|
|
13527
13596
|
setDiscussionStatus(discussionPath, "summarizing");
|
|
13528
13597
|
existing.status = "summarizing";
|
|
13529
13598
|
saveDiscussionRegistry(toolWorktree, toolRegistry);
|
|
@@ -13575,7 +13644,7 @@ Reason: ${err.message}`;
|
|
|
13575
13644
|
try {
|
|
13576
13645
|
const sessionResult = await client.session.create({
|
|
13577
13646
|
query: { directory: workflowDirectory },
|
|
13578
|
-
body: { title: `Workflow Run: ${
|
|
13647
|
+
body: { title: `Workflow Run: ${path6.basename(workflowTaskPath)}` }
|
|
13579
13648
|
});
|
|
13580
13649
|
const sessionId = sessionResult.data.id;
|
|
13581
13650
|
activeWorkflows.set(sessionId, { pmaSessionId, taskPath: workflowTaskPath, track: workflowTrack, directory: workflowDirectory });
|
|
@@ -13760,13 +13829,13 @@ function usage() {
|
|
|
13760
13829
|
}
|
|
13761
13830
|
function expandHome(inputPath) {
|
|
13762
13831
|
if (!inputPath || inputPath === "~") return os2.homedir();
|
|
13763
|
-
if (inputPath.startsWith("~/")) return
|
|
13832
|
+
if (inputPath.startsWith("~/")) return path7.join(os2.homedir(), inputPath.slice(2));
|
|
13764
13833
|
return inputPath;
|
|
13765
13834
|
}
|
|
13766
13835
|
function resolveOpenCodeDbPath(inputPath = null) {
|
|
13767
13836
|
const expanded = expandHome(inputPath || process.env.OPTIMA_OPENCODE_DB_PATH || DEFAULT_DB_PATH);
|
|
13768
13837
|
try {
|
|
13769
|
-
if (fs6.existsSync(expanded) && fs6.statSync(expanded).isDirectory()) return
|
|
13838
|
+
if (fs6.existsSync(expanded) && fs6.statSync(expanded).isDirectory()) return path7.join(expanded, "opencode.db");
|
|
13770
13839
|
} catch {
|
|
13771
13840
|
return expanded;
|
|
13772
13841
|
}
|
|
@@ -13830,8 +13899,8 @@ function extractOpenedPathValue(value) {
|
|
|
13830
13899
|
}
|
|
13831
13900
|
function normalizePathCandidate(candidate) {
|
|
13832
13901
|
const expanded = expandHome(candidate);
|
|
13833
|
-
if (!
|
|
13834
|
-
return
|
|
13902
|
+
if (!path7.isAbsolute(expanded)) return null;
|
|
13903
|
+
return path7.resolve(expanded);
|
|
13835
13904
|
}
|
|
13836
13905
|
function discoverOpenCodePaths(dbPath) {
|
|
13837
13906
|
const resolvedDb = resolveOpenCodeDbPath(dbPath);
|
|
@@ -13860,27 +13929,27 @@ function discoverOpenCodePaths(dbPath) {
|
|
|
13860
13929
|
function collectMarkdownOverridesFrom(baseDir) {
|
|
13861
13930
|
const files = [];
|
|
13862
13931
|
for (const dirName of OVERRIDE_DIRS) {
|
|
13863
|
-
const dirPath =
|
|
13932
|
+
const dirPath = path7.join(baseDir, dirName);
|
|
13864
13933
|
if (!fs6.existsSync(dirPath)) continue;
|
|
13865
13934
|
for (const entry of fs6.readdirSync(dirPath, { withFileTypes: true })) {
|
|
13866
13935
|
if (!entry.isFile()) continue;
|
|
13867
13936
|
if (!entry.name.endsWith(".md")) continue;
|
|
13868
13937
|
if (entry.name.toLowerCase() === "readme.md") continue;
|
|
13869
|
-
files.push(
|
|
13938
|
+
files.push(path7.join(dirPath, entry.name));
|
|
13870
13939
|
}
|
|
13871
13940
|
}
|
|
13872
13941
|
return files;
|
|
13873
13942
|
}
|
|
13874
13943
|
function collectOverrideFiles(worktree) {
|
|
13875
|
-
return collectMarkdownOverridesFrom(
|
|
13944
|
+
return collectMarkdownOverridesFrom(path7.join(worktree, ".optima")).sort();
|
|
13876
13945
|
}
|
|
13877
13946
|
function collectPlannedOverrideFiles(worktree) {
|
|
13878
13947
|
return [
|
|
13879
13948
|
...collectOverrideFiles(worktree),
|
|
13880
|
-
...collectMarkdownOverridesFrom(
|
|
13881
|
-
...collectMarkdownOverridesFrom(
|
|
13882
|
-
...collectMarkdownOverridesFrom(
|
|
13883
|
-
...collectMarkdownOverridesFrom(
|
|
13949
|
+
...collectMarkdownOverridesFrom(path7.join(worktree, ".staticeng")),
|
|
13950
|
+
...collectMarkdownOverridesFrom(path7.join(worktree, ".orbita")),
|
|
13951
|
+
...collectMarkdownOverridesFrom(path7.join(worktree, ".nomadwork")),
|
|
13952
|
+
...collectMarkdownOverridesFrom(path7.join(worktree, ".nomadworks"))
|
|
13884
13953
|
].sort();
|
|
13885
13954
|
}
|
|
13886
13955
|
var CRC_TABLE = (() => {
|
|
@@ -13913,14 +13982,14 @@ function writeUInt16LE(value) {
|
|
|
13913
13982
|
return buffer;
|
|
13914
13983
|
}
|
|
13915
13984
|
function createZipBackup(files, backupPath) {
|
|
13916
|
-
fs6.mkdirSync(
|
|
13985
|
+
fs6.mkdirSync(path7.dirname(backupPath), { recursive: true });
|
|
13917
13986
|
const localParts = [];
|
|
13918
13987
|
const centralParts = [];
|
|
13919
13988
|
let offset = 0;
|
|
13920
13989
|
const now = dosTimeDate();
|
|
13921
13990
|
for (const filePath of files) {
|
|
13922
13991
|
const data = fs6.readFileSync(filePath);
|
|
13923
|
-
const name =
|
|
13992
|
+
const name = path7.resolve(filePath).replace(/^\//, "").split(path7.sep).join("/");
|
|
13924
13993
|
const nameBuffer = Buffer.from(name, "utf8");
|
|
13925
13994
|
const crc = crc32(data);
|
|
13926
13995
|
const local = Buffer.concat([
|
|
@@ -13982,15 +14051,15 @@ function validationStatus(result) {
|
|
|
13982
14051
|
return result.ok ? "passed" : "failed";
|
|
13983
14052
|
}
|
|
13984
14053
|
function hasLegacyMarker(worktree) {
|
|
13985
|
-
return fs6.existsSync(
|
|
14054
|
+
return fs6.existsSync(path7.join(worktree, ".staticeng")) || fs6.existsSync(path7.join(worktree, ".orbita")) || fs6.existsSync(path7.join(worktree, ".nomadwork")) || fs6.existsSync(path7.join(worktree, ".nomadworks"));
|
|
13986
14055
|
}
|
|
13987
14056
|
function rootOptimaArtifacts(worktree) {
|
|
13988
14057
|
const artifacts = [
|
|
13989
|
-
["tasks/",
|
|
13990
|
-
["evidences/",
|
|
13991
|
-
["docs/scrs/",
|
|
13992
|
-
["codemap.yml",
|
|
13993
|
-
["codemap.yaml",
|
|
14058
|
+
["tasks/", path7.join(worktree, "tasks")],
|
|
14059
|
+
["evidences/", path7.join(worktree, "evidences")],
|
|
14060
|
+
["docs/scrs/", path7.join(worktree, "docs", "scrs")],
|
|
14061
|
+
["codemap.yml", path7.join(worktree, "codemap.yml")],
|
|
14062
|
+
["codemap.yaml", path7.join(worktree, "codemap.yaml")]
|
|
13994
14063
|
];
|
|
13995
14064
|
return artifacts.map(([display, artifactPath]) => ({ display, path: artifactPath })).filter((item) => fs6.existsSync(item.path));
|
|
13996
14065
|
}
|
|
@@ -14018,7 +14087,7 @@ function planOptimaMigration(worktree, dryRun) {
|
|
|
14018
14087
|
...overrides.map((file) => ({
|
|
14019
14088
|
category: "override",
|
|
14020
14089
|
action: dryRun ? "would_remove_after_backup" : "removed_after_backup",
|
|
14021
|
-
path:
|
|
14090
|
+
path: path7.relative(worktree, file).split(path7.sep).join("/"),
|
|
14022
14091
|
detail: "Remove implicit agent/policy override after host-level backup."
|
|
14023
14092
|
}))
|
|
14024
14093
|
],
|
|
@@ -14066,7 +14135,7 @@ async function sanitizeHost(options = {}) {
|
|
|
14066
14135
|
const overrides = repoStates.flatMap((state) => state.overrideFiles.map((file) => ({ repo: state.repo, file })));
|
|
14067
14136
|
report.totals.overrideFiles = overrides.length;
|
|
14068
14137
|
if (!dryRun && overrides.length > 0) {
|
|
14069
|
-
const backupPath =
|
|
14138
|
+
const backupPath = path7.join(os2.homedir(), BACKUP_DIRNAME, `${timestamp()}.zip`);
|
|
14070
14139
|
try {
|
|
14071
14140
|
createZipBackup(overrides.map((item) => item.file), backupPath);
|
|
14072
14141
|
report.backupPath = backupPath;
|
|
@@ -14095,7 +14164,7 @@ async function sanitizeHost(options = {}) {
|
|
|
14095
14164
|
repairActions: state.plan.actions.length,
|
|
14096
14165
|
repairSkipped: state.plan.skippedRepair === true,
|
|
14097
14166
|
overrideFiles: state.overrideFiles.length,
|
|
14098
|
-
overridePaths: state.overrideFiles.map((file) =>
|
|
14167
|
+
overridePaths: state.overrideFiles.map((file) => path7.relative(state.repo, file).split(path7.sep).join("/")),
|
|
14099
14168
|
validation: validation ? validationStatus(validation) : "skipped",
|
|
14100
14169
|
unresolved: state.plan.unresolved
|
|
14101
14170
|
});
|