@defend-tech/opencode-optima 0.1.75 → 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,24 +7834,438 @@ 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";
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;
7851
+ }
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 "";
7862
+ }
7863
+ }
7864
+ return raw;
7865
+ }
7866
+
7867
+ // src/github.js
7868
+ function base64UrlJson(value) {
7869
+ return Buffer.from(JSON.stringify(value)).toString("base64url");
7870
+ }
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
+ }
7881
+ }
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}`;
7892
+ }
7893
+ function encodeGitHubPathSegment(value) {
7894
+ return encodeURIComponent(String(value || ""));
7895
+ }
7896
+ function encodeGitHubBranchRef(branch = "") {
7897
+ return String(branch || "").split("/").map(encodeGitHubPathSegment).join("/");
7898
+ }
7899
+ function parseNullSeparatedGitOutput(output = "") {
7900
+ return String(output || "").split("\0").map((item) => item.trim()).filter(Boolean);
7901
+ }
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));
7906
+ }
7907
+ function currentGitBranch(worktree, runGitFn = runGit) {
7908
+ return String(runGitFn(worktree, ["rev-parse", "--abbrev-ref", "HEAD"]) || "").trim();
7909
+ }
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
+ };
7923
+ }
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
+ };
7931
+ }
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));
7937
+ }
7938
+ const suffix = query.toString();
7939
+ return suffix ? `${pathname}?${suffix}` : pathname;
7940
+ }
7941
+ function timestampMs(value = "") {
7942
+ const parsed = Date.parse(String(value || ""));
7943
+ return Number.isFinite(parsed) ? parsed : 0;
7944
+ }
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
+ });
7951
+ }
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));
7961
+ }
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";
7808
8254
  function compactPromptPath(filePath) {
7809
8255
  if (!filePath.endsWith(".md") || filePath.endsWith(".prompt.md")) return null;
7810
8256
  return filePath.replace(/\.md$/, ".prompt.md");
7811
8257
  }
7812
8258
  function isSameOrNestedPath(candidate, root) {
7813
8259
  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);
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);
7818
8264
  }
7819
8265
  function resolveWithin(baseDir, relativePath) {
7820
8266
  if (!relativePath) return null;
7821
- if (path2.isAbsolute(relativePath)) return null;
7822
- const resolved = path2.resolve(baseDir, relativePath);
8267
+ if (path4.isAbsolute(relativePath)) return null;
8268
+ const resolved = path4.resolve(baseDir, relativePath);
7823
8269
  return isSameOrNestedPath(resolved, baseDir) ? resolved : null;
7824
8270
  }
7825
8271
  function withCompactPreference(paths, options = {}) {
@@ -7832,18 +8278,18 @@ function resolveIncludeFile(includeRef, repoRoot, bundleRoot, options = {}) {
7832
8278
  const scopedMatch = trimmed.match(/^([a-z]+):(.*)$/i);
7833
8279
  const scope = scopedMatch?.[1]?.toLowerCase();
7834
8280
  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");
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");
7838
8284
  if (scope === "plugin") {
7839
8285
  for (const filePath of withCompactPreference([resolveWithin(bundleRoot, target)], options)) {
7840
- if (filePath && fs2.existsSync(filePath)) return filePath;
8286
+ if (filePath && fs4.existsSync(filePath)) return filePath;
7841
8287
  }
7842
8288
  return null;
7843
8289
  }
7844
8290
  if (scope === "repo") {
7845
8291
  for (const filePath of withCompactPreference([resolveWithin(optimaRoot, target)], options)) {
7846
- if (filePath && fs2.existsSync(filePath)) return filePath;
8292
+ if (filePath && fs4.existsSync(filePath)) return filePath;
7847
8293
  }
7848
8294
  return null;
7849
8295
  }
@@ -7853,7 +8299,7 @@ function resolveIncludeFile(includeRef, repoRoot, bundleRoot, options = {}) {
7853
8299
  resolveWithin(bundlePolicyRoot, target)
7854
8300
  ], options);
7855
8301
  for (const filePath of candidates2) {
7856
- if (filePath && fs2.existsSync(filePath)) return filePath;
8302
+ if (filePath && fs4.existsSync(filePath)) return filePath;
7857
8303
  }
7858
8304
  return null;
7859
8305
  }
@@ -7862,7 +8308,7 @@ function resolveIncludeFile(includeRef, repoRoot, bundleRoot, options = {}) {
7862
8308
  resolveWithin(bundleRoot, target)
7863
8309
  ], options);
7864
8310
  for (const filePath of candidates) {
7865
- if (filePath && fs2.existsSync(filePath)) return filePath;
8311
+ if (filePath && fs4.existsSync(filePath)) return filePath;
7866
8312
  }
7867
8313
  return null;
7868
8314
  }
@@ -7883,16 +8329,69 @@ function resolveIncludes(text, repoRoot, bundleRoot, options = {}) {
7883
8329
 
7884
8330
  `;
7885
8331
  }
7886
- const content = fs2.readFileSync(filePath, "utf8");
8332
+ const content = fs4.readFileSync(filePath, "utf8");
7887
8333
  return resolveIncludes(content, repoRoot, bundleRoot, { ...options, includeDepth: includeDepth + 1, maxIncludeDepth });
7888
8334
  });
7889
8335
  }
7890
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
+
7891
8390
  // src/repair.js
7892
8391
  var import_yaml = __toESM(require_dist(), 1);
7893
8392
  var import_ignore = __toESM(require_ignore(), 1);
7894
- import fs3 from "node:fs";
7895
- import path3 from "node:path";
8393
+ import fs6 from "node:fs";
8394
+ import path5 from "node:path";
7896
8395
  var CODEMAP_SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([
7897
8396
  ".js",
7898
8397
  ".ts",
@@ -7930,10 +8429,10 @@ var LEGACY_OPERATIONAL_ROOTS = /* @__PURE__ */ new Set([
7930
8429
  ]);
7931
8430
  var OPTIMA_OPERATIONAL_FOLDERS = [".optima", "templates", "dist"];
7932
8431
  function relPath(worktree, targetPath) {
7933
- return path3.relative(worktree, targetPath).split(path3.sep).join("/") || ".";
8432
+ return path5.relative(worktree, targetPath).split(path5.sep).join("/") || ".";
7934
8433
  }
7935
8434
  function normalizeCodemapRelPath(relPathValue) {
7936
- return path3.normalize(relPathValue).replace(/\\/g, "/").replace(/\/$/, "");
8435
+ return path5.normalize(relPathValue).replace(/\\/g, "/").replace(/\/$/, "");
7937
8436
  }
7938
8437
  function firstPathSegment(relPathValue) {
7939
8438
  return normalizeCodemapRelPath(relPathValue).split("/").filter(Boolean)[0] || "";
@@ -7952,8 +8451,8 @@ function isHiddenTree(relPathValue) {
7952
8451
  function loadGitIgnoreMatcher(worktree) {
7953
8452
  const ig = (0, import_ignore.default)();
7954
8453
  ig.add(".git");
7955
- const gitignorePath = path3.join(worktree, ".gitignore");
7956
- if (fs3.existsSync(gitignorePath)) ig.add(fs3.readFileSync(gitignorePath, "utf8"));
8454
+ const gitignorePath = path5.join(worktree, ".gitignore");
8455
+ if (fs6.existsSync(gitignorePath)) ig.add(fs6.readFileSync(gitignorePath, "utf8"));
7957
8456
  return ig;
7958
8457
  }
7959
8458
  function codemapSectionEntries(value) {
@@ -7972,7 +8471,7 @@ function codemapIndexedPaths(map) {
7972
8471
  }
7973
8472
  function readCodemap(filePath, unresolved, worktree) {
7974
8473
  try {
7975
- const parsed = import_yaml.default.parse(fs3.readFileSync(filePath, "utf8"));
8474
+ const parsed = import_yaml.default.parse(fs6.readFileSync(filePath, "utf8"));
7976
8475
  if (!parsed || typeof parsed !== "object") {
7977
8476
  unresolved.push({ category: "codemap", path: relPath(worktree, filePath), message: "CodeMap is empty or invalid; manual repair required." });
7978
8477
  return null;
@@ -7984,42 +8483,42 @@ function readCodemap(filePath, unresolved, worktree) {
7984
8483
  }
7985
8484
  }
7986
8485
  function writeCodemap(filePath, map) {
7987
- fs3.writeFileSync(filePath, import_yaml.default.stringify(map), "utf8");
8486
+ fs6.writeFileSync(filePath, import_yaml.default.stringify(map), "utf8");
7988
8487
  }
7989
8488
  function isIgnoredPath(ig, relativePath) {
7990
8489
  const normalized = normalizeCodemapRelPath(relativePath);
7991
8490
  return Boolean(normalized) && ig.ignores(normalized);
7992
8491
  }
7993
8492
  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);
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);
7998
8497
  if (isIgnoredPath(ig, relative) || isOperationalRelPath(relative)) continue;
7999
- if (item.isFile() && CODEMAP_SOURCE_EXTENSIONS.has(path3.extname(item.name))) return true;
8498
+ if (item.isFile() && CODEMAP_SOURCE_EXTENSIONS.has(path5.extname(item.name))) return true;
8000
8499
  }
8001
8500
  return false;
8002
8501
  }
8003
8502
  function containsSource(dirPath, ig, worktree) {
8004
- if (!fs3.existsSync(dirPath)) return false;
8005
- const dirRelPath = path3.relative(worktree, dirPath);
8503
+ if (!fs6.existsSync(dirPath)) return false;
8504
+ const dirRelPath = path5.relative(worktree, dirPath);
8006
8505
  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);
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))];
@@ -8893,78 +9392,28 @@ function buildClickUpReviewAutomationPlan({ isSubtask = false, humanApprover = "
8893
9392
  }
8894
9393
  };
8895
9394
  }
