@defend-tech/opencode-optima 0.1.76 → 0.1.77

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.
@@ -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, path8) {
113
- const ctrl = callVisitor(key, node, visitor, path8);
112
+ function visit_(key, node, visitor, path10) {
113
+ const ctrl = callVisitor(key, node, visitor, path10);
114
114
  if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
115
- replaceNode(key, path8, ctrl);
116
- return visit_(key, ctrl, visitor, path8);
115
+ replaceNode(key, path10, ctrl);
116
+ return visit_(key, ctrl, visitor, path10);
117
117
  }
118
118
  if (typeof ctrl !== "symbol") {
119
119
  if (identity.isCollection(node)) {
120
- path8 = Object.freeze(path8.concat(node));
120
+ path10 = Object.freeze(path10.concat(node));
121
121
  for (let i = 0; i < node.items.length; ++i) {
122
- const ci = visit_(i, node.items[i], visitor, path8);
122
+ const ci = visit_(i, node.items[i], visitor, path10);
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
- path8 = Object.freeze(path8.concat(node));
134
- const ck = visit_("key", node.key, visitor, path8);
133
+ path10 = Object.freeze(path10.concat(node));
134
+ const ck = visit_("key", node.key, visitor, path10);
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, path8);
139
+ const cv = visit_("value", node.value, visitor, path10);
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, path8) {
161
- const ctrl = await callVisitor(key, node, visitor, path8);
160
+ async function visitAsync_(key, node, visitor, path10) {
161
+ const ctrl = await callVisitor(key, node, visitor, path10);
162
162
  if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
163
- replaceNode(key, path8, ctrl);
164
- return visitAsync_(key, ctrl, visitor, path8);
163
+ replaceNode(key, path10, ctrl);
164
+ return visitAsync_(key, ctrl, visitor, path10);
165
165
  }
166
166
  if (typeof ctrl !== "symbol") {
167
167
  if (identity.isCollection(node)) {
168
- path8 = Object.freeze(path8.concat(node));
168
+ path10 = Object.freeze(path10.concat(node));
169
169
  for (let i = 0; i < node.items.length; ++i) {
170
- const ci = await visitAsync_(i, node.items[i], visitor, path8);
170
+ const ci = await visitAsync_(i, node.items[i], visitor, path10);
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
- path8 = Object.freeze(path8.concat(node));
182
- const ck = await visitAsync_("key", node.key, visitor, path8);
181
+ path10 = Object.freeze(path10.concat(node));
182
+ const ck = await visitAsync_("key", node.key, visitor, path10);
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, path8);
187
+ const cv = await visitAsync_("value", node.value, visitor, path10);
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, path8) {
214
+ function callVisitor(key, node, visitor, path10) {
215
215
  if (typeof visitor === "function")
216
- return visitor(key, node, path8);
216
+ return visitor(key, node, path10);
217
217
  if (identity.isMap(node))
218
- return visitor.Map?.(key, node, path8);
218
+ return visitor.Map?.(key, node, path10);
219
219
  if (identity.isSeq(node))
220
- return visitor.Seq?.(key, node, path8);
220
+ return visitor.Seq?.(key, node, path10);
221
221
  if (identity.isPair(node))
222
- return visitor.Pair?.(key, node, path8);
222
+ return visitor.Pair?.(key, node, path10);
223
223
  if (identity.isScalar(node))
224
- return visitor.Scalar?.(key, node, path8);
224
+ return visitor.Scalar?.(key, node, path10);
225
225
  if (identity.isAlias(node))
226
- return visitor.Alias?.(key, node, path8);
226
+ return visitor.Alias?.(key, node, path10);
227
227
  return void 0;
228
228
  }
229
- function replaceNode(key, path8, node) {
230
- const parent = path8[path8.length - 1];
229
+ function replaceNode(key, path10, node) {
230
+ const parent = path10[path10.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, path8, value) {
838
+ function collectionFromPath(schema, path10, value) {
839
839
  let v = value;
840
- for (let i = path8.length - 1; i >= 0; --i) {
841
- const k = path8[i];
840
+ for (let i = path10.length - 1; i >= 0; --i) {
841
+ const k = path10[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 = (path8) => path8 == null || typeof path8 === "object" && !!path8[Symbol.iterator]().next().done;
860
+ var isEmptyPath = (path10) => path10 == null || typeof path10 === "object" && !!path10[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(path8, value) {
891
- if (isEmptyPath(path8))
890
+ addIn(path10, value) {
891
+ if (isEmptyPath(path10))
892
892
  this.add(value);
893
893
  else {
894
- const [key, ...rest] = path8;
894
+ const [key, ...rest] = path10;
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(path8) {
909
- const [key, ...rest] = path8;
908
+ deleteIn(path10) {
909
+ const [key, ...rest] = path10;
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(path8, keepScalar) {
924
- const [key, ...rest] = path8;
923
+ getIn(path10, keepScalar) {
924
+ const [key, ...rest] = path10;
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(path8) {
943
- const [key, ...rest] = path8;
942
+ hasIn(path10) {
943
+ const [key, ...rest] = path10;
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(path8, value) {
954
- const [key, ...rest] = path8;
953
+ setIn(path10, value) {
954
+ const [key, ...rest] = path10;
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(path8, value) {
3458
+ addIn(path10, value) {
3459
3459
  if (assertCollection(this.contents))
3460
- this.contents.addIn(path8, value);
3460
+ this.contents.addIn(path10, 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(path8) {
3536
- if (Collection.isEmptyPath(path8)) {
3535
+ deleteIn(path10) {
3536
+ if (Collection.isEmptyPath(path10)) {
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(path8) : false;
3542
+ return assertCollection(this.contents) ? this.contents.deleteIn(path10) : 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(path8, keepScalar) {
3558
- if (Collection.isEmptyPath(path8))
3557
+ getIn(path10, keepScalar) {
3558
+ if (Collection.isEmptyPath(path10))
3559
3559
  return !keepScalar && identity.isScalar(this.contents) ? this.contents.value : this.contents;
3560
- return identity.isCollection(this.contents) ? this.contents.getIn(path8, keepScalar) : void 0;
3560
+ return identity.isCollection(this.contents) ? this.contents.getIn(path10, 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(path8) {
3572
- if (Collection.isEmptyPath(path8))
3571
+ hasIn(path10) {
3572
+ if (Collection.isEmptyPath(path10))
3573
3573
  return this.contents !== void 0;
3574
- return identity.isCollection(this.contents) ? this.contents.hasIn(path8) : false;
3574
+ return identity.isCollection(this.contents) ? this.contents.hasIn(path10) : 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(path8, value) {
3592
- if (Collection.isEmptyPath(path8)) {
3591
+ setIn(path10, value) {
3592
+ if (Collection.isEmptyPath(path10)) {
3593
3593
  this.contents = value;
3594
3594
  } else if (this.contents == null) {
3595
- this.contents = Collection.collectionFromPath(this.schema, Array.from(path8), value);
3595
+ this.contents = Collection.collectionFromPath(this.schema, Array.from(path10), value);
3596
3596
  } else if (assertCollection(this.contents)) {
3597
- this.contents.setIn(path8, value);
3597
+ this.contents.setIn(path10, 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, path8) => {
5549
+ visit.itemAtPath = (cst, path10) => {
5550
5550
  let item = cst;
5551
- for (const [field, index] of path8) {
5551
+ for (const [field, index] of path10) {
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, path8) => {
5561
- const parent = visit.itemAtPath(cst, path8.slice(0, -1));
5562
- const field = path8[path8.length - 1][0];
5560
+ visit.parentCollection = (cst, path10) => {
5561
+ const parent = visit.itemAtPath(cst, path10.slice(0, -1));
5562
+ const field = path10[path10.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(path8, item, visitor) {
5569
- let ctrl = visitor(item, path8);
5568
+ function _visit(path10, item, visitor) {
5569
+ let ctrl = visitor(item, path10);
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(path8.concat([[field, i]])), token.items[i], visitor);
5576
+ const ci = _visit(Object.freeze(path10.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, path8);
5587
+ ctrl = ctrl(item, path10);
5588
5588
  }
5589
5589
  }
5590
- return typeof ctrl === "function" ? ctrl(item, path8) : ctrl;
5590
+ return typeof ctrl === "function" ? ctrl(item, path10) : ctrl;
5591
5591
  }
5592
5592
  exports.visit = visit;
5593
5593
  }
@@ -6872,14 +6872,14 @@ var require_parser = __commonJS({
6872
6872
  case "scalar":
6873
6873
  case "single-quoted-scalar":
6874
6874
  case "double-quoted-scalar": {
6875
- const fs7 = this.flowScalar(this.type);
6875
+ const fs10 = this.flowScalar(this.type);
6876
6876
  if (atNextItem || it.value) {
6877
- map.items.push({ start, key: fs7, sep: [] });
6877
+ map.items.push({ start, key: fs10, sep: [] });
6878
6878
  this.onKeyLine = true;
6879
6879
  } else if (it.sep) {
6880
- this.stack.push(fs7);
6880
+ this.stack.push(fs10);
6881
6881
  } else {
6882
- Object.assign(it, { key: fs7, sep: [] });
6882
+ Object.assign(it, { key: fs10, sep: [] });
6883
6883
  this.onKeyLine = true;
6884
6884
  }
6885
6885
  return;
@@ -7007,13 +7007,13 @@ var require_parser = __commonJS({
7007
7007
  case "scalar":
7008
7008
  case "single-quoted-scalar":
7009
7009
  case "double-quoted-scalar": {
7010
- const fs7 = this.flowScalar(this.type);
7010
+ const fs10 = this.flowScalar(this.type);
7011
7011
  if (!it || it.value)
7012
- fc.items.push({ start: [], key: fs7, sep: [] });
7012
+ fc.items.push({ start: [], key: fs10, sep: [] });
7013
7013
  else if (it.sep)
7014
- this.stack.push(fs7);
7014
+ this.stack.push(fs10);
7015
7015
  else
7016
- Object.assign(it, { key: fs7, sep: [] });
7016
+ Object.assign(it, { key: fs10, sep: [] });
7017
7017
  return;
7018
7018
  }
7019
7019
  case "flow-map-end":
@@ -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 = (path8, originalPath, doThrow) => {
7555
- if (!isString(path8)) {
7554
+ var checkPath = (path10, originalPath, doThrow) => {
7555
+ if (!isString(path10)) {
7556
7556
  return doThrow(
7557
7557
  `path must be a string, but got \`${originalPath}\``,
7558
7558
  TypeError
7559
7559
  );
7560
7560
  }
7561
- if (!path8) {
7561
+ if (!path10) {
7562
7562
  return doThrow(`path must not be empty`, TypeError);
7563
7563
  }
7564
- if (checkPath.isNotRelative(path8)) {
7564
+ if (checkPath.isNotRelative(path10)) {
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 = (path8) => REGEX_TEST_INVALID_PATH.test(path8);
7573
+ var isNotRelative = (path10) => REGEX_TEST_INVALID_PATH.test(path10);
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(path8, checkUnignored) {
7632
+ _testOne(path10, 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(path8);
7640
+ const matched = rule.regex.test(path10);
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 path8 = originalPath && checkPath.convert(originalPath);
7653
+ const path10 = originalPath && checkPath.convert(originalPath);
7654
7654
  checkPath(
7655
- path8,
7655
+ path10,
7656
7656
  originalPath,
7657
7657
  this._allowRelativePaths ? RETURN_FALSE : throwError
7658
7658
  );
7659
- return this._t(path8, cache, checkUnignored, slices);
7659
+ return this._t(path10, cache, checkUnignored, slices);
7660
7660
  }
7661
- _t(path8, cache, checkUnignored, slices) {
7662
- if (path8 in cache) {
7663
- return cache[path8];
7661
+ _t(path10, cache, checkUnignored, slices) {
7662
+ if (path10 in cache) {
7663
+ return cache[path10];
7664
7664
  }
7665
7665
  if (!slices) {
7666
- slices = path8.split(SLASH);
7666
+ slices = path10.split(SLASH);
7667
7667
  }
7668
7668
  slices.pop();
7669
7669
  if (!slices.length) {
7670
- return cache[path8] = this._testOne(path8, checkUnignored);
7670
+ return cache[path10] = this._testOne(path10, 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[path8] = parent.ignored ? parent : this._testOne(path8, checkUnignored);
7678
+ return cache[path10] = parent.ignored ? parent : this._testOne(path10, checkUnignored);
7679
7679
  }
7680
- ignores(path8) {
7681
- return this._test(path8, this._ignoreCache, false).ignored;
7680
+ ignores(path10) {
7681
+ return this._test(path10, this._ignoreCache, false).ignored;
7682
7682
  }
7683
7683
  createFilter() {
7684
- return (path8) => !this.ignores(path8);
7684
+ return (path10) => !this.ignores(path10);
7685
7685
  }
7686
7686
  filter(paths) {
7687
7687
  return makeArray(paths).filter(this.createFilter());
7688
7688
  }
7689
7689
  // @returns {TestResult}
7690
- test(path8) {
7691
- return this._test(path8, this._testCache, true);
7690
+ test(path10) {
7691
+ return this._test(path10, this._testCache, true);
7692
7692
  }
7693
7693
  };
7694
7694
  var factory = (options) => new Ignore(options);
7695
- var isPathValid = (path8) => checkPath(path8 && checkPath.convert(path8), path8, RETURN_FALSE);
7695
+ var isPathValid = (path10) => checkPath(path10 && checkPath.convert(path10), path10, RETURN_FALSE);
7696
7696
  factory.isPathValid = isPathValid;
7697
7697
  factory.default = factory;
7698
7698
  module.exports = factory;
@@ -7703,27 +7703,59 @@ 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 = (path8) => REGIX_IS_WINDOWS_PATH_ABSOLUTE.test(path8) || isNotRelative(path8);
7706
+ checkPath.isNotRelative = (path10) => REGIX_IS_WINDOWS_PATH_ABSOLUTE.test(path10) || isNotRelative(path10);
7707
7707
  }
7708
7708
  }
7709
7709
  });
7710
7710
 
7711
7711
  // src/sanitize_cli.js
7712
- import fs6 from "node:fs";
7713
- import os2 from "node:os";
7714
- import path7 from "node:path";
7712
+ import fs9 from "node:fs";
7713
+ import os3 from "node:os";
7714
+ import path9 from "node:path";
7715
7715
  import { execFileSync as execFileSync2, spawnSync } from "node:child_process";
7716
7716
 
7717
7717
  // src/index.js
7718
7718
  var import_yaml3 = __toESM(require_dist(), 1);
7719
7719
  var import_ignore3 = __toESM(require_ignore(), 1);
7720
- import crypto from "node:crypto";
7721
- import fs5 from "node:fs";
7720
+ import crypto2 from "node:crypto";
7721
+ import fs8 from "node:fs";
7722
7722
  import http from "node:http";
7723
- import os from "node:os";
7724
- import path6 from "node:path";
7723
+ import os2 from "node:os";
7724
+ import path8 from "node:path";
7725
7725
  import { tool } from "@opencode-ai/plugin/tool";
7726
7726
 
7727
+ // src/clickup_comments.js
7728
+ var COMMENT_TEXT_KEYS = /* @__PURE__ */ new Set(["comment", "body", "description"]);
7729
+ function normalizeClickUpMarkdown(value = "") {
7730
+ return String(value ?? "").replace(/\\r\\n/g, "\n").replace(/\\n/g, "\n").replace(/\r\n/g, "\n").replace(/\r/g, "\n").split("\n").map((line) => line.trimEnd()).join("\n").replace(/\n{3,}/g, "\n\n").trim();
7731
+ }
7732
+ function formatClickUpStatusComment({ title = "", summary = "", sections = [], context = [] } = {}) {
7733
+ const lines = [];
7734
+ const heading = normalizeClickUpMarkdown(title);
7735
+ if (heading) lines.push(`## ${heading}`, "");
7736
+ const intro = normalizeClickUpMarkdown(summary);
7737
+ if (intro) lines.push(intro, "");
7738
+ for (const section of sections) {
7739
+ const sectionTitle = normalizeClickUpMarkdown(section?.title);
7740
+ const sectionBody = normalizeClickUpMarkdown(section?.body);
7741
+ if (!sectionTitle || !sectionBody) continue;
7742
+ lines.push(`### ${sectionTitle}`, sectionBody, "");
7743
+ }
7744
+ const contextLines = context.map(normalizeClickUpMarkdown).filter(Boolean);
7745
+ if (contextLines.length > 0) lines.push("### Context", contextLines.map((item) => item.startsWith("- ") ? item : `- ${item}`).join("\n"));
7746
+ return normalizeClickUpMarkdown(lines.join("\n"));
7747
+ }
7748
+ function normalizeClickUpPayloadComments(value) {
7749
+ if (Array.isArray(value)) return value.map(normalizeClickUpPayloadComments);
7750
+ if (!value || typeof value !== "object") return value;
7751
+ return Object.fromEntries(
7752
+ Object.entries(value).map(([key, entry]) => [
7753
+ key,
7754
+ COMMENT_TEXT_KEYS.has(key) && typeof entry === "string" ? normalizeClickUpMarkdown(entry) : normalizeClickUpPayloadComments(entry)
7755
+ ])
7756
+ );
7757
+ }
7758
+
7727
7759
  // src/git_utils.js
7728
7760
  import fs from "node:fs";
7729
7761
  import path from "node:path";
@@ -7802,224 +7834,691 @@ function stageGitAwareMerge(sourcePath, destinationPath, gitState) {
7802
7834
  }
7803
7835
  }
7804
7836
 
7805
- // src/include_resolver.js
7837
+ // src/github.js
7838
+ import crypto from "node:crypto";
7839
+ import fs3 from "node:fs";
7840
+ import path3 from "node:path";
7841
+
7842
+ // src/secrets.js
7806
7843
  import fs2 from "node:fs";
7844
+ import os from "node:os";
7807
7845
  import path2 from "node:path";
7808
- function compactPromptPath(filePath) {
7809
- if (!filePath.endsWith(".md") || filePath.endsWith(".prompt.md")) return null;
7810
- return filePath.replace(/\.md$/, ".prompt.md");
7811
- }
7812
- function isSameOrNestedPath(candidate, root) {
7813
- if (typeof candidate !== "string" || typeof root !== "string" || !candidate.trim() || !root.trim()) return false;
7814
- const resolvedCandidate = path2.resolve(candidate);
7815
- const resolvedRoot = path2.resolve(root);
7816
- const relative = path2.relative(resolvedRoot, resolvedCandidate);
7817
- return relative === "" || !!relative && !relative.startsWith("..") && !path2.isAbsolute(relative);
7818
- }
7819
- function resolveWithin(baseDir, relativePath) {
7820
- if (!relativePath) return null;
7821
- if (path2.isAbsolute(relativePath)) return null;
7822
- const resolved = path2.resolve(baseDir, relativePath);
7823
- return isSameOrNestedPath(resolved, baseDir) ? resolved : null;
7824
- }
7825
- function withCompactPreference(paths, options = {}) {
7826
- if (!options.preferCompactPromptDocs) return paths;
7827
- const compactPaths = paths.map((filePath) => filePath ? compactPromptPath(filePath) : null).filter(Boolean);
7828
- return [...compactPaths, ...paths];
7846
+ function expandHomePath(value = "") {
7847
+ const input = String(value || "").trim();
7848
+ if (input === "~") return os.homedir();
7849
+ if (input.startsWith("~/")) return path2.join(os.homedir(), input.slice(2));
7850
+ return input;
7829
7851
  }
7830
- function resolveIncludeFile(includeRef, repoRoot, bundleRoot, options = {}) {
7831
- const trimmed = String(includeRef || "").trim();
7832
- const scopedMatch = trimmed.match(/^([a-z]+):(.*)$/i);
7833
- const scope = scopedMatch?.[1]?.toLowerCase();
7834
- const target = scopedMatch ? scopedMatch[2].trim() : trimmed;
7835
- const optimaRoot = options.optimaRoot || path2.join(repoRoot, ".optima");
7836
- const repoPolicyRoot = options.repoPolicyRoot || path2.join(optimaRoot, "policies");
7837
- const bundlePolicyRoot = options.bundlePolicyRoot || path2.join(bundleRoot, "assets", "policies");
7838
- if (scope === "plugin") {
7839
- for (const filePath of withCompactPreference([resolveWithin(bundleRoot, target)], options)) {
7840
- if (filePath && fs2.existsSync(filePath)) return filePath;
7841
- }
7842
- return null;
7843
- }
7844
- if (scope === "repo") {
7845
- for (const filePath of withCompactPreference([resolveWithin(optimaRoot, target)], options)) {
7846
- if (filePath && fs2.existsSync(filePath)) return filePath;
7847
- }
7848
- return null;
7849
- }
7850
- if (scope === "policy") {
7851
- const candidates2 = withCompactPreference([
7852
- resolveWithin(repoPolicyRoot, target),
7853
- resolveWithin(bundlePolicyRoot, target)
7854
- ], options);
7855
- for (const filePath of candidates2) {
7856
- if (filePath && fs2.existsSync(filePath)) return filePath;
7852
+ function resolveSecretReference(value = "") {
7853
+ const raw = String(value || "").trim();
7854
+ const envMatch = raw.match(/^\{env:([A-Za-z_][A-Za-z0-9_]*)\}$/);
7855
+ if (envMatch) return process.env[envMatch[1]] || "";
7856
+ const fileMatch = raw.match(/^\{file:(.+)\}$/);
7857
+ if (fileMatch) {
7858
+ try {
7859
+ return fs2.readFileSync(expandHomePath(fileMatch[1]), "utf8").trim();
7860
+ } catch {
7861
+ return "";
7857
7862
  }
7858
- return null;
7859
- }
7860
- const candidates = withCompactPreference([
7861
- resolveWithin(repoRoot, target),
7862
- resolveWithin(bundleRoot, target)
7863
- ], options);
7864
- for (const filePath of candidates) {
7865
- if (filePath && fs2.existsSync(filePath)) return filePath;
7866
7863
  }
7867
- return null;
7864
+ return raw;
7868
7865
  }
7869
- function resolveIncludes(text, repoRoot, bundleRoot, options = {}) {
7870
- const includeDepth = Number(options.includeDepth || 0);
7871
- const maxIncludeDepth = Number(options.maxIncludeDepth || 20);
7872
- if (includeDepth > maxIncludeDepth) {
7873
- return "\n\n# ERROR: Include recursion limit exceeded.\n\n";
7874
- }
7875
- const includeRegex = /<include:(.*?)>/g;
7876
- return String(text || "").replace(includeRegex, (match, includeRef) => {
7877
- const filePath = resolveIncludeFile(includeRef, repoRoot, bundleRoot, options);
7878
- if (!filePath) {
7879
- console.warn(`[Optima] Include file not found: ${includeRef}`);
7880
- return `
7881
7866
 
7882
- # ERROR: Include file not found: ${includeRef}
7883
-
7884
- `;
7885
- }
7886
- const content = fs2.readFileSync(filePath, "utf8");
7887
- return resolveIncludes(content, repoRoot, bundleRoot, { ...options, includeDepth: includeDepth + 1, maxIncludeDepth });
7888
- });
7867
+ // src/github.js
7868
+ function base64UrlJson(value) {
7869
+ return Buffer.from(JSON.stringify(value)).toString("base64url");
7889
7870
  }
7890
-
7891
- // src/repair.js
7892
- var import_yaml = __toESM(require_dist(), 1);
7893
- var import_ignore = __toESM(require_ignore(), 1);
7894
- import fs3 from "node:fs";
7895
- import path3 from "node:path";
7896
- var CODEMAP_SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([
7897
- ".js",
7898
- ".ts",
7899
- ".tsx",
7900
- ".jsx",
7901
- ".dart",
7902
- ".py",
7903
- ".go",
7904
- ".rs",
7905
- ".java",
7906
- ".c",
7907
- ".cpp",
7908
- ".cs",
7909
- ".php",
7910
- ".rb",
7911
- ".swift",
7912
- ".kt",
7913
- ".m",
7914
- ".sh",
7915
- ".sql",
7916
- ".yaml",
7917
- ".yml",
7918
- ".json",
7919
- ".md"
7920
- ]);
7921
- var LEGACY_OPERATIONAL_ROOTS = /* @__PURE__ */ new Set([
7922
- "tasks",
7923
- "evidences",
7924
- ".orbita",
7925
- ".staticeng",
7926
- ".nomadworks",
7927
- ".nomadwork",
7928
- "nomadworks",
7929
- ".codenomad"
7930
- ]);
7931
- var OPTIMA_OPERATIONAL_FOLDERS = [".optima", "templates", "dist"];
7932
- function relPath(worktree, targetPath) {
7933
- return path3.relative(worktree, targetPath).split(path3.sep).join("/") || ".";
7871
+ function resolveGitHubAppPrivateKey(app = {}) {
7872
+ const direct = resolveSecretReference(app.privateKey || "");
7873
+ if (direct) return direct.replace(/\\n/g, "\n");
7874
+ const file = expandHomePath(app.privateKeyFile || "");
7875
+ if (!file) return "";
7876
+ try {
7877
+ return fs3.readFileSync(file, "utf8").trim().replace(/\\n/g, "\n");
7878
+ } catch {
7879
+ return "";
7880
+ }
7934
7881
  }
7935
- function normalizeCodemapRelPath(relPathValue) {
7936
- return path3.normalize(relPathValue).replace(/\\/g, "/").replace(/\/$/, "");
7882
+ function createGitHubAppJwt({ appId, privateKey, now = () => /* @__PURE__ */ new Date() } = {}) {
7883
+ const key = String(privateKey || "").trim();
7884
+ const issuer = String(appId || "").trim();
7885
+ if (!issuer || !key) throw new Error("GitHub App app_id and private key are required");
7886
+ const nowSeconds = Math.floor(now().getTime() / 1e3);
7887
+ const header = base64UrlJson({ alg: "RS256", typ: "JWT" });
7888
+ const payload = base64UrlJson({ iat: nowSeconds - 60, exp: nowSeconds + 540, iss: issuer });
7889
+ const unsigned = `${header}.${payload}`;
7890
+ const signature = crypto.createSign("RSA-SHA256").update(unsigned).end().sign(key, "base64url");
7891
+ return `${unsigned}.${signature}`;
7937
7892
  }
7938
- function firstPathSegment(relPathValue) {
7939
- return normalizeCodemapRelPath(relPathValue).split("/").filter(Boolean)[0] || "";
7893
+ function encodeGitHubPathSegment(value) {
7894
+ return encodeURIComponent(String(value || ""));
7940
7895
  }
7941
- function isOperationalRelPath(relPathValue) {
7942
- if (!relPathValue) return false;
7943
- const normalized = normalizeCodemapRelPath(relPathValue);
7944
- const firstSegment = firstPathSegment(normalized);
7945
- if (LEGACY_OPERATIONAL_ROOTS.has(firstSegment)) return true;
7946
- return OPTIMA_OPERATIONAL_FOLDERS.some((folder) => normalized === folder || normalized.startsWith(`${folder}/`));
7896
+ function encodeGitHubBranchRef(branch = "") {
7897
+ return String(branch || "").split("/").map(encodeGitHubPathSegment).join("/");
7947
7898
  }
7948
- function isHiddenTree(relPathValue) {
7949
- if (!relPathValue) return false;
7950
- return normalizeCodemapRelPath(relPathValue).split("/").some((part) => part.startsWith("."));
7899
+ function parseNullSeparatedGitOutput(output = "") {
7900
+ return String(output || "").split("\0").map((item) => item.trim()).filter(Boolean);
7951
7901
  }
7952
- function loadGitIgnoreMatcher(worktree) {
7953
- const ig = (0, import_ignore.default)();
7954
- ig.add(".git");
7955
- const gitignorePath = path3.join(worktree, ".gitignore");
7956
- if (fs3.existsSync(gitignorePath)) ig.add(fs3.readFileSync(gitignorePath, "utf8"));
7957
- return ig;
7902
+ function listWorktreeChangedPaths(worktree, runGitFn = runGit) {
7903
+ const tracked = parseNullSeparatedGitOutput(runGitFn(worktree, ["diff", "--name-only", "-z", "HEAD", "--"]));
7904
+ const untracked = parseNullSeparatedGitOutput(runGitFn(worktree, ["ls-files", "--others", "--exclude-standard", "-z", "--"]));
7905
+ return [.../* @__PURE__ */ new Set([...tracked, ...untracked])].filter((item) => item && !item.startsWith("../") && !path3.isAbsolute(item));
7958
7906
  }
7959
- function codemapSectionEntries(value) {
7960
- if (Array.isArray(value)) return value;
7961
- if (value && typeof value === "object") return Object.values(value);
7962
- return [];
7907
+ function currentGitBranch(worktree, runGitFn = runGit) {
7908
+ return String(runGitFn(worktree, ["rev-parse", "--abbrev-ref", "HEAD"]) || "").trim();
7963
7909
  }
7964
- function codemapIndexedPaths(map) {
7965
- const indexed = /* @__PURE__ */ new Set();
7966
- for (const section of ["modules", "entrypoints", "sources_of_truth", "links", "internals"]) {
7967
- for (const item of codemapSectionEntries(map?.[section])) {
7968
- if (item?.path) indexed.add(normalizeCodemapRelPath(item.path));
7969
- }
7910
+ function treeEntryForWorktreePath(worktree, gitPath) {
7911
+ const absolutePath = path3.join(worktree, ...String(gitPath || "").split("/"));
7912
+ if (!fs3.existsSync(absolutePath)) return { path: gitPath, mode: "100644", type: "blob", sha: null, deleted: true };
7913
+ const stat = fs3.lstatSync(absolutePath);
7914
+ if (stat.isDirectory()) return null;
7915
+ if (stat.isSymbolicLink()) {
7916
+ return {
7917
+ path: gitPath,
7918
+ mode: "120000",
7919
+ type: "blob",
7920
+ content: fs3.readlinkSync(absolutePath),
7921
+ encoding: "utf-8"
7922
+ };
7970
7923
  }
7971
- return indexed;
7924
+ return {
7925
+ path: gitPath,
7926
+ mode: stat.mode & 73 ? "100755" : "100644",
7927
+ type: "blob",
7928
+ content: fs3.readFileSync(absolutePath).toString("base64"),
7929
+ encoding: "base64"
7930
+ };
7972
7931
  }
7973
- function readCodemap(filePath, unresolved, worktree) {
7974
- try {
7975
- const parsed = import_yaml.default.parse(fs3.readFileSync(filePath, "utf8"));
7976
- if (!parsed || typeof parsed !== "object") {
7977
- unresolved.push({ category: "codemap", path: relPath(worktree, filePath), message: "CodeMap is empty or invalid; manual repair required." });
7978
- return null;
7979
- }
7980
- return parsed;
7981
- } catch {
7982
- unresolved.push({ category: "codemap", path: relPath(worktree, filePath), message: "CodeMap has invalid YAML; manual repair required." });
7983
- return null;
7932
+ function appendGitHubQuery(pathname, params = {}) {
7933
+ const query = new URLSearchParams();
7934
+ for (const [key, value] of Object.entries(params || {})) {
7935
+ if (value === void 0 || value === null || value === "") continue;
7936
+ query.set(key, String(value));
7984
7937
  }
7938
+ const suffix = query.toString();
7939
+ return suffix ? `${pathname}?${suffix}` : pathname;
7985
7940
  }
7986
- function writeCodemap(filePath, map) {
7987
- fs3.writeFileSync(filePath, import_yaml.default.stringify(map), "utf8");
7941
+ function timestampMs(value = "") {
7942
+ const parsed = Date.parse(String(value || ""));
7943
+ return Number.isFinite(parsed) ? parsed : 0;
7988
7944
  }
7989
- function isIgnoredPath(ig, relativePath) {
7990
- const normalized = normalizeCodemapRelPath(relativePath);
7991
- return Boolean(normalized) && ig.ignores(normalized);
7945
+ function sortNewestFirst(items = []) {
7946
+ return [...items].sort((a, b) => {
7947
+ const bTime = Math.max(timestampMs(b?.updated_at), timestampMs(b?.created_at));
7948
+ const aTime = Math.max(timestampMs(a?.updated_at), timestampMs(a?.created_at));
7949
+ return bTime - aTime;
7950
+ });
7992
7951
  }
7993
- function hasImmediateSourceFile(dirPath, ig, worktree) {
7994
- if (!fs3.existsSync(dirPath)) return false;
7995
- for (const item of fs3.readdirSync(dirPath, { withFileTypes: true })) {
7996
- const childPath = path3.join(dirPath, item.name);
7997
- const relative = path3.relative(worktree, childPath);
7998
- if (isIgnoredPath(ig, relative) || isOperationalRelPath(relative)) continue;
7999
- if (item.isFile() && CODEMAP_SOURCE_EXTENSIONS.has(path3.extname(item.name))) return true;
8000
- }
8001
- return false;
7952
+ function matchesVercelStatusContext(context = "", expected = "") {
7953
+ const actual = String(context || "").trim();
7954
+ const wanted = String(expected || "").trim();
7955
+ if (wanted && actual === wanted) return true;
7956
+ const lower = actual.toLowerCase();
7957
+ if (!lower.includes("vercel")) return false;
7958
+ if (!wanted) return lower.includes("preproduction") || lower.includes("defend-preproduction");
7959
+ const wantedLower = wanted.toLowerCase();
7960
+ return wantedLower.split(/\s+|–|-/).filter((part) => part && part !== "vercel").every((part) => lower.includes(part));
8002
7961
  }
8003
- function containsSource(dirPath, ig, worktree) {
8004
- if (!fs3.existsSync(dirPath)) return false;
8005
- const dirRelPath = path3.relative(worktree, dirPath);
8006
- if (isOperationalRelPath(dirRelPath) || isHiddenTree(dirRelPath)) return false;
8007
- for (const item of fs3.readdirSync(dirPath, { withFileTypes: true })) {
8008
- const childPath = path3.join(dirPath, item.name);
8009
- const relative = path3.relative(worktree, childPath);
7962
+ function selectFunctionalDeploymentUrl(status = {}, deployment = {}) {
7963
+ for (const candidate of [
7964
+ status?.environment_url,
7965
+ deployment?.environment_url,
7966
+ status?.target_url,
7967
+ deployment?.target_url
7968
+ ]) {
7969
+ const value = String(candidate || "").trim();
7970
+ if (!value) continue;
7971
+ try {
7972
+ const url = new URL(value);
7973
+ if (url.protocol === "http:" || url.protocol === "https:") return value;
7974
+ } catch {
7975
+ }
7976
+ }
7977
+ return "";
7978
+ }
7979
+ async function checkFunctionalDeploymentUrl(url, fetchImpl = globalThis.fetch) {
7980
+ const target = String(url || "").trim();
7981
+ if (!target) return { ok: false, reason: "url_missing" };
7982
+ if (typeof fetchImpl !== "function") return { ok: false, reason: "fetch_unavailable", url: target };
7983
+ const signal = typeof AbortSignal !== "undefined" && typeof AbortSignal.timeout === "function" ? AbortSignal.timeout(8e3) : void 0;
7984
+ const probe = async (method) => {
7985
+ const response = await fetchImpl(target, { method, redirect: "follow", signal });
7986
+ return {
7987
+ ok: response.status >= 200 && response.status < 400,
7988
+ status: response.status,
7989
+ statusText: response.statusText || "",
7990
+ url: response.url || target,
7991
+ method
7992
+ };
7993
+ };
7994
+ try {
7995
+ const head = await probe("HEAD");
7996
+ if (head.ok) return head;
7997
+ const get = await probe("GET");
7998
+ return get.ok ? get : { ...get, reason: "http_not_ok" };
7999
+ } catch (error) {
8000
+ try {
8001
+ const get = await probe("GET");
8002
+ return get.ok ? get : { ...get, reason: "http_not_ok" };
8003
+ } catch (secondError) {
8004
+ return { ok: false, reason: "request_failed", url: target, error: secondError.message || error.message };
8005
+ }
8006
+ }
8007
+ }
8008
+ function createGitHubApiClient(config = {}, fetchImpl = globalThis.fetch) {
8009
+ const staticToken = resolveSecretReference(config?.apiToken);
8010
+ const appConfig = typeof config?.app === "object" && config.app !== null ? config.app : {};
8011
+ const appId = resolveSecretReference(appConfig.appId || appConfig.app_id || "");
8012
+ const installationId = resolveSecretReference(appConfig.installationId || appConfig.installation_id || "");
8013
+ const appEnabled = appConfig.enabled === true || Boolean(appId && installationId && (appConfig.privateKey || appConfig.privateKeyFile));
8014
+ const privateKey = resolveGitHubAppPrivateKey(appConfig);
8015
+ const owner = String(config?.owner || "").trim();
8016
+ const repo = String(config?.repo || "").trim();
8017
+ let installationToken = null;
8018
+ let installationTokenExpiresAt = 0;
8019
+ const requestJson = async (url, { method = "GET", headers = {}, body = void 0 } = {}) => {
8020
+ if (typeof fetchImpl !== "function") throw new Error("fetch is unavailable; inject a GitHub client for live PR lookup");
8021
+ const response = await fetchImpl(url, {
8022
+ method,
8023
+ headers: {
8024
+ Accept: "application/vnd.github+json",
8025
+ "X-GitHub-Api-Version": "2022-11-28",
8026
+ ...body === void 0 ? {} : { "Content-Type": "application/json" },
8027
+ ...headers
8028
+ },
8029
+ ...body === void 0 ? {} : { body: JSON.stringify(body) }
8030
+ });
8031
+ if (!response.ok) throw new Error(`GitHub API request failed: ${response.status}`);
8032
+ return response.status === 204 ? null : response.json();
8033
+ };
8034
+ const getAuthToken = async () => {
8035
+ if (!appEnabled) return staticToken || "";
8036
+ const nowMs = Date.now();
8037
+ if (installationToken && installationTokenExpiresAt - 6e4 > nowMs) return installationToken;
8038
+ const jwt = createGitHubAppJwt({ appId, privateKey });
8039
+ const installation = await requestJson(`https://api.github.com/app/installations/${encodeURIComponent(installationId)}/access_tokens`, {
8040
+ method: "POST",
8041
+ headers: { Authorization: `Bearer ${jwt}` }
8042
+ });
8043
+ installationToken = String(installation?.token || "").trim();
8044
+ installationTokenExpiresAt = Date.parse(installation?.expires_at || "") || nowMs + 3e6;
8045
+ if (!installationToken) throw new Error("GitHub App installation token response did not include a token");
8046
+ return installationToken;
8047
+ };
8048
+ const request = async (pathname, { method = "GET", body = void 0 } = {}) => {
8049
+ if (!owner || !repo) throw new Error("GitHub repository owner/repo is not configured");
8050
+ const token = await getAuthToken();
8051
+ return requestJson(`https://api.github.com/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}${pathname}`, {
8052
+ method,
8053
+ body,
8054
+ headers: token ? { Authorization: `Bearer ${token}` } : {}
8055
+ });
8056
+ };
8057
+ const getRef = async (branch) => request(`/git/ref/heads/${encodeGitHubBranchRef(branch)}`);
8058
+ const getCommitObject = async (sha) => request(`/git/commits/${encodeURIComponent(sha)}`);
8059
+ const createBlob = async ({ content, encoding }) => request("/git/blobs", { method: "POST", body: { content, encoding } });
8060
+ const createTree = async ({ baseTree, tree }) => request("/git/trees", { method: "POST", body: { base_tree: baseTree, tree } });
8061
+ const createCommit = async ({ message, treeSha, parents }) => request("/git/commits", { method: "POST", body: { message, tree: treeSha, parents } });
8062
+ const updateRef = async ({ branch, sha, force = false }) => request(`/git/refs/heads/${encodeGitHubBranchRef(branch)}`, { method: "PATCH", body: { sha, force } });
8063
+ return {
8064
+ async getPullRequest(number) {
8065
+ return request(`/pulls/${encodeURIComponent(number)}`);
8066
+ },
8067
+ async createPullRequest({ title, head, base, body = "", draft = false, maintainerCanModify = true }) {
8068
+ return request("/pulls", {
8069
+ method: "POST",
8070
+ body: {
8071
+ title: String(title || ""),
8072
+ head: String(head || ""),
8073
+ base: String(base || ""),
8074
+ body: String(body || ""),
8075
+ draft: draft === true,
8076
+ maintainer_can_modify: maintainerCanModify !== false
8077
+ }
8078
+ });
8079
+ },
8080
+ async createIssueComment({ issueNumber, body }) {
8081
+ return request(`/issues/${encodeURIComponent(issueNumber)}/comments`, { method: "POST", body: { body: String(body || "") } });
8082
+ },
8083
+ async replyToReviewComment({ commentId, body }) {
8084
+ return request(`/pulls/comments/${encodeURIComponent(commentId)}/replies`, { method: "POST", body: { body: String(body || "") } });
8085
+ },
8086
+ async createPullRequestReview({ pullNumber, body, event = "COMMENT" }) {
8087
+ return request(`/pulls/${encodeURIComponent(pullNumber)}/reviews`, { method: "POST", body: { body: String(body || ""), event: String(event || "COMMENT").toUpperCase() } });
8088
+ },
8089
+ async mergePullRequest({ pullNumber, commitTitle = "", commitMessage = "", mergeMethod = "squash" }) {
8090
+ const body = { merge_method: String(mergeMethod || "squash") };
8091
+ if (commitTitle) body.commit_title = String(commitTitle);
8092
+ if (commitMessage) body.commit_message = String(commitMessage);
8093
+ return request(`/pulls/${encodeURIComponent(pullNumber)}/merge`, { method: "PUT", body });
8094
+ },
8095
+ async getCombinedStatus(ref) {
8096
+ return request(`/commits/${encodeURIComponent(String(ref || ""))}/status`);
8097
+ },
8098
+ async listDeployments({ sha = "", ref = "", environment = "", perPage = 30 } = {}) {
8099
+ return request(appendGitHubQuery("/deployments", { sha, ref, environment, per_page: perPage }));
8100
+ },
8101
+ async listDeploymentStatuses(deploymentId) {
8102
+ return request(`/deployments/${encodeURIComponent(deploymentId)}/statuses`);
8103
+ },
8104
+ async verifyVercelPullRequestDeployment({
8105
+ pullNumber,
8106
+ context = "Vercel \u2013 defend-preproduction",
8107
+ environment = "Preview \u2013 defend-preproduction",
8108
+ requireFunctionalUrl = true
8109
+ } = {}) {
8110
+ const pr = await this.getPullRequest(pullNumber);
8111
+ const headSha = String(pr?.head?.sha || "").trim();
8112
+ if (!headSha) return { ok: true, ready: false, reason: "pr_head_sha_missing", pull_request: { number: pullNumber } };
8113
+ const combined = await this.getCombinedStatus(headSha);
8114
+ const statuses = Array.isArray(combined?.statuses) ? combined.statuses : [];
8115
+ const selectedStatus = sortNewestFirst(statuses.filter((status) => matchesVercelStatusContext(status?.context, context)))[0] || null;
8116
+ if (!selectedStatus) {
8117
+ return {
8118
+ ok: true,
8119
+ ready: false,
8120
+ reason: "vercel_status_missing",
8121
+ pull_request: { number: pr.number, url: pr.html_url, head_sha: headSha },
8122
+ required_context: context,
8123
+ combined_state: combined?.state || null
8124
+ };
8125
+ }
8126
+ if (String(selectedStatus.state || "").toLowerCase() !== "success") {
8127
+ return {
8128
+ ok: true,
8129
+ ready: false,
8130
+ reason: "vercel_status_not_success",
8131
+ pull_request: { number: pr.number, url: pr.html_url, head_sha: headSha },
8132
+ required_context: context,
8133
+ status: selectedStatus,
8134
+ combined_state: combined?.state || null
8135
+ };
8136
+ }
8137
+ let deployments = await this.listDeployments({ sha: headSha, environment });
8138
+ if (!Array.isArray(deployments) || deployments.length === 0) deployments = await this.listDeployments({ sha: headSha });
8139
+ const newestDeployments = sortNewestFirst(Array.isArray(deployments) ? deployments : []);
8140
+ const selectedDeployment = newestDeployments.find((deployment) => !environment || String(deployment?.environment || "") === environment) || newestDeployments[0] || null;
8141
+ if (!selectedDeployment?.id) {
8142
+ return {
8143
+ ok: true,
8144
+ ready: false,
8145
+ reason: "vercel_deployment_missing",
8146
+ pull_request: { number: pr.number, url: pr.html_url, head_sha: headSha },
8147
+ required_environment: environment,
8148
+ status: selectedStatus
8149
+ };
8150
+ }
8151
+ const deploymentStatuses = await this.listDeploymentStatuses(selectedDeployment.id);
8152
+ const selectedDeploymentStatus = sortNewestFirst(Array.isArray(deploymentStatuses) ? deploymentStatuses : [])[0] || null;
8153
+ if (!selectedDeploymentStatus || String(selectedDeploymentStatus.state || "").toLowerCase() !== "success") {
8154
+ return {
8155
+ ok: true,
8156
+ ready: false,
8157
+ reason: "vercel_deployment_not_success",
8158
+ pull_request: { number: pr.number, url: pr.html_url, head_sha: headSha },
8159
+ required_environment: environment,
8160
+ status: selectedStatus,
8161
+ deployment: selectedDeployment,
8162
+ deployment_status: selectedDeploymentStatus
8163
+ };
8164
+ }
8165
+ const url = selectFunctionalDeploymentUrl(selectedDeploymentStatus, selectedDeployment);
8166
+ const urlCheck = requireFunctionalUrl ? await checkFunctionalDeploymentUrl(url, fetchImpl) : { ok: Boolean(url), reason: url ? void 0 : "url_missing", url };
8167
+ if (requireFunctionalUrl && !urlCheck.ok) {
8168
+ return {
8169
+ ok: true,
8170
+ ready: false,
8171
+ reason: "vercel_url_not_functional",
8172
+ pull_request: { number: pr.number, url: pr.html_url, head_sha: headSha },
8173
+ required_environment: environment,
8174
+ status: selectedStatus,
8175
+ deployment: selectedDeployment,
8176
+ deployment_status: selectedDeploymentStatus,
8177
+ url,
8178
+ url_check: urlCheck
8179
+ };
8180
+ }
8181
+ return {
8182
+ ok: true,
8183
+ ready: true,
8184
+ reason: "vercel_pr_deployment_ready",
8185
+ pull_request: { number: pr.number, url: pr.html_url, head_sha: headSha },
8186
+ required_context: context,
8187
+ required_environment: environment,
8188
+ status: selectedStatus,
8189
+ deployment: selectedDeployment,
8190
+ deployment_status: selectedDeploymentStatus,
8191
+ url,
8192
+ url_check: urlCheck
8193
+ };
8194
+ },
8195
+ async commitWorktree({ worktree, branch = "", message = "", runGitFn = runGit, syncLocal = false } = {}) {
8196
+ const directory = path3.resolve(String(worktree || ""));
8197
+ if (!directory || !fs3.existsSync(directory)) throw new Error("worktree does not exist");
8198
+ const targetBranch = String(branch || currentGitBranch(directory, runGitFn)).trim();
8199
+ if (!targetBranch || targetBranch === "HEAD") throw new Error("target branch is required for GitHub API commit");
8200
+ const commitMessage = String(message || "").trim();
8201
+ if (!commitMessage) throw new Error("commit message is required");
8202
+ const changedPaths = listWorktreeChangedPaths(directory, runGitFn);
8203
+ if (changedPaths.length === 0) return { ok: true, action: "no_changes", branch: targetBranch, changedPaths: [] };
8204
+ const ref = await getRef(targetBranch);
8205
+ const headSha = ref?.object?.sha;
8206
+ if (!headSha) throw new Error(`GitHub ref for ${targetBranch} did not include a head sha`);
8207
+ const headCommit = await getCommitObject(headSha);
8208
+ const baseTree = headCommit?.tree?.sha;
8209
+ if (!baseTree) throw new Error(`GitHub commit ${headSha} did not include a tree sha`);
8210
+ const tree = [];
8211
+ for (const gitPath of changedPaths) {
8212
+ const entry = treeEntryForWorktreePath(directory, gitPath);
8213
+ if (!entry) continue;
8214
+ if (entry.deleted) {
8215
+ tree.push({ path: entry.path, mode: entry.mode, type: entry.type, sha: null });
8216
+ continue;
8217
+ }
8218
+ const blob = await createBlob({ content: entry.content, encoding: entry.encoding });
8219
+ if (!blob?.sha) throw new Error(`GitHub blob creation failed for ${gitPath}`);
8220
+ tree.push({ path: entry.path, mode: entry.mode, type: entry.type, sha: blob.sha });
8221
+ }
8222
+ if (tree.length === 0) return { ok: true, action: "no_changes", branch: targetBranch, changedPaths: [] };
8223
+ const nextTree = await createTree({ baseTree, tree });
8224
+ const nextCommit = await createCommit({ message: commitMessage, treeSha: nextTree.sha, parents: [headSha] });
8225
+ if (!nextCommit?.sha) throw new Error("GitHub commit creation did not return a sha");
8226
+ const updatedRef = await updateRef({ branch: targetBranch, sha: nextCommit.sha, force: false });
8227
+ if (syncLocal) {
8228
+ runGitFn(directory, ["fetch", "origin", targetBranch]);
8229
+ runGitFn(directory, ["reset", "--hard", "FETCH_HEAD"]);
8230
+ }
8231
+ return {
8232
+ ok: true,
8233
+ action: "committed",
8234
+ branch: targetBranch,
8235
+ before: headSha,
8236
+ after: nextCommit.sha,
8237
+ changedPaths,
8238
+ treeEntries: tree.length,
8239
+ verification: nextCommit.verification || null,
8240
+ ref: updatedRef
8241
+ };
8242
+ },
8243
+ async authMode() {
8244
+ if (appEnabled) return { mode: "github_app", appId, installationId };
8245
+ if (staticToken) return { mode: "token" };
8246
+ return { mode: "anonymous" };
8247
+ }
8248
+ };
8249
+ }
8250
+
8251
+ // src/include_resolver.js
8252
+ import fs4 from "node:fs";
8253
+ import path4 from "node:path";
8254
+ function compactPromptPath(filePath) {
8255
+ if (!filePath.endsWith(".md") || filePath.endsWith(".prompt.md")) return null;
8256
+ return filePath.replace(/\.md$/, ".prompt.md");
8257
+ }
8258
+ function isSameOrNestedPath(candidate, root) {
8259
+ if (typeof candidate !== "string" || typeof root !== "string" || !candidate.trim() || !root.trim()) return false;
8260
+ const resolvedCandidate = path4.resolve(candidate);
8261
+ const resolvedRoot = path4.resolve(root);
8262
+ const relative = path4.relative(resolvedRoot, resolvedCandidate);
8263
+ return relative === "" || !!relative && !relative.startsWith("..") && !path4.isAbsolute(relative);
8264
+ }
8265
+ function resolveWithin(baseDir, relativePath) {
8266
+ if (!relativePath) return null;
8267
+ if (path4.isAbsolute(relativePath)) return null;
8268
+ const resolved = path4.resolve(baseDir, relativePath);
8269
+ return isSameOrNestedPath(resolved, baseDir) ? resolved : null;
8270
+ }
8271
+ function withCompactPreference(paths, options = {}) {
8272
+ if (!options.preferCompactPromptDocs) return paths;
8273
+ const compactPaths = paths.map((filePath) => filePath ? compactPromptPath(filePath) : null).filter(Boolean);
8274
+ return [...compactPaths, ...paths];
8275
+ }
8276
+ function resolveIncludeFile(includeRef, repoRoot, bundleRoot, options = {}) {
8277
+ const trimmed = String(includeRef || "").trim();
8278
+ const scopedMatch = trimmed.match(/^([a-z]+):(.*)$/i);
8279
+ const scope = scopedMatch?.[1]?.toLowerCase();
8280
+ const target = scopedMatch ? scopedMatch[2].trim() : trimmed;
8281
+ const optimaRoot = options.optimaRoot || path4.join(repoRoot, ".optima");
8282
+ const repoPolicyRoot = options.repoPolicyRoot || path4.join(optimaRoot, "policies");
8283
+ const bundlePolicyRoot = options.bundlePolicyRoot || path4.join(bundleRoot, "assets", "policies");
8284
+ if (scope === "plugin") {
8285
+ for (const filePath of withCompactPreference([resolveWithin(bundleRoot, target)], options)) {
8286
+ if (filePath && fs4.existsSync(filePath)) return filePath;
8287
+ }
8288
+ return null;
8289
+ }
8290
+ if (scope === "repo") {
8291
+ for (const filePath of withCompactPreference([resolveWithin(optimaRoot, target)], options)) {
8292
+ if (filePath && fs4.existsSync(filePath)) return filePath;
8293
+ }
8294
+ return null;
8295
+ }
8296
+ if (scope === "policy") {
8297
+ const candidates2 = withCompactPreference([
8298
+ resolveWithin(repoPolicyRoot, target),
8299
+ resolveWithin(bundlePolicyRoot, target)
8300
+ ], options);
8301
+ for (const filePath of candidates2) {
8302
+ if (filePath && fs4.existsSync(filePath)) return filePath;
8303
+ }
8304
+ return null;
8305
+ }
8306
+ const candidates = withCompactPreference([
8307
+ resolveWithin(repoRoot, target),
8308
+ resolveWithin(bundleRoot, target)
8309
+ ], options);
8310
+ for (const filePath of candidates) {
8311
+ if (filePath && fs4.existsSync(filePath)) return filePath;
8312
+ }
8313
+ return null;
8314
+ }
8315
+ function resolveIncludes(text, repoRoot, bundleRoot, options = {}) {
8316
+ const includeDepth = Number(options.includeDepth || 0);
8317
+ const maxIncludeDepth = Number(options.maxIncludeDepth || 20);
8318
+ if (includeDepth > maxIncludeDepth) {
8319
+ return "\n\n# ERROR: Include recursion limit exceeded.\n\n";
8320
+ }
8321
+ const includeRegex = /<include:(.*?)>/g;
8322
+ return String(text || "").replace(includeRegex, (match, includeRef) => {
8323
+ const filePath = resolveIncludeFile(includeRef, repoRoot, bundleRoot, options);
8324
+ if (!filePath) {
8325
+ console.warn(`[Optima] Include file not found: ${includeRef}`);
8326
+ return `
8327
+
8328
+ # ERROR: Include file not found: ${includeRef}
8329
+
8330
+ `;
8331
+ }
8332
+ const content = fs4.readFileSync(filePath, "utf8");
8333
+ return resolveIncludes(content, repoRoot, bundleRoot, { ...options, includeDepth: includeDepth + 1, maxIncludeDepth });
8334
+ });
8335
+ }
8336
+
8337
+ // src/markdown_artifacts.js
8338
+ import fs5 from "node:fs";
8339
+ var CLICKUP_REQUIRED_SUMMARY_SECTIONS = [
8340
+ "Summary",
8341
+ "Work Performed",
8342
+ "AC Coverage",
8343
+ "Verification Results",
8344
+ "Documentation Impact",
8345
+ "Open Risks",
8346
+ "Recommended Next Step"
8347
+ ];
8348
+ var RAW_LOG_SECTION_NAMES = /* @__PURE__ */ new Set(["Raw Logs", "Logs", "Full Logs", "Command Output", "Transcript"]);
8349
+ function parseMarkdownSections(markdown = "") {
8350
+ const sections = {};
8351
+ let current = null;
8352
+ let buffer = [];
8353
+ const flush = () => {
8354
+ if (!current) return;
8355
+ sections[current] = buffer.join("\n").trim();
8356
+ };
8357
+ for (const line of String(markdown).split(/\r?\n/)) {
8358
+ const heading = /^(#{2,3})\s+(.+?)\s*$/.exec(line);
8359
+ if (heading) {
8360
+ flush();
8361
+ current = heading[2].trim();
8362
+ buffer = [];
8363
+ continue;
8364
+ }
8365
+ if (current) buffer.push(line);
8366
+ }
8367
+ flush();
8368
+ return sections;
8369
+ }
8370
+ function parseMarkdownArtifact(markdown = "", { requiredSections = [] } = {}) {
8371
+ const sections = parseMarkdownSections(markdown);
8372
+ const missing = requiredSections.filter((section) => !sections[section]);
8373
+ return {
8374
+ ok: missing.length === 0,
8375
+ sections,
8376
+ missing,
8377
+ message: missing.length ? `Missing required section(s): ${missing.join(", ")}` : "ok"
8378
+ };
8379
+ }
8380
+ function readMarkdownArtifact(filePath, options = {}) {
8381
+ const markdown = fs5.readFileSync(filePath, "utf8");
8382
+ return parseMarkdownArtifact(markdown, options);
8383
+ }
8384
+ function stripRawLogSections(sections = {}) {
8385
+ return Object.fromEntries(
8386
+ Object.entries(sections).filter(([name]) => !RAW_LOG_SECTION_NAMES.has(name))
8387
+ );
8388
+ }
8389
+
8390
+ // src/repair.js
8391
+ var import_yaml = __toESM(require_dist(), 1);
8392
+ var import_ignore = __toESM(require_ignore(), 1);
8393
+ import fs6 from "node:fs";
8394
+ import path5 from "node:path";
8395
+ var CODEMAP_SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([
8396
+ ".js",
8397
+ ".ts",
8398
+ ".tsx",
8399
+ ".jsx",
8400
+ ".dart",
8401
+ ".py",
8402
+ ".go",
8403
+ ".rs",
8404
+ ".java",
8405
+ ".c",
8406
+ ".cpp",
8407
+ ".cs",
8408
+ ".php",
8409
+ ".rb",
8410
+ ".swift",
8411
+ ".kt",
8412
+ ".m",
8413
+ ".sh",
8414
+ ".sql",
8415
+ ".yaml",
8416
+ ".yml",
8417
+ ".json",
8418
+ ".md"
8419
+ ]);
8420
+ var LEGACY_OPERATIONAL_ROOTS = /* @__PURE__ */ new Set([
8421
+ "tasks",
8422
+ "evidences",
8423
+ ".orbita",
8424
+ ".staticeng",
8425
+ ".nomadworks",
8426
+ ".nomadwork",
8427
+ "nomadworks",
8428
+ ".codenomad"
8429
+ ]);
8430
+ var OPTIMA_OPERATIONAL_FOLDERS = [".optima", "templates", "dist"];
8431
+ function relPath(worktree, targetPath) {
8432
+ return path5.relative(worktree, targetPath).split(path5.sep).join("/") || ".";
8433
+ }
8434
+ function normalizeCodemapRelPath(relPathValue) {
8435
+ return path5.normalize(relPathValue).replace(/\\/g, "/").replace(/\/$/, "");
8436
+ }
8437
+ function firstPathSegment(relPathValue) {
8438
+ return normalizeCodemapRelPath(relPathValue).split("/").filter(Boolean)[0] || "";
8439
+ }
8440
+ function isOperationalRelPath(relPathValue) {
8441
+ if (!relPathValue) return false;
8442
+ const normalized = normalizeCodemapRelPath(relPathValue);
8443
+ const firstSegment = firstPathSegment(normalized);
8444
+ if (LEGACY_OPERATIONAL_ROOTS.has(firstSegment)) return true;
8445
+ return OPTIMA_OPERATIONAL_FOLDERS.some((folder) => normalized === folder || normalized.startsWith(`${folder}/`));
8446
+ }
8447
+ function isHiddenTree(relPathValue) {
8448
+ if (!relPathValue) return false;
8449
+ return normalizeCodemapRelPath(relPathValue).split("/").some((part) => part.startsWith("."));
8450
+ }
8451
+ function loadGitIgnoreMatcher(worktree) {
8452
+ const ig = (0, import_ignore.default)();
8453
+ ig.add(".git");
8454
+ const gitignorePath = path5.join(worktree, ".gitignore");
8455
+ if (fs6.existsSync(gitignorePath)) ig.add(fs6.readFileSync(gitignorePath, "utf8"));
8456
+ return ig;
8457
+ }
8458
+ function codemapSectionEntries(value) {
8459
+ if (Array.isArray(value)) return value;
8460
+ if (value && typeof value === "object") return Object.values(value);
8461
+ return [];
8462
+ }
8463
+ function codemapIndexedPaths(map) {
8464
+ const indexed = /* @__PURE__ */ new Set();
8465
+ for (const section of ["modules", "entrypoints", "sources_of_truth", "links", "internals"]) {
8466
+ for (const item of codemapSectionEntries(map?.[section])) {
8467
+ if (item?.path) indexed.add(normalizeCodemapRelPath(item.path));
8468
+ }
8469
+ }
8470
+ return indexed;
8471
+ }
8472
+ function readCodemap(filePath, unresolved, worktree) {
8473
+ try {
8474
+ const parsed = import_yaml.default.parse(fs6.readFileSync(filePath, "utf8"));
8475
+ if (!parsed || typeof parsed !== "object") {
8476
+ unresolved.push({ category: "codemap", path: relPath(worktree, filePath), message: "CodeMap is empty or invalid; manual repair required." });
8477
+ return null;
8478
+ }
8479
+ return parsed;
8480
+ } catch {
8481
+ unresolved.push({ category: "codemap", path: relPath(worktree, filePath), message: "CodeMap has invalid YAML; manual repair required." });
8482
+ return null;
8483
+ }
8484
+ }
8485
+ function writeCodemap(filePath, map) {
8486
+ fs6.writeFileSync(filePath, import_yaml.default.stringify(map), "utf8");
8487
+ }
8488
+ function isIgnoredPath(ig, relativePath) {
8489
+ const normalized = normalizeCodemapRelPath(relativePath);
8490
+ return Boolean(normalized) && ig.ignores(normalized);
8491
+ }
8492
+ function hasImmediateSourceFile(dirPath, ig, worktree) {
8493
+ if (!fs6.existsSync(dirPath)) return false;
8494
+ for (const item of fs6.readdirSync(dirPath, { withFileTypes: true })) {
8495
+ const childPath = path5.join(dirPath, item.name);
8496
+ const relative = path5.relative(worktree, childPath);
8497
+ if (isIgnoredPath(ig, relative) || isOperationalRelPath(relative)) continue;
8498
+ if (item.isFile() && CODEMAP_SOURCE_EXTENSIONS.has(path5.extname(item.name))) return true;
8499
+ }
8500
+ return false;
8501
+ }
8502
+ function containsSource(dirPath, ig, worktree) {
8503
+ if (!fs6.existsSync(dirPath)) return false;
8504
+ const dirRelPath = path5.relative(worktree, dirPath);
8505
+ if (isOperationalRelPath(dirRelPath) || isHiddenTree(dirRelPath)) return false;
8506
+ for (const item of fs6.readdirSync(dirPath, { withFileTypes: true })) {
8507
+ const childPath = path5.join(dirPath, item.name);
8508
+ const relative = path5.relative(worktree, childPath);
8010
8509
  if (isIgnoredPath(ig, relative) || isOperationalRelPath(relative) || isHiddenTree(relative)) continue;
8011
- if (item.isFile() && CODEMAP_SOURCE_EXTENSIONS.has(path3.extname(item.name))) return true;
8510
+ if (item.isFile() && CODEMAP_SOURCE_EXTENSIONS.has(path5.extname(item.name))) return true;
8012
8511
  if (item.isDirectory() && containsSource(childPath, ig, worktree)) return true;
8013
8512
  }
8014
8513
  return false;
8015
8514
  }
8016
8515
  function createModuleCodemap(dirPath, worktree, deps) {
8017
- const entries = fs3.readdirSync(dirPath, { withFileTypes: true });
8516
+ const entries = fs6.readdirSync(dirPath, { withFileTypes: true });
8018
8517
  const entrypoints = [];
8019
8518
  const internals = [];
8020
- const relToRoot = path3.relative(dirPath, deps.optimaCodemapPath(worktree)).split(path3.sep).join("/");
8519
+ const relToRoot = path5.relative(dirPath, deps.optimaCodemapPath(worktree)).split(path5.sep).join("/");
8021
8520
  for (const item of entries) {
8022
- if (!item.isFile() || item.name === "codemap.yml" || !CODEMAP_SOURCE_EXTENSIONS.has(path3.extname(item.name))) continue;
8521
+ if (!item.isFile() || item.name === "codemap.yml" || !CODEMAP_SOURCE_EXTENSIONS.has(path5.extname(item.name))) continue;
8023
8522
  const bucket = /^index\.(js|ts|tsx|jsx)$|^main\.(js|ts|tsx|jsx|py|go|rs|java)$/.test(item.name) ? entrypoints : internals;
8024
8523
  bucket.push({ path: item.name });
8025
8524
  }
@@ -8032,7 +8531,7 @@ function repairSingleCodemap(codemapPath, worktree, apply, registerAction, unres
8032
8531
  const map = readCodemap(codemapPath, unresolved, worktree);
8033
8532
  if (!map) return;
8034
8533
  const isRootMap = codemapPath === deps.optimaCodemapPath(worktree);
8035
- const mapDir = path3.dirname(codemapPath);
8534
+ const mapDir = path5.dirname(codemapPath);
8036
8535
  const pathBase = isRootMap ? worktree : mapDir;
8037
8536
  let changed = false;
8038
8537
  for (const section of ["modules", "entrypoints", "sources_of_truth", "links", "internals"]) {
@@ -8043,13 +8542,13 @@ function repairSingleCodemap(codemapPath, worktree, apply, registerAction, unres
8043
8542
  }
8044
8543
  const nextEntries = [];
8045
8544
  for (const entry of originalEntries) {
8046
- if (!entry?.path || entry.path.startsWith("http://") || entry.path.startsWith("https://") || path3.isAbsolute(entry.path)) {
8545
+ if (!entry?.path || entry.path.startsWith("http://") || entry.path.startsWith("https://") || path5.isAbsolute(entry.path)) {
8047
8546
  nextEntries.push(entry);
8048
8547
  continue;
8049
8548
  }
8050
8549
  const normalizedPath = normalizeCodemapRelPath(entry.path);
8051
- const absPath = path3.join(pathBase, normalizedPath);
8052
- if (!fs3.existsSync(absPath)) {
8550
+ const absPath = path5.join(pathBase, normalizedPath);
8551
+ if (!fs6.existsSync(absPath)) {
8053
8552
  registerAction({ category: "codemap", action: apply ? "removed" : "would_remove", path: relPath(worktree, codemapPath), detail: `Remove broken ${section.slice(0, -1)} reference '${entry.path}'.` });
8054
8553
  changed = true;
8055
8554
  continue;
@@ -8058,8 +8557,8 @@ function repairSingleCodemap(codemapPath, worktree, apply, registerAction, unres
8058
8557
  const maxParts = isRootMap ? 2 : 1;
8059
8558
  if (parts.length > maxParts) {
8060
8559
  const localPath = isRootMap ? parts.slice(0, 2).join("/") : parts[0];
8061
- const localAbs = path3.join(pathBase, localPath);
8062
- if (fs3.existsSync(localAbs)) {
8560
+ const localAbs = path5.join(pathBase, localPath);
8561
+ if (fs6.existsSync(localAbs)) {
8063
8562
  nextEntries.push({ ...entry, path: localPath });
8064
8563
  changed = true;
8065
8564
  registerAction({ category: "codemap", action: apply ? "updated" : "would_update", path: relPath(worktree, codemapPath), detail: `Shorten '${entry.path}' to local path '${localPath}'.` });
@@ -8073,11 +8572,11 @@ function repairSingleCodemap(codemapPath, worktree, apply, registerAction, unres
8073
8572
  }
8074
8573
  if (Array.isArray(map[section])) map[section] = nextEntries;
8075
8574
  }
8076
- if (map.scope === "module" && !isOperationalRelPath(path3.relative(worktree, mapDir))) {
8575
+ if (map.scope === "module" && !isOperationalRelPath(path5.relative(worktree, mapDir))) {
8077
8576
  const indexed = codemapIndexedPaths(map);
8078
8577
  const internals = Array.isArray(map.internals) ? map.internals : [];
8079
- for (const item of fs3.readdirSync(mapDir, { withFileTypes: true })) {
8080
- if (!item.isFile() || item.name === "codemap.yml" || !CODEMAP_SOURCE_EXTENSIONS.has(path3.extname(item.name))) continue;
8578
+ for (const item of fs6.readdirSync(mapDir, { withFileTypes: true })) {
8579
+ if (!item.isFile() || item.name === "codemap.yml" || !CODEMAP_SOURCE_EXTENSIONS.has(path5.extname(item.name))) continue;
8081
8580
  if (indexed.has(item.name)) continue;
8082
8581
  internals.push({ path: item.name });
8083
8582
  indexed.add(item.name);
@@ -8091,13 +8590,13 @@ function repairSingleCodemap(codemapPath, worktree, apply, registerAction, unres
8091
8590
  function repairCodemaps(worktree, apply, actions, unresolved, deps) {
8092
8591
  const ig = loadGitIgnoreMatcher(worktree);
8093
8592
  const rootCodemapPath = deps.optimaCodemapPath(worktree);
8094
- const rootCodemapMissing = !fs3.existsSync(rootCodemapPath);
8593
+ const rootCodemapMissing = !fs6.existsSync(rootCodemapPath);
8095
8594
  if (rootCodemapMissing) {
8096
8595
  actions.push({ category: "codemap", action: apply ? "created" : "would_create", path: ".optima/codemap.yml", detail: "Create missing root CodeMap from template." });
8097
8596
  if (apply) deps.scaffoldOptimaRootCodemap(worktree);
8098
8597
  }
8099
- if (fs3.existsSync(rootCodemapPath)) repairSingleCodemap(rootCodemapPath, worktree, apply, (action) => actions.push(action), unresolved, deps);
8100
- const rootMap = fs3.existsSync(rootCodemapPath) ? readCodemap(rootCodemapPath, unresolved, worktree) : null;
8598
+ if (fs6.existsSync(rootCodemapPath)) repairSingleCodemap(rootCodemapPath, worktree, apply, (action) => actions.push(action), unresolved, deps);
8599
+ const rootMap = fs6.existsSync(rootCodemapPath) ? readCodemap(rootCodemapPath, unresolved, worktree) : null;
8101
8600
  let rootChanged = false;
8102
8601
  const rootModulesRepairable = rootMap && (rootMap.modules === void 0 || Array.isArray(rootMap.modules));
8103
8602
  if (rootMap) {
@@ -8109,10 +8608,10 @@ function repairCodemaps(worktree, apply, actions, unresolved, deps) {
8109
8608
  }
8110
8609
  }
8111
8610
  function walk(dirPath) {
8112
- const relative = path3.relative(worktree, dirPath);
8611
+ const relative = path5.relative(worktree, dirPath);
8113
8612
  if (relative && (isIgnoredPath(ig, relative) || isOperationalRelPath(relative) || isHiddenTree(relative))) return;
8114
- const codemapPath = path3.join(dirPath, "codemap.yml");
8115
- const hasCodemap = fs3.existsSync(codemapPath);
8613
+ const codemapPath = path5.join(dirPath, "codemap.yml");
8614
+ const hasCodemap = fs6.existsSync(codemapPath);
8116
8615
  const sourceDir = relative && containsSource(dirPath, ig, worktree);
8117
8616
  if (sourceDir && !hasCodemap && dirPath !== worktree) {
8118
8617
  if (hasImmediateSourceFile(dirPath, ig, worktree)) {
@@ -8131,19 +8630,19 @@ function repairCodemaps(worktree, apply, actions, unresolved, deps) {
8131
8630
  actions.push({ category: "codemap", action: apply ? "updated" : "would_update", path: ".optima/codemap.yml", detail: `Register top-level source module '${normalizeCodemapRelPath(relative)}'.` });
8132
8631
  }
8133
8632
  }
8134
- if (fs3.existsSync(codemapPath) && codemapPath !== rootCodemapPath) repairSingleCodemap(codemapPath, worktree, apply, (action) => actions.push(action), unresolved, deps);
8135
- for (const item of fs3.readdirSync(dirPath, { withFileTypes: true })) {
8136
- if (item.isDirectory()) walk(path3.join(dirPath, item.name));
8633
+ if (fs6.existsSync(codemapPath) && codemapPath !== rootCodemapPath) repairSingleCodemap(codemapPath, worktree, apply, (action) => actions.push(action), unresolved, deps);
8634
+ for (const item of fs6.readdirSync(dirPath, { withFileTypes: true })) {
8635
+ if (item.isDirectory()) walk(path5.join(dirPath, item.name));
8137
8636
  }
8138
8637
  }
8139
- if (fs3.existsSync(worktree)) walk(worktree);
8638
+ if (fs6.existsSync(worktree)) walk(worktree);
8140
8639
  if (rootMap && rootChanged && apply) writeCodemap(rootCodemapPath, rootMap);
8141
8640
  }
8142
8641
  function walkMarkdownFiles(dirPath) {
8143
- if (!fs3.existsSync(dirPath)) return [];
8642
+ if (!fs6.existsSync(dirPath)) return [];
8144
8643
  const files = [];
8145
- for (const entry of fs3.readdirSync(dirPath, { withFileTypes: true })) {
8146
- const entryPath = path3.join(dirPath, entry.name);
8644
+ for (const entry of fs6.readdirSync(dirPath, { withFileTypes: true })) {
8645
+ const entryPath = path5.join(dirPath, entry.name);
8147
8646
  if (entry.isDirectory()) {
8148
8647
  files.push(...walkMarkdownFiles(entryPath));
8149
8648
  } else if (entry.isFile() && entry.name.endsWith(".md")) {
@@ -8182,7 +8681,7 @@ function rewriteOptimaMarkdownReferences(content, evidenceBasePath = null) {
8182
8681
  }
8183
8682
  function optimaEvidenceBaseForFile(worktree, filePath, deps) {
8184
8683
  const evidenceRoot = deps.optimaEvidencesDir(worktree);
8185
- const relative = path3.relative(evidenceRoot, filePath).split(path3.sep).join("/");
8684
+ const relative = path5.relative(evidenceRoot, filePath).split(path5.sep).join("/");
8186
8685
  const [taskId] = relative.split("/");
8187
8686
  if (!taskId || taskId === ".." || relative.startsWith("../")) return null;
8188
8687
  return `.optima/evidences/${taskId}`;
@@ -8195,11 +8694,11 @@ function normalizeOptimaMarkdownReferences(worktree, deps) {
8195
8694
  ];
8196
8695
  const changed = [];
8197
8696
  for (const filePath of scanRoots.flatMap(walkMarkdownFiles)) {
8198
- const raw = fs3.readFileSync(filePath, "utf8");
8199
- const evidenceBasePath = filePath.startsWith(deps.optimaEvidencesDir(worktree) + path3.sep) ? optimaEvidenceBaseForFile(worktree, filePath, deps) : null;
8697
+ const raw = fs6.readFileSync(filePath, "utf8");
8698
+ const evidenceBasePath = filePath.startsWith(deps.optimaEvidencesDir(worktree) + path5.sep) ? optimaEvidenceBaseForFile(worktree, filePath, deps) : null;
8200
8699
  const rewritten = rewriteOptimaMarkdownReferences(raw, evidenceBasePath);
8201
8700
  if (rewritten !== raw) {
8202
- fs3.writeFileSync(filePath, rewritten, "utf8");
8701
+ fs6.writeFileSync(filePath, rewritten, "utf8");
8203
8702
  changed.push(relPath(worktree, filePath));
8204
8703
  }
8205
8704
  }
@@ -8207,8 +8706,8 @@ function normalizeOptimaMarkdownReferences(worktree, deps) {
8207
8706
  }
8208
8707
  function missingOptimaGitignoreRules(worktree, deps) {
8209
8708
  if (!deps.isGitRepository(worktree)) return [];
8210
- const gitignorePath = path3.join(worktree, ".gitignore");
8211
- const existing = fs3.existsSync(gitignorePath) ? fs3.readFileSync(gitignorePath, "utf8") : "";
8709
+ const gitignorePath = path5.join(worktree, ".gitignore");
8710
+ const existing = fs6.existsSync(gitignorePath) ? fs6.readFileSync(gitignorePath, "utf8") : "";
8212
8711
  const existingRules = new Set(existing.split(/\r?\n/).map((line) => line.trim()).filter(Boolean));
8213
8712
  return deps.optimaGitignoreRules.filter((rule) => !existingRules.has(rule));
8214
8713
  }
@@ -8225,11 +8724,11 @@ function planOptimaRepair(worktree, args = {}, deps) {
8225
8724
  const apply = mode === "apply";
8226
8725
  const actions = [];
8227
8726
  const unresolved = [];
8228
- const hadOptima = fs3.existsSync(deps.optimaDir(worktree));
8727
+ const hadOptima = fs6.existsSync(deps.optimaDir(worktree));
8229
8728
  const missingGitignoreRules = missingOptimaGitignoreRules(worktree, deps);
8230
8729
  const markdownBefore = apply ? [] : walkMarkdownFiles(deps.optimaDir(worktree)).filter((filePath) => {
8231
- const raw = fs3.readFileSync(filePath, "utf8");
8232
- const evidenceBasePath = filePath.startsWith(deps.optimaEvidencesDir(worktree) + path3.sep) ? optimaEvidenceBaseForFile(worktree, filePath, deps) : null;
8730
+ const raw = fs6.readFileSync(filePath, "utf8");
8731
+ const evidenceBasePath = filePath.startsWith(deps.optimaEvidencesDir(worktree) + path5.sep) ? optimaEvidenceBaseForFile(worktree, filePath, deps) : null;
8233
8732
  return rewriteOptimaMarkdownReferences(raw, evidenceBasePath) !== raw;
8234
8733
  }).map((filePath) => relPath(worktree, filePath));
8235
8734
  if (!hadOptima) pushRepairAction(actions, "operational", apply ? "created" : "would_create", ".optima/", "Create Optima operational root.");
@@ -8238,31 +8737,31 @@ function planOptimaRepair(worktree, args = {}, deps) {
8238
8737
  [".staticeng/", deps.legacyStaticEngDir(worktree)],
8239
8738
  [".nomadwork/", deps.legacyNomadworkDir(worktree)],
8240
8739
  [".nomadworks/", deps.legacyNomadworksDir(worktree)],
8241
- ["tasks/", path3.join(worktree, "tasks")],
8242
- ["evidences/", path3.join(worktree, "evidences")],
8243
- ["docs/scrs/", path3.join(worktree, "docs", "scrs")],
8244
- ["codemap.yml", path3.join(worktree, "codemap.yml")],
8245
- ["codemap.yaml", path3.join(worktree, "codemap.yaml")]
8740
+ ["tasks/", path5.join(worktree, "tasks")],
8741
+ ["evidences/", path5.join(worktree, "evidences")],
8742
+ ["docs/scrs/", path5.join(worktree, "docs", "scrs")],
8743
+ ["codemap.yml", path5.join(worktree, "codemap.yml")],
8744
+ ["codemap.yaml", path5.join(worktree, "codemap.yaml")]
8246
8745
  ];
8247
- if (!deps.isOptimaPluginPackageWorktree(worktree)) legacySources.push(["policies/", path3.join(worktree, "policies")]);
8746
+ if (!deps.isOptimaPluginPackageWorktree(worktree)) legacySources.push(["policies/", path5.join(worktree, "policies")]);
8248
8747
  for (const [display, sourcePath] of legacySources) {
8249
- if (fs3.existsSync(sourcePath)) pushRepairAction(actions, "legacy", apply ? "migrated" : "would_migrate", display, "Move or merge legacy/root Optima artifact into .optima using preservation safeguards.");
8748
+ if (fs6.existsSync(sourcePath)) pushRepairAction(actions, "legacy", apply ? "migrated" : "would_migrate", display, "Move or merge legacy/root Optima artifact into .optima using preservation safeguards.");
8250
8749
  }
8251
8750
  if (apply) deps.migrateLegacyOptimaLayout(worktree);
8252
- const configMissing = !fs3.existsSync(deps.repoConfigPath(worktree));
8751
+ const configMissing = !fs6.existsSync(deps.repoConfigPath(worktree));
8253
8752
  if (configMissing) pushRepairAction(actions, "config", apply ? "created" : "would_create", ".optima/.config/optima.yaml", "Create missing local Optima config from template.");
8254
8753
  if (apply) deps.scaffoldOptimaConfig(worktree, args.team_mode || "full");
8255
8754
  const requiredFiles = [
8256
- [path3.join(deps.optimaTasksDir(worktree), "current.md"), "registry", ".optima/tasks/current.md", deps.currentTasksRegistryContent()],
8257
- [path3.join(deps.optimaTasksDir(worktree), "done.md"), "registry", ".optima/tasks/done.md", deps.doneTasksRegistryContent()],
8258
- [path3.join(deps.optimaScrsDir(worktree), "current.md"), "registry", ".optima/docs/scrs/current.md", deps.currentScrRegistryContent()],
8259
- [path3.join(deps.optimaScrsDir(worktree), "done.md"), "registry", ".optima/docs/scrs/done.md", deps.doneScrRegistryContent()],
8260
- [path3.join(deps.optimaTasksDir(worktree), "task-template.md"), "template", ".optima/tasks/task-template.md", deps.taskTemplateContent()],
8261
- [path3.join(deps.optimaTasksDir(worktree), "subtask-template.md"), "template", ".optima/tasks/subtask-template.md", deps.subtaskTemplateContent()],
8262
- [path3.join(deps.repoPoliciesDir(worktree), "README.md"), "policy", ".optima/policies/README.md", deps.repoLocalPoliciesReadme]
8755
+ [path5.join(deps.optimaTasksDir(worktree), "current.md"), "registry", ".optima/tasks/current.md", deps.currentTasksRegistryContent()],
8756
+ [path5.join(deps.optimaTasksDir(worktree), "done.md"), "registry", ".optima/tasks/done.md", deps.doneTasksRegistryContent()],
8757
+ [path5.join(deps.optimaScrsDir(worktree), "current.md"), "registry", ".optima/docs/scrs/current.md", deps.currentScrRegistryContent()],
8758
+ [path5.join(deps.optimaScrsDir(worktree), "done.md"), "registry", ".optima/docs/scrs/done.md", deps.doneScrRegistryContent()],
8759
+ [path5.join(deps.optimaTasksDir(worktree), "task-template.md"), "template", ".optima/tasks/task-template.md", deps.taskTemplateContent()],
8760
+ [path5.join(deps.optimaTasksDir(worktree), "subtask-template.md"), "template", ".optima/tasks/subtask-template.md", deps.subtaskTemplateContent()],
8761
+ [path5.join(deps.repoPoliciesDir(worktree), "README.md"), "policy", ".optima/policies/README.md", deps.repoLocalPoliciesReadme]
8263
8762
  ];
8264
8763
  for (const [filePath, category, displayPath, content] of requiredFiles) {
8265
- if (!fs3.existsSync(filePath)) {
8764
+ if (!fs6.existsSync(filePath)) {
8266
8765
  pushRepairAction(actions, category, apply ? "created" : "would_create", displayPath, "Create missing Optima scaffold file without overwriting existing content.");
8267
8766
  if (apply) deps.ensureFileIfMissing(filePath, content);
8268
8767
  }
@@ -8316,18 +8815,18 @@ function formatRepairResult(plan, validationResult = null, formatValidationResul
8316
8815
  // src/validate_logic.js
8317
8816
  var import_yaml2 = __toESM(require_dist(), 1);
8318
8817
  var import_ignore2 = __toESM(require_ignore(), 1);
8319
- import fs4 from "node:fs";
8320
- import path4 from "node:path";
8818
+ import fs7 from "node:fs";
8819
+ import path6 from "node:path";
8321
8820
  async function optima_validate_logic(worktree) {
8322
- const rootCodemapPath = path4.join(worktree, ".optima", "codemap.yml");
8323
- if (!fs4.existsSync(rootCodemapPath)) return { ok: false, errors: [".optima/codemap.yml not found."], warnings: [] };
8821
+ const rootCodemapPath = path6.join(worktree, ".optima", "codemap.yml");
8822
+ if (!fs7.existsSync(rootCodemapPath)) return { ok: false, errors: [".optima/codemap.yml not found."], warnings: [] };
8324
8823
  const errors = [];
8325
8824
  const warnings = [];
8326
8825
  const ig = (0, import_ignore2.default)();
8327
8826
  ig.add(".git");
8328
- const gitignorePath = path4.join(worktree, ".gitignore");
8329
- if (fs4.existsSync(gitignorePath)) {
8330
- ig.add(fs4.readFileSync(gitignorePath, "utf8"));
8827
+ const gitignorePath = path6.join(worktree, ".gitignore");
8828
+ if (fs7.existsSync(gitignorePath)) {
8829
+ ig.add(fs7.readFileSync(gitignorePath, "utf8"));
8331
8830
  }
8332
8831
  const sourceExtensions = [
8333
8832
  ".js",
@@ -8367,30 +8866,30 @@ async function optima_validate_logic(worktree) {
8367
8866
  const operationalFolders = [".optima", "templates", "dist"];
8368
8867
  const isHiddenTree2 = (relPath2) => {
8369
8868
  if (!relPath2) return false;
8370
- return relPath2.split(path4.sep).some((part) => part.startsWith("."));
8869
+ return relPath2.split(path6.sep).some((part) => part.startsWith("."));
8371
8870
  };
8372
- const firstPathSegment2 = (relPath2) => relPath2.split(path4.sep).filter(Boolean)[0] || "";
8871
+ const firstPathSegment2 = (relPath2) => relPath2.split(path6.sep).filter(Boolean)[0] || "";
8373
8872
  const isOperationalRelPath2 = (relPath2) => {
8374
8873
  if (!relPath2) return false;
8375
8874
  const firstSegment = firstPathSegment2(relPath2);
8376
8875
  if (legacyOperationalRoots.has(firstSegment)) return true;
8377
- return operationalFolders.some((f) => relPath2 === f || relPath2.startsWith(f + path4.sep));
8876
+ return operationalFolders.some((f) => relPath2 === f || relPath2.startsWith(f + path6.sep));
8378
8877
  };
8379
8878
  const getSectionEntries = (value) => {
8380
8879
  if (Array.isArray(value)) return value;
8381
8880
  if (value && typeof value === "object") return Object.values(value);
8382
8881
  return [];
8383
8882
  };
8384
- const normalizeRelativePath = (relPath2) => path4.normalize(relPath2).replace(/\\/g, "/").replace(/\/$/, "");
8883
+ const normalizeRelativePath = (relPath2) => path6.normalize(relPath2).replace(/\\/g, "/").replace(/\/$/, "");
8385
8884
  const isSourceDir = (dirPath) => {
8386
- const dirRelPath = path4.relative(worktree, dirPath);
8885
+ const dirRelPath = path6.relative(worktree, dirPath);
8387
8886
  if (isOperationalRelPath2(dirRelPath)) return false;
8388
- const items = fs4.readdirSync(dirPath, { withFileTypes: true });
8887
+ const items = fs7.readdirSync(dirPath, { withFileTypes: true });
8389
8888
  for (const item of items) {
8390
- const childPath = path4.join(dirPath, item.name);
8391
- const relPath2 = path4.relative(worktree, childPath);
8889
+ const childPath = path6.join(dirPath, item.name);
8890
+ const relPath2 = path6.relative(worktree, childPath);
8392
8891
  if (ig.ignores(relPath2) || isOperationalRelPath2(relPath2)) continue;
8393
- if (item.isFile() && sourceExtensions.includes(path4.extname(item.name))) return true;
8892
+ if (item.isFile() && sourceExtensions.includes(path6.extname(item.name))) return true;
8394
8893
  if (item.isDirectory()) {
8395
8894
  if (isSourceDir(childPath)) return true;
8396
8895
  }
@@ -8398,7 +8897,7 @@ async function optima_validate_logic(worktree) {
8398
8897
  return false;
8399
8898
  };
8400
8899
  function validateMap(filePath) {
8401
- const content = fs4.readFileSync(filePath, "utf8");
8900
+ const content = fs7.readFileSync(filePath, "utf8");
8402
8901
  let map;
8403
8902
  try {
8404
8903
  map = import_yaml2.default.parse(content);
@@ -8410,32 +8909,32 @@ async function optima_validate_logic(worktree) {
8410
8909
  errors.push(`${filePath}: Invalid YAML.`);
8411
8910
  return;
8412
8911
  }
8413
- const dir = path4.dirname(filePath);
8912
+ const dir = path6.dirname(filePath);
8414
8913
  const pathBase = filePath === rootCodemapPath ? worktree : dir;
8415
8914
  const indexedPaths = /* @__PURE__ */ new Set();
8416
8915
  const sectionsToVerify = ["modules", "entrypoints", "sources_of_truth", "links", "internals"];
8417
8916
  for (const section of sectionsToVerify) {
8418
8917
  for (const item of getSectionEntries(map[section])) {
8419
8918
  if (item?.path) {
8420
- indexedPaths.add(path4.normalize(item.path));
8919
+ indexedPaths.add(path6.normalize(item.path));
8421
8920
  if (section === "links" && (item.path.startsWith("http://") || item.path.startsWith("https://"))) {
8422
8921
  continue;
8423
8922
  }
8424
- const absPath = path4.isAbsolute(item.path) ? item.path : path4.join(pathBase, item.path);
8425
- if (!fs4.existsSync(absPath)) {
8923
+ const absPath = path6.isAbsolute(item.path) ? item.path : path6.join(pathBase, item.path);
8924
+ if (!fs7.existsSync(absPath)) {
8426
8925
  errors.push(`${filePath}: ${section.slice(0, -1)} path does not exist: ${item.path}`);
8427
8926
  }
8428
8927
  }
8429
8928
  }
8430
8929
  }
8431
- const relDir = path4.relative(worktree, dir);
8930
+ const relDir = path6.relative(worktree, dir);
8432
8931
  const isOperational = isOperationalRelPath2(relDir);
8433
8932
  if (map.scope === "module" && !isOperational) {
8434
- const items = fs4.readdirSync(dir, { withFileTypes: true });
8933
+ const items = fs7.readdirSync(dir, { withFileTypes: true });
8435
8934
  for (const item of items) {
8436
- if (item.isFile() && sourceExtensions.includes(path4.extname(item.name))) {
8935
+ if (item.isFile() && sourceExtensions.includes(path6.extname(item.name))) {
8437
8936
  if (item.name === "codemap.yml") continue;
8438
- if (!indexedPaths.has(path4.normalize(item.name))) {
8937
+ if (!indexedPaths.has(path6.normalize(item.name))) {
8439
8938
  errors.push(`${filePath}: Unindexed source file found: '${item.name}'. Every source file must be categorized in a section (e.g., 'internals').`);
8440
8939
  }
8441
8940
  }
@@ -8445,7 +8944,7 @@ async function optima_validate_logic(worktree) {
8445
8944
  for (const key of pathKeys) {
8446
8945
  for (const entry of getSectionEntries(map[key])) {
8447
8946
  if (!entry?.path || entry.path.startsWith("http://") || entry.path.startsWith("https://")) continue;
8448
- if (path4.isAbsolute(entry.path)) continue;
8947
+ if (path6.isAbsolute(entry.path)) continue;
8449
8948
  const normalizedPath = normalizeRelativePath(entry.path);
8450
8949
  if (!normalizedPath || normalizedPath === ".") continue;
8451
8950
  const parts = normalizedPath.split("/").filter((p) => p && p !== ".");
@@ -8457,18 +8956,18 @@ async function optima_validate_logic(worktree) {
8457
8956
  }
8458
8957
  }
8459
8958
  const walk = (dir) => {
8460
- const relDir = path4.relative(worktree, dir);
8959
+ const relDir = path6.relative(worktree, dir);
8461
8960
  if (relDir && ig.ignores(relDir)) return;
8462
8961
  if (isOperationalRelPath2(relDir)) return;
8463
8962
  if (isHiddenTree2(relDir)) return;
8464
- const hasCodemap = fs4.existsSync(path4.join(dir, "codemap.yml"));
8465
- const items = fs4.readdirSync(dir, { withFileTypes: true });
8466
- if (!relDir.startsWith(path4.join(".optima", "tasks", "done"))) {
8963
+ const hasCodemap = fs7.existsSync(path6.join(dir, "codemap.yml"));
8964
+ const items = fs7.readdirSync(dir, { withFileTypes: true });
8965
+ if (!relDir.startsWith(path6.join(".optima", "tasks", "done"))) {
8467
8966
  for (const item of items) {
8468
8967
  if (item.isFile() && item.name.endsWith(".md")) {
8469
- const content = fs4.readFileSync(path4.join(dir, item.name), "utf8");
8968
+ const content = fs7.readFileSync(path6.join(dir, item.name), "utf8");
8470
8969
  if (content.includes("[To be defined]") || content.includes("[Insert ")) {
8471
- const relFilePath = path4.join(relDir, item.name);
8970
+ const relFilePath = path6.join(relDir, item.name);
8472
8971
  errors.push(`Documentation Placeholder found: '${relFilePath}' still contains [To be defined] or [Insert ...] placeholders.`);
8473
8972
  }
8474
8973
  }
@@ -8478,9 +8977,9 @@ async function optima_validate_logic(worktree) {
8478
8977
  if (relDir !== "" && !hasCodemap && isSourceDir(dir) && !isOperational) {
8479
8978
  errors.push(`Missing CodeMap: Directory '${relDir}' contains source but has no codemap.yml.`);
8480
8979
  }
8481
- if (hasCodemap) validateMap(path4.join(dir, "codemap.yml"));
8980
+ if (hasCodemap) validateMap(path6.join(dir, "codemap.yml"));
8482
8981
  for (const item of items) {
8483
- if (item.isDirectory()) walk(path4.join(dir, item.name));
8982
+ if (item.isDirectory()) walk(path6.join(dir, item.name));
8484
8983
  }
8485
8984
  };
8486
8985
  validateMap(rootCodemapPath);
@@ -8493,14 +8992,14 @@ async function optima_validate_logic(worktree) {
8493
8992
  }
8494
8993
 
8495
8994
  // src/constants.js
8496
- import path5 from "node:path";
8995
+ import path7 from "node:path";
8497
8996
  import { fileURLToPath } from "node:url";
8498
- var PKG_ROOT = path5.resolve(path5.dirname(fileURLToPath(import.meta.url)), "..");
8499
- var BUNDLE_ASSETS_DIR = path5.join(PKG_ROOT, "assets");
8500
- var BUNDLE_AGENTS_DIR = path5.join(BUNDLE_ASSETS_DIR, "agents");
8501
- var BUNDLE_POLICIES_DIR = path5.join(BUNDLE_ASSETS_DIR, "policies");
8502
- var TEMPLATES_DIR = path5.join(PKG_ROOT, "templates");
8503
- var HUMANS_REGISTRY_PATH = path5.join(PKG_ROOT, "docs", "core", "humans.md");
8997
+ var PKG_ROOT = path7.resolve(path7.dirname(fileURLToPath(import.meta.url)), "..");
8998
+ var BUNDLE_ASSETS_DIR = path7.join(PKG_ROOT, "assets");
8999
+ var BUNDLE_AGENTS_DIR = path7.join(BUNDLE_ASSETS_DIR, "agents");
9000
+ var BUNDLE_POLICIES_DIR = path7.join(BUNDLE_ASSETS_DIR, "policies");
9001
+ var TEMPLATES_DIR = path7.join(PKG_ROOT, "templates");
9002
+ var HUMANS_REGISTRY_PATH = path7.join(PKG_ROOT, "docs", "core", "humans.md");
8504
9003
  var MANDATORY_AGENTS = /* @__PURE__ */ new Set(["product_manager", "business_analyst", "tech_lead"]);
8505
9004
  var MINI_MODE_AGENTS = /* @__PURE__ */ new Set(["product_manager", "business_analyst", "tech_lead"]);
8506
9005
  var CLICKUP_IGNORED_TASK_TYPES = ["Idea", "Backlog", "Hito", "Nota de reuni\xF3n", "Respuesta del formulario"];
@@ -8638,18 +9137,18 @@ var GITHUB_WEBHOOK_EVENTS = ["pull_request", "pull_request_review", "pull_reques
8638
9137
  var OPTIMA_GITHUB_COMMITTER_NAME = "Optima Product Manager";
8639
9138
  var OPTIMA_GITHUB_COMMITTER_EMAIL = "optima-product-manager[bot]@users.noreply.github.com";
8640
9139
  function isRootDirectory(candidate) {
8641
- const resolved = path6.resolve(candidate);
8642
- return resolved === path6.parse(resolved).root;
9140
+ const resolved = path8.resolve(candidate);
9141
+ return resolved === path8.parse(resolved).root;
8643
9142
  }
8644
9143
  function isSafeWritableDirectory(candidate) {
8645
9144
  if (typeof candidate !== "string" || !candidate.trim()) return false;
8646
- if (!path6.isAbsolute(candidate)) return false;
8647
- const resolved = path6.resolve(candidate);
9145
+ if (!path8.isAbsolute(candidate)) return false;
9146
+ const resolved = path8.resolve(candidate);
8648
9147
  if (isRootDirectory(resolved)) return false;
8649
9148
  try {
8650
- const stat = fs5.statSync(resolved);
9149
+ const stat = fs8.statSync(resolved);
8651
9150
  if (!stat.isDirectory()) return false;
8652
- fs5.accessSync(resolved, fs5.constants.W_OK);
9151
+ fs8.accessSync(resolved, fs8.constants.W_OK);
8653
9152
  return true;
8654
9153
  } catch {
8655
9154
  return false;
@@ -8661,11 +9160,11 @@ function resolveSafeWorktree(context = {}, pluginWorktree = null) {
8661
9160
  context?.directory,
8662
9161
  pluginWorktree,
8663
9162
  process.cwd(),
8664
- os.homedir()
9163
+ os2.homedir()
8665
9164
  ];
8666
9165
  for (const candidate of candidates) {
8667
9166
  if (typeof candidate !== "string" || !candidate.trim()) continue;
8668
- const resolved = path6.resolve(candidate);
9167
+ const resolved = path8.resolve(candidate);
8669
9168
  if (isSafeWritableDirectory(resolved)) return resolved;
8670
9169
  }
8671
9170
  throw new Error(SAFE_WORKTREE_FAILURE);
@@ -8680,13 +9179,13 @@ function safeWorktreeOrFailure(context, pluginWorktree) {
8680
9179
  function explicitSafeInputWorktree(input = {}) {
8681
9180
  for (const candidate of [input?.worktree, input?.directory]) {
8682
9181
  if (typeof candidate !== "string" || !candidate.trim()) continue;
8683
- const resolved = path6.resolve(candidate);
9182
+ const resolved = path8.resolve(candidate);
8684
9183
  if (isSafeWritableDirectory(resolved)) return resolved;
8685
9184
  }
8686
9185
  return null;
8687
9186
  }
8688
9187
  function isGitRepository(worktree) {
8689
- return fs5.existsSync(path6.join(worktree, ".git"));
9188
+ return fs8.existsSync(path8.join(worktree, ".git"));
8690
9189
  }
8691
9190
  function normalizeLooseToken(value) {
8692
9191
  return String(value ?? "").trim().normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
@@ -8720,8 +9219,8 @@ function parseHumansRegistry(markdown = "") {
8720
9219
  return roles;
8721
9220
  }
8722
9221
  function loadHumansRegistry(registryPath = HUMANS_REGISTRY_PATH) {
8723
- if (!fs5.existsSync(registryPath)) return {};
8724
- return parseHumansRegistry(fs5.readFileSync(registryPath, "utf8"));
9222
+ if (!fs8.existsSync(registryPath)) return {};
9223
+ return parseHumansRegistry(fs8.readFileSync(registryPath, "utf8"));
8725
9224
  }
8726
9225
  function resolveHumanRoles(roles = CLICKUP_FINAL_APPROVER_ROLES, registry = loadHumansRegistry()) {
8727
9226
  return [...new Set(roles.map((role) => registry[String(role ?? "").trim()] || "").filter(Boolean))];
@@ -8897,74 +9396,24 @@ function validateMainWorkspaceBranchSafety({ currentBranch, requiredBranch = "de
8897
9396
  const normalized = String(currentBranch ?? "").trim();
8898
9397
  if (!normalized) {
8899
9398
  return { ok: false, branch: normalized, message: "Unable to determine the current branch; expected main workspace on dev." };
8900
- }
8901
- if (normalized === forbiddenBranch) {
8902
- return { ok: false, branch: normalized, message: "Unsafe workspace branch: main is never allowed for Optima delivery work." };
8903
- }
8904
- if (normalized !== requiredBranch) {
8905
- return { ok: false, branch: normalized, message: `Unsafe workspace branch: expected ${requiredBranch}, got ${normalized}.` };
8906
- }
8907
- return { ok: true, branch: normalized, message: `Workspace branch is safe on ${requiredBranch}.` };
8908
- }
8909
- var CLICKUP_REQUIRED_SUMMARY_SECTIONS = [
8910
- "Summary",
8911
- "Work Performed",
8912
- "AC Coverage",
8913
- "Verification Results",
8914
- "Documentation Impact",
8915
- "Open Risks",
8916
- "Recommended Next Step"
8917
- ];
8918
- var CLICKUP_RAW_LOG_SECTION_NAMES = /* @__PURE__ */ new Set(["Raw Logs", "Logs", "Full Logs", "Command Output", "Transcript"]);
8919
- var CLICKUP_TRANSITIONS = /* @__PURE__ */ new Map([
8920
- ["plan->in progress", { status: "in progress", comment: "Plan complete; moving to implementation without generic CTO/PO assignment." }],
8921
- ["in progress->validation", { status: "validation", comment: "Implementation complete; ready for validation." }],
8922
- ["validation->merge", { status: "merge", assignFinalApprovers: true, parentOnlyFinalApproval: true, comment: "Parent validation passed with a functional preview URL; ready for CTO/PO approval flow." }],
8923
- ["validation->in progress", { status: "in progress", comment: "Validation failed; returning to implementation." }],
8924
- ["merge->completed", { status: "completed", comment: "Merge complete; closing delivery task." }],
8925
- ["completed->in progress", { status: "in progress", comment: "Task reopened; returning to implementation." }],
8926
- ["closed->in progress", { status: "in progress", comment: "Task reopened; returning to implementation." }]
8927
- ]);
8928
- function parseMarkdownSections(markdown = "") {
8929
- const sections = {};
8930
- let current = null;
8931
- let buffer = [];
8932
- const flush = () => {
8933
- if (!current) return;
8934
- sections[current] = buffer.join("\n").trim();
8935
- };
8936
- for (const line of String(markdown).split(/\r?\n/)) {
8937
- const heading = /^(#{2,3})\s+(.+?)\s*$/.exec(line);
8938
- if (heading) {
8939
- flush();
8940
- current = heading[2].trim();
8941
- buffer = [];
8942
- continue;
8943
- }
8944
- if (current) buffer.push(line);
8945
- }
8946
- flush();
8947
- return sections;
8948
- }
8949
- function parseMarkdownArtifact(markdown = "", { requiredSections = [] } = {}) {
8950
- const sections = parseMarkdownSections(markdown);
8951
- const missing = requiredSections.filter((section) => !sections[section]);
8952
- return {
8953
- ok: missing.length === 0,
8954
- sections,
8955
- missing,
8956
- message: missing.length ? `Missing required section(s): ${missing.join(", ")}` : "ok"
8957
- };
8958
- }
8959
- function readMarkdownArtifact(filePath, options = {}) {
8960
- const markdown = fs5.readFileSync(filePath, "utf8");
8961
- return parseMarkdownArtifact(markdown, options);
8962
- }
8963
- function stripRawLogSections(sections = {}) {
8964
- return Object.fromEntries(
8965
- Object.entries(sections).filter(([name]) => !CLICKUP_RAW_LOG_SECTION_NAMES.has(name))
8966
- );
9399
+ }
9400
+ if (normalized === forbiddenBranch) {
9401
+ return { ok: false, branch: normalized, message: "Unsafe workspace branch: main is never allowed for Optima delivery work." };
9402
+ }
9403
+ if (normalized !== requiredBranch) {
9404
+ return { ok: false, branch: normalized, message: `Unsafe workspace branch: expected ${requiredBranch}, got ${normalized}.` };
9405
+ }
9406
+ return { ok: true, branch: normalized, message: `Workspace branch is safe on ${requiredBranch}.` };
8967
9407
  }
9408
+ var CLICKUP_TRANSITIONS = /* @__PURE__ */ new Map([
9409
+ ["plan->in progress", { status: "in progress", comment: "Plan complete; moving to implementation without generic CTO/PO assignment." }],
9410
+ ["in progress->validation", { status: "validation", comment: "Implementation complete; ready for validation." }],
9411
+ ["validation->merge", { status: "merge", assignFinalApprovers: true, parentOnlyFinalApproval: true, comment: "Parent validation passed with a functional preview URL; ready for CTO/PO approval flow." }],
9412
+ ["validation->in progress", { status: "in progress", comment: "Validation failed; returning to implementation." }],
9413
+ ["merge->completed", { status: "completed", comment: "Merge complete; closing delivery task." }],
9414
+ ["completed->in progress", { status: "in progress", comment: "Task reopened; returning to implementation." }],
9415
+ ["closed->in progress", { status: "in progress", comment: "Task reopened; returning to implementation." }]
9416
+ ]);
8968
9417
  var CLICKUP_SUBTASK_REQUIRED_FIELDS = ["Type", "Owner Role", "Story Points", "Slice", "Acceptance Criteria"];
8969
9418
  var CLICKUP_SUBTASK_OPTIONAL_FIELDS = ["Depends On", "Branch", "Description", "Definition", "Documentation"];
8970
9419
  var CLICKUP_SUBTASK_KNOWN_FIELDS = /* @__PURE__ */ new Set([...CLICKUP_SUBTASK_REQUIRED_FIELDS, ...CLICKUP_SUBTASK_OPTIONAL_FIELDS]);
@@ -9168,7 +9617,7 @@ function buildClickUpApplyPayloadResult({ payload, apply = false } = {}) {
9168
9617
  noop: true,
9169
9618
  applied: false,
9170
9619
  message: "Dry-run only. Payload validated; no ClickUp calls were made.",
9171
- payload: parsed
9620
+ payload: normalizeClickUpPayloadComments(parsed)
9172
9621
  };
9173
9622
  }
9174
9623
  return {
@@ -9178,7 +9627,7 @@ function buildClickUpApplyPayloadResult({ payload, apply = false } = {}) {
9178
9627
  applyRequested: true,
9179
9628
  applied: false,
9180
9629
  message: "Live ClickUp execution is not implemented/configured in this safe boundary; no ClickUp calls were made.",
9181
- payload: parsed
9630
+ payload: normalizeClickUpPayloadComments(parsed)
9182
9631
  };
9183
9632
  }
9184
9633
  function sectionValue(sections, names) {
@@ -9188,7 +9637,7 @@ function sectionValue(sections, names) {
9188
9637
  return "";
9189
9638
  }
9190
9639
  function compactMarkdownValue(value = "") {
9191
- return String(value).split(/\r?\n/).map((line) => line.trimEnd()).join("\n").replace(/\n{3,}/g, "\n\n").trim();
9640
+ return normalizeClickUpMarkdown(value);
9192
9641
  }
9193
9642
  function buildClickUpSummaryPayload({ summaryMarkdown = "", summaryPath = "", taskMarkdown = "", taskPath = "", branch = "", worktree = "", pr = "" } = {}) {
9194
9643
  const parsedSummary = parseMarkdownArtifact(summaryMarkdown, { requiredSections: CLICKUP_REQUIRED_SUMMARY_SECTIONS });
@@ -9213,13 +9662,12 @@ function buildClickUpSummaryPayload({ summaryMarkdown = "", summaryPath = "", ta
9213
9662
  deliveryPath ? `- Delivery evidence: ${compactMarkdownValue(deliveryPath)}` : null,
9214
9663
  prValue ? `- PR: ${compactMarkdownValue(prValue)}` : null
9215
9664
  ].filter(Boolean);
9216
- const comment = [
9217
- "ClickUp sync payload generated from Optima Markdown artifacts.",
9218
- "",
9219
- ...commentParts.flatMap(([title, value]) => [`## ${title}`, compactMarkdownValue(value) || "Not specified.", ""]),
9220
- contextParts.length ? "## PR/Branch/Worktree" : null,
9221
- contextParts.length ? contextParts.join("\n") : null
9222
- ].filter((part) => part !== null).join("\n").trim();
9665
+ const comment = formatClickUpStatusComment({
9666
+ title: "Optima Delivery Summary",
9667
+ summary: "ClickUp sync payload generated from Optima Markdown artifacts.",
9668
+ sections: commentParts.map(([title, value]) => ({ title, body: compactMarkdownValue(value) || "Not specified." })),
9669
+ context: contextParts
9670
+ });
9223
9671
  return {
9224
9672
  ok: true,
9225
9673
  mode: "payload",
@@ -9245,7 +9693,7 @@ function buildClickUpSummaryPayload({ summaryMarkdown = "", summaryPath = "", ta
9245
9693
  function deriveClickUpWorktree({ baseWorktree = "", taskId, taskType, parentTaskId, subtaskId } = {}) {
9246
9694
  const branch = deriveClickUpBranchName({ taskType, parentTaskId, subtaskId, taskId });
9247
9695
  const root = baseWorktree || process.cwd();
9248
- return path6.join(path6.dirname(root), `${path6.basename(root)}-${branch.replace(/\//g, "-")}`);
9696
+ return path8.join(path8.dirname(root), `${path8.basename(root)}-${branch.replace(/\//g, "-")}`);
9249
9697
  }
9250
9698
  function clickUpCustomFieldValue(task = {}, names = []) {
9251
9699
  const fields = Array.isArray(task.custom_fields) ? task.custom_fields : [];
@@ -9269,12 +9717,12 @@ function safeExistingClickUpWorktree({ metadata = {}, branch = "" } = {}) {
9269
9717
  const taskMetadata = metadataTaskRouting(metadata);
9270
9718
  const existingWorktree = typeof taskMetadata.worktree === "string" ? taskMetadata.worktree.trim() : "";
9271
9719
  const existingBranch = typeof taskMetadata.branch === "string" ? taskMetadata.branch.trim() : "";
9272
- if (!existingWorktree || !path6.isAbsolute(existingWorktree) || !fs5.existsSync(existingWorktree)) return null;
9720
+ if (!existingWorktree || !path8.isAbsolute(existingWorktree) || !fs8.existsSync(existingWorktree)) return null;
9273
9721
  try {
9274
- const stat = fs5.statSync(existingWorktree);
9722
+ const stat = fs8.statSync(existingWorktree);
9275
9723
  if (!stat.isDirectory()) return null;
9276
9724
  if (branch && existingBranch && existingBranch !== branch) return null;
9277
- return { branch: existingBranch || branch, worktree: path6.resolve(existingWorktree), reused: true };
9725
+ return { branch: existingBranch || branch, worktree: path8.resolve(existingWorktree), reused: true };
9278
9726
  } catch {
9279
9727
  return null;
9280
9728
  }
@@ -9308,7 +9756,7 @@ function normalizeOptimaGitIdentity(identity = {}) {
9308
9756
  };
9309
9757
  }
9310
9758
  function configureOptimaWorktreeGitIdentity({ worktreePath, identity = {}, runGitFn = runGit } = {}) {
9311
- if (!worktreePath || !fs5.existsSync(worktreePath)) return { configured: false, reason: "worktree_missing" };
9759
+ if (!worktreePath || !fs8.existsSync(worktreePath)) return { configured: false, reason: "worktree_missing" };
9312
9760
  const normalized = normalizeOptimaGitIdentity(identity);
9313
9761
  if (!normalized.name || !normalized.email) return { configured: false, reason: "identity_missing" };
9314
9762
  try {
@@ -9394,17 +9842,17 @@ function openChamberEntryBranch(entry) {
9394
9842
  return String(entry?.branch || entry?.branchName || entry?.branch_name || entry?.worktree?.branch || "").replace(/^refs\/heads\//, "");
9395
9843
  }
9396
9844
  function openChamberListIncludesDirectory(list, directory) {
9397
- const resolved = path6.resolve(directory);
9845
+ const resolved = path8.resolve(directory);
9398
9846
  return normalizeOpenChamberCollection(list).some((entry) => {
9399
9847
  const entryDirectory = openChamberEntryDirectory(entry);
9400
- return entryDirectory && path6.resolve(entryDirectory) === resolved;
9848
+ return entryDirectory && path8.resolve(entryDirectory) === resolved;
9401
9849
  });
9402
9850
  }
9403
9851
  function openChamberListIncludesBranch(list, directory, branch) {
9404
- const resolved = path6.resolve(directory);
9852
+ const resolved = path8.resolve(directory);
9405
9853
  return normalizeOpenChamberCollection(list).some((entry) => {
9406
9854
  const entryDirectory = openChamberEntryDirectory(entry);
9407
- if (!entryDirectory || path6.resolve(entryDirectory) !== resolved) return false;
9855
+ if (!entryDirectory || path8.resolve(entryDirectory) !== resolved) return false;
9408
9856
  const entryBranch = openChamberEntryBranch(entry);
9409
9857
  return !entryBranch || entryBranch === branch;
9410
9858
  });
@@ -9412,8 +9860,8 @@ function openChamberListIncludesBranch(list, directory, branch) {
9412
9860
  async function findOpenChamberProject({ opencodeBaseUrl, baseWorktree, fetchImpl = globalThis.fetch } = {}) {
9413
9861
  const projects = await requestOpenCodeJson({ baseUrl: opencodeBaseUrl, endpoint: "/project", directory: baseWorktree, fetchImpl });
9414
9862
  if (!Array.isArray(projects)) return null;
9415
- const resolvedBase = path6.resolve(baseWorktree);
9416
- return projects.find((project) => path6.resolve(String(project?.worktree || project?.path || "")) === resolvedBase) || null;
9863
+ const resolvedBase = path8.resolve(baseWorktree);
9864
+ return projects.find((project) => path8.resolve(String(project?.worktree || project?.path || "")) === resolvedBase) || null;
9417
9865
  }
9418
9866
  async function refreshOpenChamberProjectCopy({ opencodeBaseUrl, projectId, fetchImpl = globalThis.fetch } = {}) {
9419
9867
  if (!projectId) return { refreshed: false, reason: "project_id_unavailable" };
@@ -9468,18 +9916,18 @@ async function createOpenChamberClickUpWorktree({ openchamberBaseUrl, baseUrl, b
9468
9916
  }
9469
9917
  const createdDirectory = openChamberEntryDirectory(created);
9470
9918
  const createdBranch = openChamberEntryBranch(created);
9471
- if (!createdDirectory || !path6.isAbsolute(createdDirectory)) {
9919
+ if (!createdDirectory || !path8.isAbsolute(createdDirectory)) {
9472
9920
  throw new Error(`OpenChamber did not return an absolute worktree path for ${branch}.`);
9473
9921
  }
9474
9922
  if (createdBranch !== branch) {
9475
9923
  throw new Error(`OpenChamber created unexpected branch ${createdBranch || "<unknown>"}; expected ${branch}.`);
9476
9924
  }
9477
9925
  const verified = await verifyOpenChamberGitWorktree({ openchamberBaseUrl: effectiveOpenChamberBaseUrl, baseWorktree, worktreePath: createdDirectory, branch, fetchImpl });
9478
- return { created, worktree: path6.resolve(createdDirectory), branch: createdBranch, verified };
9926
+ return { created, worktree: path8.resolve(createdDirectory), branch: createdBranch, verified };
9479
9927
  }
9480
9928
  async function registerOpenChamberClickUpWorktree({ openchamberBaseUrl, opencodeBaseUrl, baseUrl, baseWorktree, branch, worktreePath, fetchImpl = globalThis.fetch, source = "reuse" } = {}) {
9481
9929
  const visibility = await syncOpenChamberWorktreeVisibility({ openchamberBaseUrl: openchamberBaseUrl || baseUrl, opencodeBaseUrl: opencodeBaseUrl || baseUrl, baseWorktree, worktreePath, branch, fetchImpl });
9482
- return { branch, worktree: path6.resolve(worktreePath), reused: true, provider: "openchamber", openChamber: { source, visibility } };
9930
+ return { branch, worktree: path8.resolve(worktreePath), reused: true, provider: "openchamber", openChamber: { source, visibility } };
9483
9931
  }
9484
9932
  async function ensureClickUpTaskWorktreeOpenChamber({ baseWorktree = "", taskId, taskType = "Tarea", parentTaskId = "", subtaskId = "", existingMetadata = {}, runGitFn = runGit, openchamberBaseUrl = "", opencodeBaseUrl = "", baseUrl = "", fetchImpl = globalThis.fetch, log = null, gitIdentity = {} } = {}) {
9485
9933
  const effectiveOpenChamberBaseUrl = openchamberBaseUrl || baseUrl;
@@ -9497,7 +9945,7 @@ async function ensureClickUpTaskWorktreeOpenChamber({ baseWorktree = "", taskId,
9497
9945
  return { ...registered, parentBranch: parentBranch || void 0, prTarget, gitIdentity: identity2 };
9498
9946
  }
9499
9947
  const worktreePath = deriveClickUpWorktree({ baseWorktree, taskId, taskType, parentTaskId: effectiveParent, subtaskId });
9500
- if (fs5.existsSync(worktreePath)) {
9948
+ if (fs8.existsSync(worktreePath)) {
9501
9949
  const registered = await registerOpenChamberClickUpWorktree({ openchamberBaseUrl: effectiveOpenChamberBaseUrl, opencodeBaseUrl: effectiveOpenCodeBaseUrl, baseWorktree, branch, worktreePath, fetchImpl, source: "existing_directory" });
9502
9950
  const identity2 = configureOptimaWorktreeGitIdentity({ worktreePath: registered.worktree, identity: gitIdentity, runGitFn });
9503
9951
  log?.({ type: "openchamber_worktree_registered", taskId, branch, worktree: registered.worktree, source: "existing_directory", visibility: registered.openChamber.visibility });
@@ -9506,7 +9954,7 @@ async function ensureClickUpTaskWorktreeOpenChamber({ baseWorktree = "", taskId,
9506
9954
  let parentBootstrap = null;
9507
9955
  if (isSubtask) {
9508
9956
  const parentWorktree = deriveClickUpWorktree({ baseWorktree, taskId: effectiveParent, taskType, parentTaskId: effectiveParent });
9509
- if (fs5.existsSync(parentWorktree)) {
9957
+ if (fs8.existsSync(parentWorktree)) {
9510
9958
  const registeredParent = await registerOpenChamberClickUpWorktree({ openchamberBaseUrl: effectiveOpenChamberBaseUrl, opencodeBaseUrl: effectiveOpenCodeBaseUrl, baseWorktree, branch: parentBranch, worktreePath: parentWorktree, fetchImpl, source: "parent_existing_directory" });
9511
9959
  const parentIdentity = configureOptimaWorktreeGitIdentity({ worktreePath: registeredParent.worktree, identity: gitIdentity, runGitFn });
9512
9960
  parentBootstrap = { branch: parentBranch, worktree: registeredParent.worktree, reused: true, provider: "openchamber", visibility: registeredParent.openChamber.visibility };
@@ -9549,33 +9997,33 @@ function ensureClickUpTaskWorktree({ baseWorktree = "", taskId, taskType = "Tare
9549
9997
  const existing = safeExistingClickUpWorktree({ metadata: existingMetadata, branch });
9550
9998
  if (existing) return { ...existing, branch, parentBranch: parentBranch || void 0, prTarget: parentBranch || "dev", gitIdentity: configureOptimaWorktreeGitIdentity({ worktreePath: existing.worktree, identity: gitIdentity, runGitFn }) };
9551
9999
  const worktreePath = deriveClickUpWorktree({ baseWorktree, taskId, taskType, parentTaskId: effectiveParent, subtaskId });
9552
- if (fs5.existsSync(worktreePath)) {
9553
- const resolvedWorktree2 = path6.resolve(worktreePath);
10000
+ if (fs8.existsSync(worktreePath)) {
10001
+ const resolvedWorktree2 = path8.resolve(worktreePath);
9554
10002
  return { branch, worktree: resolvedWorktree2, reused: true, parentBranch: parentBranch || void 0, prTarget: parentBranch || "dev", gitIdentity: configureOptimaWorktreeGitIdentity({ worktreePath: resolvedWorktree2, identity: gitIdentity, runGitFn }) };
9555
10003
  }
9556
10004
  if (allowNonGitFallback) {
9557
- fs5.mkdirSync(worktreePath, { recursive: true });
9558
- return { branch, worktree: path6.resolve(worktreePath), reused: false, fallback: "non_git", parentBranch: parentBranch || void 0, prTarget: parentBranch || "dev", startPoint: parentBranch || "dev" };
10005
+ fs8.mkdirSync(worktreePath, { recursive: true });
10006
+ return { branch, worktree: path8.resolve(worktreePath), reused: false, fallback: "non_git", parentBranch: parentBranch || void 0, prTarget: parentBranch || "dev", startPoint: parentBranch || "dev" };
9559
10007
  }
9560
10008
  let parentBootstrap = null;
9561
10009
  if (isSubtask) {
9562
10010
  const parentWorktree = deriveClickUpWorktree({ baseWorktree, taskId: effectiveParent, taskType, parentTaskId: effectiveParent });
9563
- if (!fs5.existsSync(parentWorktree)) {
10011
+ if (!fs8.existsSync(parentWorktree)) {
9564
10012
  const parentStartPoint = resolveClickUpDevStartPoint(baseWorktree, runGitFn);
9565
10013
  const parentBranchExists = clickUpGitRefExists(baseWorktree, parentBranch, runGitFn);
9566
10014
  addClickUpWorktreeForBranch({ baseWorktree, branch: parentBranch, worktreePath: parentWorktree, startPoint: parentStartPoint, runGitFn });
9567
- parentBootstrap = { branch: parentBranch, worktree: path6.resolve(parentWorktree), startPoint: parentBranchExists ? parentBranch : parentStartPoint, reused: parentBranchExists };
10015
+ parentBootstrap = { branch: parentBranch, worktree: path8.resolve(parentWorktree), startPoint: parentBranchExists ? parentBranch : parentStartPoint, reused: parentBranchExists };
9568
10016
  const parentIdentity = configureOptimaWorktreeGitIdentity({ worktreePath: parentBootstrap.worktree, identity: gitIdentity, runGitFn });
9569
10017
  if (parentIdentity.configured) parentBootstrap.gitIdentity = parentIdentity;
9570
10018
  } else {
9571
- parentBootstrap = { branch: parentBranch, worktree: path6.resolve(parentWorktree), reused: true };
10019
+ parentBootstrap = { branch: parentBranch, worktree: path8.resolve(parentWorktree), reused: true };
9572
10020
  const parentIdentity = configureOptimaWorktreeGitIdentity({ worktreePath: parentBootstrap.worktree, identity: gitIdentity, runGitFn });
9573
10021
  if (parentIdentity.configured) parentBootstrap.gitIdentity = parentIdentity;
9574
10022
  }
9575
10023
  }
9576
10024
  const startPoint = isSubtask ? parentBranch : resolveClickUpDevStartPoint(baseWorktree, runGitFn);
9577
10025
  addClickUpWorktreeForBranch({ baseWorktree, branch, worktreePath, startPoint, runGitFn });
9578
- const resolvedWorktree = path6.resolve(worktreePath);
10026
+ const resolvedWorktree = path8.resolve(worktreePath);
9579
10027
  return { branch, worktree: resolvedWorktree, reused: false, startPoint, parentBranch: parentBranch || void 0, prTarget: parentBranch || "dev", parentBootstrap: parentBootstrap || void 0, gitIdentity: configureOptimaWorktreeGitIdentity({ worktreePath: resolvedWorktree, identity: gitIdentity, runGitFn }) };
9580
10028
  }
9581
10029
  function normalizeClickUpDefinitionDocParent(parent = {}) {
@@ -9658,7 +10106,17 @@ function buildClickUpStartTaskPayload({ taskId, taskType = "Tarea", parentTaskId
9658
10106
  wouldCreate: true
9659
10107
  },
9660
10108
  clickup: {
9661
- comment: `Starting task from ${startFrom}. Branch: ${branch}. Worktree: ${worktree}. Validation PR target: ${requiredPullRequest.targetBranch}. Delivery evidence: ${deliveryEvidencePathForClickUpTask(taskId || subtaskId || effectiveParent)}.`,
10109
+ comment: formatClickUpStatusComment({
10110
+ title: "Task Workspace Ready",
10111
+ summary: "Optima prepared the task workspace and validation target.",
10112
+ context: [
10113
+ `Branch: ${branch}`,
10114
+ `Start from: ${startFrom}`,
10115
+ `Worktree: ${worktree}`,
10116
+ `Validation PR target: ${requiredPullRequest.targetBranch}`,
10117
+ `Delivery evidence: ${deliveryEvidencePathForClickUpTask(taskId || subtaskId || effectiveParent)}`
10118
+ ]
10119
+ }),
9662
10120
  description,
9663
10121
  fields: {
9664
10122
  Definition: definitionContent,
@@ -9744,7 +10202,18 @@ function buildClickUpTransitionPayload({ fromStatus, toStatus, validationPassed
9744
10202
  remove: removalTargets,
9745
10203
  objective: assignsFinalApprovers ? "zero_product_manager_assigned_tasks" : "preserve_existing_owner_policy"
9746
10204
  },
9747
- comment: rule.comment,
10205
+ comment: formatClickUpStatusComment({
10206
+ title: "Workflow Status Update",
10207
+ summary: rule.comment,
10208
+ context: [
10209
+ `From: ${from}`,
10210
+ `To: ${rule.status}`,
10211
+ requiredPullRequest?.prUrl ? `PR: ${requiredPullRequest.prUrl}` : null,
10212
+ requiredPullRequest?.prNumber ? `PR number: ${requiredPullRequest.prNumber}` : null,
10213
+ requiredPullRequest?.sourceBranch ? `Source branch: ${requiredPullRequest.sourceBranch}` : null,
10214
+ requiredPullRequest?.targetBranch ? `Target branch: ${requiredPullRequest.targetBranch}` : null
10215
+ ].filter(Boolean)
10216
+ }),
9748
10217
  description,
9749
10218
  fields,
9750
10219
  definition_doc: definitionContent ? {
@@ -9757,8 +10226,8 @@ function buildClickUpTransitionPayload({ fromStatus, toStatus, validationPassed
9757
10226
  }
9758
10227
  function ensureOptimaGitignoreRules(worktree) {
9759
10228
  if (!isGitRepository(worktree)) return { touched: false, added: [] };
9760
- const gitignorePath = path6.join(worktree, ".gitignore");
9761
- const existing = fs5.existsSync(gitignorePath) ? fs5.readFileSync(gitignorePath, "utf8") : "";
10229
+ const gitignorePath = path8.join(worktree, ".gitignore");
10230
+ const existing = fs8.existsSync(gitignorePath) ? fs8.readFileSync(gitignorePath, "utf8") : "";
9762
10231
  const existingRules = new Set(existing.split(/\r?\n/).map((line) => line.trim()).filter(Boolean));
9763
10232
  const missingRules = OPTIMA_GITIGNORE_RULES.filter((rule) => !existingRules.has(rule));
9764
10233
  if (missingRules.length === 0) return { touched: false, added: [] };
@@ -9768,45 +10237,45 @@ function ensureOptimaGitignoreRules(worktree) {
9768
10237
  "# Optima local/private state",
9769
10238
  ...missingRules
9770
10239
  ].join("\n");
9771
- fs5.writeFileSync(gitignorePath, `${existing}${prefix}${separator}${block}
10240
+ fs8.writeFileSync(gitignorePath, `${existing}${prefix}${separator}${block}
9772
10241
  `, "utf8");
9773
10242
  return { touched: true, added: missingRules };
9774
10243
  }
9775
10244
  function optimaDir(worktree) {
9776
- return path6.join(worktree, OPTIMA_DIRNAME);
10245
+ return path8.join(worktree, OPTIMA_DIRNAME);
9777
10246
  }
9778
10247
  function optimaLocalConfigDir(worktree) {
9779
- return path6.join(optimaDir(worktree), ".config");
10248
+ return path8.join(optimaDir(worktree), ".config");
9780
10249
  }
9781
10250
  function optimaConfigDir(worktree) {
9782
10251
  return optimaLocalConfigDir(worktree);
9783
10252
  }
9784
10253
  function optimaCodemapPath(worktree) {
9785
- return path6.join(optimaDir(worktree), "codemap.yml");
10254
+ return path8.join(optimaDir(worktree), "codemap.yml");
9786
10255
  }
9787
10256
  function optimaTasksDir(worktree) {
9788
- return path6.join(optimaDir(worktree), "tasks");
10257
+ return path8.join(optimaDir(worktree), "tasks");
9789
10258
  }
9790
10259
  function optimaEvidencesDir(worktree) {
9791
- return path6.join(optimaDir(worktree), "evidences");
10260
+ return path8.join(optimaDir(worktree), "evidences");
9792
10261
  }
9793
10262
  function optimaScrsDir(worktree) {
9794
- return path6.join(optimaDir(worktree), "docs", "scrs");
10263
+ return path8.join(optimaDir(worktree), "docs", "scrs");
9795
10264
  }
9796
10265
  function legacyNomadworkDir(worktree) {
9797
- return path6.join(worktree, LEGACY_NOMADWORK_DIRNAME);
10266
+ return path8.join(worktree, LEGACY_NOMADWORK_DIRNAME);
9798
10267
  }
9799
10268
  function legacyNomadworksDir(worktree) {
9800
- return path6.join(worktree, LEGACY_NOMADWORKS_DIRNAME);
10269
+ return path8.join(worktree, LEGACY_NOMADWORKS_DIRNAME);
9801
10270
  }
9802
10271
  function legacyOrbitaDir(worktree) {
9803
- return path6.join(worktree, LEGACY_ORBITA_DIRNAME);
10272
+ return path8.join(worktree, LEGACY_ORBITA_DIRNAME);
9804
10273
  }
9805
10274
  function legacyStaticEngDir(worktree) {
9806
- return path6.join(worktree, LEGACY_STATICENG_DIRNAME);
10275
+ return path8.join(worktree, LEGACY_STATICENG_DIRNAME);
9807
10276
  }
9808
10277
  function repoConfigPath(worktree) {
9809
- return path6.join(optimaConfigDir(worktree), "optima.yaml");
10278
+ return path8.join(optimaConfigDir(worktree), "optima.yaml");
9810
10279
  }
9811
10280
  function normalizeLegacyDiscussionEntry(entry) {
9812
10281
  if (!entry || typeof entry !== "object") return entry;
@@ -9819,25 +10288,25 @@ function normalizeLegacyDiscussionEntry(entry) {
9819
10288
  return next;
9820
10289
  }
9821
10290
  function repoPoliciesDir(worktree) {
9822
- return path6.join(optimaDir(worktree), "policies");
10291
+ return path8.join(optimaDir(worktree), "policies");
9823
10292
  }
9824
10293
  function generatedPoliciesDir(worktree) {
9825
- return path6.join(optimaLocalConfigDir(worktree), "generated", "policies");
10294
+ return path8.join(optimaLocalConfigDir(worktree), "generated", "policies");
9826
10295
  }
9827
10296
  function generatedAgentsDir(worktree) {
9828
- return path6.join(optimaLocalConfigDir(worktree), "generated", "agents");
10297
+ return path8.join(optimaLocalConfigDir(worktree), "generated", "agents");
9829
10298
  }
9830
10299
  function repoAgentsDir(worktree) {
9831
- return path6.join(optimaDir(worktree), "agents");
10300
+ return path8.join(optimaDir(worktree), "agents");
9832
10301
  }
9833
10302
  function repoAgentAdditionsDir(worktree) {
9834
- return path6.join(optimaDir(worktree), "agent-additions");
10303
+ return path8.join(optimaDir(worktree), "agent-additions");
9835
10304
  }
9836
10305
  function legacyRepoAgentsDir(worktree) {
9837
- return path6.join(legacyNomadworksDir(worktree), "agents");
10306
+ return path8.join(legacyNomadworksDir(worktree), "agents");
9838
10307
  }
9839
10308
  function runtimeDiscussionRegistryPath(worktree) {
9840
- return path6.join(optimaLocalConfigDir(worktree), "runtime", "discussions.json");
10309
+ return path8.join(optimaLocalConfigDir(worktree), "runtime", "discussions.json");
9841
10310
  }
9842
10311
  function resolveConfigPath(worktree) {
9843
10312
  return repoConfigPath(worktree);
@@ -9880,32 +10349,32 @@ function mergeClickUpAgentMetadata(existing, update = {}) {
9880
10349
  return JSON.stringify(sortJsonValue(merged), null, 2);
9881
10350
  }
9882
10351
  function optimaRuntimeDir(worktree) {
9883
- return path6.join(optimaLocalConfigDir(worktree), "runtime");
10352
+ return path8.join(optimaLocalConfigDir(worktree), "runtime");
9884
10353
  }
9885
10354
  function clickUpWebhookStatePath(worktree) {
9886
- return path6.join(optimaRuntimeDir(worktree), "clickup-webhook.json");
10355
+ return path8.join(optimaRuntimeDir(worktree), "clickup-webhook.json");
9887
10356
  }
9888
10357
  function clickUpCommentLedgerPath(worktree) {
9889
- return path6.join(optimaRuntimeDir(worktree), "clickup-comment-ledger.jsonl");
10358
+ return path8.join(optimaRuntimeDir(worktree), "clickup-comment-ledger.jsonl");
9890
10359
  }
9891
10360
  function clickUpWebhookLogPath(worktree) {
9892
- return path6.join(optimaRuntimeDir(worktree), "clickup-webhook.log.jsonl");
10361
+ return path8.join(optimaRuntimeDir(worktree), "clickup-webhook.log.jsonl");
9893
10362
  }
9894
10363
  function normalizeClickUpWebhookLogLevel(value) {
9895
10364
  const level = String(value || "info").trim().toLowerCase();
9896
10365
  return CLICKUP_WEBHOOK_LOG_LEVELS.has(level) ? level : "info";
9897
10366
  }
9898
10367
  function clickUpWebhookAuditLogDir() {
9899
- 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");
9900
- return path6.join(dataHome, "opencode-optima");
10368
+ const dataHome = process.env.XDG_DATA_HOME && path8.isAbsolute(process.env.XDG_DATA_HOME) ? process.env.XDG_DATA_HOME : path8.join(os2.homedir(), ".local", "share", "opencode");
10369
+ return path8.join(dataHome, "opencode-optima");
9901
10370
  }
9902
10371
  function clickUpWebhookAuditLogPath(at = /* @__PURE__ */ new Date(), logDir = clickUpWebhookAuditLogDir()) {
9903
- return path6.join(logDir, `clickup-webhook-${at.toISOString().slice(0, 10)}.jsonl`);
10372
+ return path8.join(logDir, `clickup-webhook-${at.toISOString().slice(0, 10)}.jsonl`);
9904
10373
  }
9905
10374
  function clickUpWebhookRequestFilePath(at = /* @__PURE__ */ new Date(), logDir = clickUpWebhookAuditLogDir()) {
9906
10375
  const stamp = at.toISOString().replace(/:/g, "-").replace(/\./g, "-");
9907
- const shortId = crypto.randomBytes(4).toString("hex");
9908
- return path6.join(logDir, "requests", `clickup-webhook-${stamp}-${shortId}.json`);
10376
+ const shortId = crypto2.randomBytes(4).toString("hex");
10377
+ return path8.join(logDir, "requests", `clickup-webhook-${stamp}-${shortId}.json`);
9909
10378
  }
9910
10379
  function findOptimaPluginTupleOptions(pluginEntries = []) {
9911
10380
  if (!Array.isArray(pluginEntries)) return null;
@@ -10065,7 +10534,7 @@ function normalizeClickUpWebhookConfig(rawClickUp = null, worktree = process.cwd
10065
10534
  };
10066
10535
  const errors = [];
10067
10536
  if (!config.enabled) errors.push("clickup.enabled must be true");
10068
- if (!config.basePath || !path6.isAbsolute(config.basePath)) errors.push("clickup.base_path must be an absolute path");
10537
+ if (!config.basePath || !path8.isAbsolute(config.basePath)) errors.push("clickup.base_path must be an absolute path");
10069
10538
  if (!config.teamId) errors.push("clickup.team_id is required");
10070
10539
  if (!config.apiToken) errors.push("clickup.api_token is required");
10071
10540
  if (!config.webhook.publicUrl) errors.push("clickup.webhook.public_url is required");
@@ -10128,503 +10597,94 @@ function sanitizeClickUpWebhookState(state = {}, config = null) {
10128
10597
  }
10129
10598
  function readClickUpWebhookState(worktree, config = null) {
10130
10599
  const statePath = clickUpWebhookStatePath(worktree);
10131
- if (!fs5.existsSync(statePath)) return sanitizeClickUpWebhookState({}, config);
10600
+ if (!fs8.existsSync(statePath)) return sanitizeClickUpWebhookState({}, config);
10132
10601
  try {
10133
- return sanitizeClickUpWebhookState(JSON.parse(fs5.readFileSync(statePath, "utf8")), config);
10602
+ return sanitizeClickUpWebhookState(JSON.parse(fs8.readFileSync(statePath, "utf8")), config);
10134
10603
  } catch {
10135
10604
  return sanitizeClickUpWebhookState({}, config);
10136
10605
  }
10137
10606
  }
10138
10607
  function writeClickUpWebhookState(worktree, state, config = null) {
10139
10608
  const statePath = clickUpWebhookStatePath(worktree);
10140
- fs5.mkdirSync(path6.dirname(statePath), { recursive: true, mode: 448 });
10609
+ fs8.mkdirSync(path8.dirname(statePath), { recursive: true, mode: 448 });
10141
10610
  const next = sanitizeClickUpWebhookState(state, config);
10142
- fs5.writeFileSync(statePath, `${JSON.stringify(next, null, 2)}
10611
+ fs8.writeFileSync(statePath, `${JSON.stringify(next, null, 2)}
10143
10612
  `, { encoding: "utf8", mode: 384 });
10144
10613
  try {
10145
- fs5.chmodSync(statePath, 384);
10614
+ fs8.chmodSync(statePath, 384);
10146
10615
  } catch {
10147
10616
  }
10148
10617
  return next;
10149
10618
  }
10150
10619
  function isClickUpWebhookStateActive(state, config) {
10151
- const expectedEvents = new Set(config?.webhook?.events || []);
10152
- const actualEvents = new Set(state?.events || []);
10153
- const hasEvents = [...expectedEvents].every((event) => actualEvents.has(event));
10154
- return Boolean(
10155
- state?.active && state?.webhookId && state?.secret && state?.publicUrl === config?.webhook?.publicUrl && hasEvents
10156
- );
10157
- }
10158
- function expandHomePath(value = "") {
10159
- const input = String(value || "").trim();
10160
- if (input === "~") return os.homedir();
10161
- if (input.startsWith("~/")) return path6.join(os.homedir(), input.slice(2));
10162
- return input;
10163
- }
10164
- function resolveSecretReference(value = "") {
10165
- const raw = String(value || "").trim();
10166
- const envMatch = raw.match(/^\{env:([A-Za-z_][A-Za-z0-9_]*)\}$/);
10167
- if (envMatch) return process.env[envMatch[1]] || "";
10168
- const fileMatch = raw.match(/^\{file:(.+)\}$/);
10169
- if (fileMatch) {
10170
- try {
10171
- return fs5.readFileSync(expandHomePath(fileMatch[1]), "utf8").trim();
10172
- } catch {
10173
- return "";
10174
- }
10175
- }
10176
- return raw;
10177
- }
10178
- function createClickUpApiClient(config, fetchImpl = globalThis.fetch) {
10179
- const token = resolveSecretReference(config?.apiToken);
10180
- const request = async (url, options = {}) => {
10181
- if (typeof fetchImpl !== "function") throw new Error("fetch is unavailable; inject a ClickUp client for live webhook setup");
10182
- if (!token) throw new Error("ClickUp API token is not available");
10183
- const response = await fetchImpl(url, {
10184
- ...options,
10185
- headers: {
10186
- Authorization: token,
10187
- "Content-Type": "application/json",
10188
- ...options.headers || {}
10189
- }
10190
- });
10191
- if (!response.ok) throw new Error(`ClickUp API request failed: ${response.status}`);
10192
- return response.json();
10193
- };
10194
- return {
10195
- async createWebhook({ endpoint, events, location }) {
10196
- const body = { endpoint, events, ...Object.fromEntries(Object.entries(location || {}).filter(([, value]) => value)) };
10197
- return request(`https://api.clickup.com/api/v2/team/${encodeURIComponent(config.teamId)}/webhook`, {
10198
- method: "POST",
10199
- body: JSON.stringify(body)
10200
- });
10201
- },
10202
- async listWebhooks() {
10203
- return request(`https://api.clickup.com/api/v2/team/${encodeURIComponent(config.teamId)}/webhook`);
10204
- },
10205
- async deleteWebhook(webhookId) {
10206
- return request(`https://api.clickup.com/api/v2/webhook/${encodeURIComponent(webhookId)}`, { method: "DELETE" });
10207
- },
10208
- async getAuthorizedUser() {
10209
- return request("https://api.clickup.com/api/v2/user");
10210
- },
10211
- async getTask(taskId) {
10212
- return request(`https://api.clickup.com/api/v2/task/${encodeURIComponent(taskId)}`);
10213
- },
10214
- async updateTaskMetadata({ taskId, fieldId, value }) {
10215
- return request(`https://api.clickup.com/api/v2/task/${encodeURIComponent(taskId)}/field/${encodeURIComponent(fieldId)}`, {
10216
- method: "POST",
10217
- body: JSON.stringify({ value })
10218
- });
10219
- },
10220
- async postTaskComment() {
10221
- throw new Error("Optima runtime does not post ClickUp task comments; use local logs for process failures.");
10222
- },
10223
- async addTaskTag() {
10224
- throw new Error("Optima runtime does not add ClickUp task tags; use local logs for process failures.");
10225
- },
10226
- async listAssignedTasks({ assigneeId, statuses = [], limit = CLICKUP_WEBHOOK_STARTUP_TASK_LIMIT } = {}) {
10227
- const params = new URLSearchParams();
10228
- if (assigneeId) params.append("assignees[]", assigneeId);
10229
- for (const status of statuses) if (status) params.append("statuses[]", status);
10230
- if (limit) params.append("limit", String(limit));
10231
- return request(`https://api.clickup.com/api/v2/team/${encodeURIComponent(config.teamId)}/task?${params.toString()}`);
10232
- },
10233
- async getTaskComments({ taskId, start, limit = CLICKUP_WEBHOOK_STARTUP_COMMENT_LIMIT } = {}) {
10234
- const params = new URLSearchParams();
10235
- if (start) params.set("start", String(start));
10236
- if (limit) params.set("limit", String(limit));
10237
- const suffix = params.toString() ? `?${params.toString()}` : "";
10238
- return request(`https://api.clickup.com/api/v2/task/${encodeURIComponent(taskId)}/comment${suffix}`);
10239
- }
10240
- };
10241
- }
10242
- function base64UrlJson(value) {
10243
- return Buffer.from(JSON.stringify(value)).toString("base64url");
10244
- }
10245
- function resolveGitHubAppPrivateKey(app = {}) {
10246
- const direct = resolveSecretReference(app.privateKey || "");
10247
- if (direct) return direct.replace(/\\n/g, "\n");
10248
- const file = expandHomePath(app.privateKeyFile || "");
10249
- if (!file) return "";
10250
- try {
10251
- return fs5.readFileSync(file, "utf8").trim().replace(/\\n/g, "\n");
10252
- } catch {
10253
- return "";
10254
- }
10255
- }
10256
- function createGitHubAppJwt({ appId, privateKey, now = () => /* @__PURE__ */ new Date() } = {}) {
10257
- const key = String(privateKey || "").trim();
10258
- const issuer = String(appId || "").trim();
10259
- if (!issuer || !key) throw new Error("GitHub App app_id and private key are required");
10260
- const nowSeconds = Math.floor(now().getTime() / 1e3);
10261
- const header = base64UrlJson({ alg: "RS256", typ: "JWT" });
10262
- const payload = base64UrlJson({ iat: nowSeconds - 60, exp: nowSeconds + 540, iss: issuer });
10263
- const unsigned = `${header}.${payload}`;
10264
- const signature = crypto.createSign("RSA-SHA256").update(unsigned).end().sign(key, "base64url");
10265
- return `${unsigned}.${signature}`;
10266
- }
10267
- function encodeGitHubPathSegment(value) {
10268
- return encodeURIComponent(String(value || ""));
10269
- }
10270
- function encodeGitHubBranchRef(branch = "") {
10271
- return String(branch || "").split("/").map(encodeGitHubPathSegment).join("/");
10272
- }
10273
- function parseNullSeparatedGitOutput(output = "") {
10274
- return String(output || "").split("\0").map((item) => item.trim()).filter(Boolean);
10275
- }
10276
- function listWorktreeChangedPaths(worktree, runGitFn = runGit) {
10277
- const tracked = parseNullSeparatedGitOutput(runGitFn(worktree, ["diff", "--name-only", "-z", "HEAD", "--"]));
10278
- const untracked = parseNullSeparatedGitOutput(runGitFn(worktree, ["ls-files", "--others", "--exclude-standard", "-z", "--"]));
10279
- return [.../* @__PURE__ */ new Set([...tracked, ...untracked])].filter((item) => item && !item.startsWith("../") && !path6.isAbsolute(item));
10280
- }
10281
- function currentGitBranch(worktree, runGitFn = runGit) {
10282
- return String(runGitFn(worktree, ["rev-parse", "--abbrev-ref", "HEAD"]) || "").trim();
10283
- }
10284
- function treeEntryForWorktreePath(worktree, gitPath) {
10285
- const absolutePath = path6.join(worktree, ...String(gitPath || "").split("/"));
10286
- if (!fs5.existsSync(absolutePath)) return { path: gitPath, mode: "100644", type: "blob", sha: null, deleted: true };
10287
- const stat = fs5.lstatSync(absolutePath);
10288
- if (stat.isDirectory()) return null;
10289
- if (stat.isSymbolicLink()) {
10290
- return {
10291
- path: gitPath,
10292
- mode: "120000",
10293
- type: "blob",
10294
- content: fs5.readlinkSync(absolutePath),
10295
- encoding: "utf-8"
10296
- };
10297
- }
10298
- return {
10299
- path: gitPath,
10300
- mode: stat.mode & 73 ? "100755" : "100644",
10301
- type: "blob",
10302
- content: fs5.readFileSync(absolutePath).toString("base64"),
10303
- encoding: "base64"
10304
- };
10305
- }
10306
- function appendGitHubQuery(pathname, params = {}) {
10307
- const query = new URLSearchParams();
10308
- for (const [key, value] of Object.entries(params || {})) {
10309
- if (value === void 0 || value === null || value === "") continue;
10310
- query.set(key, String(value));
10311
- }
10312
- const suffix = query.toString();
10313
- return suffix ? `${pathname}?${suffix}` : pathname;
10314
- }
10315
- function timestampMs(value = "") {
10316
- const parsed = Date.parse(String(value || ""));
10317
- return Number.isFinite(parsed) ? parsed : 0;
10318
- }
10319
- function sortNewestFirst(items = []) {
10320
- return [...items].sort((a, b) => {
10321
- const bTime = Math.max(timestampMs(b?.updated_at), timestampMs(b?.created_at));
10322
- const aTime = Math.max(timestampMs(a?.updated_at), timestampMs(a?.created_at));
10323
- return bTime - aTime;
10324
- });
10325
- }
10326
- function matchesVercelStatusContext(context = "", expected = "") {
10327
- const actual = String(context || "").trim();
10328
- const wanted = String(expected || "").trim();
10329
- if (wanted && actual === wanted) return true;
10330
- const lower = actual.toLowerCase();
10331
- if (!lower.includes("vercel")) return false;
10332
- if (!wanted) return lower.includes("preproduction") || lower.includes("defend-preproduction");
10333
- const wantedLower = wanted.toLowerCase();
10334
- return wantedLower.split(/\s+|–|-/).filter((part) => part && part !== "vercel").every((part) => lower.includes(part));
10335
- }
10336
- function selectFunctionalDeploymentUrl(status = {}, deployment = {}) {
10337
- for (const candidate of [
10338
- status?.environment_url,
10339
- deployment?.environment_url,
10340
- status?.target_url,
10341
- deployment?.target_url
10342
- ]) {
10343
- const value = String(candidate || "").trim();
10344
- if (!value) continue;
10345
- try {
10346
- const url = new URL(value);
10347
- if (url.protocol === "http:" || url.protocol === "https:") return value;
10348
- } catch {
10349
- }
10350
- }
10351
- return "";
10352
- }
10353
- async function checkFunctionalDeploymentUrl(url, fetchImpl = globalThis.fetch) {
10354
- const target = String(url || "").trim();
10355
- if (!target) return { ok: false, reason: "url_missing" };
10356
- if (typeof fetchImpl !== "function") return { ok: false, reason: "fetch_unavailable", url: target };
10357
- const signal = typeof AbortSignal !== "undefined" && typeof AbortSignal.timeout === "function" ? AbortSignal.timeout(8e3) : void 0;
10358
- const probe = async (method) => {
10359
- const response = await fetchImpl(target, { method, redirect: "follow", signal });
10360
- return {
10361
- ok: response.status >= 200 && response.status < 400,
10362
- status: response.status,
10363
- statusText: response.statusText || "",
10364
- url: response.url || target,
10365
- method
10366
- };
10367
- };
10368
- try {
10369
- const head = await probe("HEAD");
10370
- if (head.ok) return head;
10371
- const get = await probe("GET");
10372
- return get.ok ? get : { ...get, reason: "http_not_ok" };
10373
- } catch (error) {
10374
- try {
10375
- const get = await probe("GET");
10376
- return get.ok ? get : { ...get, reason: "http_not_ok" };
10377
- } catch (secondError) {
10378
- return { ok: false, reason: "request_failed", url: target, error: secondError.message || error.message };
10379
- }
10380
- }
10381
- }
10382
- function createGitHubApiClient(config = {}, fetchImpl = globalThis.fetch) {
10383
- const staticToken = resolveSecretReference(config?.apiToken);
10384
- const appConfig = isPlainObject(config?.app) ? config.app : {};
10385
- const appId = resolveSecretReference(appConfig.appId || appConfig.app_id || "");
10386
- const installationId = resolveSecretReference(appConfig.installationId || appConfig.installation_id || "");
10387
- const appEnabled = appConfig.enabled === true || Boolean(appId && installationId && (appConfig.privateKey || appConfig.privateKeyFile));
10388
- const privateKey = resolveGitHubAppPrivateKey(appConfig);
10389
- const owner = String(config?.owner || "").trim();
10390
- const repo = String(config?.repo || "").trim();
10391
- let installationToken = null;
10392
- let installationTokenExpiresAt = 0;
10393
- const requestJson = async (url, { method = "GET", headers = {}, body = void 0 } = {}) => {
10394
- if (typeof fetchImpl !== "function") throw new Error("fetch is unavailable; inject a GitHub client for live PR lookup");
10620
+ const expectedEvents = new Set(config?.webhook?.events || []);
10621
+ const actualEvents = new Set(state?.events || []);
10622
+ const hasEvents = [...expectedEvents].every((event) => actualEvents.has(event));
10623
+ return Boolean(
10624
+ state?.active && state?.webhookId && state?.secret && state?.publicUrl === config?.webhook?.publicUrl && hasEvents
10625
+ );
10626
+ }
10627
+ function createClickUpApiClient(config, fetchImpl = globalThis.fetch) {
10628
+ const token = resolveSecretReference(config?.apiToken);
10629
+ const request = async (url, options = {}) => {
10630
+ if (typeof fetchImpl !== "function") throw new Error("fetch is unavailable; inject a ClickUp client for live webhook setup");
10631
+ if (!token) throw new Error("ClickUp API token is not available");
10395
10632
  const response = await fetchImpl(url, {
10396
- method,
10633
+ ...options,
10397
10634
  headers: {
10398
- Accept: "application/vnd.github+json",
10399
- "X-GitHub-Api-Version": "2022-11-28",
10400
- ...body === void 0 ? {} : { "Content-Type": "application/json" },
10401
- ...headers
10402
- },
10403
- ...body === void 0 ? {} : { body: JSON.stringify(body) }
10404
- });
10405
- if (!response.ok) throw new Error(`GitHub API request failed: ${response.status}`);
10406
- return response.status === 204 ? null : response.json();
10407
- };
10408
- const getAuthToken = async () => {
10409
- if (!appEnabled) return staticToken || "";
10410
- const nowMs = Date.now();
10411
- if (installationToken && installationTokenExpiresAt - 6e4 > nowMs) return installationToken;
10412
- const jwt = createGitHubAppJwt({ appId, privateKey });
10413
- const installation = await requestJson(`https://api.github.com/app/installations/${encodeURIComponent(installationId)}/access_tokens`, {
10414
- method: "POST",
10415
- headers: { Authorization: `Bearer ${jwt}` }
10416
- });
10417
- installationToken = String(installation?.token || "").trim();
10418
- installationTokenExpiresAt = Date.parse(installation?.expires_at || "") || nowMs + 3e6;
10419
- if (!installationToken) throw new Error("GitHub App installation token response did not include a token");
10420
- return installationToken;
10421
- };
10422
- const request = async (pathname, { method = "GET", body = void 0 } = {}) => {
10423
- if (!owner || !repo) throw new Error("GitHub repository owner/repo is not configured");
10424
- const token = await getAuthToken();
10425
- return requestJson(`https://api.github.com/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}${pathname}`, {
10426
- method,
10427
- body,
10428
- headers: token ? { Authorization: `Bearer ${token}` } : {}
10635
+ Authorization: token,
10636
+ "Content-Type": "application/json",
10637
+ ...options.headers || {}
10638
+ }
10429
10639
  });
10640
+ if (!response.ok) throw new Error(`ClickUp API request failed: ${response.status}`);
10641
+ return response.json();
10430
10642
  };
10431
- const getRef = async (branch) => request(`/git/ref/heads/${encodeGitHubBranchRef(branch)}`);
10432
- const getCommitObject = async (sha) => request(`/git/commits/${encodeURIComponent(sha)}`);
10433
- const createBlob = async ({ content, encoding }) => request("/git/blobs", { method: "POST", body: { content, encoding } });
10434
- const createTree = async ({ baseTree, tree }) => request("/git/trees", { method: "POST", body: { base_tree: baseTree, tree } });
10435
- const createCommit = async ({ message, treeSha, parents }) => request("/git/commits", { method: "POST", body: { message, tree: treeSha, parents } });
10436
- const updateRef = async ({ branch, sha, force = false }) => request(`/git/refs/heads/${encodeGitHubBranchRef(branch)}`, { method: "PATCH", body: { sha, force } });
10437
10643
  return {
10438
- async getPullRequest(number) {
10439
- return request(`/pulls/${encodeURIComponent(number)}`);
10440
- },
10441
- async createPullRequest({ title, head, base, body = "", draft = false, maintainerCanModify = true }) {
10442
- return request("/pulls", {
10644
+ async createWebhook({ endpoint, events, location }) {
10645
+ const body = { endpoint, events, ...Object.fromEntries(Object.entries(location || {}).filter(([, value]) => value)) };
10646
+ return request(`https://api.clickup.com/api/v2/team/${encodeURIComponent(config.teamId)}/webhook`, {
10443
10647
  method: "POST",
10444
- body: {
10445
- title: String(title || ""),
10446
- head: String(head || ""),
10447
- base: String(base || ""),
10448
- body: String(body || ""),
10449
- draft: draft === true,
10450
- maintainer_can_modify: maintainerCanModify !== false
10451
- }
10648
+ body: JSON.stringify(body)
10452
10649
  });
10453
10650
  },
10454
- async createIssueComment({ issueNumber, body }) {
10455
- return request(`/issues/${encodeURIComponent(issueNumber)}/comments`, { method: "POST", body: { body: String(body || "") } });
10456
- },
10457
- async replyToReviewComment({ commentId, body }) {
10458
- return request(`/pulls/comments/${encodeURIComponent(commentId)}/replies`, { method: "POST", body: { body: String(body || "") } });
10651
+ async listWebhooks() {
10652
+ return request(`https://api.clickup.com/api/v2/team/${encodeURIComponent(config.teamId)}/webhook`);
10459
10653
  },
10460
- async createPullRequestReview({ pullNumber, body, event = "COMMENT" }) {
10461
- return request(`/pulls/${encodeURIComponent(pullNumber)}/reviews`, { method: "POST", body: { body: String(body || ""), event: String(event || "COMMENT").toUpperCase() } });
10654
+ async deleteWebhook(webhookId) {
10655
+ return request(`https://api.clickup.com/api/v2/webhook/${encodeURIComponent(webhookId)}`, { method: "DELETE" });
10462
10656
  },
10463
- async mergePullRequest({ pullNumber, commitTitle = "", commitMessage = "", mergeMethod = "squash" }) {
10464
- const body = {
10465
- merge_method: String(mergeMethod || "squash")
10466
- };
10467
- if (commitTitle) body.commit_title = String(commitTitle);
10468
- if (commitMessage) body.commit_message = String(commitMessage);
10469
- return request(`/pulls/${encodeURIComponent(pullNumber)}/merge`, { method: "PUT", body });
10657
+ async getAuthorizedUser() {
10658
+ return request("https://api.clickup.com/api/v2/user");
10470
10659
  },
10471
- async getCombinedStatus(ref) {
10472
- return request(`/commits/${encodeURIComponent(String(ref || ""))}/status`);
10660
+ async getTask(taskId) {
10661
+ return request(`https://api.clickup.com/api/v2/task/${encodeURIComponent(taskId)}`);
10473
10662
  },
10474
- async listDeployments({ sha = "", ref = "", environment = "", perPage = 30 } = {}) {
10475
- return request(appendGitHubQuery("/deployments", {
10476
- sha,
10477
- ref,
10478
- environment,
10479
- per_page: perPage
10480
- }));
10663
+ async updateTaskMetadata({ taskId, fieldId, value }) {
10664
+ return request(`https://api.clickup.com/api/v2/task/${encodeURIComponent(taskId)}/field/${encodeURIComponent(fieldId)}`, {
10665
+ method: "POST",
10666
+ body: JSON.stringify({ value })
10667
+ });
10481
10668
  },
10482
- async listDeploymentStatuses(deploymentId) {
10483
- return request(`/deployments/${encodeURIComponent(deploymentId)}/statuses`);
10669
+ async postTaskComment() {
10670
+ throw new Error("Optima runtime does not post ClickUp task comments; use local logs for process failures.");
10484
10671
  },
10485
- async verifyVercelPullRequestDeployment({
10486
- pullNumber,
10487
- context = "Vercel \u2013 defend-preproduction",
10488
- environment = "Preview \u2013 defend-preproduction",
10489
- requireFunctionalUrl = true
10490
- } = {}) {
10491
- const pr = await this.getPullRequest(pullNumber);
10492
- const headSha = String(pr?.head?.sha || "").trim();
10493
- if (!headSha) return { ok: true, ready: false, reason: "pr_head_sha_missing", pull_request: { number: pullNumber } };
10494
- const combined = await this.getCombinedStatus(headSha);
10495
- const statuses = Array.isArray(combined?.statuses) ? combined.statuses : [];
10496
- const matchingStatuses = statuses.filter((status) => matchesVercelStatusContext(status?.context, context));
10497
- const selectedStatus = sortNewestFirst(matchingStatuses)[0] || null;
10498
- if (!selectedStatus) {
10499
- return {
10500
- ok: true,
10501
- ready: false,
10502
- reason: "vercel_status_missing",
10503
- pull_request: { number: pr.number, url: pr.html_url, head_sha: headSha },
10504
- required_context: context,
10505
- combined_state: combined?.state || null
10506
- };
10507
- }
10508
- if (String(selectedStatus.state || "").toLowerCase() !== "success") {
10509
- return {
10510
- ok: true,
10511
- ready: false,
10512
- reason: "vercel_status_not_success",
10513
- pull_request: { number: pr.number, url: pr.html_url, head_sha: headSha },
10514
- required_context: context,
10515
- status: selectedStatus,
10516
- combined_state: combined?.state || null
10517
- };
10518
- }
10519
- let deployments = await this.listDeployments({ sha: headSha, environment });
10520
- if (!Array.isArray(deployments) || deployments.length === 0) deployments = await this.listDeployments({ sha: headSha });
10521
- const selectedDeployment = sortNewestFirst(Array.isArray(deployments) ? deployments : []).find((deployment) => !environment || String(deployment?.environment || "") === environment) || sortNewestFirst(Array.isArray(deployments) ? deployments : [])[0] || null;
10522
- if (!selectedDeployment?.id) {
10523
- return {
10524
- ok: true,
10525
- ready: false,
10526
- reason: "vercel_deployment_missing",
10527
- pull_request: { number: pr.number, url: pr.html_url, head_sha: headSha },
10528
- required_environment: environment,
10529
- status: selectedStatus
10530
- };
10531
- }
10532
- const deploymentStatuses = await this.listDeploymentStatuses(selectedDeployment.id);
10533
- const selectedDeploymentStatus = sortNewestFirst(Array.isArray(deploymentStatuses) ? deploymentStatuses : [])[0] || null;
10534
- if (!selectedDeploymentStatus || String(selectedDeploymentStatus.state || "").toLowerCase() !== "success") {
10535
- return {
10536
- ok: true,
10537
- ready: false,
10538
- reason: "vercel_deployment_not_success",
10539
- pull_request: { number: pr.number, url: pr.html_url, head_sha: headSha },
10540
- required_environment: environment,
10541
- status: selectedStatus,
10542
- deployment: selectedDeployment,
10543
- deployment_status: selectedDeploymentStatus
10544
- };
10545
- }
10546
- const url = selectFunctionalDeploymentUrl(selectedDeploymentStatus, selectedDeployment);
10547
- const urlCheck = requireFunctionalUrl ? await checkFunctionalDeploymentUrl(url, fetchImpl) : { ok: Boolean(url), reason: url ? void 0 : "url_missing", url };
10548
- if (requireFunctionalUrl && !urlCheck.ok) {
10549
- return {
10550
- ok: true,
10551
- ready: false,
10552
- reason: "vercel_url_not_functional",
10553
- pull_request: { number: pr.number, url: pr.html_url, head_sha: headSha },
10554
- required_environment: environment,
10555
- status: selectedStatus,
10556
- deployment: selectedDeployment,
10557
- deployment_status: selectedDeploymentStatus,
10558
- url,
10559
- url_check: urlCheck
10560
- };
10561
- }
10562
- return {
10563
- ok: true,
10564
- ready: true,
10565
- reason: "vercel_pr_deployment_ready",
10566
- pull_request: { number: pr.number, url: pr.html_url, head_sha: headSha },
10567
- required_context: context,
10568
- required_environment: environment,
10569
- status: selectedStatus,
10570
- deployment: selectedDeployment,
10571
- deployment_status: selectedDeploymentStatus,
10572
- url,
10573
- url_check: urlCheck
10574
- };
10672
+ async addTaskTag() {
10673
+ throw new Error("Optima runtime does not add ClickUp task tags; use local logs for process failures.");
10575
10674
  },
10576
- async commitWorktree({ worktree, branch = "", message = "", runGitFn = runGit, syncLocal = false } = {}) {
10577
- const directory = path6.resolve(String(worktree || ""));
10578
- if (!directory || !fs5.existsSync(directory)) throw new Error("worktree does not exist");
10579
- const targetBranch = String(branch || currentGitBranch(directory, runGitFn)).trim();
10580
- if (!targetBranch || targetBranch === "HEAD") throw new Error("target branch is required for GitHub API commit");
10581
- const commitMessage = String(message || "").trim();
10582
- if (!commitMessage) throw new Error("commit message is required");
10583
- const changedPaths = listWorktreeChangedPaths(directory, runGitFn);
10584
- if (changedPaths.length === 0) return { ok: true, action: "no_changes", branch: targetBranch, changedPaths: [] };
10585
- const ref = await getRef(targetBranch);
10586
- const headSha = ref?.object?.sha;
10587
- if (!headSha) throw new Error(`GitHub ref for ${targetBranch} did not include a head sha`);
10588
- const headCommit = await getCommitObject(headSha);
10589
- const baseTree = headCommit?.tree?.sha;
10590
- if (!baseTree) throw new Error(`GitHub commit ${headSha} did not include a tree sha`);
10591
- const tree = [];
10592
- for (const gitPath of changedPaths) {
10593
- const entry = treeEntryForWorktreePath(directory, gitPath);
10594
- if (!entry) continue;
10595
- if (entry.deleted) {
10596
- tree.push({ path: entry.path, mode: entry.mode, type: entry.type, sha: null });
10597
- continue;
10598
- }
10599
- const blob = await createBlob({ content: entry.content, encoding: entry.encoding });
10600
- if (!blob?.sha) throw new Error(`GitHub blob creation failed for ${gitPath}`);
10601
- tree.push({ path: entry.path, mode: entry.mode, type: entry.type, sha: blob.sha });
10602
- }
10603
- if (tree.length === 0) return { ok: true, action: "no_changes", branch: targetBranch, changedPaths: [] };
10604
- const nextTree = await createTree({ baseTree, tree });
10605
- const nextCommit = await createCommit({ message: commitMessage, treeSha: nextTree.sha, parents: [headSha] });
10606
- if (!nextCommit?.sha) throw new Error("GitHub commit creation did not return a sha");
10607
- const updatedRef = await updateRef({ branch: targetBranch, sha: nextCommit.sha, force: false });
10608
- if (syncLocal) {
10609
- runGitFn(directory, ["fetch", "origin", targetBranch]);
10610
- runGitFn(directory, ["reset", "--hard", "FETCH_HEAD"]);
10611
- }
10612
- return {
10613
- ok: true,
10614
- action: "committed",
10615
- branch: targetBranch,
10616
- before: headSha,
10617
- after: nextCommit.sha,
10618
- changedPaths,
10619
- treeEntries: tree.length,
10620
- verification: nextCommit.verification || null,
10621
- ref: updatedRef
10622
- };
10675
+ async listAssignedTasks({ assigneeId, statuses = [], limit = CLICKUP_WEBHOOK_STARTUP_TASK_LIMIT } = {}) {
10676
+ const params = new URLSearchParams();
10677
+ if (assigneeId) params.append("assignees[]", assigneeId);
10678
+ for (const status of statuses) if (status) params.append("statuses[]", status);
10679
+ if (limit) params.append("limit", String(limit));
10680
+ return request(`https://api.clickup.com/api/v2/team/${encodeURIComponent(config.teamId)}/task?${params.toString()}`);
10623
10681
  },
10624
- async authMode() {
10625
- if (appEnabled) return { mode: "github_app", appId, installationId };
10626
- if (staticToken) return { mode: "token" };
10627
- return { mode: "anonymous" };
10682
+ async getTaskComments({ taskId, start, limit = CLICKUP_WEBHOOK_STARTUP_COMMENT_LIMIT } = {}) {
10683
+ const params = new URLSearchParams();
10684
+ if (start) params.set("start", String(start));
10685
+ if (limit) params.set("limit", String(limit));
10686
+ const suffix = params.toString() ? `?${params.toString()}` : "";
10687
+ return request(`https://api.clickup.com/api/v2/task/${encodeURIComponent(taskId)}/comment${suffix}`);
10628
10688
  }
10629
10689
  };
10630
10690
  }
@@ -10853,10 +10913,10 @@ async function ensureClickUpWebhookSubscription({ validation, worktree, clickupC
10853
10913
  function verifyClickUpSignature(rawBody, signatureHeader, secret) {
10854
10914
  const signature = String(signatureHeader || "").replace(/^sha256=/i, "").trim();
10855
10915
  if (!signature || !secret) return false;
10856
- const expected = crypto.createHmac("sha256", secret).update(Buffer.isBuffer(rawBody) ? rawBody : String(rawBody || ""), "utf8").digest("hex");
10916
+ const expected = crypto2.createHmac("sha256", secret).update(Buffer.isBuffer(rawBody) ? rawBody : String(rawBody || ""), "utf8").digest("hex");
10857
10917
  const given = Buffer.from(signature, "hex");
10858
10918
  const wanted = Buffer.from(expected, "hex");
10859
- return given.length === wanted.length && crypto.timingSafeEqual(given, wanted);
10919
+ return given.length === wanted.length && crypto2.timingSafeEqual(given, wanted);
10860
10920
  }
10861
10921
  function verifyGitHubSignature(rawBody, signatureHeader, secret) {
10862
10922
  return verifyClickUpSignature(rawBody, signatureHeader, secret);
@@ -10910,9 +10970,9 @@ function rememberClickUpWebhookEvent(state = {}, eventKey, limit = 200) {
10910
10970
  return { duplicate: false, state: { ...state, recentEventKeys: [...recent, eventKey].slice(-limit) } };
10911
10971
  }
10912
10972
  function readClickUpCommentLedgerEntries(ledgerPath) {
10913
- if (!ledgerPath || !fs5.existsSync(ledgerPath)) return [];
10973
+ if (!ledgerPath || !fs8.existsSync(ledgerPath)) return [];
10914
10974
  try {
10915
- const raw = fs5.readFileSync(ledgerPath, "utf8");
10975
+ const raw = fs8.readFileSync(ledgerPath, "utf8");
10916
10976
  const entries = [];
10917
10977
  for (const [index, line] of raw.split(/\r?\n/).entries()) {
10918
10978
  if (!line.trim()) continue;
@@ -10936,11 +10996,11 @@ function readClickUpCommentLedger(ledgerPath) {
10936
10996
  }
10937
10997
  function appendClickUpCommentLedgerEntry(ledgerPath, entry = {}) {
10938
10998
  if (!ledgerPath || !entry.key) return;
10939
- fs5.mkdirSync(path6.dirname(ledgerPath), { recursive: true, mode: 448 });
10940
- fs5.appendFileSync(ledgerPath, `${JSON.stringify(entry)}
10999
+ fs8.mkdirSync(path8.dirname(ledgerPath), { recursive: true, mode: 448 });
11000
+ fs8.appendFileSync(ledgerPath, `${JSON.stringify(entry)}
10941
11001
  `, { encoding: "utf8", mode: 384 });
10942
11002
  try {
10943
- fs5.chmodSync(ledgerPath, 384);
11003
+ fs8.chmodSync(ledgerPath, 384);
10944
11004
  } catch {
10945
11005
  }
10946
11006
  }
@@ -10959,7 +11019,7 @@ function stableClickUpCommentVersionMarker(value) {
10959
11019
  const direct = value.version ?? value.date_updated ?? value.updated_at ?? value.revision ?? value.modified_at;
10960
11020
  const directMarker = stableClickUpCommentVersionMarker(direct);
10961
11021
  if (directMarker) return directMarker;
10962
- return `json:${crypto.createHash("sha256").update(JSON.stringify(value, Object.keys(value).sort())).digest("hex").slice(0, 16)}`;
11022
+ return `json:${crypto2.createHash("sha256").update(JSON.stringify(value, Object.keys(value).sort())).digest("hex").slice(0, 16)}`;
10963
11023
  }
10964
11024
  function clickUpCommentLedgerKey({ taskId, eventType, payload }) {
10965
11025
  const history = Array.isArray(payload?.history_items) ? payload.history_items[0] : payload?.history_item;
@@ -10969,7 +11029,7 @@ function clickUpCommentLedgerKey({ taskId, eventType, payload }) {
10969
11029
  const explicitVersion = stableClickUpCommentVersionMarker(
10970
11030
  comment?.date_updated || comment?.dateUpdated || comment?.updated_at || comment?.updatedAt || comment?._version_vector || comment?.version_vector || comment?.versionVector || comment?.version || comment?.revision || comment?.modified_at || comment?.modifiedAt || ""
10971
11031
  );
10972
- const contentVersion = crypto.createHash("sha256").update(JSON.stringify({ text: clickUpCommentText(comment), parts: Array.isArray(comment.comment) ? comment.comment : null })).digest("hex").slice(0, 16);
11032
+ const contentVersion = crypto2.createHash("sha256").update(JSON.stringify({ text: clickUpCommentText(comment), parts: Array.isArray(comment.comment) ? comment.comment : null })).digest("hex").slice(0, 16);
10973
11033
  return [String(taskId || "").trim(), "comment", commentId, explicitVersion || `sha256-${contentVersion}`].filter(Boolean).join(":");
10974
11034
  }
10975
11035
  function isClickUpCommentVersionProcessed({ ledgerPath, key, ledger = null, worktree = process.cwd() } = {}) {
@@ -11499,7 +11559,7 @@ function clampOpenCodeSessionText(text = "", maxLength = 12e3) {
11499
11559
  return value.length > maxLength ? value.slice(0, maxLength) : value;
11500
11560
  }
11501
11561
  function hashOpenCodeSessionText(text = "") {
11502
- return crypto.createHash("sha256").update(String(text ?? "")).digest("hex");
11562
+ return crypto2.createHash("sha256").update(String(text ?? "")).digest("hex");
11503
11563
  }
11504
11564
  async function readOpenCodeSessionMessages(client, { sessionId, directory, limit = 20 } = {}) {
11505
11565
  if (typeof client?.session?.messages !== "function") return null;
@@ -11737,7 +11797,7 @@ async function readOpenCodeSessionControl(client, { sessionId, directory, limit
11737
11797
  };
11738
11798
  }
11739
11799
  async function probeOpenCodeSessionControl(client, { directory, agent, omitAgentOnPrompt = false, text = "" } = {}) {
11740
- const requestedMarker = text || `optima-session-probe-${crypto.randomUUID()}`;
11800
+ const requestedMarker = text || `optima-session-probe-${crypto2.randomUUID()}`;
11741
11801
  const marker = clampOpenCodeSessionText(requestedMarker);
11742
11802
  const create = await createOpenCodeSessionControl(client, {
11743
11803
  directory,
@@ -11965,9 +12025,9 @@ function formatClickUpWebhookPrompt({ eventType, taskId, payload, branch = "", w
11965
12025
  }
11966
12026
  function appendClickUpWebhookLocalLog(worktree, entry) {
11967
12027
  const logPath = clickUpWebhookLogPath(worktree);
11968
- fs5.mkdirSync(path6.dirname(logPath), { recursive: true });
12028
+ fs8.mkdirSync(path8.dirname(logPath), { recursive: true });
11969
12029
  const safeEntry = { ...entry, at: entry.at || (/* @__PURE__ */ new Date()).toISOString() };
11970
- fs5.appendFileSync(logPath, `${JSON.stringify(safeEntry)}
12030
+ fs8.appendFileSync(logPath, `${JSON.stringify(safeEntry)}
11971
12031
  `, "utf8");
11972
12032
  }
11973
12033
  function clickUpWebhookLifecycleLog(worktree, entry) {
@@ -11996,7 +12056,7 @@ function closeClickUpWebhookServer(server) {
11996
12056
  });
11997
12057
  }
11998
12058
  function managedClickUpWebhookKey({ worktree, state, config } = {}) {
11999
- return [path6.resolve(worktree || process.cwd()), state?.webhookId || "", config?.webhook?.publicUrl || ""].join("|");
12059
+ return [path8.resolve(worktree || process.cwd()), state?.webhookId || "", config?.webhook?.publicUrl || ""].join("|");
12000
12060
  }
12001
12061
  async function deleteClickUpWebhookBestEffort({ webhookId, clickupClient, worktree, reason = "cleanup" } = {}) {
12002
12062
  const id = String(webhookId || "").trim();
@@ -12096,7 +12156,7 @@ function writeClickUpWebhookAuditLog({ method, url, headers = {}, rawBody = "",
12096
12156
  const failed = Boolean(error || !handled?.ok || (handled?.status || 500) >= 400);
12097
12157
  if (level === "error" && !failed) return;
12098
12158
  const logDir = clickUpWebhookAuditLogDir();
12099
- fs5.mkdirSync(logDir, { recursive: true });
12159
+ fs8.mkdirSync(logDir, { recursive: true });
12100
12160
  const secretValues = [
12101
12161
  resolveSecretReference(config?.apiToken),
12102
12162
  resolveSecretReference(config?.github?.apiToken),
@@ -12107,8 +12167,8 @@ function writeClickUpWebhookAuditLog({ method, url, headers = {}, rawBody = "",
12107
12167
  let requestFile;
12108
12168
  if (level === "verbose") {
12109
12169
  const absoluteRequestFile = clickUpWebhookRequestFilePath(at, logDir);
12110
- fs5.mkdirSync(path6.dirname(absoluteRequestFile), { recursive: true });
12111
- requestFile = path6.relative(logDir, absoluteRequestFile).split(path6.sep).join("/");
12170
+ fs8.mkdirSync(path8.dirname(absoluteRequestFile), { recursive: true });
12171
+ requestFile = path8.relative(logDir, absoluteRequestFile).split(path8.sep).join("/");
12112
12172
  const parsedBody = payload || (() => {
12113
12173
  try {
12114
12174
  return JSON.parse(Buffer.isBuffer(rawBody) ? rawBody.toString("utf8") : String(rawBody || ""));
@@ -12124,11 +12184,11 @@ function writeClickUpWebhookAuditLog({ method, url, headers = {}, rawBody = "",
12124
12184
  headers,
12125
12185
  body: parsedBody === void 0 ? Buffer.isBuffer(rawBody) ? rawBody.toString("utf8") : String(rawBody || "") : parsedBody
12126
12186
  }, secretValues);
12127
- fs5.writeFileSync(absoluteRequestFile, `${JSON.stringify(requestArtifact, null, 2)}
12187
+ fs8.writeFileSync(absoluteRequestFile, `${JSON.stringify(requestArtifact, null, 2)}
12128
12188
  `, "utf8");
12129
12189
  }
12130
12190
  const summary = redactClickUpWebhookAuditValue(buildClickUpWebhookAuditSummary({ method, url, config, handled, error, payload, requestFile, at }), secretValues);
12131
- fs5.appendFileSync(clickUpWebhookAuditLogPath(at, logDir), `${JSON.stringify(summary)}
12191
+ fs8.appendFileSync(clickUpWebhookAuditLogPath(at, logDir), `${JSON.stringify(summary)}
12132
12192
  `, "utf8");
12133
12193
  } catch {
12134
12194
  }
@@ -12146,7 +12206,7 @@ async function withClickUpTaskRouteLock(taskId, operation) {
12146
12206
  if (activeClickUpTaskRoutes.get(key) === current) activeClickUpTaskRoutes.delete(key);
12147
12207
  }
12148
12208
  }
12149
- async function routeClickUpWebhookEventUnlocked({ payload, config, state = {}, worktree = process.cwd(), clickupClient, openCodeClient, sessionExists = openCodeSessionExists, createSession = createOpenCodeSession, sendSessionEvent = sendOpenCodeSessionEvent, ensureTaskWorktree = ensureClickUpTaskWorktreeForWebhook, verifySessionEventDelivery = verifyOpenCodeSessionEventDelivery, saveState = null, now = () => /* @__PURE__ */ new Date(), host = os.hostname(), commentLedgerPath = clickUpCommentLedgerPath(worktree) } = {}) {
12209
+ async function routeClickUpWebhookEventUnlocked({ payload, config, state = {}, worktree = process.cwd(), clickupClient, openCodeClient, sessionExists = openCodeSessionExists, createSession = createOpenCodeSession, sendSessionEvent = sendOpenCodeSessionEvent, ensureTaskWorktree = ensureClickUpTaskWorktreeForWebhook, verifySessionEventDelivery = verifyOpenCodeSessionEventDelivery, saveState = null, now = () => /* @__PURE__ */ new Date(), host = os2.hostname(), commentLedgerPath = clickUpCommentLedgerPath(worktree) } = {}) {
12150
12210
  const eventType = clickUpEventType(payload);
12151
12211
  const eventKey = clickUpWebhookEventKey(payload);
12152
12212
  const isStartupAssignmentReconciliation = payload?.startup_reconciliation === true && eventType === "taskAssigneeUpdated";
@@ -12915,17 +12975,17 @@ function startClickUpWebhookListener({ config, state, worktree, clickupClient, g
12915
12975
  return result;
12916
12976
  }
12917
12977
  function legacyVariantPath(destinationPath) {
12918
- const parsed = path6.parse(destinationPath);
12978
+ const parsed = path8.parse(destinationPath);
12919
12979
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:TZ.]/g, "").slice(0, 14);
12920
- if (parsed.ext) return path6.join(parsed.dir, `${parsed.name}.legacy-${stamp}${parsed.ext}`);
12921
- return path6.join(parsed.dir, `${parsed.base}.legacy-${stamp}`);
12980
+ if (parsed.ext) return path8.join(parsed.dir, `${parsed.name}.legacy-${stamp}${parsed.ext}`);
12981
+ return path8.join(parsed.dir, `${parsed.base}.legacy-${stamp}`);
12922
12982
  }
12923
12983
  function normalizeWorkflowTaskPath(taskPath) {
12924
12984
  if (typeof taskPath !== "string") return { ok: false, message: "Error: task_path is required." };
12925
12985
  const trimmed = taskPath.trim();
12926
12986
  if (!trimmed) return { ok: false, message: "Error: task_path is required." };
12927
12987
  const normalized = trimmed.replace(/\\/g, "/");
12928
- if (path6.isAbsolute(trimmed)) return { ok: true, taskPath: trimmed };
12988
+ if (path8.isAbsolute(trimmed)) return { ok: true, taskPath: trimmed };
12929
12989
  if (normalized === "tasks" || normalized.startsWith("tasks/")) {
12930
12990
  return {
12931
12991
  ok: false,
@@ -12943,78 +13003,78 @@ function normalizeWorkflowTaskPath(taskPath) {
12943
13003
  function mergeFileIntoDestination(sourcePath, destinationPath, relativeSource, gitState = null) {
12944
13004
  const sourceWasTracked = isGitTracked(gitState, sourcePath);
12945
13005
  if (gitAwareMoveIfTracked(sourcePath, destinationPath, gitState)) return;
12946
- if (!fs5.existsSync(destinationPath)) {
12947
- fs5.mkdirSync(path6.dirname(destinationPath), { recursive: true });
12948
- fs5.renameSync(sourcePath, destinationPath);
13006
+ if (!fs8.existsSync(destinationPath)) {
13007
+ fs8.mkdirSync(path8.dirname(destinationPath), { recursive: true });
13008
+ fs8.renameSync(sourcePath, destinationPath);
12949
13009
  if (sourceWasTracked) stageGitAwareMerge(sourcePath, destinationPath, gitState);
12950
13010
  return;
12951
13011
  }
12952
- const ext = path6.extname(destinationPath).toLowerCase();
13012
+ const ext = path8.extname(destinationPath).toLowerCase();
12953
13013
  if ([".yaml", ".yml", ".json"].includes(ext)) {
12954
- const sourceRaw = fs5.readFileSync(sourcePath, "utf8");
12955
- const destRaw = fs5.readFileSync(destinationPath, "utf8");
13014
+ const sourceRaw = fs8.readFileSync(sourcePath, "utf8");
13015
+ const destRaw = fs8.readFileSync(destinationPath, "utf8");
12956
13016
  const parser = ext === ".json" ? JSON : import_yaml3.default;
12957
13017
  const sourceValue = parser.parse(sourceRaw) || {};
12958
13018
  const destValue = parser.parse(destRaw) || {};
12959
13019
  const merged = mergeStructuredValues(sourceValue, destValue);
12960
13020
  const serialized = ext === ".json" ? `${JSON.stringify(merged, null, 2)}
12961
13021
  ` : import_yaml3.default.stringify(merged);
12962
- fs5.writeFileSync(destinationPath, serialized, "utf8");
12963
- fs5.unlinkSync(sourcePath);
13022
+ fs8.writeFileSync(destinationPath, serialized, "utf8");
13023
+ fs8.unlinkSync(sourcePath);
12964
13024
  stageGitAwareMerge(sourcePath, destinationPath, gitState);
12965
13025
  return;
12966
13026
  }
12967
13027
  if (ext === ".md") {
12968
- const sourceRaw = fs5.readFileSync(sourcePath, "utf8").trimEnd();
12969
- const destRaw = fs5.readFileSync(destinationPath, "utf8").trimEnd();
13028
+ const sourceRaw = fs8.readFileSync(sourcePath, "utf8").trimEnd();
13029
+ const destRaw = fs8.readFileSync(destinationPath, "utf8").trimEnd();
12970
13030
  if (sourceRaw && !destRaw.includes(sourceRaw)) {
12971
13031
  const marker = `## Legacy Content From ${relativeSource}`;
12972
- fs5.writeFileSync(destinationPath, `${destRaw}
13032
+ fs8.writeFileSync(destinationPath, `${destRaw}
12973
13033
 
12974
13034
  ${marker}
12975
13035
 
12976
13036
  ${sourceRaw}
12977
13037
  `, "utf8");
12978
13038
  }
12979
- fs5.unlinkSync(sourcePath);
13039
+ fs8.unlinkSync(sourcePath);
12980
13040
  stageGitAwareMerge(sourcePath, destinationPath, gitState);
12981
13041
  return;
12982
13042
  }
12983
13043
  const preservedPath = legacyVariantPath(destinationPath);
12984
- fs5.renameSync(sourcePath, preservedPath);
13044
+ fs8.renameSync(sourcePath, preservedPath);
12985
13045
  stageGitAwareMerge(sourcePath, preservedPath, gitState);
12986
13046
  }
12987
- function mergePathIntoDestination(sourcePath, destinationPath, relativeSource = path6.basename(sourcePath), gitState = null) {
12988
- if (!fs5.existsSync(sourcePath)) return;
12989
- const stat = fs5.statSync(sourcePath);
13047
+ function mergePathIntoDestination(sourcePath, destinationPath, relativeSource = path8.basename(sourcePath), gitState = null) {
13048
+ if (!fs8.existsSync(sourcePath)) return;
13049
+ const stat = fs8.statSync(sourcePath);
12990
13050
  if (stat.isDirectory()) {
12991
13051
  const sourceWasTracked = isGitTracked(gitState, sourcePath) || hasGitTrackedChildren(gitState, sourcePath);
12992
13052
  if (gitAwareMoveIfTracked(sourcePath, destinationPath, gitState)) return;
12993
- if (!fs5.existsSync(destinationPath)) {
12994
- fs5.mkdirSync(path6.dirname(destinationPath), { recursive: true });
12995
- fs5.renameSync(sourcePath, destinationPath);
13053
+ if (!fs8.existsSync(destinationPath)) {
13054
+ fs8.mkdirSync(path8.dirname(destinationPath), { recursive: true });
13055
+ fs8.renameSync(sourcePath, destinationPath);
12996
13056
  if (sourceWasTracked) stageGitAwareMerge(sourcePath, destinationPath, gitState);
12997
13057
  return;
12998
13058
  }
12999
- fs5.mkdirSync(destinationPath, { recursive: true });
13000
- for (const entry of fs5.readdirSync(sourcePath)) {
13059
+ fs8.mkdirSync(destinationPath, { recursive: true });
13060
+ for (const entry of fs8.readdirSync(sourcePath)) {
13001
13061
  mergePathIntoDestination(
13002
- path6.join(sourcePath, entry),
13003
- path6.join(destinationPath, entry),
13004
- path6.join(relativeSource, entry),
13062
+ path8.join(sourcePath, entry),
13063
+ path8.join(destinationPath, entry),
13064
+ path8.join(relativeSource, entry),
13005
13065
  gitState
13006
13066
  );
13007
13067
  }
13008
- fs5.rmSync(sourcePath, { recursive: true, force: true });
13068
+ fs8.rmSync(sourcePath, { recursive: true, force: true });
13009
13069
  return;
13010
13070
  }
13011
13071
  mergeFileIntoDestination(sourcePath, destinationPath, relativeSource, gitState);
13012
13072
  }
13013
13073
  function isOptimaPluginPackageWorktree(worktree) {
13014
- const packageJsonPath = path6.join(worktree, "package.json");
13015
- if (!fs5.existsSync(packageJsonPath)) return false;
13074
+ const packageJsonPath = path8.join(worktree, "package.json");
13075
+ if (!fs8.existsSync(packageJsonPath)) return false;
13016
13076
  try {
13017
- const pkg = JSON.parse(fs5.readFileSync(packageJsonPath, "utf8"));
13077
+ const pkg = JSON.parse(fs8.readFileSync(packageJsonPath, "utf8"));
13018
13078
  return pkg?.name === "@defend-tech/opencode-optima";
13019
13079
  } catch {
13020
13080
  return false;
@@ -13023,59 +13083,59 @@ function isOptimaPluginPackageWorktree(worktree) {
13023
13083
  function migrateLegacyOptimaLayout(worktree) {
13024
13084
  const gitState = gitMigrationState(worktree);
13025
13085
  const migrations = [
13026
- [path6.join(legacyOrbitaDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path6.join(".orbita", "orbita.yaml")],
13027
- [path6.join(legacyOrbitaDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path6.join(".orbita", "staticeng.yaml")],
13028
- [path6.join(legacyOrbitaDir(worktree), ".config"), optimaLocalConfigDir(worktree), path6.join(".orbita", ".config")],
13029
- [path6.join(legacyOrbitaDir(worktree), "config"), optimaLocalConfigDir(worktree), path6.join(".orbita", "config")],
13030
- [path6.join(legacyOrbitaDir(worktree), "runtime"), path6.join(optimaLocalConfigDir(worktree), "runtime"), path6.join(".orbita", "runtime")],
13031
- [path6.join(legacyOrbitaDir(worktree), "generated"), path6.join(optimaLocalConfigDir(worktree), "generated"), path6.join(".orbita", "generated")],
13086
+ [path8.join(legacyOrbitaDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path8.join(".orbita", "orbita.yaml")],
13087
+ [path8.join(legacyOrbitaDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path8.join(".orbita", "staticeng.yaml")],
13088
+ [path8.join(legacyOrbitaDir(worktree), ".config"), optimaLocalConfigDir(worktree), path8.join(".orbita", ".config")],
13089
+ [path8.join(legacyOrbitaDir(worktree), "config"), optimaLocalConfigDir(worktree), path8.join(".orbita", "config")],
13090
+ [path8.join(legacyOrbitaDir(worktree), "runtime"), path8.join(optimaLocalConfigDir(worktree), "runtime"), path8.join(".orbita", "runtime")],
13091
+ [path8.join(legacyOrbitaDir(worktree), "generated"), path8.join(optimaLocalConfigDir(worktree), "generated"), path8.join(".orbita", "generated")],
13032
13092
  [legacyOrbitaDir(worktree), optimaDir(worktree), ".orbita"],
13033
- [path6.join(legacyStaticEngDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path6.join(".staticeng", "staticeng.yaml")],
13034
- [path6.join(legacyStaticEngDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path6.join(".staticeng", "orbita.yaml")],
13035
- [path6.join(legacyStaticEngDir(worktree), ".config"), optimaLocalConfigDir(worktree), path6.join(".staticeng", ".config")],
13036
- [path6.join(legacyStaticEngDir(worktree), "config"), optimaLocalConfigDir(worktree), path6.join(".staticeng", "config")],
13037
- [path6.join(legacyStaticEngDir(worktree), "runtime"), path6.join(optimaLocalConfigDir(worktree), "runtime"), path6.join(".staticeng", "runtime")],
13038
- [path6.join(legacyStaticEngDir(worktree), "generated"), path6.join(optimaLocalConfigDir(worktree), "generated"), path6.join(".staticeng", "generated")],
13093
+ [path8.join(legacyStaticEngDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path8.join(".staticeng", "staticeng.yaml")],
13094
+ [path8.join(legacyStaticEngDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path8.join(".staticeng", "orbita.yaml")],
13095
+ [path8.join(legacyStaticEngDir(worktree), ".config"), optimaLocalConfigDir(worktree), path8.join(".staticeng", ".config")],
13096
+ [path8.join(legacyStaticEngDir(worktree), "config"), optimaLocalConfigDir(worktree), path8.join(".staticeng", "config")],
13097
+ [path8.join(legacyStaticEngDir(worktree), "runtime"), path8.join(optimaLocalConfigDir(worktree), "runtime"), path8.join(".staticeng", "runtime")],
13098
+ [path8.join(legacyStaticEngDir(worktree), "generated"), path8.join(optimaLocalConfigDir(worktree), "generated"), path8.join(".staticeng", "generated")],
13039
13099
  [legacyStaticEngDir(worktree), optimaDir(worktree), ".staticeng"],
13040
- [path6.join(legacyNomadworkDir(worktree), "nomadworks.yaml"), repoConfigPath(worktree), path6.join(".nomadwork", "nomadworks.yaml")],
13041
- [path6.join(legacyNomadworksDir(worktree), "nomadworks.yaml"), repoConfigPath(worktree), path6.join(".nomadworks", "nomadworks.yaml")],
13042
- [path6.join(legacyNomadworkDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path6.join(".nomadwork", "staticeng.yaml")],
13043
- [path6.join(legacyNomadworksDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path6.join(".nomadworks", "staticeng.yaml")],
13044
- [path6.join(legacyNomadworkDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path6.join(".nomadwork", "orbita.yaml")],
13045
- [path6.join(legacyNomadworksDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path6.join(".nomadworks", "orbita.yaml")],
13046
- [path6.join(legacyNomadworkDir(worktree), "runtime"), path6.join(optimaLocalConfigDir(worktree), "runtime"), path6.join(".nomadwork", "runtime")],
13047
- [path6.join(legacyNomadworksDir(worktree), "runtime"), path6.join(optimaLocalConfigDir(worktree), "runtime"), path6.join(".nomadworks", "runtime")],
13048
- [path6.join(legacyNomadworkDir(worktree), "generated"), path6.join(optimaLocalConfigDir(worktree), "generated"), path6.join(".nomadwork", "generated")],
13049
- [path6.join(legacyNomadworksDir(worktree), "generated"), path6.join(optimaLocalConfigDir(worktree), "generated"), path6.join(".nomadworks", "generated")],
13050
- [path6.join(legacyNomadworkDir(worktree), "config"), optimaLocalConfigDir(worktree), path6.join(".nomadwork", "config")],
13051
- [path6.join(legacyNomadworksDir(worktree), "config"), optimaLocalConfigDir(worktree), path6.join(".nomadworks", "config")],
13100
+ [path8.join(legacyNomadworkDir(worktree), "nomadworks.yaml"), repoConfigPath(worktree), path8.join(".nomadwork", "nomadworks.yaml")],
13101
+ [path8.join(legacyNomadworksDir(worktree), "nomadworks.yaml"), repoConfigPath(worktree), path8.join(".nomadworks", "nomadworks.yaml")],
13102
+ [path8.join(legacyNomadworkDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path8.join(".nomadwork", "staticeng.yaml")],
13103
+ [path8.join(legacyNomadworksDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path8.join(".nomadworks", "staticeng.yaml")],
13104
+ [path8.join(legacyNomadworkDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path8.join(".nomadwork", "orbita.yaml")],
13105
+ [path8.join(legacyNomadworksDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path8.join(".nomadworks", "orbita.yaml")],
13106
+ [path8.join(legacyNomadworkDir(worktree), "runtime"), path8.join(optimaLocalConfigDir(worktree), "runtime"), path8.join(".nomadwork", "runtime")],
13107
+ [path8.join(legacyNomadworksDir(worktree), "runtime"), path8.join(optimaLocalConfigDir(worktree), "runtime"), path8.join(".nomadworks", "runtime")],
13108
+ [path8.join(legacyNomadworkDir(worktree), "generated"), path8.join(optimaLocalConfigDir(worktree), "generated"), path8.join(".nomadwork", "generated")],
13109
+ [path8.join(legacyNomadworksDir(worktree), "generated"), path8.join(optimaLocalConfigDir(worktree), "generated"), path8.join(".nomadworks", "generated")],
13110
+ [path8.join(legacyNomadworkDir(worktree), "config"), optimaLocalConfigDir(worktree), path8.join(".nomadwork", "config")],
13111
+ [path8.join(legacyNomadworksDir(worktree), "config"), optimaLocalConfigDir(worktree), path8.join(".nomadworks", "config")],
13052
13112
  [legacyNomadworkDir(worktree), optimaDir(worktree), ".nomadwork"],
13053
13113
  [legacyNomadworksDir(worktree), optimaDir(worktree), ".nomadworks"],
13054
- [path6.join(worktree, "tasks"), optimaTasksDir(worktree), "tasks"],
13055
- [path6.join(worktree, "evidences"), optimaEvidencesDir(worktree), "evidences"],
13056
- [path6.join(worktree, "docs", "scrs"), optimaScrsDir(worktree), path6.join("docs", "scrs")],
13057
- [path6.join(worktree, "codemap.yml"), optimaCodemapPath(worktree), "codemap.yml"],
13058
- [path6.join(worktree, "codemap.yaml"), optimaCodemapPath(worktree), "codemap.yaml"]
13114
+ [path8.join(worktree, "tasks"), optimaTasksDir(worktree), "tasks"],
13115
+ [path8.join(worktree, "evidences"), optimaEvidencesDir(worktree), "evidences"],
13116
+ [path8.join(worktree, "docs", "scrs"), optimaScrsDir(worktree), path8.join("docs", "scrs")],
13117
+ [path8.join(worktree, "codemap.yml"), optimaCodemapPath(worktree), "codemap.yml"],
13118
+ [path8.join(worktree, "codemap.yaml"), optimaCodemapPath(worktree), "codemap.yaml"]
13059
13119
  ];
13060
13120
  if (!isOptimaPluginPackageWorktree(worktree)) {
13061
- migrations.push([path6.join(worktree, "policies"), repoPoliciesDir(worktree), "policies"]);
13121
+ migrations.push([path8.join(worktree, "policies"), repoPoliciesDir(worktree), "policies"]);
13062
13122
  }
13063
13123
  for (const [source, destination, relativeSource] of migrations) {
13064
- if (fs5.existsSync(source)) mergePathIntoDestination(source, destination, relativeSource, gitState);
13124
+ if (fs8.existsSync(source)) mergePathIntoDestination(source, destination, relativeSource, gitState);
13065
13125
  }
13066
13126
  for (const [source, destination, relativeSource] of [
13067
- [path6.join(optimaDir(worktree), "optima.yaml"), repoConfigPath(worktree), path6.join(".optima", "optima.yaml")],
13068
- [path6.join(optimaDir(worktree), "config"), optimaLocalConfigDir(worktree), path6.join(".optima", "config")],
13069
- [path6.join(optimaDir(worktree), "runtime"), path6.join(optimaLocalConfigDir(worktree), "runtime"), path6.join(".optima", "runtime")],
13070
- [path6.join(optimaDir(worktree), "generated"), path6.join(optimaLocalConfigDir(worktree), "generated"), path6.join(".optima", "generated")]
13127
+ [path8.join(optimaDir(worktree), "optima.yaml"), repoConfigPath(worktree), path8.join(".optima", "optima.yaml")],
13128
+ [path8.join(optimaDir(worktree), "config"), optimaLocalConfigDir(worktree), path8.join(".optima", "config")],
13129
+ [path8.join(optimaDir(worktree), "runtime"), path8.join(optimaLocalConfigDir(worktree), "runtime"), path8.join(".optima", "runtime")],
13130
+ [path8.join(optimaDir(worktree), "generated"), path8.join(optimaLocalConfigDir(worktree), "generated"), path8.join(".optima", "generated")]
13071
13131
  ]) {
13072
- if (fs5.existsSync(source)) mergePathIntoDestination(source, destination, relativeSource, gitState);
13132
+ if (fs8.existsSync(source)) mergePathIntoDestination(source, destination, relativeSource, gitState);
13073
13133
  }
13074
13134
  }
13075
13135
  function listMarkdownFiles(dirPath) {
13076
- if (!fs5.existsSync(dirPath)) return [];
13136
+ if (!fs8.existsSync(dirPath)) return [];
13077
13137
  try {
13078
- return fs5.readdirSync(dirPath).filter((file) => file.endsWith(".md") && file.toLowerCase() !== "readme.md");
13138
+ return fs8.readdirSync(dirPath).filter((file) => file.endsWith(".md") && file.toLowerCase() !== "readme.md");
13079
13139
  } catch (e) {
13080
13140
  console.error(`[Optima] Failed to read markdown files from ${dirPath}:`, e);
13081
13141
  return [];
@@ -13116,10 +13176,10 @@ function toModelString(provider, model) {
13116
13176
  }
13117
13177
  function readTaskMetadata(taskPath, worktree) {
13118
13178
  if (!taskPath) return {};
13119
- const absoluteTaskPath = path6.isAbsolute(taskPath) ? taskPath : path6.join(worktree, taskPath);
13120
- if (!fs5.existsSync(absoluteTaskPath)) return {};
13179
+ const absoluteTaskPath = path8.isAbsolute(taskPath) ? taskPath : path8.join(worktree, taskPath);
13180
+ if (!fs8.existsSync(absoluteTaskPath)) return {};
13121
13181
  try {
13122
- const raw = fs5.readFileSync(absoluteTaskPath, "utf8");
13182
+ const raw = fs8.readFileSync(absoluteTaskPath, "utf8");
13123
13183
  const { data } = parseFrontmatter(raw);
13124
13184
  return {
13125
13185
  complexity: typeof data.complexity === "string" ? data.complexity.trim().toLowerCase() : void 0,
@@ -13144,11 +13204,11 @@ function slugifyTitle(input) {
13144
13204
  }
13145
13205
  function loadDiscussionRegistry(worktree) {
13146
13206
  const registryPath = runtimeDiscussionRegistryPath(worktree);
13147
- if (!fs5.existsSync(registryPath)) {
13207
+ if (!fs8.existsSync(registryPath)) {
13148
13208
  return { version: 1, active: {} };
13149
13209
  }
13150
13210
  try {
13151
- const parsed = JSON.parse(fs5.readFileSync(registryPath, "utf8"));
13211
+ const parsed = JSON.parse(fs8.readFileSync(registryPath, "utf8"));
13152
13212
  const registry = {
13153
13213
  version: 1,
13154
13214
  active: Object.fromEntries(Object.entries(parsed.active || {}).map(([key, value]) => [key, normalizeLegacyDiscussionEntry(value)]))
@@ -13161,34 +13221,34 @@ function loadDiscussionRegistry(worktree) {
13161
13221
  }
13162
13222
  function saveDiscussionRegistry(worktree, registry) {
13163
13223
  const registryPath = runtimeDiscussionRegistryPath(worktree);
13164
- const runtimeDir = path6.dirname(registryPath);
13165
- if (!fs5.existsSync(runtimeDir)) fs5.mkdirSync(runtimeDir, { recursive: true });
13166
- fs5.writeFileSync(registryPath, JSON.stringify(registry, null, 2), "utf8");
13224
+ const runtimeDir = path8.dirname(registryPath);
13225
+ if (!fs8.existsSync(runtimeDir)) fs8.mkdirSync(runtimeDir, { recursive: true });
13226
+ fs8.writeFileSync(registryPath, JSON.stringify(registry, null, 2), "utf8");
13167
13227
  }
13168
13228
  function runtimeDiscussionsDir(worktree) {
13169
- return path6.join(optimaLocalConfigDir(worktree), "runtime", "discussions");
13229
+ return path8.join(optimaLocalConfigDir(worktree), "runtime", "discussions");
13170
13230
  }
13171
13231
  function archivedRuntimeDiscussionsDir(worktree) {
13172
- return path6.join(runtimeDiscussionsDir(worktree), "archive");
13232
+ return path8.join(runtimeDiscussionsDir(worktree), "archive");
13173
13233
  }
13174
13234
  function finalDiscussionsDir(worktree) {
13175
- return path6.join(optimaTasksDir(worktree), "discussions");
13235
+ return path8.join(optimaTasksDir(worktree), "discussions");
13176
13236
  }
13177
13237
  function nextDiscussionIdentity(worktree, title) {
13178
13238
  const discussionsDir = finalDiscussionsDir(worktree);
13179
13239
  const runtimeDir = runtimeDiscussionsDir(worktree);
13180
- if (!fs5.existsSync(discussionsDir)) fs5.mkdirSync(discussionsDir, { recursive: true });
13181
- if (!fs5.existsSync(runtimeDir)) fs5.mkdirSync(runtimeDir, { recursive: true });
13240
+ if (!fs8.existsSync(discussionsDir)) fs8.mkdirSync(discussionsDir, { recursive: true });
13241
+ if (!fs8.existsSync(runtimeDir)) fs8.mkdirSync(runtimeDir, { recursive: true });
13182
13242
  let sequence = 1;
13183
13243
  while (true) {
13184
13244
  const id = `DISCUSSION-${String(sequence).padStart(3, "0")}`;
13185
13245
  const filename = `${id}-${slugifyTitle(title)}.md`;
13186
- const summaryRelativePath = path6.join(".optima", "tasks", "discussions", filename);
13187
- const summaryAbsolutePath = path6.join(worktree, summaryRelativePath);
13246
+ const summaryRelativePath = path8.join(".optima", "tasks", "discussions", filename);
13247
+ const summaryAbsolutePath = path8.join(worktree, summaryRelativePath);
13188
13248
  const transcriptFilename = `${id}-transcript.md`;
13189
- const transcriptRelativePath = path6.join(".optima", ".config", "runtime", "discussions", transcriptFilename);
13190
- const transcriptAbsolutePath = path6.join(worktree, transcriptRelativePath);
13191
- if (!fs5.existsSync(summaryAbsolutePath) && !fs5.existsSync(transcriptAbsolutePath)) {
13249
+ const transcriptRelativePath = path8.join(".optima", ".config", "runtime", "discussions", transcriptFilename);
13250
+ const transcriptAbsolutePath = path8.join(worktree, transcriptRelativePath);
13251
+ if (!fs8.existsSync(summaryAbsolutePath) && !fs8.existsSync(transcriptAbsolutePath)) {
13192
13252
  return {
13193
13253
  id,
13194
13254
  filename,
@@ -13204,23 +13264,23 @@ function nextDiscussionIdentity(worktree, title) {
13204
13264
  }
13205
13265
  function findDiscussionById(worktree, discussionID) {
13206
13266
  const discussionsDir = finalDiscussionsDir(worktree);
13207
- if (!fs5.existsSync(discussionsDir)) return null;
13208
- const entries = fs5.readdirSync(discussionsDir).filter((name) => name.startsWith(`${discussionID}-`) && name.endsWith(".md"));
13267
+ if (!fs8.existsSync(discussionsDir)) return null;
13268
+ const entries = fs8.readdirSync(discussionsDir).filter((name) => name.startsWith(`${discussionID}-`) && name.endsWith(".md"));
13209
13269
  if (entries.length === 0) return null;
13210
13270
  const filename = entries.sort()[0];
13211
13271
  const transcriptFilename = `${discussionID}-transcript.md`;
13212
13272
  return {
13213
13273
  id: discussionID,
13214
13274
  filename,
13215
- summaryRelativePath: path6.join(".optima", "tasks", "discussions", filename),
13216
- summaryAbsolutePath: path6.join(discussionsDir, filename),
13275
+ summaryRelativePath: path8.join(".optima", "tasks", "discussions", filename),
13276
+ summaryAbsolutePath: path8.join(discussionsDir, filename),
13217
13277
  transcriptFilename,
13218
- transcriptRelativePath: path6.join(".optima", ".config", "runtime", "discussions", transcriptFilename),
13219
- transcriptAbsolutePath: path6.join(runtimeDiscussionsDir(worktree), transcriptFilename)
13278
+ transcriptRelativePath: path8.join(".optima", ".config", "runtime", "discussions", transcriptFilename),
13279
+ transcriptAbsolutePath: path8.join(runtimeDiscussionsDir(worktree), transcriptFilename)
13220
13280
  };
13221
13281
  }
13222
13282
  function parseDiscussionFile(filePath) {
13223
- const raw = fs5.readFileSync(filePath, "utf8");
13283
+ const raw = fs8.readFileSync(filePath, "utf8");
13224
13284
  const { data, body } = parseFrontmatter(raw);
13225
13285
  return { data, body: body.trimStart() };
13226
13286
  }
@@ -13231,10 +13291,10 @@ ${import_yaml3.default.stringify(frontmatter).trim()}
13231
13291
 
13232
13292
  ${body.trimEnd()}
13233
13293
  `;
13234
- fs5.writeFileSync(filePath, serialized, "utf8");
13294
+ fs8.writeFileSync(filePath, serialized, "utf8");
13235
13295
  }
13236
13296
  function setDiscussionStatus(filePath, status) {
13237
- if (!fs5.existsSync(filePath)) return;
13297
+ if (!fs8.existsSync(filePath)) return;
13238
13298
  const { data, body } = parseDiscussionFile(filePath);
13239
13299
  writeDiscussionFile(filePath, { ...data, status }, body);
13240
13300
  }
@@ -13299,18 +13359,18 @@ async function appendMessageIfNeeded(client, worktree, registry, sessionID, mess
13299
13359
  });
13300
13360
  const text = extractTextParts(response.data.parts || []);
13301
13361
  if (!text) return;
13302
- appendDiscussionMessage(path6.join(worktree, discussion.transcriptPath), speaker, text, messageID);
13362
+ appendDiscussionMessage(path8.join(worktree, discussion.transcriptPath), speaker, text, messageID);
13303
13363
  discussion.appendedMessageIDs ??= [];
13304
13364
  discussion.appendedMessageIDs.push(messageID);
13305
13365
  saveDiscussionRegistry(worktree, registry);
13306
13366
  }
13307
13367
  async function summarizeDiscussionWithBA(client, worktree, discussion) {
13308
- const transcriptPath = path6.join(worktree, discussion.transcriptPath);
13309
- const summaryPath = path6.join(worktree, discussion.summaryPath);
13310
- const summaryDir = path6.dirname(summaryPath);
13311
- if (!fs5.existsSync(summaryDir)) fs5.mkdirSync(summaryDir, { recursive: true });
13312
- const hasExistingSummary = fs5.existsSync(summaryPath);
13313
- const priorMtimeMs = hasExistingSummary ? fs5.statSync(summaryPath).mtimeMs : null;
13368
+ const transcriptPath = path8.join(worktree, discussion.transcriptPath);
13369
+ const summaryPath = path8.join(worktree, discussion.summaryPath);
13370
+ const summaryDir = path8.dirname(summaryPath);
13371
+ if (!fs8.existsSync(summaryDir)) fs8.mkdirSync(summaryDir, { recursive: true });
13372
+ const hasExistingSummary = fs8.existsSync(summaryPath);
13373
+ const priorMtimeMs = hasExistingSummary ? fs8.statSync(summaryPath).mtimeMs : null;
13314
13374
  const summarizerSession = await client.session.create({
13315
13375
  body: { title: `Discussion Summary: ${discussion.id}` }
13316
13376
  });
@@ -13410,30 +13470,30 @@ async function summarizeDiscussionWithBA(client, worktree, discussion) {
13410
13470
  return { confirmation, summaryPath, transcriptPath, hasExistingSummary, priorMtimeMs };
13411
13471
  }
13412
13472
  function archiveDiscussionTranscript(worktree, transcriptRelativePath) {
13413
- const sourcePath = path6.join(worktree, transcriptRelativePath);
13414
- if (!fs5.existsSync(sourcePath)) return null;
13473
+ const sourcePath = path8.join(worktree, transcriptRelativePath);
13474
+ if (!fs8.existsSync(sourcePath)) return null;
13415
13475
  const archiveDir = archivedRuntimeDiscussionsDir(worktree);
13416
- if (!fs5.existsSync(archiveDir)) fs5.mkdirSync(archiveDir, { recursive: true });
13417
- const targetPath = path6.join(archiveDir, path6.basename(sourcePath));
13418
- fs5.renameSync(sourcePath, targetPath);
13476
+ if (!fs8.existsSync(archiveDir)) fs8.mkdirSync(archiveDir, { recursive: true });
13477
+ const targetPath = path8.join(archiveDir, path8.basename(sourcePath));
13478
+ fs8.renameSync(sourcePath, targetPath);
13419
13479
  return targetPath;
13420
13480
  }
13421
13481
  async function finalizeClosingDiscussion(client, worktree, registry, sessionID, discussion) {
13422
13482
  const { confirmation, summaryPath, hasExistingSummary, priorMtimeMs } = await summarizeDiscussionWithBA(client, worktree, discussion);
13423
- if (!fs5.existsSync(summaryPath)) {
13483
+ if (!fs8.existsSync(summaryPath)) {
13424
13484
  throw new Error(`Discussion summary was not written to ${discussion.summaryPath}`);
13425
13485
  }
13426
13486
  if (hasExistingSummary) {
13427
- const currentMtimeMs = fs5.statSync(summaryPath).mtimeMs;
13487
+ const currentMtimeMs = fs8.statSync(summaryPath).mtimeMs;
13428
13488
  if (currentMtimeMs <= priorMtimeMs) {
13429
13489
  throw new Error(`Discussion summary file was not updated at ${discussion.summaryPath}`);
13430
13490
  }
13431
13491
  }
13432
- const summaryContent = fs5.readFileSync(summaryPath, "utf8").trim();
13492
+ const summaryContent = fs8.readFileSync(summaryPath, "utf8").trim();
13433
13493
  if (!summaryContent) {
13434
13494
  throw new Error(`Discussion summary file is empty at ${discussion.summaryPath}`);
13435
13495
  }
13436
- const transcriptPath = path6.join(worktree, discussion.transcriptPath);
13496
+ const transcriptPath = path8.join(worktree, discussion.transcriptPath);
13437
13497
  setDiscussionStatus(transcriptPath, "closed");
13438
13498
  const archivedTranscriptPath = archiveDiscussionTranscript(worktree, discussion.transcriptPath);
13439
13499
  delete registry.active[sessionID];
@@ -13441,7 +13501,7 @@ async function finalizeClosingDiscussion(client, worktree, registry, sessionID,
13441
13501
  return {
13442
13502
  confirmation,
13443
13503
  summaryPath: discussion.summaryPath,
13444
- archivedTranscriptPath: archivedTranscriptPath ? path6.relative(worktree, archivedTranscriptPath) : path6.join(".optima", ".config", "runtime", "discussions", "archive", path6.basename(discussion.transcriptPath))
13504
+ archivedTranscriptPath: archivedTranscriptPath ? path8.relative(worktree, archivedTranscriptPath) : path8.join(".optima", ".config", "runtime", "discussions", "archive", path8.basename(discussion.transcriptPath))
13445
13505
  };
13446
13506
  }
13447
13507
  function normalizeTeamMode(value) {
@@ -13480,13 +13540,13 @@ function getOperatingTeamMode(repoCfg) {
13480
13540
  }
13481
13541
  function readResolvedFile(relativePath, worktree, options = {}) {
13482
13542
  const filePath = resolveIncludeFile(`plugin:${relativePath}`, worktree, PKG_ROOT, options);
13483
- if (!filePath || !fs5.existsSync(filePath)) return "";
13484
- return resolveIncludes(fs5.readFileSync(filePath, "utf8"), worktree, PKG_ROOT, options).trim();
13543
+ if (!filePath || !fs8.existsSync(filePath)) return "";
13544
+ return resolveIncludes(fs8.readFileSync(filePath, "utf8"), worktree, PKG_ROOT, options).trim();
13485
13545
  }
13486
13546
  function loadMarkdownFragment(filePath, worktree) {
13487
- if (!fs5.existsSync(filePath)) return "";
13547
+ if (!fs8.existsSync(filePath)) return "";
13488
13548
  try {
13489
- const raw = fs5.readFileSync(filePath, "utf8");
13549
+ const raw = fs8.readFileSync(filePath, "utf8");
13490
13550
  const { body } = parseFrontmatter(raw);
13491
13551
  return resolveIncludes(body.trim(), worktree, PKG_ROOT);
13492
13552
  } catch (e) {
@@ -13495,9 +13555,9 @@ function loadMarkdownFragment(filePath, worktree) {
13495
13555
  }
13496
13556
  }
13497
13557
  function loadAgentDefinition(filePath, worktree, options = {}) {
13498
- if (!fs5.existsSync(filePath)) return null;
13558
+ if (!fs8.existsSync(filePath)) return null;
13499
13559
  try {
13500
- const rawContent = fs5.readFileSync(filePath, "utf8");
13560
+ const rawContent = fs8.readFileSync(filePath, "utf8");
13501
13561
  const { data, body } = parseFrontmatter(rawContent);
13502
13562
  const prompt = resolveIncludes(body.trim(), worktree, PKG_ROOT, options);
13503
13563
  return { data, prompt };
@@ -13508,13 +13568,13 @@ function loadAgentDefinition(filePath, worktree, options = {}) {
13508
13568
  }
13509
13569
  function syncGeneratedPolicies(worktree, repoCfg) {
13510
13570
  if (repoCfg.policies?.extract_defaults !== "all") return;
13511
- if (!fs5.existsSync(BUNDLE_POLICIES_DIR)) return;
13571
+ if (!fs8.existsSync(BUNDLE_POLICIES_DIR)) return;
13512
13572
  const generatedDir = generatedPoliciesDir(worktree);
13513
- if (!fs5.existsSync(generatedDir)) fs5.mkdirSync(generatedDir, { recursive: true });
13514
- const policyFiles = fs5.readdirSync(BUNDLE_POLICIES_DIR).filter((file) => file.endsWith(".md") && file !== "README.md");
13573
+ if (!fs8.existsSync(generatedDir)) fs8.mkdirSync(generatedDir, { recursive: true });
13574
+ const policyFiles = fs8.readdirSync(BUNDLE_POLICIES_DIR).filter((file) => file.endsWith(".md") && file !== "README.md");
13515
13575
  for (const file of policyFiles) {
13516
- const sourcePath = path6.join(BUNDLE_POLICIES_DIR, file);
13517
- const source = fs5.readFileSync(sourcePath, "utf8").trimEnd();
13576
+ const sourcePath = path8.join(BUNDLE_POLICIES_DIR, file);
13577
+ const source = fs8.readFileSync(sourcePath, "utf8").trimEnd();
13518
13578
  const generated = [
13519
13579
  "<!--",
13520
13580
  "Generated from Optima plugin defaults.",
@@ -13525,19 +13585,19 @@ function syncGeneratedPolicies(worktree, repoCfg) {
13525
13585
  source,
13526
13586
  ""
13527
13587
  ].join("\n");
13528
- fs5.writeFileSync(path6.join(generatedDir, file), generated, "utf8");
13588
+ fs8.writeFileSync(path8.join(generatedDir, file), generated, "utf8");
13529
13589
  }
13530
13590
  }
13531
13591
  function ensureReadmeFile(dirPath, content) {
13532
- if (!fs5.existsSync(dirPath)) fs5.mkdirSync(dirPath, { recursive: true });
13533
- const readmePath = path6.join(dirPath, "README.md");
13534
- if (!fs5.existsSync(readmePath)) {
13535
- fs5.writeFileSync(readmePath, content, "utf8");
13592
+ if (!fs8.existsSync(dirPath)) fs8.mkdirSync(dirPath, { recursive: true });
13593
+ const readmePath = path8.join(dirPath, "README.md");
13594
+ if (!fs8.existsSync(readmePath)) {
13595
+ fs8.writeFileSync(readmePath, content, "utf8");
13536
13596
  }
13537
13597
  }
13538
13598
  function ensureFileIfMissing(filePath, content) {
13539
- if (!fs5.existsSync(path6.dirname(filePath))) fs5.mkdirSync(path6.dirname(filePath), { recursive: true });
13540
- if (!fs5.existsSync(filePath)) fs5.writeFileSync(filePath, content, "utf8");
13599
+ if (!fs8.existsSync(path8.dirname(filePath))) fs8.mkdirSync(path8.dirname(filePath), { recursive: true });
13600
+ if (!fs8.existsSync(filePath)) fs8.writeFileSync(filePath, content, "utf8");
13541
13601
  }
13542
13602
  function currentTasksRegistryContent() {
13543
13603
  return "# Current Tasks (Backlog)\n\n## \u{1F4AC} Active Discussions\n- (None)\n\n## \u{1F680} Active\n- (None)\n\n## \u{1F4CB} Todo\n- (None)\n\n## \u{1F6D1} Blocked\n- (None)\n";
@@ -13623,16 +13683,16 @@ Never place implementation evidence under root \`evidences/\`.
13623
13683
  }
13624
13684
  function ensureOptimaTaskTemplates(worktree) {
13625
13685
  const tasksDir = optimaTasksDir(worktree);
13626
- ensureFileIfMissing(path6.join(tasksDir, "task-template.md"), taskTemplateContent());
13627
- ensureFileIfMissing(path6.join(tasksDir, "subtask-template.md"), subtaskTemplateContent());
13686
+ ensureFileIfMissing(path8.join(tasksDir, "task-template.md"), taskTemplateContent());
13687
+ ensureFileIfMissing(path8.join(tasksDir, "subtask-template.md"), subtaskTemplateContent());
13628
13688
  }
13629
13689
  function scaffoldOptimaConfig(worktree, teamMode = "full") {
13630
13690
  const configPath = repoConfigPath(worktree);
13631
- if (fs5.existsSync(configPath)) return false;
13632
- const templatePath = path6.join(TEMPLATES_DIR, "optima.yaml.template");
13633
- if (!fs5.existsSync(templatePath)) return false;
13634
- const agentIds = fs5.existsSync(BUNDLE_AGENTS_DIR) ? fs5.readdirSync(BUNDLE_AGENTS_DIR).filter((f) => f.endsWith(".md")).map((f) => f.replace(".md", "")) : [];
13635
- let optimaConfig = fs5.readFileSync(templatePath, "utf8");
13691
+ if (fs8.existsSync(configPath)) return false;
13692
+ const templatePath = path8.join(TEMPLATES_DIR, "optima.yaml.template");
13693
+ if (!fs8.existsSync(templatePath)) return false;
13694
+ const agentIds = fs8.existsSync(BUNDLE_AGENTS_DIR) ? fs8.readdirSync(BUNDLE_AGENTS_DIR).filter((f) => f.endsWith(".md")).map((f) => f.replace(".md", "")) : [];
13695
+ let optimaConfig = fs8.readFileSync(templatePath, "utf8");
13636
13696
  optimaConfig = optimaConfig.replace("{{teamMode}}", normalizeTeamMode(teamMode));
13637
13697
  let agentsSection = "";
13638
13698
  for (const id of agentIds) {
@@ -13643,26 +13703,26 @@ function scaffoldOptimaConfig(worktree, teamMode = "full") {
13643
13703
  }
13644
13704
  optimaConfig = optimaConfig.replace(/^agents:/m, "agents:\n" + agentsSection);
13645
13705
  ensureFileIfMissing(configPath, optimaConfig);
13646
- return fs5.existsSync(configPath);
13706
+ return fs8.existsSync(configPath);
13647
13707
  }
13648
13708
  function scaffoldOptimaRootCodemap(worktree) {
13649
13709
  const rootCodemapPath = optimaCodemapPath(worktree);
13650
- if (fs5.existsSync(rootCodemapPath)) return false;
13651
- const templatePath = path6.join(TEMPLATES_DIR, "codemap.yml.template");
13652
- if (!fs5.existsSync(templatePath)) return false;
13653
- const codemapConfig = fs5.readFileSync(templatePath, "utf8").replace("{{projectName}}", path6.basename(worktree));
13710
+ if (fs8.existsSync(rootCodemapPath)) return false;
13711
+ const templatePath = path8.join(TEMPLATES_DIR, "codemap.yml.template");
13712
+ if (!fs8.existsSync(templatePath)) return false;
13713
+ const codemapConfig = fs8.readFileSync(templatePath, "utf8").replace("{{projectName}}", path8.basename(worktree));
13654
13714
  ensureFileIfMissing(rootCodemapPath, codemapConfig);
13655
- return fs5.existsSync(rootCodemapPath);
13715
+ return fs8.existsSync(rootCodemapPath);
13656
13716
  }
13657
13717
  function ensureOptimaRegistries(worktree) {
13658
13718
  const tasksDir = optimaTasksDir(worktree);
13659
13719
  const scrsDir = optimaScrsDir(worktree);
13660
- if (!fs5.existsSync(tasksDir)) fs5.mkdirSync(tasksDir, { recursive: true });
13661
- if (!fs5.existsSync(scrsDir)) fs5.mkdirSync(scrsDir, { recursive: true });
13662
- ensureFileIfMissing(path6.join(tasksDir, "current.md"), currentTasksRegistryContent());
13663
- ensureFileIfMissing(path6.join(tasksDir, "done.md"), doneTasksRegistryContent());
13664
- ensureFileIfMissing(path6.join(scrsDir, "current.md"), currentScrRegistryContent());
13665
- ensureFileIfMissing(path6.join(scrsDir, "done.md"), doneScrRegistryContent());
13720
+ if (!fs8.existsSync(tasksDir)) fs8.mkdirSync(tasksDir, { recursive: true });
13721
+ if (!fs8.existsSync(scrsDir)) fs8.mkdirSync(scrsDir, { recursive: true });
13722
+ ensureFileIfMissing(path8.join(tasksDir, "current.md"), currentTasksRegistryContent());
13723
+ ensureFileIfMissing(path8.join(tasksDir, "done.md"), doneTasksRegistryContent());
13724
+ ensureFileIfMissing(path8.join(scrsDir, "current.md"), currentScrRegistryContent());
13725
+ ensureFileIfMissing(path8.join(scrsDir, "done.md"), doneScrRegistryContent());
13666
13726
  }
13667
13727
  function scaffoldOptimaReadmes(worktree) {
13668
13728
  ensureReadmeFile(repoPoliciesDir(worktree), REPO_LOCAL_POLICIES_README);
@@ -13824,12 +13884,12 @@ function shouldRegisterWorkflowProductManager(options = {}, worktree = process.c
13824
13884
  }
13825
13885
  function isClickUpDerivedWorktreeSibling(candidate, basePath) {
13826
13886
  if (typeof candidate !== "string" || typeof basePath !== "string" || !candidate.trim() || !basePath.trim()) return false;
13827
- const resolvedCandidate = path6.resolve(candidate);
13828
- const resolvedBase = path6.resolve(basePath);
13829
- const baseParent = path6.dirname(resolvedBase);
13830
- if (path6.dirname(resolvedCandidate) !== baseParent) return false;
13831
- const baseName = path6.basename(resolvedBase);
13832
- const candidateName = path6.basename(resolvedCandidate);
13887
+ const resolvedCandidate = path8.resolve(candidate);
13888
+ const resolvedBase = path8.resolve(basePath);
13889
+ const baseParent = path8.dirname(resolvedBase);
13890
+ if (path8.dirname(resolvedCandidate) !== baseParent) return false;
13891
+ const baseName = path8.basename(resolvedBase);
13892
+ const candidateName = path8.basename(resolvedCandidate);
13833
13893
  if (!candidateName.startsWith(`${baseName}-`)) return false;
13834
13894
  const branchSlug = candidateName.slice(baseName.length + 1);
13835
13895
  const parts = branchSlug.split("-").filter(Boolean);
@@ -13837,11 +13897,11 @@ function isClickUpDerivedWorktreeSibling(candidate, basePath) {
13837
13897
  if (!(/* @__PURE__ */ new Set(["tarea", "bug", "doc", "poc", "idea"])).has(parts[0])) return false;
13838
13898
  if (!parts.slice(1).every((part) => /^[a-z0-9][a-z0-9-]*$/.test(part))) return false;
13839
13899
  try {
13840
- const candidateStat = fs5.lstatSync(resolvedCandidate);
13900
+ const candidateStat = fs8.lstatSync(resolvedCandidate);
13841
13901
  if (!candidateStat.isDirectory() || candidateStat.isSymbolicLink()) return false;
13842
- const realCandidate = fs5.realpathSync.native(resolvedCandidate);
13843
- const realBaseParent = fs5.realpathSync.native(baseParent);
13844
- return path6.dirname(realCandidate) === realBaseParent && path6.basename(realCandidate) === candidateName;
13902
+ const realCandidate = fs8.realpathSync.native(resolvedCandidate);
13903
+ const realBaseParent = fs8.realpathSync.native(baseParent);
13904
+ return path8.dirname(realCandidate) === realBaseParent && path8.basename(realCandidate) === candidateName;
13845
13905
  } catch {
13846
13906
  return false;
13847
13907
  }
@@ -13849,15 +13909,15 @@ function isClickUpDerivedWorktreeSibling(candidate, basePath) {
13849
13909
  function resolveSessionToolDirectory({ requestedDirectory, context, pluginWorktree, clickUpWebhookValidation } = {}) {
13850
13910
  const safe = safeWorktreeOrFailure(context, pluginWorktree);
13851
13911
  if (!safe.ok) return { ok: false, error: safe.message };
13852
- const requested = String(requestedDirectory || "").trim() ? path6.resolve(safe.worktree, String(requestedDirectory).trim()) : safe.worktree;
13912
+ const requested = String(requestedDirectory || "").trim() ? path8.resolve(safe.worktree, String(requestedDirectory).trim()) : safe.worktree;
13853
13913
  if (!isSafeWritableDirectory(requested)) return { ok: false, error: `Directory is not a safe writable directory: ${requested}` };
13854
13914
  if (isSameOrNestedPath(requested, safe.worktree)) return { ok: true, directory: requested, safeWorktree: safe.worktree, scope: "context_worktree" };
13855
13915
  const clickUpBasePath = clickUpWebhookValidation?.complete === true && clickUpWebhookValidation?.ok !== false ? clickUpWebhookValidation.config?.basePath : "";
13856
13916
  if (clickUpBasePath && isSameOrNestedPath(requested, clickUpBasePath)) {
13857
- return { ok: true, directory: requested, safeWorktree: safe.worktree, scope: "clickup_base_path", clickupBasePath: path6.resolve(clickUpBasePath) };
13917
+ return { ok: true, directory: requested, safeWorktree: safe.worktree, scope: "clickup_base_path", clickupBasePath: path8.resolve(clickUpBasePath) };
13858
13918
  }
13859
13919
  if (clickUpBasePath && isClickUpDerivedWorktreeSibling(requested, clickUpBasePath)) {
13860
- return { ok: true, directory: requested, safeWorktree: safe.worktree, scope: "clickup_derived_worktree", clickupBasePath: path6.resolve(clickUpBasePath) };
13920
+ return { ok: true, directory: requested, safeWorktree: safe.worktree, scope: "clickup_derived_worktree", clickupBasePath: path8.resolve(clickUpBasePath) };
13861
13921
  }
13862
13922
  return {
13863
13923
  ok: false,
@@ -13891,8 +13951,8 @@ function buildOptimaAgents(repoCfg, operatingTeamMode, worktree, debugDir, optio
13891
13951
  if (!enabled) continue;
13892
13952
  }
13893
13953
  const promptOptions = { preferCompactPromptDocs: repoCfg.features?.compact_prompt_docs !== false };
13894
- const bundledDefinition = loadAgentDefinition(path6.join(BUNDLE_AGENTS_DIR, file), worktree, promptOptions);
13895
- const repoDefinition = loadAgentDefinition(path6.join(repoAgentDefinitions, file), worktree, promptOptions) || loadAgentDefinition(path6.join(legacyAgentsDir, file), worktree, promptOptions);
13954
+ const bundledDefinition = loadAgentDefinition(path8.join(BUNDLE_AGENTS_DIR, file), worktree, promptOptions);
13955
+ const repoDefinition = loadAgentDefinition(path8.join(repoAgentDefinitions, file), worktree, promptOptions) || loadAgentDefinition(path8.join(legacyAgentsDir, file), worktree, promptOptions);
13896
13956
  const activeDefinition = repoDefinition || bundledDefinition;
13897
13957
  if (!activeDefinition) continue;
13898
13958
  const { data } = activeDefinition;
@@ -13901,7 +13961,7 @@ function buildOptimaAgents(repoCfg, operatingTeamMode, worktree, debugDir, optio
13901
13961
  if (modePromptFragment) finalPrompt = `${finalPrompt}
13902
13962
 
13903
13963
  ${modePromptFragment}`;
13904
- const additionFragment = loadMarkdownFragment(path6.join(repoAgentAdditions, file), worktree);
13964
+ const additionFragment = loadMarkdownFragment(path8.join(repoAgentAdditions, file), worktree);
13905
13965
  if (additionFragment) {
13906
13966
  finalPrompt = `${finalPrompt}
13907
13967
 
@@ -13954,14 +14014,14 @@ Use this Optima-provided fallback when the current task worktree lacks docs/core
13954
14014
  }
13955
14015
  ourAgents[id] = agentConfig;
13956
14016
  if (repoCfg.features?.debug_dumps !== false) {
13957
- const debugPath = path6.join(debugDir, `${id}.md`);
14017
+ const debugPath = path8.join(debugDir, `${id}.md`);
13958
14018
  const { prompt, ...dumpConfig } = agentConfig;
13959
14019
  const debugHeader = `---
13960
14020
  ${import_yaml3.default.stringify(dumpConfig).trim()}
13961
14021
  ---`;
13962
14022
  try {
13963
- if (!fs5.existsSync(debugDir)) fs5.mkdirSync(debugDir, { recursive: true });
13964
- fs5.writeFileSync(debugPath, `${debugHeader}
14023
+ if (!fs8.existsSync(debugDir)) fs8.mkdirSync(debugDir, { recursive: true });
14024
+ fs8.writeFileSync(debugPath, `${debugHeader}
13965
14025
 
13966
14026
  ${prompt}`, "utf8");
13967
14027
  } catch (e) {
@@ -13985,9 +14045,9 @@ async function OptimaPlugin(input = {}, pluginOptions = {}) {
13985
14045
  const configPath = resolveConfigPath(worktree);
13986
14046
  const discussionRegistry = loadDiscussionRegistry(worktree);
13987
14047
  let repoCfg = { agents: {}, defaults: {}, features: {} };
13988
- if (fs5.existsSync(configPath)) {
14048
+ if (fs8.existsSync(configPath)) {
13989
14049
  try {
13990
- repoCfg = import_yaml3.default.parse(fs5.readFileSync(configPath, "utf8")) || repoCfg;
14050
+ repoCfg = import_yaml3.default.parse(fs8.readFileSync(configPath, "utf8")) || repoCfg;
13991
14051
  } catch (e) {
13992
14052
  console.error(`[Optima] Failed to parse config at ${configPath}:`, e);
13993
14053
  }
@@ -14115,10 +14175,10 @@ async function OptimaPlugin(input = {}, pluginOptions = {}) {
14115
14175
  }
14116
14176
  migrateLegacyOptimaLayout(toolWorktree);
14117
14177
  const cfgDir = optimaConfigDir(toolWorktree);
14118
- if (!fs5.existsSync(cfgDir)) fs5.mkdirSync(cfgDir, { recursive: true });
14119
- const optimaTmplPath = path6.join(TEMPLATES_DIR, "optima.yaml.template");
14120
- const codemapTmplPath = path6.join(TEMPLATES_DIR, "codemap.yml.template");
14121
- if (!fs5.existsSync(optimaTmplPath) || !fs5.existsSync(codemapTmplPath)) {
14178
+ if (!fs8.existsSync(cfgDir)) fs8.mkdirSync(cfgDir, { recursive: true });
14179
+ const optimaTmplPath = path8.join(TEMPLATES_DIR, "optima.yaml.template");
14180
+ const codemapTmplPath = path8.join(TEMPLATES_DIR, "codemap.yml.template");
14181
+ if (!fs8.existsSync(optimaTmplPath) || !fs8.existsSync(codemapTmplPath)) {
14122
14182
  return "Error: Initialization templates not found in plugin.";
14123
14183
  }
14124
14184
  scaffoldOptimaConfig(toolWorktree, requestedTeamMode);
@@ -14239,14 +14299,14 @@ Restart or reload OpenCode manually if the newly scaffolded config or agents are
14239
14299
  async execute(args, context) {
14240
14300
  const safe = safeWorktreeOrFailure(context, worktree);
14241
14301
  if (!safe.ok) return safe.message;
14242
- const summaryPath = path6.resolve(safe.worktree, args.summary_path || "");
14243
- if (!fs5.existsSync(summaryPath)) return `FAIL: summary_path not found: ${summaryPath}`;
14244
- const taskPath = args.task_path ? path6.resolve(safe.worktree, args.task_path) : "";
14302
+ const summaryPath = path8.resolve(safe.worktree, args.summary_path || "");
14303
+ if (!fs8.existsSync(summaryPath)) return `FAIL: summary_path not found: ${summaryPath}`;
14304
+ const taskPath = args.task_path ? path8.resolve(safe.worktree, args.task_path) : "";
14245
14305
  const payload = buildClickUpSummaryPayload({
14246
- summaryMarkdown: fs5.readFileSync(summaryPath, "utf8"),
14247
- summaryPath: path6.relative(safe.worktree, summaryPath),
14248
- taskMarkdown: taskPath && fs5.existsSync(taskPath) ? fs5.readFileSync(taskPath, "utf8") : "",
14249
- taskPath: taskPath ? path6.relative(safe.worktree, taskPath) : "",
14306
+ summaryMarkdown: fs8.readFileSync(summaryPath, "utf8"),
14307
+ summaryPath: path8.relative(safe.worktree, summaryPath),
14308
+ taskMarkdown: taskPath && fs8.existsSync(taskPath) ? fs8.readFileSync(taskPath, "utf8") : "",
14309
+ taskPath: taskPath ? path8.relative(safe.worktree, taskPath) : "",
14250
14310
  branch: args.branch,
14251
14311
  worktree: args.worktree,
14252
14312
  pr: args.pr
@@ -14325,12 +14385,12 @@ Restart or reload OpenCode manually if the newly scaffolded config or agents are
14325
14385
  async execute(args, context) {
14326
14386
  const safe = safeWorktreeOrFailure(context, worktree);
14327
14387
  if (!safe.ok) return safe.message;
14328
- const markdownPath = path6.resolve(safe.worktree, args.markdown_path || "");
14329
- if (!fs5.existsSync(markdownPath)) return `FAIL: markdown_path not found: ${markdownPath}`;
14388
+ const markdownPath = path8.resolve(safe.worktree, args.markdown_path || "");
14389
+ if (!fs8.existsSync(markdownPath)) return `FAIL: markdown_path not found: ${markdownPath}`;
14330
14390
  const payload = buildClickUpCreateSubtasksPayload({
14331
14391
  parentTaskId: args.parent_task_id,
14332
- markdown: fs5.readFileSync(markdownPath, "utf8"),
14333
- sourcePath: path6.relative(safe.worktree, markdownPath),
14392
+ markdown: fs8.readFileSync(markdownPath, "utf8"),
14393
+ sourcePath: path8.relative(safe.worktree, markdownPath),
14334
14394
  parentBranch: args.parent_branch,
14335
14395
  parentTaskType: args.parent_task_type || "Tarea",
14336
14396
  apply: String(args.apply || "").toLowerCase() === "true"
@@ -14700,7 +14760,7 @@ Backfilled messages: ${backfilled}`;
14700
14760
  if (!existing) {
14701
14761
  return "FAIL: No active discussion exists for this session.";
14702
14762
  }
14703
- const discussionPath = path6.join(toolWorktree, existing.transcriptPath);
14763
+ const discussionPath = path8.join(toolWorktree, existing.transcriptPath);
14704
14764
  setDiscussionStatus(discussionPath, "summarizing");
14705
14765
  existing.status = "summarizing";
14706
14766
  saveDiscussionRegistry(toolWorktree, toolRegistry);
@@ -14752,7 +14812,7 @@ Reason: ${err.message}`;
14752
14812
  try {
14753
14813
  const sessionResult = await client.session.create({
14754
14814
  query: { directory: workflowDirectory },
14755
- body: { title: `Workflow Run: ${path6.basename(workflowTaskPath)}` }
14815
+ body: { title: `Workflow Run: ${path8.basename(workflowTaskPath)}` }
14756
14816
  });
14757
14817
  const sessionId = sessionResult.data.id;
14758
14818
  activeWorkflows.set(sessionId, { pmaSessionId, taskPath: workflowTaskPath, track: workflowTrack, directory: workflowDirectory });
@@ -14936,14 +14996,14 @@ function usage() {
14936
14996
  ].join("\n");
14937
14997
  }
14938
14998
  function expandHome(inputPath) {
14939
- if (!inputPath || inputPath === "~") return os2.homedir();
14940
- if (inputPath.startsWith("~/")) return path7.join(os2.homedir(), inputPath.slice(2));
14999
+ if (!inputPath || inputPath === "~") return os3.homedir();
15000
+ if (inputPath.startsWith("~/")) return path9.join(os3.homedir(), inputPath.slice(2));
14941
15001
  return inputPath;
14942
15002
  }
14943
15003
  function resolveOpenCodeDbPath(inputPath = null) {
14944
15004
  const expanded = expandHome(inputPath || process.env.OPTIMA_OPENCODE_DB_PATH || DEFAULT_DB_PATH);
14945
15005
  try {
14946
- if (fs6.existsSync(expanded) && fs6.statSync(expanded).isDirectory()) return path7.join(expanded, "opencode.db");
15006
+ if (fs9.existsSync(expanded) && fs9.statSync(expanded).isDirectory()) return path9.join(expanded, "opencode.db");
14947
15007
  } catch {
14948
15008
  return expanded;
14949
15009
  }
@@ -15007,12 +15067,12 @@ function extractOpenedPathValue(value) {
15007
15067
  }
15008
15068
  function normalizePathCandidate(candidate) {
15009
15069
  const expanded = expandHome(candidate);
15010
- if (!path7.isAbsolute(expanded)) return null;
15011
- return path7.resolve(expanded);
15070
+ if (!path9.isAbsolute(expanded)) return null;
15071
+ return path9.resolve(expanded);
15012
15072
  }
15013
15073
  function discoverOpenCodePaths(dbPath) {
15014
15074
  const resolvedDb = resolveOpenCodeDbPath(dbPath);
15015
- if (!fs6.existsSync(resolvedDb)) throw new Error(`OpenCode database not found: ${resolvedDb}`);
15075
+ if (!fs9.existsSync(resolvedDb)) throw new Error(`OpenCode database not found: ${resolvedDb}`);
15016
15076
  const tables = sqliteJson(resolvedDb, "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name");
15017
15077
  const discovered = /* @__PURE__ */ new Set();
15018
15078
  for (const table of tables) {
@@ -15037,27 +15097,27 @@ function discoverOpenCodePaths(dbPath) {
15037
15097
  function collectMarkdownOverridesFrom(baseDir) {
15038
15098
  const files = [];
15039
15099
  for (const dirName of OVERRIDE_DIRS) {
15040
- const dirPath = path7.join(baseDir, dirName);
15041
- if (!fs6.existsSync(dirPath)) continue;
15042
- for (const entry of fs6.readdirSync(dirPath, { withFileTypes: true })) {
15100
+ const dirPath = path9.join(baseDir, dirName);
15101
+ if (!fs9.existsSync(dirPath)) continue;
15102
+ for (const entry of fs9.readdirSync(dirPath, { withFileTypes: true })) {
15043
15103
  if (!entry.isFile()) continue;
15044
15104
  if (!entry.name.endsWith(".md")) continue;
15045
15105
  if (entry.name.toLowerCase() === "readme.md") continue;
15046
- files.push(path7.join(dirPath, entry.name));
15106
+ files.push(path9.join(dirPath, entry.name));
15047
15107
  }
15048
15108
  }
15049
15109
  return files;
15050
15110
  }
15051
15111
  function collectOverrideFiles(worktree) {
15052
- return collectMarkdownOverridesFrom(path7.join(worktree, ".optima")).sort();
15112
+ return collectMarkdownOverridesFrom(path9.join(worktree, ".optima")).sort();
15053
15113
  }
15054
15114
  function collectPlannedOverrideFiles(worktree) {
15055
15115
  return [
15056
15116
  ...collectOverrideFiles(worktree),
15057
- ...collectMarkdownOverridesFrom(path7.join(worktree, ".staticeng")),
15058
- ...collectMarkdownOverridesFrom(path7.join(worktree, ".orbita")),
15059
- ...collectMarkdownOverridesFrom(path7.join(worktree, ".nomadwork")),
15060
- ...collectMarkdownOverridesFrom(path7.join(worktree, ".nomadworks"))
15117
+ ...collectMarkdownOverridesFrom(path9.join(worktree, ".staticeng")),
15118
+ ...collectMarkdownOverridesFrom(path9.join(worktree, ".orbita")),
15119
+ ...collectMarkdownOverridesFrom(path9.join(worktree, ".nomadwork")),
15120
+ ...collectMarkdownOverridesFrom(path9.join(worktree, ".nomadworks"))
15061
15121
  ].sort();
15062
15122
  }
15063
15123
  var CRC_TABLE = (() => {
@@ -15090,14 +15150,14 @@ function writeUInt16LE(value) {
15090
15150
  return buffer;
15091
15151
  }
15092
15152
  function createZipBackup(files, backupPath) {
15093
- fs6.mkdirSync(path7.dirname(backupPath), { recursive: true });
15153
+ fs9.mkdirSync(path9.dirname(backupPath), { recursive: true });
15094
15154
  const localParts = [];
15095
15155
  const centralParts = [];
15096
15156
  let offset = 0;
15097
15157
  const now = dosTimeDate();
15098
15158
  for (const filePath of files) {
15099
- const data = fs6.readFileSync(filePath);
15100
- const name = path7.resolve(filePath).replace(/^\//, "").split(path7.sep).join("/");
15159
+ const data = fs9.readFileSync(filePath);
15160
+ const name = path9.resolve(filePath).replace(/^\//, "").split(path9.sep).join("/");
15101
15161
  const nameBuffer = Buffer.from(name, "utf8");
15102
15162
  const crc = crc32(data);
15103
15163
  const local = Buffer.concat([
@@ -15149,7 +15209,7 @@ function createZipBackup(files, backupPath) {
15149
15209
  writeUInt32LE(offset),
15150
15210
  writeUInt16LE(0)
15151
15211
  ]);
15152
- fs6.writeFileSync(backupPath, Buffer.concat([...localParts, ...centralParts, end]));
15212
+ fs9.writeFileSync(backupPath, Buffer.concat([...localParts, ...centralParts, end]));
15153
15213
  }
15154
15214
  function timestamp() {
15155
15215
  return (/* @__PURE__ */ new Date()).toISOString().replace(/[-:]/g, "").replace(/\.\d{3}Z$/, "Z");
@@ -15159,17 +15219,17 @@ function validationStatus(result) {
15159
15219
  return result.ok ? "passed" : "failed";
15160
15220
  }
15161
15221
  function hasLegacyMarker(worktree) {
15162
- 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"));
15222
+ return fs9.existsSync(path9.join(worktree, ".staticeng")) || fs9.existsSync(path9.join(worktree, ".orbita")) || fs9.existsSync(path9.join(worktree, ".nomadwork")) || fs9.existsSync(path9.join(worktree, ".nomadworks"));
15163
15223
  }
15164
15224
  function rootOptimaArtifacts(worktree) {
15165
15225
  const artifacts = [
15166
- ["tasks/", path7.join(worktree, "tasks")],
15167
- ["evidences/", path7.join(worktree, "evidences")],
15168
- ["docs/scrs/", path7.join(worktree, "docs", "scrs")],
15169
- ["codemap.yml", path7.join(worktree, "codemap.yml")],
15170
- ["codemap.yaml", path7.join(worktree, "codemap.yaml")]
15226
+ ["tasks/", path9.join(worktree, "tasks")],
15227
+ ["evidences/", path9.join(worktree, "evidences")],
15228
+ ["docs/scrs/", path9.join(worktree, "docs", "scrs")],
15229
+ ["codemap.yml", path9.join(worktree, "codemap.yml")],
15230
+ ["codemap.yaml", path9.join(worktree, "codemap.yaml")]
15171
15231
  ];
15172
- return artifacts.map(([display, artifactPath]) => ({ display, path: artifactPath })).filter((item) => fs6.existsSync(item.path));
15232
+ return artifacts.map(([display, artifactPath]) => ({ display, path: artifactPath })).filter((item) => fs9.existsSync(item.path));
15173
15233
  }
15174
15234
  function hasSanitizableOverrides(worktree) {
15175
15235
  return collectPlannedOverrideFiles(worktree).length > 0;
@@ -15195,7 +15255,7 @@ function planOptimaMigration(worktree, dryRun) {
15195
15255
  ...overrides.map((file) => ({
15196
15256
  category: "override",
15197
15257
  action: dryRun ? "would_remove_after_backup" : "removed_after_backup",
15198
- path: path7.relative(worktree, file).split(path7.sep).join("/"),
15258
+ path: path9.relative(worktree, file).split(path9.sep).join("/"),
15199
15259
  detail: "Remove implicit agent/policy override after host-level backup."
15200
15260
  }))
15201
15261
  ],
@@ -15216,12 +15276,12 @@ async function sanitizeHost(options = {}) {
15216
15276
  const repoStates = [];
15217
15277
  for (const candidate of paths) {
15218
15278
  try {
15219
- if (!fs6.existsSync(candidate)) {
15279
+ if (!fs9.existsSync(candidate)) {
15220
15280
  report.totals.skipped += 1;
15221
15281
  report.repos.push({ path: candidate, status: "skipped", reason: "missing" });
15222
15282
  continue;
15223
15283
  }
15224
- if (!fs6.statSync(candidate).isDirectory()) {
15284
+ if (!fs9.statSync(candidate).isDirectory()) {
15225
15285
  report.totals.skipped += 1;
15226
15286
  report.repos.push({ path: candidate, status: "skipped", reason: "not_directory" });
15227
15287
  continue;
@@ -15243,7 +15303,7 @@ async function sanitizeHost(options = {}) {
15243
15303
  const overrides = repoStates.flatMap((state) => state.overrideFiles.map((file) => ({ repo: state.repo, file })));
15244
15304
  report.totals.overrideFiles = overrides.length;
15245
15305
  if (!dryRun && overrides.length > 0) {
15246
- const backupPath = path7.join(os2.homedir(), BACKUP_DIRNAME, `${timestamp()}.zip`);
15306
+ const backupPath = path9.join(os3.homedir(), BACKUP_DIRNAME, `${timestamp()}.zip`);
15247
15307
  try {
15248
15308
  createZipBackup(overrides.map((item) => item.file), backupPath);
15249
15309
  report.backupPath = backupPath;
@@ -15259,7 +15319,7 @@ async function sanitizeHost(options = {}) {
15259
15319
  for (const state of repoStates) {
15260
15320
  try {
15261
15321
  if (!dryRun) {
15262
- for (const file of state.overrideFiles) fs6.rmSync(file, { force: true });
15322
+ for (const file of state.overrideFiles) fs9.rmSync(file, { force: true });
15263
15323
  }
15264
15324
  const validation = !dryRun && hasLegacyMarker(state.repo) ? await optima_validate_logic(state.repo) : null;
15265
15325
  const status = (!validation || validation.ok) && state.plan.unresolved.length === 0 ? "repaired" : "failed";
@@ -15272,7 +15332,7 @@ async function sanitizeHost(options = {}) {
15272
15332
  repairActions: state.plan.actions.length,
15273
15333
  repairSkipped: state.plan.skippedRepair === true,
15274
15334
  overrideFiles: state.overrideFiles.length,
15275
- overridePaths: state.overrideFiles.map((file) => path7.relative(state.repo, file).split(path7.sep).join("/")),
15335
+ overridePaths: state.overrideFiles.map((file) => path9.relative(state.repo, file).split(path9.sep).join("/")),
15276
15336
  validation: validation ? validationStatus(validation) : "skipped",
15277
15337
  unresolved: state.plan.unresolved
15278
15338
  });