8896
- function validateMainWorkspaceBranchSafety({ currentBranch, requiredBranch = "dev", forbiddenBranch = "main" } = {}) {
8897
- const normalized = String(currentBranch ?? "").trim();
8898
- if (!normalized) {
8899
- 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
- );
9395
+ function validateMainWorkspaceBranchSafety({ currentBranch, requiredBranch = "dev", forbiddenBranch = "main" } = {}) {
9396
+ const normalized = String(currentBranch ?? "").trim();
9397
+ if (!normalized) {
9398
+ return { ok: false, branch: normalized, message: "Unable to determine the current branch; expected main workspace on dev." };
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,21 +10597,21 @@ 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;
@@ -10155,26 +10624,6 @@ function isClickUpWebhookStateActive(state, config) {
10155
10624
  state?.active && state?.webhookId && state?.secret && state?.publicUrl === config?.webhook?.publicUrl && hasEvents
10156
10625
  );
10157
10626
  }
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
10627
  function createClickUpApiClient(config, fetchImpl = globalThis.fetch) {
10179
10628
  const token = resolveSecretReference(config?.apiToken);
10180
10629
  const request = async (url, options = {}) => {
@@ -10239,212 +10688,6 @@ function createClickUpApiClient(config, fetchImpl = globalThis.fetch) {
10239
10688
  }
10240
10689
  };
10241
10690
  }
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 createGitHubApiClient(config = {}, fetchImpl = globalThis.fetch) {
10307
- const staticToken = resolveSecretReference(config?.apiToken);
10308
- const appConfig = isPlainObject(config?.app) ? config.app : {};
10309
- const appEnabled = appConfig.enabled === true || Boolean(appConfig.appId && appConfig.installationId && (appConfig.privateKey || appConfig.privateKeyFile));
10310
- const privateKey = resolveGitHubAppPrivateKey(appConfig);
10311
- const owner = String(config?.owner || "").trim();
10312
- const repo = String(config?.repo || "").trim();
10313
- let installationToken = null;
10314
- let installationTokenExpiresAt = 0;
10315
- const requestJson = async (url, { method = "GET", headers = {}, body = void 0 } = {}) => {
10316
- if (typeof fetchImpl !== "function") throw new Error("fetch is unavailable; inject a GitHub client for live PR lookup");
10317
- const response = await fetchImpl(url, {
10318
- method,
10319
- headers: {
10320
- Accept: "application/vnd.github+json",
10321
- "X-GitHub-Api-Version": "2022-11-28",
10322
- ...body === void 0 ? {} : { "Content-Type": "application/json" },
10323
- ...headers
10324
- },
10325
- ...body === void 0 ? {} : { body: JSON.stringify(body) }
10326
- });
10327
- if (!response.ok) throw new Error(`GitHub API request failed: ${response.status}`);
10328
- return response.status === 204 ? null : response.json();
10329
- };
10330
- const getAuthToken = async () => {
10331
- if (!appEnabled) return staticToken || "";
10332
- const nowMs = Date.now();
10333
- if (installationToken && installationTokenExpiresAt - 6e4 > nowMs) return installationToken;
10334
- const jwt = createGitHubAppJwt({ appId: appConfig.appId, privateKey });
10335
- const installation = await requestJson(`https://api.github.com/app/installations/${encodeURIComponent(appConfig.installationId)}/access_tokens`, {
10336
- method: "POST",
10337
- headers: { Authorization: `Bearer ${jwt}` }
10338
- });
10339
- installationToken = String(installation?.token || "").trim();
10340
- installationTokenExpiresAt = Date.parse(installation?.expires_at || "") || nowMs + 3e6;
10341
- if (!installationToken) throw new Error("GitHub App installation token response did not include a token");
10342
- return installationToken;
10343
- };
10344
- const request = async (pathname, { method = "GET", body = void 0 } = {}) => {
10345
- if (!owner || !repo) throw new Error("GitHub repository owner/repo is not configured");
10346
- const token = await getAuthToken();
10347
- return requestJson(`https://api.github.com/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}${pathname}`, {
10348
- method,
10349
- body,
10350
- headers: token ? { Authorization: `Bearer ${token}` } : {}
10351
- });
10352
- };
10353
- const getRef = async (branch) => request(`/git/ref/heads/${encodeGitHubBranchRef(branch)}`);
10354
- const getCommitObject = async (sha) => request(`/git/commits/${encodeURIComponent(sha)}`);
10355
- const createBlob = async ({ content, encoding }) => request("/git/blobs", { method: "POST", body: { content, encoding } });
10356
- const createTree = async ({ baseTree, tree }) => request("/git/trees", { method: "POST", body: { base_tree: baseTree, tree } });
10357
- const createCommit = async ({ message, treeSha, parents }) => request("/git/commits", { method: "POST", body: { message, tree: treeSha, parents } });
10358
- const updateRef = async ({ branch, sha, force = false }) => request(`/git/refs/heads/${encodeGitHubBranchRef(branch)}`, { method: "PATCH", body: { sha, force } });
10359
- return {
10360
- async getPullRequest(number) {
10361
- return request(`/pulls/${encodeURIComponent(number)}`);
10362
- },
10363
- async createPullRequest({ title, head, base, body = "", draft = false, maintainerCanModify = true }) {
10364
- return request("/pulls", {
10365
- method: "POST",
10366
- body: {
10367
- title: String(title || ""),
10368
- head: String(head || ""),
10369
- base: String(base || ""),
10370
- body: String(body || ""),
10371
- draft: draft === true,
10372
- maintainer_can_modify: maintainerCanModify !== false
10373
- }
10374
- });
10375
- },
10376
- async createIssueComment({ issueNumber, body }) {
10377
- return request(`/issues/${encodeURIComponent(issueNumber)}/comments`, { method: "POST", body: { body: String(body || "") } });
10378
- },
10379
- async replyToReviewComment({ commentId, body }) {
10380
- return request(`/pulls/comments/${encodeURIComponent(commentId)}/replies`, { method: "POST", body: { body: String(body || "") } });
10381
- },
10382
- async createPullRequestReview({ pullNumber, body, event = "COMMENT" }) {
10383
- return request(`/pulls/${encodeURIComponent(pullNumber)}/reviews`, { method: "POST", body: { body: String(body || ""), event: String(event || "COMMENT").toUpperCase() } });
10384
- },
10385
- async mergePullRequest({ pullNumber, commitTitle = "", commitMessage = "", mergeMethod = "squash" }) {
10386
- const body = {
10387
- merge_method: String(mergeMethod || "squash")
10388
- };
10389
- if (commitTitle) body.commit_title = String(commitTitle);
10390
- if (commitMessage) body.commit_message = String(commitMessage);
10391
- return request(`/pulls/${encodeURIComponent(pullNumber)}/merge`, { method: "PUT", body });
10392
- },
10393
- async commitWorktree({ worktree, branch = "", message = "", runGitFn = runGit, syncLocal = false } = {}) {
10394
- const directory = path6.resolve(String(worktree || ""));
10395
- if (!directory || !fs5.existsSync(directory)) throw new Error("worktree does not exist");
10396
- const targetBranch = String(branch || currentGitBranch(directory, runGitFn)).trim();
10397
- if (!targetBranch || targetBranch === "HEAD") throw new Error("target branch is required for GitHub API commit");
10398
- const commitMessage = String(message || "").trim();
10399
- if (!commitMessage) throw new Error("commit message is required");
10400
- const changedPaths = listWorktreeChangedPaths(directory, runGitFn);
10401
- if (changedPaths.length === 0) return { ok: true, action: "no_changes", branch: targetBranch, changedPaths: [] };
10402
- const ref = await getRef(targetBranch);
10403
- const headSha = ref?.object?.sha;
10404
- if (!headSha) throw new Error(`GitHub ref for ${targetBranch} did not include a head sha`);
10405
- const headCommit = await getCommitObject(headSha);
10406
- const baseTree = headCommit?.tree?.sha;
10407
- if (!baseTree) throw new Error(`GitHub commit ${headSha} did not include a tree sha`);
10408
- const tree = [];
10409
- for (const gitPath of changedPaths) {
10410
- const entry = treeEntryForWorktreePath(directory, gitPath);
10411
- if (!entry) continue;
10412
- if (entry.deleted) {
10413
- tree.push({ path: entry.path, mode: entry.mode, type: entry.type, sha: null });
10414
- continue;
10415
- }
10416
- const blob = await createBlob({ content: entry.content, encoding: entry.encoding });
10417
- if (!blob?.sha) throw new Error(`GitHub blob creation failed for ${gitPath}`);
10418
- tree.push({ path: entry.path, mode: entry.mode, type: entry.type, sha: blob.sha });
10419
- }
10420
- if (tree.length === 0) return { ok: true, action: "no_changes", branch: targetBranch, changedPaths: [] };
10421
- const nextTree = await createTree({ baseTree, tree });
10422
- const nextCommit = await createCommit({ message: commitMessage, treeSha: nextTree.sha, parents: [headSha] });
10423
- if (!nextCommit?.sha) throw new Error("GitHub commit creation did not return a sha");
10424
- const updatedRef = await updateRef({ branch: targetBranch, sha: nextCommit.sha, force: false });
10425
- if (syncLocal) {
10426
- runGitFn(directory, ["fetch", "origin", targetBranch]);
10427
- runGitFn(directory, ["reset", "--hard", "FETCH_HEAD"]);
10428
- }
10429
- return {
10430
- ok: true,
10431
- action: "committed",
10432
- branch: targetBranch,
10433
- before: headSha,
10434
- after: nextCommit.sha,
10435
- changedPaths,
10436
- treeEntries: tree.length,
10437
- verification: nextCommit.verification || null,
10438
- ref: updatedRef
10439
- };
10440
- },
10441
- async authMode() {
10442
- if (appEnabled) return { mode: "github_app", appId: String(appConfig.appId || ""), installationId: String(appConfig.installationId || "") };
10443
- if (staticToken) return { mode: "token" };
10444
- return { mode: "anonymous" };
10445
- }
10446
- };
10447
- }
10448
10691
  function createTestClickUpApiClient(config) {
10449
10692
  const metadata = /* @__PURE__ */ new Map();
10450
10693
  return {
@@ -10670,10 +10913,10 @@ async function ensureClickUpWebhookSubscription({ validation, worktree, clickupC
10670
10913
  function verifyClickUpSignature(rawBody, signatureHeader, secret) {
10671
10914
  const signature = String(signatureHeader || "").replace(/^sha256=/i, "").trim();
10672
10915
  if (!signature || !secret) return false;
10673
- 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");
10674
10917
  const given = Buffer.from(signature, "hex");
10675
10918
  const wanted = Buffer.from(expected, "hex");
10676
- return given.length === wanted.length && crypto.timingSafeEqual(given, wanted);
10919
+ return given.length === wanted.length && crypto2.timingSafeEqual(given, wanted);
10677
10920
  }
10678
10921
  function verifyGitHubSignature(rawBody, signatureHeader, secret) {
10679
10922
  return verifyClickUpSignature(rawBody, signatureHeader, secret);
@@ -10727,9 +10970,9 @@ function rememberClickUpWebhookEvent(state = {}, eventKey, limit = 200) {
10727
10970
  return { duplicate: false, state: { ...state, recentEventKeys: [...recent, eventKey].slice(-limit) } };
10728
10971
  }
10729
10972
  function readClickUpCommentLedgerEntries(ledgerPath) {
10730
- if (!ledgerPath || !fs5.existsSync(ledgerPath)) return [];
10973
+ if (!ledgerPath || !fs8.existsSync(ledgerPath)) return [];
10731
10974
  try {
10732
- const raw = fs5.readFileSync(ledgerPath, "utf8");
10975
+ const raw = fs8.readFileSync(ledgerPath, "utf8");
10733
10976
  const entries = [];
10734
10977
  for (const [index, line] of raw.split(/\r?\n/).entries()) {
10735
10978
  if (!line.trim()) continue;
@@ -10753,11 +10996,11 @@ function readClickUpCommentLedger(ledgerPath) {
10753
10996
  }
10754
10997
  function appendClickUpCommentLedgerEntry(ledgerPath, entry = {}) {
10755
10998
  if (!ledgerPath || !entry.key) return;
10756
- fs5.mkdirSync(path6.dirname(ledgerPath), { recursive: true, mode: 448 });
10757
- fs5.appendFileSync(ledgerPath, `${JSON.stringify(entry)}
10999
+ fs8.mkdirSync(path8.dirname(ledgerPath), { recursive: true, mode: 448 });
11000
+ fs8.appendFileSync(ledgerPath, `${JSON.stringify(entry)}
10758
11001
  `, { encoding: "utf8", mode: 384 });
10759
11002
  try {
10760
- fs5.chmodSync(ledgerPath, 384);
11003
+ fs8.chmodSync(ledgerPath, 384);
10761
11004
  } catch {
10762
11005
  }
10763
11006
  }
@@ -10776,7 +11019,7 @@ function stableClickUpCommentVersionMarker(value) {
10776
11019
  const direct = value.version ?? value.date_updated ?? value.updated_at ?? value.revision ?? value.modified_at;
10777
11020
  const directMarker = stableClickUpCommentVersionMarker(direct);
10778
11021
  if (directMarker) return directMarker;
10779
- 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)}`;
10780
11023
  }
10781
11024
  function clickUpCommentLedgerKey({ taskId, eventType, payload }) {
10782
11025
  const history = Array.isArray(payload?.history_items) ? payload.history_items[0] : payload?.history_item;
@@ -10786,7 +11029,7 @@ function clickUpCommentLedgerKey({ taskId, eventType, payload }) {
10786
11029
  const explicitVersion = stableClickUpCommentVersionMarker(
10787
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 || ""
10788
11031
  );
10789
- 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);
10790
11033
  return [String(taskId || "").trim(), "comment", commentId, explicitVersion || `sha256-${contentVersion}`].filter(Boolean).join(":");
10791
11034
  }
10792
11035
  function isClickUpCommentVersionProcessed({ ledgerPath, key, ledger = null, worktree = process.cwd() } = {}) {
@@ -11316,7 +11559,7 @@ function clampOpenCodeSessionText(text = "", maxLength = 12e3) {
11316
11559
  return value.length > maxLength ? value.slice(0, maxLength) : value;
11317
11560
  }
11318
11561
  function hashOpenCodeSessionText(text = "") {
11319
- return crypto.createHash("sha256").update(String(text ?? "")).digest("hex");
11562
+ return crypto2.createHash("sha256").update(String(text ?? "")).digest("hex");
11320
11563
  }
11321
11564
  async function readOpenCodeSessionMessages(client, { sessionId, directory, limit = 20 } = {}) {
11322
11565
  if (typeof client?.session?.messages !== "function") return null;
@@ -11554,7 +11797,7 @@ async function readOpenCodeSessionControl(client, { sessionId, directory, limit
11554
11797
  };
11555
11798
  }
11556
11799
  async function probeOpenCodeSessionControl(client, { directory, agent, omitAgentOnPrompt = false, text = "" } = {}) {
11557
- const requestedMarker = text || `optima-session-probe-${crypto.randomUUID()}`;
11800
+ const requestedMarker = text || `optima-session-probe-${crypto2.randomUUID()}`;
11558
11801
  const marker = clampOpenCodeSessionText(requestedMarker);
11559
11802
  const create = await createOpenCodeSessionControl(client, {
11560
11803
  directory,
@@ -11782,9 +12025,9 @@ function formatClickUpWebhookPrompt({ eventType, taskId, payload, branch = "", w
11782
12025
  }
11783
12026
  function appendClickUpWebhookLocalLog(worktree, entry) {
11784
12027
  const logPath = clickUpWebhookLogPath(worktree);
11785
- fs5.mkdirSync(path6.dirname(logPath), { recursive: true });
12028
+ fs8.mkdirSync(path8.dirname(logPath), { recursive: true });
11786
12029
  const safeEntry = { ...entry, at: entry.at || (/* @__PURE__ */ new Date()).toISOString() };
11787
- fs5.appendFileSync(logPath, `${JSON.stringify(safeEntry)}
12030
+ fs8.appendFileSync(logPath, `${JSON.stringify(safeEntry)}
11788
12031
  `, "utf8");
11789
12032
  }
11790
12033
  function clickUpWebhookLifecycleLog(worktree, entry) {
@@ -11813,7 +12056,7 @@ function closeClickUpWebhookServer(server) {
11813
12056
  });
11814
12057
  }
11815
12058
  function managedClickUpWebhookKey({ worktree, state, config } = {}) {
11816
- 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("|");
11817
12060
  }
11818
12061
  async function deleteClickUpWebhookBestEffort({ webhookId, clickupClient, worktree, reason = "cleanup" } = {}) {
11819
12062
  const id = String(webhookId || "").trim();
@@ -11913,7 +12156,7 @@ function writeClickUpWebhookAuditLog({ method, url, headers = {}, rawBody = "",
11913
12156
  const failed = Boolean(error || !handled?.ok || (handled?.status || 500) >= 400);
11914
12157
  if (level === "error" && !failed) return;
11915
12158
  const logDir = clickUpWebhookAuditLogDir();
11916
- fs5.mkdirSync(logDir, { recursive: true });
12159
+ fs8.mkdirSync(logDir, { recursive: true });
11917
12160
  const secretValues = [
11918
12161
  resolveSecretReference(config?.apiToken),
11919
12162
  resolveSecretReference(config?.github?.apiToken),
@@ -11924,8 +12167,8 @@ function writeClickUpWebhookAuditLog({ method, url, headers = {}, rawBody = "",
11924
12167
  let requestFile;
11925
12168
  if (level === "verbose") {
11926
12169
  const absoluteRequestFile = clickUpWebhookRequestFilePath(at, logDir);
11927
- fs5.mkdirSync(path6.dirname(absoluteRequestFile), { recursive: true });
11928
- 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("/");
11929
12172
  const parsedBody = payload || (() => {
11930
12173
  try {
11931
12174
  return JSON.parse(Buffer.isBuffer(rawBody) ? rawBody.toString("utf8") : String(rawBody || ""));
@@ -11941,11 +12184,11 @@ function writeClickUpWebhookAuditLog({ method, url, headers = {}, rawBody = "",
11941
12184
  headers,
11942
12185
  body: parsedBody === void 0 ? Buffer.isBuffer(rawBody) ? rawBody.toString("utf8") : String(rawBody || "") : parsedBody
11943
12186
  }, secretValues);
11944
- fs5.writeFileSync(absoluteRequestFile, `${JSON.stringify(requestArtifact, null, 2)}
12187
+ fs8.writeFileSync(absoluteRequestFile, `${JSON.stringify(requestArtifact, null, 2)}
11945
12188
  `, "utf8");
11946
12189
  }
11947
12190
  const summary = redactClickUpWebhookAuditValue(buildClickUpWebhookAuditSummary({ method, url, config, handled, error, payload, requestFile, at }), secretValues);
11948
- fs5.appendFileSync(clickUpWebhookAuditLogPath(at, logDir), `${JSON.stringify(summary)}
12191
+ fs8.appendFileSync(clickUpWebhookAuditLogPath(at, logDir), `${JSON.stringify(summary)}
11949
12192
  `, "utf8");
11950
12193
  } catch {
11951
12194
  }
@@ -11963,7 +12206,7 @@ async function withClickUpTaskRouteLock(taskId, operation) {
11963
12206
  if (activeClickUpTaskRoutes.get(key) === current) activeClickUpTaskRoutes.delete(key);
11964
12207
  }
11965
12208
  }
11966
- 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) } = {}) {
11967
12210
  const eventType = clickUpEventType(payload);
11968
12211
  const eventKey = clickUpWebhookEventKey(payload);
11969
12212
  const isStartupAssignmentReconciliation = payload?.startup_reconciliation === true && eventType === "taskAssigneeUpdated";
@@ -12732,17 +12975,17 @@ function startClickUpWebhookListener({ config, state, worktree, clickupClient, g
12732
12975
  return result;
12733
12976
  }
12734
12977
  function legacyVariantPath(destinationPath) {
12735
- const parsed = path6.parse(destinationPath);
12978
+ const parsed = path8.parse(destinationPath);
12736
12979
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:TZ.]/g, "").slice(0, 14);
12737
- if (parsed.ext) return path6.join(parsed.dir, `${parsed.name}.legacy-${stamp}${parsed.ext}`);
12738
- 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}`);
12739
12982
  }
12740
12983
  function normalizeWorkflowTaskPath(taskPath) {
12741
12984
  if (typeof taskPath !== "string") return { ok: false, message: "Error: task_path is required." };
12742
12985
  const trimmed = taskPath.trim();
12743
12986
  if (!trimmed) return { ok: false, message: "Error: task_path is required." };
12744
12987
  const normalized = trimmed.replace(/\\/g, "/");
12745
- if (path6.isAbsolute(trimmed)) return { ok: true, taskPath: trimmed };
12988
+ if (path8.isAbsolute(trimmed)) return { ok: true, taskPath: trimmed };
12746
12989
  if (normalized === "tasks" || normalized.startsWith("tasks/")) {
12747
12990
  return {
12748
12991
  ok: false,
@@ -12760,78 +13003,78 @@ function normalizeWorkflowTaskPath(taskPath) {
12760
13003
  function mergeFileIntoDestination(sourcePath, destinationPath, relativeSource, gitState = null) {
12761
13004
  const sourceWasTracked = isGitTracked(gitState, sourcePath);
12762
13005
  if (gitAwareMoveIfTracked(sourcePath, destinationPath, gitState)) return;
12763
- if (!fs5.existsSync(destinationPath)) {
12764
- fs5.mkdirSync(path6.dirname(destinationPath), { recursive: true });
12765
- fs5.renameSync(sourcePath, destinationPath);
13006
+ if (!fs8.existsSync(destinationPath)) {
13007
+ fs8.mkdirSync(path8.dirname(destinationPath), { recursive: true });
13008
+ fs8.renameSync(sourcePath, destinationPath);
12766
13009
  if (sourceWasTracked) stageGitAwareMerge(sourcePath, destinationPath, gitState);
12767
13010
  return;
12768
13011
  }
12769
- const ext = path6.extname(destinationPath).toLowerCase();
13012
+ const ext = path8.extname(destinationPath).toLowerCase();
12770
13013
  if ([".yaml", ".yml", ".json"].includes(ext)) {
12771
- const sourceRaw = fs5.readFileSync(sourcePath, "utf8");
12772
- const destRaw = fs5.readFileSync(destinationPath, "utf8");
13014
+ const sourceRaw = fs8.readFileSync(sourcePath, "utf8");
13015
+ const destRaw = fs8.readFileSync(destinationPath, "utf8");
12773
13016
  const parser = ext === ".json" ? JSON : import_yaml3.default;
12774
13017
  const sourceValue = parser.parse(sourceRaw) || {};
12775
13018
  const destValue = parser.parse(destRaw) || {};
12776
13019
  const merged = mergeStructuredValues(sourceValue, destValue);
12777
13020
  const serialized = ext === ".json" ? `${JSON.stringify(merged, null, 2)}
12778
13021
  ` : import_yaml3.default.stringify(merged);
12779
- fs5.writeFileSync(destinationPath, serialized, "utf8");
12780
- fs5.unlinkSync(sourcePath);
13022
+ fs8.writeFileSync(destinationPath, serialized, "utf8");
13023
+ fs8.unlinkSync(sourcePath);
12781
13024
  stageGitAwareMerge(sourcePath, destinationPath, gitState);
12782
13025
  return;
12783
13026
  }
12784
13027
  if (ext === ".md") {
12785
- const sourceRaw = fs5.readFileSync(sourcePath, "utf8").trimEnd();
12786
- const destRaw = fs5.readFileSync(destinationPath, "utf8").trimEnd();
13028
+ const sourceRaw = fs8.readFileSync(sourcePath, "utf8").trimEnd();
13029
+ const destRaw = fs8.readFileSync(destinationPath, "utf8").trimEnd();
12787
13030
  if (sourceRaw && !destRaw.includes(sourceRaw)) {
12788
13031
  const marker = `## Legacy Content From ${relativeSource}`;
12789
- fs5.writeFileSync(destinationPath, `${destRaw}
13032
+ fs8.writeFileSync(destinationPath, `${destRaw}
12790
13033
 
12791
13034
  ${marker}
12792
13035
 
12793
13036
  ${sourceRaw}
12794
13037
  `, "utf8");
12795
13038
  }
12796
- fs5.unlinkSync(sourcePath);
13039
+ fs8.unlinkSync(sourcePath);
12797
13040
  stageGitAwareMerge(sourcePath, destinationPath, gitState);
12798
13041
  return;
12799
13042
  }
12800
13043
  const preservedPath = legacyVariantPath(destinationPath);
12801
- fs5.renameSync(sourcePath, preservedPath);
13044
+ fs8.renameSync(sourcePath, preservedPath);
12802
13045
  stageGitAwareMerge(sourcePath, preservedPath, gitState);
12803
13046
  }
12804
- function mergePathIntoDestination(sourcePath, destinationPath, relativeSource = path6.basename(sourcePath), gitState = null) {
12805
- if (!fs5.existsSync(sourcePath)) return;
12806
- 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);
12807
13050
  if (stat.isDirectory()) {
12808
13051
  const sourceWasTracked = isGitTracked(gitState, sourcePath) || hasGitTrackedChildren(gitState, sourcePath);
12809
13052
  if (gitAwareMoveIfTracked(sourcePath, destinationPath, gitState)) return;
12810
- if (!fs5.existsSync(destinationPath)) {
12811
- fs5.mkdirSync(path6.dirname(destinationPath), { recursive: true });
12812
- fs5.renameSync(sourcePath, destinationPath);
13053
+ if (!fs8.existsSync(destinationPath)) {
13054
+ fs8.mkdirSync(path8.dirname(destinationPath), { recursive: true });
13055
+ fs8.renameSync(sourcePath, destinationPath);
12813
13056
  if (sourceWasTracked) stageGitAwareMerge(sourcePath, destinationPath, gitState);
12814
13057
  return;
12815
13058
  }
12816
- fs5.mkdirSync(destinationPath, { recursive: true });
12817
- for (const entry of fs5.readdirSync(sourcePath)) {
13059
+ fs8.mkdirSync(destinationPath, { recursive: true });
13060
+ for (const entry of fs8.readdirSync(sourcePath)) {
12818
13061
  mergePathIntoDestination(
12819
- path6.join(sourcePath, entry),
12820
- path6.join(destinationPath, entry),
12821
- path6.join(relativeSource, entry),
13062
+ path8.join(sourcePath, entry),
13063
+ path8.join(destinationPath, entry),
13064
+ path8.join(relativeSource, entry),
12822
13065
  gitState
12823
13066
  );
12824
13067
  }
12825
- fs5.rmSync(sourcePath, { recursive: true, force: true });
13068
+ fs8.rmSync(sourcePath, { recursive: true, force: true });
12826
13069
  return;
12827
13070
  }
12828
13071
  mergeFileIntoDestination(sourcePath, destinationPath, relativeSource, gitState);
12829
13072
  }
12830
13073
  function isOptimaPluginPackageWorktree(worktree) {
12831
- const packageJsonPath = path6.join(worktree, "package.json");
12832
- if (!fs5.existsSync(packageJsonPath)) return false;
13074
+ const packageJsonPath = path8.join(worktree, "package.json");
13075
+ if (!fs8.existsSync(packageJsonPath)) return false;
12833
13076
  try {
12834
- const pkg = JSON.parse(fs5.readFileSync(packageJsonPath, "utf8"));
13077
+ const pkg = JSON.parse(fs8.readFileSync(packageJsonPath, "utf8"));
12835
13078
  return pkg?.name === "@defend-tech/opencode-optima";
12836
13079
  } catch {
12837
13080
  return false;
@@ -12840,59 +13083,59 @@ function isOptimaPluginPackageWorktree(worktree) {
12840
13083
  function migrateLegacyOptimaLayout(worktree) {
12841
13084
  const gitState = gitMigrationState(worktree);
12842
13085
  const migrations = [
12843
- [path6.join(legacyOrbitaDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path6.join(".orbita", "orbita.yaml")],
12844
- [path6.join(legacyOrbitaDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path6.join(".orbita", "staticeng.yaml")],
12845
- [path6.join(legacyOrbitaDir(worktree), ".config"), optimaLocalConfigDir(worktree), path6.join(".orbita", ".config")],
12846
- [path6.join(legacyOrbitaDir(worktree), "config"), optimaLocalConfigDir(worktree), path6.join(".orbita", "config")],
12847
- [path6.join(legacyOrbitaDir(worktree), "runtime"), path6.join(optimaLocalConfigDir(worktree), "runtime"), path6.join(".orbita", "runtime")],
12848
- [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")],
12849
13092
  [legacyOrbitaDir(worktree), optimaDir(worktree), ".orbita"],
12850
- [path6.join(legacyStaticEngDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path6.join(".staticeng", "staticeng.yaml")],
12851
- [path6.join(legacyStaticEngDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path6.join(".staticeng", "orbita.yaml")],
12852
- [path6.join(legacyStaticEngDir(worktree), ".config"), optimaLocalConfigDir(worktree), path6.join(".staticeng", ".config")],
12853
- [path6.join(legacyStaticEngDir(worktree), "config"), optimaLocalConfigDir(worktree), path6.join(".staticeng", "config")],
12854
- [path6.join(legacyStaticEngDir(worktree), "runtime"), path6.join(optimaLocalConfigDir(worktree), "runtime"), path6.join(".staticeng", "runtime")],
12855
- [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")],
12856
13099
  [legacyStaticEngDir(worktree), optimaDir(worktree), ".staticeng"],
12857
- [path6.join(legacyNomadworkDir(worktree), "nomadworks.yaml"), repoConfigPath(worktree), path6.join(".nomadwork", "nomadworks.yaml")],
12858
- [path6.join(legacyNomadworksDir(worktree), "nomadworks.yaml"), repoConfigPath(worktree), path6.join(".nomadworks", "nomadworks.yaml")],
12859
- [path6.join(legacyNomadworkDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path6.join(".nomadwork", "staticeng.yaml")],
12860
- [path6.join(legacyNomadworksDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path6.join(".nomadworks", "staticeng.yaml")],
12861
- [path6.join(legacyNomadworkDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path6.join(".nomadwork", "orbita.yaml")],
12862
- [path6.join(legacyNomadworksDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path6.join(".nomadworks", "orbita.yaml")],
12863
- [path6.join(legacyNomadworkDir(worktree), "runtime"), path6.join(optimaLocalConfigDir(worktree), "runtime"), path6.join(".nomadwork", "runtime")],
12864
- [path6.join(legacyNomadworksDir(worktree), "runtime"), path6.join(optimaLocalConfigDir(worktree), "runtime"), path6.join(".nomadworks", "runtime")],
12865
- [path6.join(legacyNomadworkDir(worktree), "generated"), path6.join(optimaLocalConfigDir(worktree), "generated"), path6.join(".nomadwork", "generated")],
12866
- [path6.join(legacyNomadworksDir(worktree), "generated"), path6.join(optimaLocalConfigDir(worktree), "generated"), path6.join(".nomadworks", "generated")],
12867
- [path6.join(legacyNomadworkDir(worktree), "config"), optimaLocalConfigDir(worktree), path6.join(".nomadwork", "config")],
12868
- [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")],
12869
13112
  [legacyNomadworkDir(worktree), optimaDir(worktree), ".nomadwork"],
12870
13113
  [legacyNomadworksDir(worktree), optimaDir(worktree), ".nomadworks"],
12871
- [path6.join(worktree, "tasks"), optimaTasksDir(worktree), "tasks"],
12872
- [path6.join(worktree, "evidences"), optimaEvidencesDir(worktree), "evidences"],
12873
- [path6.join(worktree, "docs", "scrs"), optimaScrsDir(worktree), path6.join("docs", "scrs")],
12874
- [path6.join(worktree, "codemap.yml"), optimaCodemapPath(worktree), "codemap.yml"],
12875
- [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"]
12876
13119
  ];
12877
13120
  if (!isOptimaPluginPackageWorktree(worktree)) {
12878
- migrations.push([path6.join(worktree, "policies"), repoPoliciesDir(worktree), "policies"]);
13121
+ migrations.push([path8.join(worktree, "policies"), repoPoliciesDir(worktree), "policies"]);
12879
13122
  }
12880
13123
  for (const [source, destination, relativeSource] of migrations) {
12881
- if (fs5.existsSync(source)) mergePathIntoDestination(source, destination, relativeSource, gitState);
13124
+ if (fs8.existsSync(source)) mergePathIntoDestination(source, destination, relativeSource, gitState);
12882
13125
  }
12883
13126
  for (const [source, destination, relativeSource] of [
12884
- [path6.join(optimaDir(worktree), "optima.yaml"), repoConfigPath(worktree), path6.join(".optima", "optima.yaml")],
12885
- [path6.join(optimaDir(worktree), "config"), optimaLocalConfigDir(worktree), path6.join(".optima", "config")],
12886
- [path6.join(optimaDir(worktree), "runtime"), path6.join(optimaLocalConfigDir(worktree), "runtime"), path6.join(".optima", "runtime")],
12887
- [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")]
12888
13131
  ]) {
12889
- if (fs5.existsSync(source)) mergePathIntoDestination(source, destination, relativeSource, gitState);
13132
+ if (fs8.existsSync(source)) mergePathIntoDestination(source, destination, relativeSource, gitState);
12890
13133
  }
12891
13134
  }
12892
13135
  function listMarkdownFiles(dirPath) {
12893
- if (!fs5.existsSync(dirPath)) return [];
13136
+ if (!fs8.existsSync(dirPath)) return [];
12894
13137
  try {
12895
- 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");
12896
13139
  } catch (e) {
12897
13140
  console.error(`[Optima] Failed to read markdown files from ${dirPath}:`, e);
12898
13141
  return [];
@@ -12933,10 +13176,10 @@ function toModelString(provider, model) {
12933
13176
  }
12934
13177
  function readTaskMetadata(taskPath, worktree) {
12935
13178
  if (!taskPath) return {};
12936
- const absoluteTaskPath = path6.isAbsolute(taskPath) ? taskPath : path6.join(worktree, taskPath);
12937
- if (!fs5.existsSync(absoluteTaskPath)) return {};
13179
+ const absoluteTaskPath = path8.isAbsolute(taskPath) ? taskPath : path8.join(worktree, taskPath);
13180
+ if (!fs8.existsSync(absoluteTaskPath)) return {};
12938
13181
  try {
12939
- const raw = fs5.readFileSync(absoluteTaskPath, "utf8");
13182
+ const raw = fs8.readFileSync(absoluteTaskPath, "utf8");
12940
13183
  const { data } = parseFrontmatter(raw);
12941
13184
  return {
12942
13185
  complexity: typeof data.complexity === "string" ? data.complexity.trim().toLowerCase() : void 0,
@@ -12961,11 +13204,11 @@ function slugifyTitle(input) {
12961
13204
  }
12962
13205
  function loadDiscussionRegistry(worktree) {
12963
13206
  const registryPath = runtimeDiscussionRegistryPath(worktree);
12964
- if (!fs5.existsSync(registryPath)) {
13207
+ if (!fs8.existsSync(registryPath)) {
12965
13208
  return { version: 1, active: {} };
12966
13209
  }
12967
13210
  try {
12968
- const parsed = JSON.parse(fs5.readFileSync(registryPath, "utf8"));
13211
+ const parsed = JSON.parse(fs8.readFileSync(registryPath, "utf8"));
12969
13212
  const registry = {
12970
13213
  version: 1,
12971
13214
  active: Object.fromEntries(Object.entries(parsed.active || {}).map(([key, value]) => [key, normalizeLegacyDiscussionEntry(value)]))
@@ -12978,34 +13221,34 @@ function loadDiscussionRegistry(worktree) {
12978
13221
  }
12979
13222
  function saveDiscussionRegistry(worktree, registry) {
12980
13223
  const registryPath = runtimeDiscussionRegistryPath(worktree);
12981
- const runtimeDir = path6.dirname(registryPath);
12982
- if (!fs5.existsSync(runtimeDir)) fs5.mkdirSync(runtimeDir, { recursive: true });
12983
- 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");
12984
13227
  }
12985
13228
  function runtimeDiscussionsDir(worktree) {
12986
- return path6.join(optimaLocalConfigDir(worktree), "runtime", "discussions");
13229
+ return path8.join(optimaLocalConfigDir(worktree), "runtime", "discussions");
12987
13230
  }
12988
13231
  function archivedRuntimeDiscussionsDir(worktree) {
12989
- return path6.join(runtimeDiscussionsDir(worktree), "archive");
13232
+ return path8.join(runtimeDiscussionsDir(worktree), "archive");
12990
13233
  }
12991
13234
  function finalDiscussionsDir(worktree) {
12992
- return path6.join(optimaTasksDir(worktree), "discussions");
13235
+ return path8.join(optimaTasksDir(worktree), "discussions");
12993
13236
  }
12994
13237
  function nextDiscussionIdentity(worktree, title) {
12995
13238
  const discussionsDir = finalDiscussionsDir(worktree);
12996
13239
  const runtimeDir = runtimeDiscussionsDir(worktree);
12997
- if (!fs5.existsSync(discussionsDir)) fs5.mkdirSync(discussionsDir, { recursive: true });
12998
- 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 });
12999
13242
  let sequence = 1;
13000
13243
  while (true) {
13001
13244
  const id = `DISCUSSION-${String(sequence).padStart(3, "0")}`;
13002
13245
  const filename = `${id}-${slugifyTitle(title)}.md`;
13003
- const summaryRelativePath = path6.join(".optima", "tasks", "discussions", filename);
13004
- const summaryAbsolutePath = path6.join(worktree, summaryRelativePath);
13246
+ const summaryRelativePath = path8.join(".optima", "tasks", "discussions", filename);
13247
+ const summaryAbsolutePath = path8.join(worktree, summaryRelativePath);
13005
13248
  const transcriptFilename = `${id}-transcript.md`;
13006
- const transcriptRelativePath = path6.join(".optima", ".config", "runtime", "discussions", transcriptFilename);
13007
- const transcriptAbsolutePath = path6.join(worktree, transcriptRelativePath);
13008
- 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)) {
13009
13252
  return {
13010
13253
  id,
13011
13254
  filename,
@@ -13021,23 +13264,23 @@ function nextDiscussionIdentity(worktree, title) {
13021
13264
  }
13022
13265
  function findDiscussionById(worktree, discussionID) {
13023
13266
  const discussionsDir = finalDiscussionsDir(worktree);
13024
- if (!fs5.existsSync(discussionsDir)) return null;
13025
- 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"));
13026
13269
  if (entries.length === 0) return null;
13027
13270
  const filename = entries.sort()[0];
13028
13271
  const transcriptFilename = `${discussionID}-transcript.md`;
13029
13272
  return {
13030
13273
  id: discussionID,
13031
13274
  filename,
13032
- summaryRelativePath: path6.join(".optima", "tasks", "discussions", filename),
13033
- summaryAbsolutePath: path6.join(discussionsDir, filename),
13275
+ summaryRelativePath: path8.join(".optima", "tasks", "discussions", filename),
13276
+ summaryAbsolutePath: path8.join(discussionsDir, filename),
13034
13277
  transcriptFilename,
13035
- transcriptRelativePath: path6.join(".optima", ".config", "runtime", "discussions", transcriptFilename),
13036
- transcriptAbsolutePath: path6.join(runtimeDiscussionsDir(worktree), transcriptFilename)
13278
+ transcriptRelativePath: path8.join(".optima", ".config", "runtime", "discussions", transcriptFilename),
13279
+ transcriptAbsolutePath: path8.join(runtimeDiscussionsDir(worktree), transcriptFilename)
13037
13280
  };
13038
13281
  }
13039
13282
  function parseDiscussionFile(filePath) {
13040
- const raw = fs5.readFileSync(filePath, "utf8");
13283
+ const raw = fs8.readFileSync(filePath, "utf8");
13041
13284
  const { data, body } = parseFrontmatter(raw);
13042
13285
  return { data, body: body.trimStart() };
13043
13286
  }
@@ -13048,10 +13291,10 @@ ${import_yaml3.default.stringify(frontmatter).trim()}
13048
13291
 
13049
13292
  ${body.trimEnd()}
13050
13293
  `;
13051
- fs5.writeFileSync(filePath, serialized, "utf8");
13294
+ fs8.writeFileSync(filePath, serialized, "utf8");
13052
13295
  }
13053
13296
  function setDiscussionStatus(filePath, status) {
13054
- if (!fs5.existsSync(filePath)) return;
13297
+ if (!fs8.existsSync(filePath)) return;
13055
13298
  const { data, body } = parseDiscussionFile(filePath);
13056
13299
  writeDiscussionFile(filePath, { ...data, status }, body);
13057
13300
  }
@@ -13116,18 +13359,18 @@ async function appendMessageIfNeeded(client, worktree, registry, sessionID, mess
13116
13359
  });
13117
13360
  const text = extractTextParts(response.data.parts || []);
13118
13361
  if (!text) return;
13119
- appendDiscussionMessage(path6.join(worktree, discussion.transcriptPath), speaker, text, messageID);
13362
+ appendDiscussionMessage(path8.join(worktree, discussion.transcriptPath), speaker, text, messageID);
13120
13363
  discussion.appendedMessageIDs ??= [];
13121
13364
  discussion.appendedMessageIDs.push(messageID);
13122
13365
  saveDiscussionRegistry(worktree, registry);
13123
13366
  }
13124
13367
  async function summarizeDiscussionWithBA(client, worktree, discussion) {
13125
- const transcriptPath = path6.join(worktree, discussion.transcriptPath);
13126
- const summaryPath = path6.join(worktree, discussion.summaryPath);
13127
- const summaryDir = path6.dirname(summaryPath);
13128
- if (!fs5.existsSync(summaryDir)) fs5.mkdirSync(summaryDir, { recursive: true });
13129
- const hasExistingSummary = fs5.existsSync(summaryPath);
13130
- 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;
13131
13374
  const summarizerSession = await client.session.create({
13132
13375
  body: { title: `Discussion Summary: ${discussion.id}` }
13133
13376
  });
@@ -13227,30 +13470,30 @@ async function summarizeDiscussionWithBA(client, worktree, discussion) {
13227
13470
  return { confirmation, summaryPath, transcriptPath, hasExistingSummary, priorMtimeMs };
13228
13471
  }
13229
13472
  function archiveDiscussionTranscript(worktree, transcriptRelativePath) {
13230
- const sourcePath = path6.join(worktree, transcriptRelativePath);
13231
- if (!fs5.existsSync(sourcePath)) return null;
13473
+ const sourcePath = path8.join(worktree, transcriptRelativePath);
13474
+ if (!fs8.existsSync(sourcePath)) return null;
13232
13475
  const archiveDir = archivedRuntimeDiscussionsDir(worktree);
13233
- if (!fs5.existsSync(archiveDir)) fs5.mkdirSync(archiveDir, { recursive: true });
13234
- const targetPath = path6.join(archiveDir, path6.basename(sourcePath));
13235
- 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);
13236
13479
  return targetPath;
13237
13480
  }
13238
13481
  async function finalizeClosingDiscussion(client, worktree, registry, sessionID, discussion) {
13239
13482
  const { confirmation, summaryPath, hasExistingSummary, priorMtimeMs } = await summarizeDiscussionWithBA(client, worktree, discussion);
13240
- if (!fs5.existsSync(summaryPath)) {
13483
+ if (!fs8.existsSync(summaryPath)) {
13241
13484
  throw new Error(`Discussion summary was not written to ${discussion.summaryPath}`);
13242
13485
  }
13243
13486
  if (hasExistingSummary) {
13244
- const currentMtimeMs = fs5.statSync(summaryPath).mtimeMs;
13487
+ const currentMtimeMs = fs8.statSync(summaryPath).mtimeMs;
13245
13488
  if (currentMtimeMs <= priorMtimeMs) {
13246
13489
  throw new Error(`Discussion summary file was not updated at ${discussion.summaryPath}`);
13247
13490
  }
13248
13491
  }
13249
- const summaryContent = fs5.readFileSync(summaryPath, "utf8").trim();
13492
+ const summaryContent = fs8.readFileSync(summaryPath, "utf8").trim();
13250
13493
  if (!summaryContent) {
13251
13494
  throw new Error(`Discussion summary file is empty at ${discussion.summaryPath}`);
13252
13495
  }
13253
- const transcriptPath = path6.join(worktree, discussion.transcriptPath);
13496
+ const transcriptPath = path8.join(worktree, discussion.transcriptPath);
13254
13497
  setDiscussionStatus(transcriptPath, "closed");
13255
13498
  const archivedTranscriptPath = archiveDiscussionTranscript(worktree, discussion.transcriptPath);
13256
13499
  delete registry.active[sessionID];
@@ -13258,7 +13501,7 @@ async function finalizeClosingDiscussion(client, worktree, registry, sessionID,
13258
13501
  return {
13259
13502
  confirmation,
13260
13503
  summaryPath: discussion.summaryPath,
13261
- 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))
13262
13505
  };
13263
13506
  }
13264
13507
  function normalizeTeamMode(value) {
@@ -13297,13 +13540,13 @@ function getOperatingTeamMode(repoCfg) {
13297
13540
  }
13298
13541
  function readResolvedFile(relativePath, worktree, options = {}) {
13299
13542
  const filePath = resolveIncludeFile(`plugin:${relativePath}`, worktree, PKG_ROOT, options);
13300
- if (!filePath || !fs5.existsSync(filePath)) return "";
13301
- 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();
13302
13545
  }
13303
13546
  function loadMarkdownFragment(filePath, worktree) {
13304
- if (!fs5.existsSync(filePath)) return "";
13547
+ if (!fs8.existsSync(filePath)) return "";
13305
13548
  try {
13306
- const raw = fs5.readFileSync(filePath, "utf8");
13549
+ const raw = fs8.readFileSync(filePath, "utf8");
13307
13550
  const { body } = parseFrontmatter(raw);
13308
13551
  return resolveIncludes(body.trim(), worktree, PKG_ROOT);
13309
13552
  } catch (e) {
@@ -13312,9 +13555,9 @@ function loadMarkdownFragment(filePath, worktree) {
13312
13555
  }
13313
13556
  }
13314
13557
  function loadAgentDefinition(filePath, worktree, options = {}) {
13315
- if (!fs5.existsSync(filePath)) return null;
13558
+ if (!fs8.existsSync(filePath)) return null;
13316
13559
  try {
13317
- const rawContent = fs5.readFileSync(filePath, "utf8");
13560
+ const rawContent = fs8.readFileSync(filePath, "utf8");
13318
13561
  const { data, body } = parseFrontmatter(rawContent);
13319
13562
  const prompt = resolveIncludes(body.trim(), worktree, PKG_ROOT, options);
13320
13563
  return { data, prompt };
@@ -13325,13 +13568,13 @@ function loadAgentDefinition(filePath, worktree, options = {}) {
13325
13568
  }
13326
13569
  function syncGeneratedPolicies(worktree, repoCfg) {
13327
13570
  if (repoCfg.policies?.extract_defaults !== "all") return;
13328
- if (!fs5.existsSync(BUNDLE_POLICIES_DIR)) return;
13571
+ if (!fs8.existsSync(BUNDLE_POLICIES_DIR)) return;
13329
13572
  const generatedDir = generatedPoliciesDir(worktree);
13330
- if (!fs5.existsSync(generatedDir)) fs5.mkdirSync(generatedDir, { recursive: true });
13331
- 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");
13332
13575
  for (const file of policyFiles) {
13333
- const sourcePath = path6.join(BUNDLE_POLICIES_DIR, file);
13334
- const source = fs5.readFileSync(sourcePath, "utf8").trimEnd();
13576
+ const sourcePath = path8.join(BUNDLE_POLICIES_DIR, file);
13577
+ const source = fs8.readFileSync(sourcePath, "utf8").trimEnd();
13335
13578
  const generated = [
13336
13579
  "<!--",
13337
13580
  "Generated from Optima plugin defaults.",
@@ -13342,19 +13585,19 @@ function syncGeneratedPolicies(worktree, repoCfg) {
13342
13585
  source,
13343
13586
  ""
13344
13587
  ].join("\n");
13345
- fs5.writeFileSync(path6.join(generatedDir, file), generated, "utf8");
13588
+ fs8.writeFileSync(path8.join(generatedDir, file), generated, "utf8");
13346
13589
  }
13347
13590
  }
13348
13591
  function ensureReadmeFile(dirPath, content) {
13349
- if (!fs5.existsSync(dirPath)) fs5.mkdirSync(dirPath, { recursive: true });
13350
- const readmePath = path6.join(dirPath, "README.md");
13351
- if (!fs5.existsSync(readmePath)) {
13352
- 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");
13353
13596
  }
13354
13597
  }
13355
13598
  function ensureFileIfMissing(filePath, content) {
13356
- if (!fs5.existsSync(path6.dirname(filePath))) fs5.mkdirSync(path6.dirname(filePath), { recursive: true });
13357
- 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");
13358
13601
  }
13359
13602
  function currentTasksRegistryContent() {
13360
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";
@@ -13440,16 +13683,16 @@ Never place implementation evidence under root \`evidences/\`.
13440
13683
  }
13441
13684
  function ensureOptimaTaskTemplates(worktree) {
13442
13685
  const tasksDir = optimaTasksDir(worktree);
13443
- ensureFileIfMissing(path6.join(tasksDir, "task-template.md"), taskTemplateContent());
13444
- 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());
13445
13688
  }
13446
13689
  function scaffoldOptimaConfig(worktree, teamMode = "full") {
13447
13690
  const configPath = repoConfigPath(worktree);
13448
- if (fs5.existsSync(configPath)) return false;
13449
- const templatePath = path6.join(TEMPLATES_DIR, "optima.yaml.template");
13450
- if (!fs5.existsSync(templatePath)) return false;
13451
- const agentIds = fs5.existsSync(BUNDLE_AGENTS_DIR) ? fs5.readdirSync(BUNDLE_AGENTS_DIR).filter((f) => f.endsWith(".md")).map((f) => f.replace(".md", "")) : [];
13452
- 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");
13453
13696
  optimaConfig = optimaConfig.replace("{{teamMode}}", normalizeTeamMode(teamMode));
13454
13697
  let agentsSection = "";
13455
13698
  for (const id of agentIds) {
@@ -13460,26 +13703,26 @@ function scaffoldOptimaConfig(worktree, teamMode = "full") {
13460
13703
  }
13461
13704
  optimaConfig = optimaConfig.replace(/^agents:/m, "agents:\n" + agentsSection);
13462
13705
  ensureFileIfMissing(configPath, optimaConfig);
13463
- return fs5.existsSync(configPath);
13706
+ return fs8.existsSync(configPath);
13464
13707
  }
13465
13708
  function scaffoldOptimaRootCodemap(worktree) {
13466
13709
  const rootCodemapPath = optimaCodemapPath(worktree);
13467
- if (fs5.existsSync(rootCodemapPath)) return false;
13468
- const templatePath = path6.join(TEMPLATES_DIR, "codemap.yml.template");
13469
- if (!fs5.existsSync(templatePath)) return false;
13470
- 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));
13471
13714
  ensureFileIfMissing(rootCodemapPath, codemapConfig);
13472
- return fs5.existsSync(rootCodemapPath);
13715
+ return fs8.existsSync(rootCodemapPath);
13473
13716
  }
13474
13717
  function ensureOptimaRegistries(worktree) {
13475
13718
  const tasksDir = optimaTasksDir(worktree);
13476
13719
  const scrsDir = optimaScrsDir(worktree);
13477
- if (!fs5.existsSync(tasksDir)) fs5.mkdirSync(tasksDir, { recursive: true });
13478
- if (!fs5.existsSync(scrsDir)) fs5.mkdirSync(scrsDir, { recursive: true });
13479
- ensureFileIfMissing(path6.join(tasksDir, "current.md"), currentTasksRegistryContent());
13480
- ensureFileIfMissing(path6.join(tasksDir, "done.md"), doneTasksRegistryContent());
13481
- ensureFileIfMissing(path6.join(scrsDir, "current.md"), currentScrRegistryContent());
13482
- 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());
13483
13726
  }
13484
13727
  function scaffoldOptimaReadmes(worktree) {
13485
13728
  ensureReadmeFile(repoPoliciesDir(worktree), REPO_LOCAL_POLICIES_README);
@@ -13641,12 +13884,12 @@ function shouldRegisterWorkflowProductManager(options = {}, worktree = process.c
13641
13884
  }
13642
13885
  function isClickUpDerivedWorktreeSibling(candidate, basePath) {
13643
13886
  if (typeof candidate !== "string" || typeof basePath !== "string" || !candidate.trim() || !basePath.trim()) return false;
13644
- const resolvedCandidate = path6.resolve(candidate);
13645
- const resolvedBase = path6.resolve(basePath);
13646
- const baseParent = path6.dirname(resolvedBase);
13647
- if (path6.dirname(resolvedCandidate) !== baseParent) return false;
13648
- const baseName = path6.basename(resolvedBase);
13649
- 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);
13650
13893
  if (!candidateName.startsWith(`${baseName}-`)) return false;
13651
13894
  const branchSlug = candidateName.slice(baseName.length + 1);
13652
13895
  const parts = branchSlug.split("-").filter(Boolean);
@@ -13654,11 +13897,11 @@ function isClickUpDerivedWorktreeSibling(candidate, basePath) {
13654
13897
  if (!(/* @__PURE__ */ new Set(["tarea", "bug", "doc", "poc", "idea"])).has(parts[0])) return false;
13655
13898
  if (!parts.slice(1).every((part) => /^[a-z0-9][a-z0-9-]*$/.test(part))) return false;
13656
13899
  try {
13657
- const candidateStat = fs5.lstatSync(resolvedCandidate);
13900
+ const candidateStat = fs8.lstatSync(resolvedCandidate);
13658
13901
  if (!candidateStat.isDirectory() || candidateStat.isSymbolicLink()) return false;
13659
- const realCandidate = fs5.realpathSync.native(resolvedCandidate);
13660
- const realBaseParent = fs5.realpathSync.native(baseParent);
13661
- 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;
13662
13905
  } catch {
13663
13906
  return false;
13664
13907
  }
@@ -13666,15 +13909,15 @@ function isClickUpDerivedWorktreeSibling(candidate, basePath) {
13666
13909
  function resolveSessionToolDirectory({ requestedDirectory, context, pluginWorktree, clickUpWebhookValidation } = {}) {
13667
13910
  const safe = safeWorktreeOrFailure(context, pluginWorktree);
13668
13911
  if (!safe.ok) return { ok: false, error: safe.message };
13669
- 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;
13670
13913
  if (!isSafeWritableDirectory(requested)) return { ok: false, error: `Directory is not a safe writable directory: ${requested}` };
13671
13914
  if (isSameOrNestedPath(requested, safe.worktree)) return { ok: true, directory: requested, safeWorktree: safe.worktree, scope: "context_worktree" };
13672
13915
  const clickUpBasePath = clickUpWebhookValidation?.complete === true && clickUpWebhookValidation?.ok !== false ? clickUpWebhookValidation.config?.basePath : "";
13673
13916
  if (clickUpBasePath && isSameOrNestedPath(requested, clickUpBasePath)) {
13674
- 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) };
13675
13918
  }
13676
13919
  if (clickUpBasePath && isClickUpDerivedWorktreeSibling(requested, clickUpBasePath)) {
13677
- 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) };
13678
13921
  }
13679
13922
  return {
13680
13923
  ok: false,
@@ -13708,8 +13951,8 @@ function buildOptimaAgents(repoCfg, operatingTeamMode, worktree, debugDir, optio
13708
13951
  if (!enabled) continue;
13709
13952
  }
13710
13953
  const promptOptions = { preferCompactPromptDocs: repoCfg.features?.compact_prompt_docs !== false };
13711
- const bundledDefinition = loadAgentDefinition(path6.join(BUNDLE_AGENTS_DIR, file), worktree, promptOptions);
13712
- 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);
13713
13956
  const activeDefinition = repoDefinition || bundledDefinition;
13714
13957
  if (!activeDefinition) continue;
13715
13958
  const { data } = activeDefinition;
@@ -13718,7 +13961,7 @@ function buildOptimaAgents(repoCfg, operatingTeamMode, worktree, debugDir, optio
13718
13961
  if (modePromptFragment) finalPrompt = `${finalPrompt}
13719
13962
 
13720
13963
  ${modePromptFragment}`;
13721
- const additionFragment = loadMarkdownFragment(path6.join(repoAgentAdditions, file), worktree);
13964
+ const additionFragment = loadMarkdownFragment(path8.join(repoAgentAdditions, file), worktree);
13722
13965
  if (additionFragment) {
13723
13966
  finalPrompt = `${finalPrompt}
13724
13967
 
@@ -13771,14 +14014,14 @@ Use this Optima-provided fallback when the current task worktree lacks docs/core
13771
14014
  }
13772
14015
  ourAgents[id] = agentConfig;
13773
14016
  if (repoCfg.features?.debug_dumps !== false) {
13774
- const debugPath = path6.join(debugDir, `${id}.md`);
14017
+ const debugPath = path8.join(debugDir, `${id}.md`);
13775
14018
  const { prompt, ...dumpConfig } = agentConfig;
13776
14019
  const debugHeader = `---
13777
14020
  ${import_yaml3.default.stringify(dumpConfig).trim()}
13778
14021
  ---`;
13779
14022
  try {
13780
- if (!fs5.existsSync(debugDir)) fs5.mkdirSync(debugDir, { recursive: true });
13781
- fs5.writeFileSync(debugPath, `${debugHeader}
14023
+ if (!fs8.existsSync(debugDir)) fs8.mkdirSync(debugDir, { recursive: true });
14024
+ fs8.writeFileSync(debugPath, `${debugHeader}
13782
14025
 
13783
14026
  ${prompt}`, "utf8");
13784
14027
  } catch (e) {
@@ -13802,9 +14045,9 @@ async function OptimaPlugin(input = {}, pluginOptions = {}) {
13802
14045
  const configPath = resolveConfigPath(worktree);
13803
14046
  const discussionRegistry = loadDiscussionRegistry(worktree);
13804
14047
  let repoCfg = { agents: {}, defaults: {}, features: {} };
13805
- if (fs5.existsSync(configPath)) {
14048
+ if (fs8.existsSync(configPath)) {
13806
14049
  try {
13807
- repoCfg = import_yaml3.default.parse(fs5.readFileSync(configPath, "utf8")) || repoCfg;
14050
+ repoCfg = import_yaml3.default.parse(fs8.readFileSync(configPath, "utf8")) || repoCfg;
13808
14051
  } catch (e) {
13809
14052
  console.error(`[Optima] Failed to parse config at ${configPath}:`, e);
13810
14053
  }
@@ -13932,10 +14175,10 @@ async function OptimaPlugin(input = {}, pluginOptions = {}) {
13932
14175
  }
13933
14176
  migrateLegacyOptimaLayout(toolWorktree);
13934
14177
  const cfgDir = optimaConfigDir(toolWorktree);
13935
- if (!fs5.existsSync(cfgDir)) fs5.mkdirSync(cfgDir, { recursive: true });
13936
- const optimaTmplPath = path6.join(TEMPLATES_DIR, "optima.yaml.template");
13937
- const codemapTmplPath = path6.join(TEMPLATES_DIR, "codemap.yml.template");
13938
- 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)) {
13939
14182
  return "Error: Initialization templates not found in plugin.";
13940
14183
  }
13941
14184
  scaffoldOptimaConfig(toolWorktree, requestedTeamMode);
@@ -14056,14 +14299,14 @@ Restart or reload OpenCode manually if the newly scaffolded config or agents are
14056
14299
  async execute(args, context) {
14057
14300
  const safe = safeWorktreeOrFailure(context, worktree);
14058
14301
  if (!safe.ok) return safe.message;
14059
- const summaryPath = path6.resolve(safe.worktree, args.summary_path || "");
14060
- if (!fs5.existsSync(summaryPath)) return `FAIL: summary_path not found: ${summaryPath}`;
14061
- 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) : "";
14062
14305
  const payload = buildClickUpSummaryPayload({
14063
- summaryMarkdown: fs5.readFileSync(summaryPath, "utf8"),
14064
- summaryPath: path6.relative(safe.worktree, summaryPath),
14065
- taskMarkdown: taskPath && fs5.existsSync(taskPath) ? fs5.readFileSync(taskPath, "utf8") : "",
14066
- 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) : "",
14067
14310
  branch: args.branch,
14068
14311
  worktree: args.worktree,
14069
14312
  pr: args.pr
@@ -14142,12 +14385,12 @@ Restart or reload OpenCode manually if the newly scaffolded config or agents are
14142
14385
  async execute(args, context) {
14143
14386
  const safe = safeWorktreeOrFailure(context, worktree);
14144
14387
  if (!safe.ok) return safe.message;
14145
- const markdownPath = path6.resolve(safe.worktree, args.markdown_path || "");
14146
- 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}`;
14147
14390
  const payload = buildClickUpCreateSubtasksPayload({
14148
14391
  parentTaskId: args.parent_task_id,
14149
- markdown: fs5.readFileSync(markdownPath, "utf8"),
14150
- sourcePath: path6.relative(safe.worktree, markdownPath),
14392
+ markdown: fs8.readFileSync(markdownPath, "utf8"),
14393
+ sourcePath: path8.relative(safe.worktree, markdownPath),
14151
14394
  parentBranch: args.parent_branch,
14152
14395
  parentTaskType: args.parent_task_type || "Tarea",
14153
14396
  apply: String(args.apply || "").toLowerCase() === "true"
@@ -14263,6 +14506,31 @@ Restart or reload OpenCode manually if the newly scaffolded config or agents are
14263
14506
  }
14264
14507
  }
14265
14508
  }),
14509
+ optima_github_verify_vercel_pr: tool({
14510
+ description: "Verify that a PR head commit has a successful Vercel preproduction deployment and a functional deployment URL before validation/handoff",
14511
+ args: {
14512
+ pr_number: tool.schema.number().describe("Pull request number"),
14513
+ context: tool.schema.string().describe("Required GitHub status context; defaults to 'Vercel \u2013 defend-preproduction'"),
14514
+ environment: tool.schema.string().describe("Required GitHub deployment environment; defaults to 'Preview \u2013 defend-preproduction'"),
14515
+ require_functional_url: tool.schema.string().describe("Set to 'false' to skip HTTP probing of the deployment URL")
14516
+ },
14517
+ async execute(args) {
14518
+ try {
14519
+ const auth = await requireGitHubAppClient();
14520
+ if (!auth.ok) return JSON.stringify(auth, null, 2);
14521
+ if (!runtimeGitHubClient?.verifyVercelPullRequestDeployment) return JSON.stringify({ ok: false, error: "github_client_unavailable" }, null, 2);
14522
+ const result = await runtimeGitHubClient.verifyVercelPullRequestDeployment({
14523
+ pullNumber: args.pr_number,
14524
+ context: args.context || "Vercel \u2013 defend-preproduction",
14525
+ environment: args.environment || "Preview \u2013 defend-preproduction",
14526
+ requireFunctionalUrl: String(args.require_functional_url || "true").toLowerCase() !== "false"
14527
+ });
14528
+ return JSON.stringify(result, null, 2);
14529
+ } catch (error) {
14530
+ return JSON.stringify({ ok: false, error: error.message }, null, 2);
14531
+ }
14532
+ }
14533
+ }),
14266
14534
  optima_github_merge_pr: tool({
14267
14535
  description: "Merge a GitHub PR through the Optima GitHub App identity after required human approval gates pass",
14268
14536
  args: {
@@ -14492,7 +14760,7 @@ Backfilled messages: ${backfilled}`;
14492
14760
  if (!existing) {
14493
14761
  return "FAIL: No active discussion exists for this session.";
14494
14762
  }
14495
- const discussionPath = path6.join(toolWorktree, existing.transcriptPath);
14763
+ const discussionPath = path8.join(toolWorktree, existing.transcriptPath);
14496
14764
  setDiscussionStatus(discussionPath, "summarizing");
14497
14765
  existing.status = "summarizing";
14498
14766
  saveDiscussionRegistry(toolWorktree, toolRegistry);
@@ -14544,7 +14812,7 @@ Reason: ${err.message}`;
14544
14812
  try {
14545
14813
  const sessionResult = await client.session.create({
14546
14814
  query: { directory: workflowDirectory },
14547
- body: { title: `Workflow Run: ${path6.basename(workflowTaskPath)}` }
14815
+ body: { title: `Workflow Run: ${path8.basename(workflowTaskPath)}` }
14548
14816
  });
14549
14817
  const sessionId = sessionResult.data.id;
14550
14818
  activeWorkflows.set(sessionId, { pmaSessionId, taskPath: workflowTaskPath, track: workflowTrack, directory: workflowDirectory });
@@ -14728,14 +14996,14 @@ function usage() {
14728
14996
  ].join("\n");
14729
14997
  }
14730
14998
  function expandHome(inputPath) {
14731
- if (!inputPath || inputPath === "~") return os2.homedir();
14732
- 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));
14733
15001
  return inputPath;
14734
15002
  }
14735
15003
  function resolveOpenCodeDbPath(inputPath = null) {
14736
15004
  const expanded = expandHome(inputPath || process.env.OPTIMA_OPENCODE_DB_PATH || DEFAULT_DB_PATH);
14737
15005
  try {
14738
- 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");
14739
15007
  } catch {
14740
15008
  return expanded;
14741
15009
  }
@@ -14799,12 +15067,12 @@ function extractOpenedPathValue(value) {
14799
15067
  }
14800
15068
  function normalizePathCandidate(candidate) {
14801
15069
  const expanded = expandHome(candidate);
14802
- if (!path7.isAbsolute(expanded)) return null;
14803
- return path7.resolve(expanded);
15070
+ if (!path9.isAbsolute(expanded)) return null;
15071
+ return path9.resolve(expanded);
14804
15072
  }
14805
15073
  function discoverOpenCodePaths(dbPath) {
14806
15074
  const resolvedDb = resolveOpenCodeDbPath(dbPath);
14807
- 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}`);
14808
15076
  const tables = sqliteJson(resolvedDb, "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name");
14809
15077
  const discovered = /* @__PURE__ */ new Set();
14810
15078
  for (const table of tables) {
@@ -14829,27 +15097,27 @@ function discoverOpenCodePaths(dbPath) {
14829
15097
  function collectMarkdownOverridesFrom(baseDir) {
14830
15098
  const files = [];
14831
15099
  for (const dirName of OVERRIDE_DIRS) {
14832
- const dirPath = path7.join(baseDir, dirName);
14833
- if (!fs6.existsSync(dirPath)) continue;
14834
- 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 })) {
14835
15103
  if (!entry.isFile()) continue;
14836
15104
  if (!entry.name.endsWith(".md")) continue;
14837
15105
  if (entry.name.toLowerCase() === "readme.md") continue;
14838
- files.push(path7.join(dirPath, entry.name));
15106
+ files.push(path9.join(dirPath, entry.name));
14839
15107
  }
14840
15108
  }
14841
15109
  return files;
14842
15110
  }
14843
15111
  function collectOverrideFiles(worktree) {
14844
- return collectMarkdownOverridesFrom(path7.join(worktree, ".optima")).sort();
15112
+ return collectMarkdownOverridesFrom(path9.join(worktree, ".optima")).sort();
14845
15113
  }
14846
15114
  function collectPlannedOverrideFiles(worktree) {
14847
15115
  return [
14848
15116
  ...collectOverrideFiles(worktree),
14849
- ...collectMarkdownOverridesFrom(path7.join(worktree, ".staticeng")),
14850
- ...collectMarkdownOverridesFrom(path7.join(worktree, ".orbita")),
14851
- ...collectMarkdownOverridesFrom(path7.join(worktree, ".nomadwork")),
14852
- ...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"))
14853
15121
  ].sort();
14854
15122
  }
14855
15123
  var CRC_TABLE = (() => {
@@ -14882,14 +15150,14 @@ function writeUInt16LE(value) {
14882
15150
  return buffer;
14883
15151
  }
14884
15152
  function createZipBackup(files, backupPath) {
14885
- fs6.mkdirSync(path7.dirname(backupPath), { recursive: true });
15153
+ fs9.mkdirSync(path9.dirname(backupPath), { recursive: true });
14886
15154
  const localParts = [];
14887
15155
  const centralParts = [];
14888
15156
  let offset = 0;
14889
15157
  const now = dosTimeDate();
14890
15158
  for (const filePath of files) {
14891
- const data = fs6.readFileSync(filePath);
14892
- 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("/");
14893
15161
  const nameBuffer = Buffer.from(name, "utf8");
14894
15162
  const crc = crc32(data);
14895
15163
  const local = Buffer.concat([
@@ -14941,7 +15209,7 @@ function createZipBackup(files, backupPath) {
14941
15209
  writeUInt32LE(offset),
14942
15210
  writeUInt16LE(0)
14943
15211
  ]);
14944
- fs6.writeFileSync(backupPath, Buffer.concat([...localParts, ...centralParts, end]));
15212
+ fs9.writeFileSync(backupPath, Buffer.concat([...localParts, ...centralParts, end]));
14945
15213
  }
14946
15214
  function timestamp() {
14947
15215
  return (/* @__PURE__ */ new Date()).toISOString().replace(/[-:]/g, "").replace(/\.\d{3}Z$/, "Z");
@@ -14951,17 +15219,17 @@ function validationStatus(result) {
14951
15219
  return result.ok ? "passed" : "failed";
14952
15220
  }
14953
15221
  function hasLegacyMarker(worktree) {
14954
- 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"));
14955
15223
  }
14956
15224
  function rootOptimaArtifacts(worktree) {
14957
15225
  const artifacts = [
14958
- ["tasks/", path7.join(worktree, "tasks")],
14959
- ["evidences/", path7.join(worktree, "evidences")],
14960
- ["docs/scrs/", path7.join(worktree, "docs", "scrs")],
14961
- ["codemap.yml", path7.join(worktree, "codemap.yml")],
14962
- ["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")]
14963
15231
  ];
14964
- 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));
14965
15233
  }
14966
15234
  function hasSanitizableOverrides(worktree) {
14967
15235
  return collectPlannedOverrideFiles(worktree).length > 0;
@@ -14987,7 +15255,7 @@ function planOptimaMigration(worktree, dryRun) {
14987
15255
  ...overrides.map((file) => ({
14988
15256
  category: "override",
14989
15257
  action: dryRun ? "would_remove_after_backup" : "removed_after_backup",
14990
- path: path7.relative(worktree, file).split(path7.sep).join("/"),
15258
+ path: path9.relative(worktree, file).split(path9.sep).join("/"),
14991
15259
  detail: "Remove implicit agent/policy override after host-level backup."
14992
15260
  }))
14993
15261
  ],
@@ -15008,12 +15276,12 @@ async function sanitizeHost(options = {}) {
15008
15276
  const repoStates = [];
15009
15277
  for (const candidate of paths) {
15010
15278
  try {
15011
- if (!fs6.existsSync(candidate)) {
15279
+ if (!fs9.existsSync(candidate)) {
15012
15280
  report.totals.skipped += 1;
15013
15281
  report.repos.push({ path: candidate, status: "skipped", reason: "missing" });
15014
15282
  continue;
15015
15283
  }
15016
- if (!fs6.statSync(candidate).isDirectory()) {
15284
+ if (!fs9.statSync(candidate).isDirectory()) {
15017
15285
  report.totals.skipped += 1;
15018
15286
  report.repos.push({ path: candidate, status: "skipped", reason: "not_directory" });
15019
15287
  continue;
@@ -15035,7 +15303,7 @@ async function sanitizeHost(options = {}) {
15035
15303
  const overrides = repoStates.flatMap((state) => state.overrideFiles.map((file) => ({ repo: state.repo, file })));
15036
15304
  report.totals.overrideFiles = overrides.length;
15037
15305
  if (!dryRun && overrides.length > 0) {
15038
- const backupPath = path7.join(os2.homedir(), BACKUP_DIRNAME, `${timestamp()}.zip`);
15306
+ const backupPath = path9.join(os3.homedir(), BACKUP_DIRNAME, `${timestamp()}.zip`);
15039
15307
  try {
15040
15308
  createZipBackup(overrides.map((item) => item.file), backupPath);
15041
15309
  report.backupPath = backupPath;
@@ -15051,7 +15319,7 @@ async function sanitizeHost(options = {}) {
15051
15319
  for (const state of repoStates) {
15052
15320
  try {
15053
15321
  if (!dryRun) {
15054
- for (const file of state.overrideFiles) fs6.rmSync(file, { force: true });
15322
+ for (const file of state.overrideFiles) fs9.rmSync(file, { force: true });
15055
15323
  }
15056
15324
  const validation = !dryRun && hasLegacyMarker(state.repo) ? await optima_validate_logic(state.repo) : null;
15057
15325
  const status = (!validation || validation.ok) && state.plan.unresolved.length === 0 ? "repaired" : "failed";
@@ -15064,7 +15332,7 @@ async function sanitizeHost(options = {}) {
15064
15332
  repairActions: state.plan.actions.length,
15065
15333
  repairSkipped: state.plan.skippedRepair === true,
15066
15334
  overrideFiles: state.overrideFiles.length,
15067
- 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("/")),
15068
15336
  validation: validation ? validationStatus(validation) : "skipped",
15069
15337
  unresolved: state.plan.unresolved
15070
15338
  });