@defend-tech/opencode-optima 0.1.67 → 0.1.69

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, path7) {
113
- const ctrl = callVisitor(key, node, visitor, path7);
112
+ function visit_(key, node, visitor, path8) {
113
+ const ctrl = callVisitor(key, node, visitor, path8);
114
114
  if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
115
- replaceNode(key, path7, ctrl);
116
- return visit_(key, ctrl, visitor, path7);
115
+ replaceNode(key, path8, ctrl);
116
+ return visit_(key, ctrl, visitor, path8);
117
117
  }
118
118
  if (typeof ctrl !== "symbol") {
119
119
  if (identity.isCollection(node)) {
120
- path7 = Object.freeze(path7.concat(node));
120
+ path8 = Object.freeze(path8.concat(node));
121
121
  for (let i = 0; i < node.items.length; ++i) {
122
- const ci = visit_(i, node.items[i], visitor, path7);
122
+ const ci = visit_(i, node.items[i], visitor, path8);
123
123
  if (typeof ci === "number")
124
124
  i = ci - 1;
125
125
  else if (ci === BREAK)
@@ -130,13 +130,13 @@ var require_visit = __commonJS({
130
130
  }
131
131
  }
132
132
  } else if (identity.isPair(node)) {
133
- path7 = Object.freeze(path7.concat(node));
134
- const ck = visit_("key", node.key, visitor, path7);
133
+ path8 = Object.freeze(path8.concat(node));
134
+ const ck = visit_("key", node.key, visitor, path8);
135
135
  if (ck === BREAK)
136
136
  return BREAK;
137
137
  else if (ck === REMOVE)
138
138
  node.key = null;
139
- const cv = visit_("value", node.value, visitor, path7);
139
+ const cv = visit_("value", node.value, visitor, path8);
140
140
  if (cv === BREAK)
141
141
  return BREAK;
142
142
  else if (cv === REMOVE)
@@ -157,17 +157,17 @@ var require_visit = __commonJS({
157
157
  visitAsync.BREAK = BREAK;
158
158
  visitAsync.SKIP = SKIP;
159
159
  visitAsync.REMOVE = REMOVE;
160
- async function visitAsync_(key, node, visitor, path7) {
161
- const ctrl = await callVisitor(key, node, visitor, path7);
160
+ async function visitAsync_(key, node, visitor, path8) {
161
+ const ctrl = await callVisitor(key, node, visitor, path8);
162
162
  if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
163
- replaceNode(key, path7, ctrl);
164
- return visitAsync_(key, ctrl, visitor, path7);
163
+ replaceNode(key, path8, ctrl);
164
+ return visitAsync_(key, ctrl, visitor, path8);
165
165
  }
166
166
  if (typeof ctrl !== "symbol") {
167
167
  if (identity.isCollection(node)) {
168
- path7 = Object.freeze(path7.concat(node));
168
+ path8 = Object.freeze(path8.concat(node));
169
169
  for (let i = 0; i < node.items.length; ++i) {
170
- const ci = await visitAsync_(i, node.items[i], visitor, path7);
170
+ const ci = await visitAsync_(i, node.items[i], visitor, path8);
171
171
  if (typeof ci === "number")
172
172
  i = ci - 1;
173
173
  else if (ci === BREAK)
@@ -178,13 +178,13 @@ var require_visit = __commonJS({
178
178
  }
179
179
  }
180
180
  } else if (identity.isPair(node)) {
181
- path7 = Object.freeze(path7.concat(node));
182
- const ck = await visitAsync_("key", node.key, visitor, path7);
181
+ path8 = Object.freeze(path8.concat(node));
182
+ const ck = await visitAsync_("key", node.key, visitor, path8);
183
183
  if (ck === BREAK)
184
184
  return BREAK;
185
185
  else if (ck === REMOVE)
186
186
  node.key = null;
187
- const cv = await visitAsync_("value", node.value, visitor, path7);
187
+ const cv = await visitAsync_("value", node.value, visitor, path8);
188
188
  if (cv === BREAK)
189
189
  return BREAK;
190
190
  else if (cv === REMOVE)
@@ -211,23 +211,23 @@ var require_visit = __commonJS({
211
211
  }
212
212
  return visitor;
213
213
  }
214
- function callVisitor(key, node, visitor, path7) {
214
+ function callVisitor(key, node, visitor, path8) {
215
215
  if (typeof visitor === "function")
216
- return visitor(key, node, path7);
216
+ return visitor(key, node, path8);
217
217
  if (identity.isMap(node))
218
- return visitor.Map?.(key, node, path7);
218
+ return visitor.Map?.(key, node, path8);
219
219
  if (identity.isSeq(node))
220
- return visitor.Seq?.(key, node, path7);
220
+ return visitor.Seq?.(key, node, path8);
221
221
  if (identity.isPair(node))
222
- return visitor.Pair?.(key, node, path7);
222
+ return visitor.Pair?.(key, node, path8);
223
223
  if (identity.isScalar(node))
224
- return visitor.Scalar?.(key, node, path7);
224
+ return visitor.Scalar?.(key, node, path8);
225
225
  if (identity.isAlias(node))
226
- return visitor.Alias?.(key, node, path7);
226
+ return visitor.Alias?.(key, node, path8);
227
227
  return void 0;
228
228
  }
229
- function replaceNode(key, path7, node) {
230
- const parent = path7[path7.length - 1];
229
+ function replaceNode(key, path8, node) {
230
+ const parent = path8[path8.length - 1];
231
231
  if (identity.isCollection(parent)) {
232
232
  parent.items[key] = node;
233
233
  } else if (identity.isPair(parent)) {
@@ -835,10 +835,10 @@ var require_Collection = __commonJS({
835
835
  var createNode = require_createNode();
836
836
  var identity = require_identity();
837
837
  var Node = require_Node();
838
- function collectionFromPath(schema, path7, value) {
838
+ function collectionFromPath(schema, path8, value) {
839
839
  let v = value;
840
- for (let i = path7.length - 1; i >= 0; --i) {
841
- const k = path7[i];
840
+ for (let i = path8.length - 1; i >= 0; --i) {
841
+ const k = path8[i];
842
842
  if (typeof k === "number" && Number.isInteger(k) && k >= 0) {
843
843
  const a = [];
844
844
  a[k] = v;
@@ -857,7 +857,7 @@ var require_Collection = __commonJS({
857
857
  sourceObjects: /* @__PURE__ */ new Map()
858
858
  });
859
859
  }
860
- var isEmptyPath = (path7) => path7 == null || typeof path7 === "object" && !!path7[Symbol.iterator]().next().done;
860
+ var isEmptyPath = (path8) => path8 == null || typeof path8 === "object" && !!path8[Symbol.iterator]().next().done;
861
861
  var Collection = class extends Node.NodeBase {
862
862
  constructor(type, schema) {
863
863
  super(type);
@@ -887,11 +887,11 @@ var require_Collection = __commonJS({
887
887
  * be a Pair instance or a `{ key, value }` object, which may not have a key
888
888
  * that already exists in the map.
889
889
  */
890
- addIn(path7, value) {
891
- if (isEmptyPath(path7))
890
+ addIn(path8, value) {
891
+ if (isEmptyPath(path8))
892
892
  this.add(value);
893
893
  else {
894
- const [key, ...rest] = path7;
894
+ const [key, ...rest] = path8;
895
895
  const node = this.get(key, true);
896
896
  if (identity.isCollection(node))
897
897
  node.addIn(rest, value);
@@ -905,8 +905,8 @@ var require_Collection = __commonJS({
905
905
  * Removes a value from the collection.
906
906
  * @returns `true` if the item was found and removed.
907
907
  */
908
- deleteIn(path7) {
909
- const [key, ...rest] = path7;
908
+ deleteIn(path8) {
909
+ const [key, ...rest] = path8;
910
910
  if (rest.length === 0)
911
911
  return this.delete(key);
912
912
  const node = this.get(key, true);
@@ -920,8 +920,8 @@ var require_Collection = __commonJS({
920
920
  * scalar values from their surrounding node; to disable set `keepScalar` to
921
921
  * `true` (collections are always returned intact).
922
922
  */
923
- getIn(path7, keepScalar) {
924
- const [key, ...rest] = path7;
923
+ getIn(path8, keepScalar) {
924
+ const [key, ...rest] = path8;
925
925
  const node = this.get(key, true);
926
926
  if (rest.length === 0)
927
927
  return !keepScalar && identity.isScalar(node) ? node.value : node;
@@ -939,8 +939,8 @@ var require_Collection = __commonJS({
939
939
  /**
940
940
  * Checks if the collection includes a value with the key `key`.
941
941
  */
942
- hasIn(path7) {
943
- const [key, ...rest] = path7;
942
+ hasIn(path8) {
943
+ const [key, ...rest] = path8;
944
944
  if (rest.length === 0)
945
945
  return this.has(key);
946
946
  const node = this.get(key, true);
@@ -950,8 +950,8 @@ var require_Collection = __commonJS({
950
950
  * Sets a value in this collection. For `!!set`, `value` needs to be a
951
951
  * boolean to add/remove the item from the set.
952
952
  */
953
- setIn(path7, value) {
954
- const [key, ...rest] = path7;
953
+ setIn(path8, value) {
954
+ const [key, ...rest] = path8;
955
955
  if (rest.length === 0) {
956
956
  this.set(key, value);
957
957
  } else {
@@ -3455,9 +3455,9 @@ var require_Document = __commonJS({
3455
3455
  this.contents.add(value);
3456
3456
  }
3457
3457
  /** Adds a value to the document. */
3458
- addIn(path7, value) {
3458
+ addIn(path8, value) {
3459
3459
  if (assertCollection(this.contents))
3460
- this.contents.addIn(path7, value);
3460
+ this.contents.addIn(path8, value);
3461
3461
  }
3462
3462
  /**
3463
3463
  * Create a new `Alias` node, ensuring that the target `node` has the required anchor.
@@ -3532,14 +3532,14 @@ var require_Document = __commonJS({
3532
3532
  * Removes a value from the document.
3533
3533
  * @returns `true` if the item was found and removed.
3534
3534
  */
3535
- deleteIn(path7) {
3536
- if (Collection.isEmptyPath(path7)) {
3535
+ deleteIn(path8) {
3536
+ if (Collection.isEmptyPath(path8)) {
3537
3537
  if (this.contents == null)
3538
3538
  return false;
3539
3539
  this.contents = null;
3540
3540
  return true;
3541
3541
  }
3542
- return assertCollection(this.contents) ? this.contents.deleteIn(path7) : false;
3542
+ return assertCollection(this.contents) ? this.contents.deleteIn(path8) : false;
3543
3543
  }
3544
3544
  /**
3545
3545
  * Returns item at `key`, or `undefined` if not found. By default unwraps
@@ -3554,10 +3554,10 @@ var require_Document = __commonJS({
3554
3554
  * scalar values from their surrounding node; to disable set `keepScalar` to
3555
3555
  * `true` (collections are always returned intact).
3556
3556
  */
3557
- getIn(path7, keepScalar) {
3558
- if (Collection.isEmptyPath(path7))
3557
+ getIn(path8, keepScalar) {
3558
+ if (Collection.isEmptyPath(path8))
3559
3559
  return !keepScalar && identity.isScalar(this.contents) ? this.contents.value : this.contents;
3560
- return identity.isCollection(this.contents) ? this.contents.getIn(path7, keepScalar) : void 0;
3560
+ return identity.isCollection(this.contents) ? this.contents.getIn(path8, keepScalar) : void 0;
3561
3561
  }
3562
3562
  /**
3563
3563
  * Checks if the document includes a value with the key `key`.
@@ -3568,10 +3568,10 @@ var require_Document = __commonJS({
3568
3568
  /**
3569
3569
  * Checks if the document includes a value at `path`.
3570
3570
  */
3571
- hasIn(path7) {
3572
- if (Collection.isEmptyPath(path7))
3571
+ hasIn(path8) {
3572
+ if (Collection.isEmptyPath(path8))
3573
3573
  return this.contents !== void 0;
3574
- return identity.isCollection(this.contents) ? this.contents.hasIn(path7) : false;
3574
+ return identity.isCollection(this.contents) ? this.contents.hasIn(path8) : false;
3575
3575
  }
3576
3576
  /**
3577
3577
  * Sets a value in this document. For `!!set`, `value` needs to be a
@@ -3588,13 +3588,13 @@ var require_Document = __commonJS({
3588
3588
  * Sets a value in this document. For `!!set`, `value` needs to be a
3589
3589
  * boolean to add/remove the item from the set.
3590
3590
  */
3591
- setIn(path7, value) {
3592
- if (Collection.isEmptyPath(path7)) {
3591
+ setIn(path8, value) {
3592
+ if (Collection.isEmptyPath(path8)) {
3593
3593
  this.contents = value;
3594
3594
  } else if (this.contents == null) {
3595
- this.contents = Collection.collectionFromPath(this.schema, Array.from(path7), value);
3595
+ this.contents = Collection.collectionFromPath(this.schema, Array.from(path8), value);
3596
3596
  } else if (assertCollection(this.contents)) {
3597
- this.contents.setIn(path7, value);
3597
+ this.contents.setIn(path8, value);
3598
3598
  }
3599
3599
  }
3600
3600
  /**
@@ -5546,9 +5546,9 @@ var require_cst_visit = __commonJS({
5546
5546
  visit.BREAK = BREAK;
5547
5547
  visit.SKIP = SKIP;
5548
5548
  visit.REMOVE = REMOVE;
5549
- visit.itemAtPath = (cst, path7) => {
5549
+ visit.itemAtPath = (cst, path8) => {
5550
5550
  let item = cst;
5551
- for (const [field, index] of path7) {
5551
+ for (const [field, index] of path8) {
5552
5552
  const tok = item?.[field];
5553
5553
  if (tok && "items" in tok) {
5554
5554
  item = tok.items[index];
@@ -5557,23 +5557,23 @@ var require_cst_visit = __commonJS({
5557
5557
  }
5558
5558
  return item;
5559
5559
  };
5560
- visit.parentCollection = (cst, path7) => {
5561
- const parent = visit.itemAtPath(cst, path7.slice(0, -1));
5562
- const field = path7[path7.length - 1][0];
5560
+ visit.parentCollection = (cst, path8) => {
5561
+ const parent = visit.itemAtPath(cst, path8.slice(0, -1));
5562
+ const field = path8[path8.length - 1][0];
5563
5563
  const coll = parent?.[field];
5564
5564
  if (coll && "items" in coll)
5565
5565
  return coll;
5566
5566
  throw new Error("Parent collection not found");
5567
5567
  };
5568
- function _visit(path7, item, visitor) {
5569
- let ctrl = visitor(item, path7);
5568
+ function _visit(path8, item, visitor) {
5569
+ let ctrl = visitor(item, path8);
5570
5570
  if (typeof ctrl === "symbol")
5571
5571
  return ctrl;
5572
5572
  for (const field of ["key", "value"]) {
5573
5573
  const token = item[field];
5574
5574
  if (token && "items" in token) {
5575
5575
  for (let i = 0; i < token.items.length; ++i) {
5576
- const ci = _visit(Object.freeze(path7.concat([[field, i]])), token.items[i], visitor);
5576
+ const ci = _visit(Object.freeze(path8.concat([[field, i]])), token.items[i], visitor);
5577
5577
  if (typeof ci === "number")
5578
5578
  i = ci - 1;
5579
5579
  else if (ci === BREAK)
@@ -5584,10 +5584,10 @@ var require_cst_visit = __commonJS({
5584
5584
  }
5585
5585
  }
5586
5586
  if (typeof ctrl === "function" && field === "key")
5587
- ctrl = ctrl(item, path7);
5587
+ ctrl = ctrl(item, path8);
5588
5588
  }
5589
5589
  }
5590
- return typeof ctrl === "function" ? ctrl(item, path7) : ctrl;
5590
+ return typeof ctrl === "function" ? ctrl(item, path8) : ctrl;
5591
5591
  }
5592
5592
  exports.visit = visit;
5593
5593
  }
@@ -7551,17 +7551,17 @@ var require_ignore = __commonJS({
7551
7551
  var throwError = (message, Ctor) => {
7552
7552
  throw new Ctor(message);
7553
7553
  };
7554
- var checkPath = (path7, originalPath, doThrow) => {
7555
- if (!isString(path7)) {
7554
+ var checkPath = (path8, originalPath, doThrow) => {
7555
+ if (!isString(path8)) {
7556
7556
  return doThrow(
7557
7557
  `path must be a string, but got \`${originalPath}\``,
7558
7558
  TypeError
7559
7559
  );
7560
7560
  }
7561
- if (!path7) {
7561
+ if (!path8) {
7562
7562
  return doThrow(`path must not be empty`, TypeError);
7563
7563
  }
7564
- if (checkPath.isNotRelative(path7)) {
7564
+ if (checkPath.isNotRelative(path8)) {
7565
7565
  const r = "`path.relative()`d";
7566
7566
  return doThrow(
7567
7567
  `path should be a ${r} string, but got "${originalPath}"`,
@@ -7570,7 +7570,7 @@ var require_ignore = __commonJS({
7570
7570
  }
7571
7571
  return true;
7572
7572
  };
7573
- var isNotRelative = (path7) => REGEX_TEST_INVALID_PATH.test(path7);
7573
+ var isNotRelative = (path8) => REGEX_TEST_INVALID_PATH.test(path8);
7574
7574
  checkPath.isNotRelative = isNotRelative;
7575
7575
  checkPath.convert = (p) => p;
7576
7576
  var Ignore = class {
@@ -7629,7 +7629,7 @@ var require_ignore = __commonJS({
7629
7629
  // setting `checkUnignored` to `false` could reduce additional
7630
7630
  // path matching.
7631
7631
  // @returns {TestResult} true if a file is ignored
7632
- _testOne(path7, checkUnignored) {
7632
+ _testOne(path8, checkUnignored) {
7633
7633
  let ignored = false;
7634
7634
  let unignored = false;
7635
7635
  this._rules.forEach((rule) => {
@@ -7637,7 +7637,7 @@ var require_ignore = __commonJS({
7637
7637
  if (unignored === negative && ignored !== unignored || negative && !ignored && !unignored && !checkUnignored) {
7638
7638
  return;
7639
7639
  }
7640
- const matched = rule.regex.test(path7);
7640
+ const matched = rule.regex.test(path8);
7641
7641
  if (matched) {
7642
7642
  ignored = !negative;
7643
7643
  unignored = negative;
@@ -7650,24 +7650,24 @@ var require_ignore = __commonJS({
7650
7650
  }
7651
7651
  // @returns {TestResult}
7652
7652
  _test(originalPath, cache, checkUnignored, slices) {
7653
- const path7 = originalPath && checkPath.convert(originalPath);
7653
+ const path8 = originalPath && checkPath.convert(originalPath);
7654
7654
  checkPath(
7655
- path7,
7655
+ path8,
7656
7656
  originalPath,
7657
7657
  this._allowRelativePaths ? RETURN_FALSE : throwError
7658
7658
  );
7659
- return this._t(path7, cache, checkUnignored, slices);
7659
+ return this._t(path8, cache, checkUnignored, slices);
7660
7660
  }
7661
- _t(path7, cache, checkUnignored, slices) {
7662
- if (path7 in cache) {
7663
- return cache[path7];
7661
+ _t(path8, cache, checkUnignored, slices) {
7662
+ if (path8 in cache) {
7663
+ return cache[path8];
7664
7664
  }
7665
7665
  if (!slices) {
7666
- slices = path7.split(SLASH);
7666
+ slices = path8.split(SLASH);
7667
7667
  }
7668
7668
  slices.pop();
7669
7669
  if (!slices.length) {
7670
- return cache[path7] = this._testOne(path7, checkUnignored);
7670
+ return cache[path8] = this._testOne(path8, checkUnignored);
7671
7671
  }
7672
7672
  const parent = this._t(
7673
7673
  slices.join(SLASH) + SLASH,
@@ -7675,24 +7675,24 @@ var require_ignore = __commonJS({
7675
7675
  checkUnignored,
7676
7676
  slices
7677
7677
  );
7678
- return cache[path7] = parent.ignored ? parent : this._testOne(path7, checkUnignored);
7678
+ return cache[path8] = parent.ignored ? parent : this._testOne(path8, checkUnignored);
7679
7679
  }
7680
- ignores(path7) {
7681
- return this._test(path7, this._ignoreCache, false).ignored;
7680
+ ignores(path8) {
7681
+ return this._test(path8, this._ignoreCache, false).ignored;
7682
7682
  }
7683
7683
  createFilter() {
7684
- return (path7) => !this.ignores(path7);
7684
+ return (path8) => !this.ignores(path8);
7685
7685
  }
7686
7686
  filter(paths) {
7687
7687
  return makeArray(paths).filter(this.createFilter());
7688
7688
  }
7689
7689
  // @returns {TestResult}
7690
- test(path7) {
7691
- return this._test(path7, this._testCache, true);
7690
+ test(path8) {
7691
+ return this._test(path8, this._testCache, true);
7692
7692
  }
7693
7693
  };
7694
7694
  var factory = (options) => new Ignore(options);
7695
- var isPathValid = (path7) => checkPath(path7 && checkPath.convert(path7), path7, RETURN_FALSE);
7695
+ var isPathValid = (path8) => checkPath(path8 && checkPath.convert(path8), path8, RETURN_FALSE);
7696
7696
  factory.isPathValid = isPathValid;
7697
7697
  factory.default = factory;
7698
7698
  module.exports = factory;
@@ -7703,7 +7703,7 @@ var require_ignore = __commonJS({
7703
7703
  const makePosix = (str) => /^\\\\\?\\/.test(str) || /["<>|\u0000-\u001F]+/u.test(str) ? str : str.replace(/\\/g, "/");
7704
7704
  checkPath.convert = makePosix;
7705
7705
  const REGIX_IS_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i;
7706
- checkPath.isNotRelative = (path7) => REGIX_IS_WINDOWS_PATH_ABSOLUTE.test(path7) || isNotRelative(path7);
7706
+ checkPath.isNotRelative = (path8) => REGIX_IS_WINDOWS_PATH_ABSOLUTE.test(path8) || isNotRelative(path8);
7707
7707
  }
7708
7708
  }
7709
7709
  });
@@ -7711,7 +7711,7 @@ var require_ignore = __commonJS({
7711
7711
  // src/sanitize_cli.js
7712
7712
  import fs6 from "node:fs";
7713
7713
  import os2 from "node:os";
7714
- import path6 from "node:path";
7714
+ import path7 from "node:path";
7715
7715
  import { execFileSync as execFileSync2, spawnSync } from "node:child_process";
7716
7716
 
7717
7717
  // src/index.js
@@ -7721,8 +7721,7 @@ import crypto from "node:crypto";
7721
7721
  import fs5 from "node:fs";
7722
7722
  import http from "node:http";
7723
7723
  import os from "node:os";
7724
- import path5 from "node:path";
7725
- import { fileURLToPath } from "node:url";
7724
+ import path6 from "node:path";
7726
7725
  import { tool } from "@opencode-ai/plugin/tool";
7727
7726
 
7728
7727
  // src/git_utils.js
@@ -8493,7 +8492,9 @@ async function optima_validate_logic(worktree) {
8493
8492
  };
8494
8493
  }
8495
8494
 
8496
- // src/index.js
8495
+ // src/constants.js
8496
+ import path5 from "node:path";
8497
+ import { fileURLToPath } from "node:url";
8497
8498
  var PKG_ROOT = path5.resolve(path5.dirname(fileURLToPath(import.meta.url)), "..");
8498
8499
  var BUNDLE_ASSETS_DIR = path5.join(PKG_ROOT, "assets");
8499
8500
  var BUNDLE_AGENTS_DIR = path5.join(BUNDLE_ASSETS_DIR, "agents");
@@ -8534,6 +8535,8 @@ var CLICKUP_WEBHOOK_REQUEST_TIMEOUT_MS = 1e4;
8534
8535
  var CLICKUP_WEBHOOK_STARTUP_TASK_LIMIT = 50;
8535
8536
  var CLICKUP_WEBHOOK_STARTUP_COMMENT_LIMIT = 100;
8536
8537
  var CLICKUP_WEBHOOK_STARTUP_RECONCILIATION_DELAY_MS = 3e4;
8538
+ var CLICKUP_WEBHOOK_STARTUP_COMMENT_LOOKBACK_MS = 6 * 60 * 60 * 1e3;
8539
+ var CLICKUP_ASSIGNMENT_WATCHDOG_INTERVAL_MS = 5 * 60 * 1e3;
8537
8540
  var CLICKUP_WORKTREE_FAILURE_COMMENT_DEDUPE_MS = 10 * 60 * 1e3;
8538
8541
  var CLICKUP_WEBHOOK_LOG_LEVELS = /* @__PURE__ */ new Set(["error", "info", "verbose"]);
8539
8542
  var CLICKUP_WEBHOOK_REDACTED = "[REDACTED]";
@@ -8622,20 +8625,22 @@ var REPO_LOCAL_POLICIES_README = [
8622
8625
  "Only files in `.optima/policies/` affect runtime prompt behavior.",
8623
8626
  ""
8624
8627
  ].join("\n");
8628
+ var CLICKUP_WEBHOOK_CLEANUP_TIMEOUT_MS = 8e3;
8629
+ var CLICKUP_WEBHOOK_SIGNAL_STATE = Symbol.for("opencode-optima.clickup-webhook.signal-state");
8630
+
8631
+ // src/index.js
8625
8632
  var activeWorkflows = /* @__PURE__ */ new Map();
8626
8633
  var activeClickUpWebhookListeners = /* @__PURE__ */ new Map();
8627
8634
  var activeClickUpWebhookLifecycleRegistry = /* @__PURE__ */ new Map();
8628
- var CLICKUP_WEBHOOK_CLEANUP_TIMEOUT_MS = 8e3;
8629
- var CLICKUP_WEBHOOK_SIGNAL_STATE = Symbol.for("opencode-optima.clickup-webhook.signal-state");
8630
8635
  var activeClickUpTaskRoutes = /* @__PURE__ */ new Map();
8631
8636
  function isRootDirectory(candidate) {
8632
- const resolved = path5.resolve(candidate);
8633
- return resolved === path5.parse(resolved).root;
8637
+ const resolved = path6.resolve(candidate);
8638
+ return resolved === path6.parse(resolved).root;
8634
8639
  }
8635
8640
  function isSafeWritableDirectory(candidate) {
8636
8641
  if (typeof candidate !== "string" || !candidate.trim()) return false;
8637
- if (!path5.isAbsolute(candidate)) return false;
8638
- const resolved = path5.resolve(candidate);
8642
+ if (!path6.isAbsolute(candidate)) return false;
8643
+ const resolved = path6.resolve(candidate);
8639
8644
  if (isRootDirectory(resolved)) return false;
8640
8645
  try {
8641
8646
  const stat = fs5.statSync(resolved);
@@ -8656,7 +8661,7 @@ function resolveSafeWorktree(context = {}, pluginWorktree = null) {
8656
8661
  ];
8657
8662
  for (const candidate of candidates) {
8658
8663
  if (typeof candidate !== "string" || !candidate.trim()) continue;
8659
- const resolved = path5.resolve(candidate);
8664
+ const resolved = path6.resolve(candidate);
8660
8665
  if (isSafeWritableDirectory(resolved)) return resolved;
8661
8666
  }
8662
8667
  throw new Error(SAFE_WORKTREE_FAILURE);
@@ -8671,13 +8676,13 @@ function safeWorktreeOrFailure(context, pluginWorktree) {
8671
8676
  function explicitSafeInputWorktree(input = {}) {
8672
8677
  for (const candidate of [input?.worktree, input?.directory]) {
8673
8678
  if (typeof candidate !== "string" || !candidate.trim()) continue;
8674
- const resolved = path5.resolve(candidate);
8679
+ const resolved = path6.resolve(candidate);
8675
8680
  if (isSafeWritableDirectory(resolved)) return resolved;
8676
8681
  }
8677
8682
  return null;
8678
8683
  }
8679
8684
  function isGitRepository(worktree) {
8680
- return fs5.existsSync(path5.join(worktree, ".git"));
8685
+ return fs5.existsSync(path6.join(worktree, ".git"));
8681
8686
  }
8682
8687
  function normalizeLooseToken(value) {
8683
8688
  return String(value ?? "").trim().normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
@@ -9172,7 +9177,7 @@ function buildClickUpSummaryPayload({ summaryMarkdown = "", summaryPath = "", ta
9172
9177
  function deriveClickUpWorktree({ baseWorktree = "", taskId, taskType, parentTaskId, subtaskId } = {}) {
9173
9178
  const branch = deriveClickUpBranchName({ taskType, parentTaskId, subtaskId, taskId });
9174
9179
  const root = baseWorktree || process.cwd();
9175
- return path5.join(path5.dirname(root), `${path5.basename(root)}-${branch.replace(/\//g, "-")}`);
9180
+ return path6.join(path6.dirname(root), `${path6.basename(root)}-${branch.replace(/\//g, "-")}`);
9176
9181
  }
9177
9182
  function clickUpCustomFieldValue(task = {}, names = []) {
9178
9183
  const fields = Array.isArray(task.custom_fields) ? task.custom_fields : [];
@@ -9196,12 +9201,12 @@ function safeExistingClickUpWorktree({ metadata = {}, branch = "" } = {}) {
9196
9201
  const taskMetadata = metadataTaskRouting(metadata);
9197
9202
  const existingWorktree = typeof taskMetadata.worktree === "string" ? taskMetadata.worktree.trim() : "";
9198
9203
  const existingBranch = typeof taskMetadata.branch === "string" ? taskMetadata.branch.trim() : "";
9199
- if (!existingWorktree || !path5.isAbsolute(existingWorktree) || !fs5.existsSync(existingWorktree)) return null;
9204
+ if (!existingWorktree || !path6.isAbsolute(existingWorktree) || !fs5.existsSync(existingWorktree)) return null;
9200
9205
  try {
9201
9206
  const stat = fs5.statSync(existingWorktree);
9202
9207
  if (!stat.isDirectory()) return null;
9203
9208
  if (branch && existingBranch && existingBranch !== branch) return null;
9204
- return { branch: existingBranch || branch, worktree: path5.resolve(existingWorktree), reused: true };
9209
+ return { branch: existingBranch || branch, worktree: path6.resolve(existingWorktree), reused: true };
9205
9210
  } catch {
9206
9211
  return null;
9207
9212
  }
@@ -9287,17 +9292,17 @@ function openChamberEntryBranch(entry) {
9287
9292
  return String(entry?.branch || entry?.branchName || entry?.branch_name || entry?.worktree?.branch || "").replace(/^refs\/heads\//, "");
9288
9293
  }
9289
9294
  function openChamberListIncludesDirectory(list, directory) {
9290
- const resolved = path5.resolve(directory);
9295
+ const resolved = path6.resolve(directory);
9291
9296
  return normalizeOpenChamberCollection(list).some((entry) => {
9292
9297
  const entryDirectory = openChamberEntryDirectory(entry);
9293
- return entryDirectory && path5.resolve(entryDirectory) === resolved;
9298
+ return entryDirectory && path6.resolve(entryDirectory) === resolved;
9294
9299
  });
9295
9300
  }
9296
9301
  function openChamberListIncludesBranch(list, directory, branch) {
9297
- const resolved = path5.resolve(directory);
9302
+ const resolved = path6.resolve(directory);
9298
9303
  return normalizeOpenChamberCollection(list).some((entry) => {
9299
9304
  const entryDirectory = openChamberEntryDirectory(entry);
9300
- if (!entryDirectory || path5.resolve(entryDirectory) !== resolved) return false;
9305
+ if (!entryDirectory || path6.resolve(entryDirectory) !== resolved) return false;
9301
9306
  const entryBranch = openChamberEntryBranch(entry);
9302
9307
  return !entryBranch || entryBranch === branch;
9303
9308
  });
@@ -9305,8 +9310,8 @@ function openChamberListIncludesBranch(list, directory, branch) {
9305
9310
  async function findOpenChamberProject({ opencodeBaseUrl, baseWorktree, fetchImpl = globalThis.fetch } = {}) {
9306
9311
  const projects = await requestOpenCodeJson({ baseUrl: opencodeBaseUrl, endpoint: "/project", directory: baseWorktree, fetchImpl });
9307
9312
  if (!Array.isArray(projects)) return null;
9308
- const resolvedBase = path5.resolve(baseWorktree);
9309
- return projects.find((project) => path5.resolve(String(project?.worktree || project?.path || "")) === resolvedBase) || null;
9313
+ const resolvedBase = path6.resolve(baseWorktree);
9314
+ return projects.find((project) => path6.resolve(String(project?.worktree || project?.path || "")) === resolvedBase) || null;
9310
9315
  }
9311
9316
  async function refreshOpenChamberProjectCopy({ opencodeBaseUrl, projectId, fetchImpl = globalThis.fetch } = {}) {
9312
9317
  if (!projectId) return { refreshed: false, reason: "project_id_unavailable" };
@@ -9361,18 +9366,18 @@ async function createOpenChamberClickUpWorktree({ openchamberBaseUrl, baseUrl, b
9361
9366
  }
9362
9367
  const createdDirectory = openChamberEntryDirectory(created);
9363
9368
  const createdBranch = openChamberEntryBranch(created);
9364
- if (!createdDirectory || !path5.isAbsolute(createdDirectory)) {
9369
+ if (!createdDirectory || !path6.isAbsolute(createdDirectory)) {
9365
9370
  throw new Error(`OpenChamber did not return an absolute worktree path for ${branch}.`);
9366
9371
  }
9367
9372
  if (createdBranch !== branch) {
9368
9373
  throw new Error(`OpenChamber created unexpected branch ${createdBranch || "<unknown>"}; expected ${branch}.`);
9369
9374
  }
9370
9375
  const verified = await verifyOpenChamberGitWorktree({ openchamberBaseUrl: effectiveOpenChamberBaseUrl, baseWorktree, worktreePath: createdDirectory, branch, fetchImpl });
9371
- return { created, worktree: path5.resolve(createdDirectory), branch: createdBranch, verified };
9376
+ return { created, worktree: path6.resolve(createdDirectory), branch: createdBranch, verified };
9372
9377
  }
9373
9378
  async function registerOpenChamberClickUpWorktree({ openchamberBaseUrl, opencodeBaseUrl, baseUrl, baseWorktree, branch, worktreePath, fetchImpl = globalThis.fetch, source = "reuse" } = {}) {
9374
9379
  const visibility = await syncOpenChamberWorktreeVisibility({ openchamberBaseUrl: openchamberBaseUrl || baseUrl, opencodeBaseUrl: opencodeBaseUrl || baseUrl, baseWorktree, worktreePath, branch, fetchImpl });
9375
- return { branch, worktree: path5.resolve(worktreePath), reused: true, provider: "openchamber", openChamber: { source, visibility } };
9380
+ return { branch, worktree: path6.resolve(worktreePath), reused: true, provider: "openchamber", openChamber: { source, visibility } };
9376
9381
  }
9377
9382
  async function ensureClickUpTaskWorktreeOpenChamber({ baseWorktree = "", taskId, taskType = "Tarea", parentTaskId = "", subtaskId = "", existingMetadata = {}, runGitFn = runGit, openchamberBaseUrl = "", opencodeBaseUrl = "", baseUrl = "", fetchImpl = globalThis.fetch, log = null } = {}) {
9378
9383
  const effectiveOpenChamberBaseUrl = openchamberBaseUrl || baseUrl;
@@ -9435,10 +9440,10 @@ function ensureClickUpTaskWorktree({ baseWorktree = "", taskId, taskType = "Tare
9435
9440
  const existing = safeExistingClickUpWorktree({ metadata: existingMetadata, branch });
9436
9441
  if (existing) return { ...existing, branch, parentBranch: parentBranch || void 0, prTarget: parentBranch || "dev" };
9437
9442
  const worktreePath = deriveClickUpWorktree({ baseWorktree, taskId, taskType, parentTaskId: effectiveParent, subtaskId });
9438
- if (fs5.existsSync(worktreePath)) return { branch, worktree: path5.resolve(worktreePath), reused: true, parentBranch: parentBranch || void 0, prTarget: parentBranch || "dev" };
9443
+ if (fs5.existsSync(worktreePath)) return { branch, worktree: path6.resolve(worktreePath), reused: true, parentBranch: parentBranch || void 0, prTarget: parentBranch || "dev" };
9439
9444
  if (allowNonGitFallback) {
9440
9445
  fs5.mkdirSync(worktreePath, { recursive: true });
9441
- return { branch, worktree: path5.resolve(worktreePath), reused: false, fallback: "non_git", parentBranch: parentBranch || void 0, prTarget: parentBranch || "dev", startPoint: parentBranch || "dev" };
9446
+ return { branch, worktree: path6.resolve(worktreePath), reused: false, fallback: "non_git", parentBranch: parentBranch || void 0, prTarget: parentBranch || "dev", startPoint: parentBranch || "dev" };
9442
9447
  }
9443
9448
  let parentBootstrap = null;
9444
9449
  if (isSubtask) {
@@ -9447,14 +9452,14 @@ function ensureClickUpTaskWorktree({ baseWorktree = "", taskId, taskType = "Tare
9447
9452
  const parentStartPoint = resolveClickUpDevStartPoint(baseWorktree, runGitFn);
9448
9453
  const parentBranchExists = clickUpGitRefExists(baseWorktree, parentBranch, runGitFn);
9449
9454
  addClickUpWorktreeForBranch({ baseWorktree, branch: parentBranch, worktreePath: parentWorktree, startPoint: parentStartPoint, runGitFn });
9450
- parentBootstrap = { branch: parentBranch, worktree: path5.resolve(parentWorktree), startPoint: parentBranchExists ? parentBranch : parentStartPoint, reused: parentBranchExists };
9455
+ parentBootstrap = { branch: parentBranch, worktree: path6.resolve(parentWorktree), startPoint: parentBranchExists ? parentBranch : parentStartPoint, reused: parentBranchExists };
9451
9456
  } else {
9452
- parentBootstrap = { branch: parentBranch, worktree: path5.resolve(parentWorktree), reused: true };
9457
+ parentBootstrap = { branch: parentBranch, worktree: path6.resolve(parentWorktree), reused: true };
9453
9458
  }
9454
9459
  }
9455
9460
  const startPoint = isSubtask ? parentBranch : resolveClickUpDevStartPoint(baseWorktree, runGitFn);
9456
9461
  addClickUpWorktreeForBranch({ baseWorktree, branch, worktreePath, startPoint, runGitFn });
9457
- return { branch, worktree: path5.resolve(worktreePath), reused: false, startPoint, parentBranch: parentBranch || void 0, prTarget: parentBranch || "dev", parentBootstrap: parentBootstrap || void 0 };
9462
+ return { branch, worktree: path6.resolve(worktreePath), reused: false, startPoint, parentBranch: parentBranch || void 0, prTarget: parentBranch || "dev", parentBootstrap: parentBootstrap || void 0 };
9458
9463
  }
9459
9464
  function normalizeClickUpDefinitionDocParent(parent = {}) {
9460
9465
  const docId = String(parent.doc_id || parent.docId || CLICKUP_DEFINITION_DOC_PARENT.doc_id).trim();
@@ -9604,7 +9609,7 @@ function buildClickUpTransitionPayload({ fromStatus, toStatus, validationPassed
9604
9609
  }
9605
9610
  function ensureOptimaGitignoreRules(worktree) {
9606
9611
  if (!isGitRepository(worktree)) return { touched: false, added: [] };
9607
- const gitignorePath = path5.join(worktree, ".gitignore");
9612
+ const gitignorePath = path6.join(worktree, ".gitignore");
9608
9613
  const existing = fs5.existsSync(gitignorePath) ? fs5.readFileSync(gitignorePath, "utf8") : "";
9609
9614
  const existingRules = new Set(existing.split(/\r?\n/).map((line) => line.trim()).filter(Boolean));
9610
9615
  const missingRules = OPTIMA_GITIGNORE_RULES.filter((rule) => !existingRules.has(rule));
@@ -9620,40 +9625,40 @@ function ensureOptimaGitignoreRules(worktree) {
9620
9625
  return { touched: true, added: missingRules };
9621
9626
  }
9622
9627
  function optimaDir(worktree) {
9623
- return path5.join(worktree, OPTIMA_DIRNAME);
9628
+ return path6.join(worktree, OPTIMA_DIRNAME);
9624
9629
  }
9625
9630
  function optimaLocalConfigDir(worktree) {
9626
- return path5.join(optimaDir(worktree), ".config");
9631
+ return path6.join(optimaDir(worktree), ".config");
9627
9632
  }
9628
9633
  function optimaConfigDir(worktree) {
9629
9634
  return optimaLocalConfigDir(worktree);
9630
9635
  }
9631
9636
  function optimaCodemapPath(worktree) {
9632
- return path5.join(optimaDir(worktree), "codemap.yml");
9637
+ return path6.join(optimaDir(worktree), "codemap.yml");
9633
9638
  }
9634
9639
  function optimaTasksDir(worktree) {
9635
- return path5.join(optimaDir(worktree), "tasks");
9640
+ return path6.join(optimaDir(worktree), "tasks");
9636
9641
  }
9637
9642
  function optimaEvidencesDir(worktree) {
9638
- return path5.join(optimaDir(worktree), "evidences");
9643
+ return path6.join(optimaDir(worktree), "evidences");
9639
9644
  }
9640
9645
  function optimaScrsDir(worktree) {
9641
- return path5.join(optimaDir(worktree), "docs", "scrs");
9646
+ return path6.join(optimaDir(worktree), "docs", "scrs");
9642
9647
  }
9643
9648
  function legacyNomadworkDir(worktree) {
9644
- return path5.join(worktree, LEGACY_NOMADWORK_DIRNAME);
9649
+ return path6.join(worktree, LEGACY_NOMADWORK_DIRNAME);
9645
9650
  }
9646
9651
  function legacyNomadworksDir(worktree) {
9647
- return path5.join(worktree, LEGACY_NOMADWORKS_DIRNAME);
9652
+ return path6.join(worktree, LEGACY_NOMADWORKS_DIRNAME);
9648
9653
  }
9649
9654
  function legacyOrbitaDir(worktree) {
9650
- return path5.join(worktree, LEGACY_ORBITA_DIRNAME);
9655
+ return path6.join(worktree, LEGACY_ORBITA_DIRNAME);
9651
9656
  }
9652
9657
  function legacyStaticEngDir(worktree) {
9653
- return path5.join(worktree, LEGACY_STATICENG_DIRNAME);
9658
+ return path6.join(worktree, LEGACY_STATICENG_DIRNAME);
9654
9659
  }
9655
9660
  function repoConfigPath(worktree) {
9656
- return path5.join(optimaConfigDir(worktree), "optima.yaml");
9661
+ return path6.join(optimaConfigDir(worktree), "optima.yaml");
9657
9662
  }
9658
9663
  function normalizeLegacyDiscussionEntry(entry) {
9659
9664
  if (!entry || typeof entry !== "object") return entry;
@@ -9666,25 +9671,25 @@ function normalizeLegacyDiscussionEntry(entry) {
9666
9671
  return next;
9667
9672
  }
9668
9673
  function repoPoliciesDir(worktree) {
9669
- return path5.join(optimaDir(worktree), "policies");
9674
+ return path6.join(optimaDir(worktree), "policies");
9670
9675
  }
9671
9676
  function generatedPoliciesDir(worktree) {
9672
- return path5.join(optimaLocalConfigDir(worktree), "generated", "policies");
9677
+ return path6.join(optimaLocalConfigDir(worktree), "generated", "policies");
9673
9678
  }
9674
9679
  function generatedAgentsDir(worktree) {
9675
- return path5.join(optimaLocalConfigDir(worktree), "generated", "agents");
9680
+ return path6.join(optimaLocalConfigDir(worktree), "generated", "agents");
9676
9681
  }
9677
9682
  function repoAgentsDir(worktree) {
9678
- return path5.join(optimaDir(worktree), "agents");
9683
+ return path6.join(optimaDir(worktree), "agents");
9679
9684
  }
9680
9685
  function repoAgentAdditionsDir(worktree) {
9681
- return path5.join(optimaDir(worktree), "agent-additions");
9686
+ return path6.join(optimaDir(worktree), "agent-additions");
9682
9687
  }
9683
9688
  function legacyRepoAgentsDir(worktree) {
9684
- return path5.join(legacyNomadworksDir(worktree), "agents");
9689
+ return path6.join(legacyNomadworksDir(worktree), "agents");
9685
9690
  }
9686
9691
  function runtimeDiscussionRegistryPath(worktree) {
9687
- return path5.join(optimaLocalConfigDir(worktree), "runtime", "discussions.json");
9692
+ return path6.join(optimaLocalConfigDir(worktree), "runtime", "discussions.json");
9688
9693
  }
9689
9694
  function resolveConfigPath(worktree) {
9690
9695
  return repoConfigPath(worktree);
@@ -9727,32 +9732,32 @@ function mergeClickUpAgentMetadata(existing, update = {}) {
9727
9732
  return JSON.stringify(sortJsonValue(merged), null, 2);
9728
9733
  }
9729
9734
  function optimaRuntimeDir(worktree) {
9730
- return path5.join(optimaLocalConfigDir(worktree), "runtime");
9735
+ return path6.join(optimaLocalConfigDir(worktree), "runtime");
9731
9736
  }
9732
9737
  function clickUpWebhookStatePath(worktree) {
9733
- return path5.join(optimaRuntimeDir(worktree), "clickup-webhook.json");
9738
+ return path6.join(optimaRuntimeDir(worktree), "clickup-webhook.json");
9734
9739
  }
9735
9740
  function clickUpCommentLedgerPath(worktree) {
9736
- return path5.join(optimaRuntimeDir(worktree), "clickup-comment-ledger.jsonl");
9741
+ return path6.join(optimaRuntimeDir(worktree), "clickup-comment-ledger.jsonl");
9737
9742
  }
9738
9743
  function clickUpWebhookLogPath(worktree) {
9739
- return path5.join(optimaRuntimeDir(worktree), "clickup-webhook.log.jsonl");
9744
+ return path6.join(optimaRuntimeDir(worktree), "clickup-webhook.log.jsonl");
9740
9745
  }
9741
9746
  function normalizeClickUpWebhookLogLevel(value) {
9742
9747
  const level = String(value || "info").trim().toLowerCase();
9743
9748
  return CLICKUP_WEBHOOK_LOG_LEVELS.has(level) ? level : "info";
9744
9749
  }
9745
9750
  function clickUpWebhookAuditLogDir() {
9746
- const dataHome = process.env.XDG_DATA_HOME && path5.isAbsolute(process.env.XDG_DATA_HOME) ? process.env.XDG_DATA_HOME : path5.join(os.homedir(), ".local", "share", "opencode");
9747
- return path5.join(dataHome, "opencode-optima");
9751
+ 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");
9752
+ return path6.join(dataHome, "opencode-optima");
9748
9753
  }
9749
9754
  function clickUpWebhookAuditLogPath(at = /* @__PURE__ */ new Date(), logDir = clickUpWebhookAuditLogDir()) {
9750
- return path5.join(logDir, `clickup-webhook-${at.toISOString().slice(0, 10)}.jsonl`);
9755
+ return path6.join(logDir, `clickup-webhook-${at.toISOString().slice(0, 10)}.jsonl`);
9751
9756
  }
9752
9757
  function clickUpWebhookRequestFilePath(at = /* @__PURE__ */ new Date(), logDir = clickUpWebhookAuditLogDir()) {
9753
9758
  const stamp = at.toISOString().replace(/:/g, "-").replace(/\./g, "-");
9754
9759
  const shortId = crypto.randomBytes(4).toString("hex");
9755
- return path5.join(logDir, "requests", `clickup-webhook-${stamp}-${shortId}.json`);
9760
+ return path6.join(logDir, "requests", `clickup-webhook-${stamp}-${shortId}.json`);
9756
9761
  }
9757
9762
  function findOptimaPluginTupleOptions(pluginEntries = []) {
9758
9763
  if (!Array.isArray(pluginEntries)) return null;
@@ -9814,6 +9819,10 @@ function normalizeClickUpWebhookConfig(rawClickUp = null, worktree = process.cwd
9814
9819
  startupReconciliationDelayMs: normalizeNonNegativeInteger(
9815
9820
  opencode.startup_reconciliation_delay_ms ?? opencode.startupReconciliationDelayMs ?? raw.startup_reconciliation_delay_ms ?? raw.startupReconciliationDelayMs,
9816
9821
  CLICKUP_WEBHOOK_STARTUP_RECONCILIATION_DELAY_MS
9822
+ ),
9823
+ assignmentWatchdogIntervalMs: normalizeNonNegativeInteger(
9824
+ opencode.assignment_watchdog_interval_ms ?? opencode.assignmentWatchdogIntervalMs ?? raw.assignment_watchdog_interval_ms ?? raw.assignmentWatchdogIntervalMs,
9825
+ CLICKUP_ASSIGNMENT_WATCHDOG_INTERVAL_MS
9817
9826
  )
9818
9827
  },
9819
9828
  openchamber: {
@@ -9847,7 +9856,7 @@ function normalizeClickUpWebhookConfig(rawClickUp = null, worktree = process.cwd
9847
9856
  };
9848
9857
  const errors = [];
9849
9858
  if (!config.enabled) errors.push("clickup.enabled must be true");
9850
- if (!config.basePath || !path5.isAbsolute(config.basePath)) errors.push("clickup.base_path must be an absolute path");
9859
+ if (!config.basePath || !path6.isAbsolute(config.basePath)) errors.push("clickup.base_path must be an absolute path");
9851
9860
  if (!config.teamId) errors.push("clickup.team_id is required");
9852
9861
  if (!config.apiToken) errors.push("clickup.api_token is required");
9853
9862
  if (!config.webhook.publicUrl) errors.push("clickup.webhook.public_url is required");
@@ -9905,7 +9914,7 @@ function readClickUpWebhookState(worktree, config = null) {
9905
9914
  }
9906
9915
  function writeClickUpWebhookState(worktree, state, config = null) {
9907
9916
  const statePath = clickUpWebhookStatePath(worktree);
9908
- fs5.mkdirSync(path5.dirname(statePath), { recursive: true, mode: 448 });
9917
+ fs5.mkdirSync(path6.dirname(statePath), { recursive: true, mode: 448 });
9909
9918
  const next = sanitizeClickUpWebhookState(state, config);
9910
9919
  fs5.writeFileSync(statePath, `${JSON.stringify(next, null, 2)}
9911
9920
  `, { encoding: "utf8", mode: 384 });
@@ -9926,7 +9935,7 @@ function isClickUpWebhookStateActive(state, config) {
9926
9935
  function expandHomePath(value = "") {
9927
9936
  const input = String(value || "").trim();
9928
9937
  if (input === "~") return os.homedir();
9929
- if (input.startsWith("~/")) return path5.join(os.homedir(), input.slice(2));
9938
+ if (input.startsWith("~/")) return path6.join(os.homedir(), input.slice(2));
9930
9939
  return input;
9931
9940
  }
9932
9941
  function resolveSecretReference(value = "") {
@@ -10302,7 +10311,7 @@ function readClickUpCommentLedger(ledgerPath) {
10302
10311
  }
10303
10312
  function appendClickUpCommentLedgerEntry(ledgerPath, entry = {}) {
10304
10313
  if (!ledgerPath || !entry.key) return;
10305
- fs5.mkdirSync(path5.dirname(ledgerPath), { recursive: true, mode: 448 });
10314
+ fs5.mkdirSync(path6.dirname(ledgerPath), { recursive: true, mode: 448 });
10306
10315
  fs5.appendFileSync(ledgerPath, `${JSON.stringify(entry)}
10307
10316
  `, { encoding: "utf8", mode: 384 });
10308
10317
  try {
@@ -10779,17 +10788,87 @@ function openCodeResultSummary(result) {
10779
10788
  status: result?.status || result?.response?.status || null
10780
10789
  };
10781
10790
  }
10791
+ function openCodeMessagePayload(message = {}) {
10792
+ if (!isPlainObject(message)) return {};
10793
+ const rawData = message.data;
10794
+ if (isPlainObject(rawData)) {
10795
+ return {
10796
+ ...rawData,
10797
+ id: rawData.id || message.id,
10798
+ time_created: rawData.time_created ?? message.time_created,
10799
+ time_updated: rawData.time_updated ?? message.time_updated
10800
+ };
10801
+ }
10802
+ if (typeof rawData === "string" && rawData.trim()) {
10803
+ try {
10804
+ const parsed = JSON.parse(rawData);
10805
+ if (isPlainObject(parsed)) {
10806
+ return {
10807
+ ...parsed,
10808
+ id: parsed.id || message.id,
10809
+ time_created: parsed.time_created ?? message.time_created,
10810
+ time_updated: parsed.time_updated ?? message.time_updated
10811
+ };
10812
+ }
10813
+ } catch {
10814
+ }
10815
+ }
10816
+ return message;
10817
+ }
10782
10818
  function normalizeOpenCodeMessageRole(message = {}) {
10783
- return message.role || message.info?.role || message.author?.role || message.type || "";
10819
+ const payload = openCodeMessagePayload(message);
10820
+ return payload.role || payload.info?.role || payload.author?.role || payload.type || "";
10784
10821
  }
10785
10822
  function normalizeOpenCodeMessageAgent(message = {}) {
10786
- return message.agent || message.info?.agent || message.mode?.agent || message.author?.agent || "";
10823
+ const payload = openCodeMessagePayload(message);
10824
+ return payload.agent || payload.info?.agent || payload.mode?.agent || payload.author?.agent || "";
10787
10825
  }
10788
10826
  function normalizeOpenCodeMessageMode(message = {}) {
10789
- return message.mode || message.info?.mode || message.metadata?.mode || "";
10827
+ const payload = openCodeMessagePayload(message);
10828
+ return payload.mode || payload.info?.mode || payload.metadata?.mode || "";
10790
10829
  }
10791
10830
  function normalizeOpenCodeMessageId(message = {}) {
10792
- return message.id || message.messageID || message.messageId || message.info?.id || message.data?.id || null;
10831
+ const payload = openCodeMessagePayload(message);
10832
+ return payload.id || payload.messageID || payload.messageId || payload.info?.id || payload.data?.id || message.id || null;
10833
+ }
10834
+ function openCodeMessageTimestampMs(message = {}, key = "updated") {
10835
+ const payload = openCodeMessagePayload(message);
10836
+ const time = payload.time || payload.info?.time || {};
10837
+ const value = key === "completed" ? payload.time_completed ?? payload.timeCompleted ?? time.completed : key === "created" ? payload.time_created ?? payload.timeCreated ?? time.created : payload.time_updated ?? payload.timeUpdated ?? time.updated ?? payload.time_created ?? payload.timeCreated ?? time.created;
10838
+ const number = Number(value);
10839
+ return Number.isFinite(number) && number > 0 ? number : 0;
10840
+ }
10841
+ function isOpenCodeAssistantMessageRunning(message = {}) {
10842
+ if (normalizeLooseToken(normalizeOpenCodeMessageRole(message)) !== "assistant") return false;
10843
+ const started = openCodeMessageTimestampMs(message, "created") > 0;
10844
+ if (!started) return false;
10845
+ return openCodeMessageTimestampMs(message, "completed") === 0;
10846
+ }
10847
+ async function inspectOpenCodeSessionActivity(client, { sessionId, directory, limit = 10 } = {}) {
10848
+ const messages = await readOpenCodeSessionMessages(client, { sessionId, directory, limit });
10849
+ if (!messages) return { ok: false, reason: "message_inspection_unavailable", sessionId, directory };
10850
+ const enriched = messages.map((message, index) => ({
10851
+ message,
10852
+ index,
10853
+ sortTime: openCodeMessageTimestampMs(message, "updated") || index,
10854
+ createdAt: openCodeMessageTimestampMs(message, "created"),
10855
+ completedAt: openCodeMessageTimestampMs(message, "completed")
10856
+ })).sort((a, b) => a.sortTime - b.sortTime || a.index - b.index);
10857
+ const assistantMessages = enriched.filter((entry) => normalizeLooseToken(normalizeOpenCodeMessageRole(entry.message)) === "assistant");
10858
+ const latestAssistant = assistantMessages.at(-1) || null;
10859
+ const latest = enriched.at(-1) || null;
10860
+ const running = latestAssistant ? isOpenCodeAssistantMessageRunning(latestAssistant.message) : false;
10861
+ return {
10862
+ ok: true,
10863
+ sessionId,
10864
+ directory,
10865
+ count: messages.length,
10866
+ running,
10867
+ latestMessageId: latest ? normalizeOpenCodeMessageId(latest.message) : null,
10868
+ latestAssistantMessageId: latestAssistant ? normalizeOpenCodeMessageId(latestAssistant.message) : null,
10869
+ latestAssistantCreatedAt: latestAssistant?.createdAt || 0,
10870
+ latestAssistantCompletedAt: latestAssistant?.completedAt || 0
10871
+ };
10793
10872
  }
10794
10873
  function summarizeOpenCodeMessages(messages = [], { snippetLength = 160, maxMessages = 50 } = {}) {
10795
10874
  const list = Array.isArray(messages) ? messages.slice(0, maxMessages) : [];
@@ -10929,8 +11008,9 @@ async function probeOpenCodeSessionControl(client, { directory, agent, omitAgent
10929
11008
  };
10930
11009
  }
10931
11010
  function openCodeMessageText(message) {
10932
- const parts = [message?.text, message?.content, message?.message, message?.body?.text, message?.data?.text];
10933
- const partList = Array.isArray(message?.parts) ? message.parts : Array.isArray(message?.body?.parts) ? message.body.parts : [];
11011
+ const payload = openCodeMessagePayload(message);
11012
+ const parts = [payload?.text, payload?.content, payload?.message, payload?.body?.text, payload?.data?.text];
11013
+ const partList = Array.isArray(payload?.parts) ? payload.parts : Array.isArray(payload?.body?.parts) ? payload.body.parts : [];
10934
11014
  for (const part of partList) parts.push(part?.text, part?.content);
10935
11015
  return parts.filter((value) => typeof value === "string").join("\n");
10936
11016
  }
@@ -11094,7 +11174,7 @@ function formatClickUpWebhookPrompt({ eventType, taskId, payload, branch = "", w
11094
11174
  }
11095
11175
  function appendClickUpWebhookLocalLog(worktree, entry) {
11096
11176
  const logPath = clickUpWebhookLogPath(worktree);
11097
- fs5.mkdirSync(path5.dirname(logPath), { recursive: true });
11177
+ fs5.mkdirSync(path6.dirname(logPath), { recursive: true });
11098
11178
  const safeEntry = { ...entry, at: entry.at || (/* @__PURE__ */ new Date()).toISOString() };
11099
11179
  fs5.appendFileSync(logPath, `${JSON.stringify(safeEntry)}
11100
11180
  `, "utf8");
@@ -11125,7 +11205,7 @@ function closeClickUpWebhookServer(server) {
11125
11205
  });
11126
11206
  }
11127
11207
  function managedClickUpWebhookKey({ worktree, state, config } = {}) {
11128
- return [path5.resolve(worktree || process.cwd()), state?.webhookId || "", config?.webhook?.publicUrl || ""].join("|");
11208
+ return [path6.resolve(worktree || process.cwd()), state?.webhookId || "", config?.webhook?.publicUrl || ""].join("|");
11129
11209
  }
11130
11210
  async function deleteClickUpWebhookBestEffort({ webhookId, clickupClient, worktree, reason = "cleanup" } = {}) {
11131
11211
  const id = String(webhookId || "").trim();
@@ -11148,6 +11228,7 @@ async function cleanupManagedClickUpWebhook(entry = {}, { timeoutMs = CLICKUP_WE
11148
11228
  entry.cleaning = true;
11149
11229
  const cleanup = (async () => {
11150
11230
  clickUpWebhookLifecycleLog(entry.worktree, { type: "cleanup_started", reason, key: entry.key, webhookId: entry.state?.webhookId });
11231
+ if (entry.assignmentWatchdog?.interval) clearInterval(entry.assignmentWatchdog.interval);
11151
11232
  const closeResult = await closeClickUpWebhookServer(entry.listener?.server);
11152
11233
  if (entry.listenerRegistry && entry.listener?.key) entry.listenerRegistry.delete(entry.listener.key);
11153
11234
  const preservedResult = { ok: true, skipped: true, reason: "remote_webhook_preserved" };
@@ -11161,10 +11242,10 @@ async function cleanupManagedClickUpWebhook(entry = {}, { timeoutMs = CLICKUP_WE
11161
11242
  if (result?.timeout) clickUpWebhookLifecycleLog(entry.worktree, { type: "cleanup_timeout", reason, webhookId: entry.state?.webhookId });
11162
11243
  return result;
11163
11244
  }
11164
- function registerClickUpWebhookLifecycle({ config, state, worktree, clickupClient, listener, listenerRegistry = activeClickUpWebhookListeners } = {}) {
11245
+ function registerClickUpWebhookLifecycle({ config, state, worktree, clickupClient, listener, listenerRegistry = activeClickUpWebhookListeners, assignmentWatchdog = null } = {}) {
11165
11246
  if (!isClickUpWebhookStateActive(state, config)) return null;
11166
11247
  const key = managedClickUpWebhookKey({ worktree, state, config });
11167
- const entry = { key, config, state, worktree, clickupClient, listener, listenerRegistry, registeredAt: (/* @__PURE__ */ new Date()).toISOString() };
11248
+ const entry = { key, config, state, worktree, clickupClient, listener, listenerRegistry, assignmentWatchdog, registeredAt: (/* @__PURE__ */ new Date()).toISOString() };
11168
11249
  activeClickUpWebhookLifecycleRegistry.set(key, entry);
11169
11250
  installClickUpWebhookSignalHandlers();
11170
11251
  clickUpWebhookLifecycleLog(worktree, { type: "lifecycle_registered", key, webhookId: state.webhookId });
@@ -11229,8 +11310,8 @@ function writeClickUpWebhookAuditLog({ method, url, headers = {}, rawBody = "",
11229
11310
  let requestFile;
11230
11311
  if (level === "verbose") {
11231
11312
  const absoluteRequestFile = clickUpWebhookRequestFilePath(at, logDir);
11232
- fs5.mkdirSync(path5.dirname(absoluteRequestFile), { recursive: true });
11233
- requestFile = path5.relative(logDir, absoluteRequestFile).split(path5.sep).join("/");
11313
+ fs5.mkdirSync(path6.dirname(absoluteRequestFile), { recursive: true });
11314
+ requestFile = path6.relative(logDir, absoluteRequestFile).split(path6.sep).join("/");
11234
11315
  const parsedBody = payload || (() => {
11235
11316
  try {
11236
11317
  return JSON.parse(Buffer.isBuffer(rawBody) ? rawBody.toString("utf8") : String(rawBody || ""));
@@ -11454,19 +11535,54 @@ function scheduleClickUpStartupReconciliation({ config, state = {}, worktree = p
11454
11535
  timer?.unref?.();
11455
11536
  return { scheduled: true, delayMs: normalizedDelayMs, timer };
11456
11537
  }
11457
- async function reconcileClickUpStartup({ config, state = {}, worktree = process.cwd(), clickupClient, openCodeClient, sessionExists = openCodeSessionExists, createSession = createOpenCodeSession, sendSessionEvent = sendOpenCodeSessionEvent, verifySessionEventDelivery = verifyOpenCodeSessionEventDelivery, waitForReadiness = waitForOpenCodeReadiness, saveState = null, now = () => /* @__PURE__ */ new Date(), limit = CLICKUP_WEBHOOK_STARTUP_TASK_LIMIT } = {}) {
11458
- clickUpWebhookLifecycleLog(worktree, { type: "startup_reconciliation_started", lastWebhookAt: state.lastWebhookAt || null });
11538
+ function scheduleClickUpAssignmentWatchdog({ config, state = {}, worktree = process.cwd(), clickupClient, openCodeClient, scheduler = setInterval, intervalMs = config?.opencode?.assignmentWatchdogIntervalMs ?? CLICKUP_ASSIGNMENT_WATCHDOG_INTERVAL_MS, saveState = null, reconcile = reconcileClickUpStartup } = {}) {
11539
+ const normalizedIntervalMs = normalizeNonNegativeInteger(intervalMs, CLICKUP_ASSIGNMENT_WATCHDOG_INTERVAL_MS);
11540
+ if (!normalizedIntervalMs) {
11541
+ clickUpWebhookLifecycleLog(worktree, { type: "assignment_watchdog_disabled", webhookId: state?.webhookId || null });
11542
+ return { scheduled: false, intervalMs: 0, reason: "disabled" };
11543
+ }
11544
+ let running = false;
11545
+ const run = () => {
11546
+ if (running) {
11547
+ appendClickUpWebhookLocalLog(worktree, { type: "assignment_watchdog_tick_skipped", reason: "previous_tick_running" });
11548
+ return;
11549
+ }
11550
+ running = true;
11551
+ const latestState = readClickUpWebhookState(worktree, config);
11552
+ Promise.resolve().then(() => reconcile({
11553
+ config,
11554
+ state: latestState?.webhookId ? latestState : state,
11555
+ worktree,
11556
+ clickupClient,
11557
+ openCodeClient,
11558
+ saveState,
11559
+ assignmentMode: "watchdog"
11560
+ })).catch((error) => {
11561
+ clickUpWebhookLifecycleLog(worktree, { type: "assignment_watchdog_failed", message: error.message });
11562
+ appendClickUpWebhookLocalLog(worktree, { type: "assignment_watchdog_failed", message: error.message });
11563
+ }).finally(() => {
11564
+ running = false;
11565
+ });
11566
+ };
11567
+ const interval = scheduler(run, normalizedIntervalMs);
11568
+ interval?.unref?.();
11569
+ clickUpWebhookLifecycleLog(worktree, { type: "assignment_watchdog_scheduled", intervalMs: normalizedIntervalMs, webhookId: state?.webhookId || null });
11570
+ return { scheduled: true, intervalMs: normalizedIntervalMs, interval };
11571
+ }
11572
+ async function reconcileClickUpStartup({ config, state = {}, worktree = process.cwd(), clickupClient, openCodeClient, sessionExists = openCodeSessionExists, createSession = createOpenCodeSession, sendSessionEvent = sendOpenCodeSessionEvent, verifySessionEventDelivery = verifyOpenCodeSessionEventDelivery, waitForReadiness = waitForOpenCodeReadiness, saveState = null, now = () => /* @__PURE__ */ new Date(), limit = CLICKUP_WEBHOOK_STARTUP_TASK_LIMIT, assignmentMode = "startup" } = {}) {
11573
+ const watchdogMode = assignmentMode === "watchdog";
11574
+ clickUpWebhookLifecycleLog(worktree, { type: watchdogMode ? "assignment_watchdog_started" : "startup_reconciliation_started", lastWebhookAt: state.lastWebhookAt || null });
11459
11575
  if (!config || !clickupClient?.listAssignedTasks) {
11460
11576
  const skipped = { ok: true, skipped: true, reason: "clickup_task_listing_unavailable", assigned: 0, comments: 0 };
11461
- clickUpWebhookLifecycleLog(worktree, { type: "startup_reconciliation_finished", ...skipped });
11577
+ clickUpWebhookLifecycleLog(worktree, { type: watchdogMode ? "assignment_watchdog_finished" : "startup_reconciliation_finished", ...skipped });
11462
11578
  return skipped;
11463
11579
  }
11464
11580
  const readiness = await waitForReadiness(openCodeClient, { worktree, now, opencodeBaseUrl: config.opencode?.baseUrl });
11465
11581
  appendClickUpWebhookLocalLog(worktree, { type: readiness.ok ? "startup_reconciliation_readiness_ready" : "startup_reconciliation_readiness_failed", ...readiness });
11466
11582
  if (!readiness.ok) {
11467
11583
  const failed = { ok: false, skipped: true, reason: "opencode_not_ready", readiness, assigned: 0, comments: 0, ignored: 0, errors: 1, undelivered: 1, tasks: [], validation: { undelivered: 1, emptyPromptSessions: [] } };
11468
- clickUpWebhookLifecycleLog(worktree, { type: "startup_reconciliation_failed", reason: failed.reason, readiness });
11469
- clickUpWebhookLifecycleLog(worktree, { type: "startup_reconciliation_finished", ...failed });
11584
+ clickUpWebhookLifecycleLog(worktree, { type: watchdogMode ? "assignment_watchdog_failed" : "startup_reconciliation_failed", reason: failed.reason, readiness });
11585
+ clickUpWebhookLifecycleLog(worktree, { type: watchdogMode ? "assignment_watchdog_finished" : "startup_reconciliation_finished", ...failed });
11470
11586
  return failed;
11471
11587
  }
11472
11588
  let authorizedUserId = "";
@@ -11484,6 +11600,7 @@ async function reconcileClickUpStartup({ config, state = {}, worktree = process.
11484
11600
  if (saveState) saveState(nextState);
11485
11601
  };
11486
11602
  const lastWebhookMs = clickUpTimestampMs(mutableState.lastWebhookAt);
11603
+ const startupCommentStartMs = lastWebhookMs || Math.max(0, now().getTime() - CLICKUP_WEBHOOK_STARTUP_COMMENT_LOOKBACK_MS);
11487
11604
  const ignored = new Set((config.routing?.ignoredStatuses || CLICKUP_WEBHOOK_TERMINAL_STATUSES).map(normalizeClickUpStatus));
11488
11605
  const routed = { assigned: 0, comments: 0, ignored: 0, errors: 0, undelivered: 0, tasks: [] };
11489
11606
  const listed = await clickupClient.listAssignedTasks({ assigneeId: config.routing.productManagerAssigneeId, limit });
@@ -11502,9 +11619,29 @@ async function reconcileClickUpStartup({ config, state = {}, worktree = process.
11502
11619
  routed.ignored += 1;
11503
11620
  continue;
11504
11621
  }
11622
+ if (watchdogMode) {
11623
+ const existingMetadata = clickUpTaskAgentMetadata(task, config.routing.metadataFieldId);
11624
+ const metadata = normalizeAgentMetadataJson(existingMetadata);
11625
+ const rawSessionId = getNestedMetadataValue(metadata, config.routing.metadataKey);
11626
+ const sessionId = typeof rawSessionId === "string" && rawSessionId.startsWith("ses_") ? rawSessionId : "";
11627
+ const directory = String(getNestedMetadataValue(metadata, "task.worktree") || "").trim();
11628
+ if (sessionId) {
11629
+ try {
11630
+ const activity = await inspectOpenCodeSessionActivity(openCodeClient, { sessionId, directory });
11631
+ appendClickUpWebhookLocalLog(worktree, { type: "assignment_watchdog_session_activity", taskId, sessionId, directory: directory || null, ...activity });
11632
+ if (activity.running) {
11633
+ routed.ignored += 1;
11634
+ routed.tasks.push({ taskId, action: "ignored", ok: true, sessionId, branch: getNestedMetadataValue(metadata, "task.branch") || null, worktree: directory || null, verification: "session_running", delivered: false });
11635
+ continue;
11636
+ }
11637
+ } catch (error) {
11638
+ appendClickUpWebhookLocalLog(worktree, { type: "assignment_watchdog_session_activity_failed", taskId, sessionId, directory: directory || null, message: error.message });
11639
+ }
11640
+ }
11641
+ }
11505
11642
  try {
11506
11643
  const result = await routeClickUpWebhookEvent({
11507
- payload: { webhook_id: mutableState.webhookId || "startup", event: "taskAssigneeUpdated", task_id: taskId, task, startup_reconciliation: true },
11644
+ payload: { webhook_id: mutableState.webhookId || "startup", event: "taskAssigneeUpdated", task_id: taskId, task, startup_reconciliation: true, assignment_watchdog: watchdogMode },
11508
11645
  config,
11509
11646
  state: mutableState,
11510
11647
  worktree,
@@ -11554,12 +11691,12 @@ async function reconcileClickUpStartup({ config, state = {}, worktree = process.
11554
11691
  appendClickUpWebhookLocalLog(worktree, { type: "startup_reconciliation_task_undelivered", taskId, action: "error", sessionId: null, reason: "startup_reconciliation_task_failed" });
11555
11692
  await applyClickUpBlockerTag({ clickupClient, worktree, taskId, reason: "startup_reconciliation_task_failed", source: "startup_reconciliation_task" });
11556
11693
  }
11557
- if (!lastWebhookMs || !clickupClient?.getTaskComments) continue;
11694
+ if (!startupCommentStartMs || !clickupClient?.getTaskComments) continue;
11558
11695
  try {
11559
- const commentsResponse = await clickupClient.getTaskComments({ taskId, start: lastWebhookMs, limit: CLICKUP_WEBHOOK_STARTUP_COMMENT_LIMIT });
11696
+ const commentsResponse = await clickupClient.getTaskComments({ taskId, start: startupCommentStartMs, limit: CLICKUP_WEBHOOK_STARTUP_COMMENT_LIMIT });
11560
11697
  for (const comment of clickUpCommentListItems(commentsResponse).slice(0, CLICKUP_WEBHOOK_STARTUP_COMMENT_LIMIT)) {
11561
11698
  const commentMs = clickUpCommentUpdatedMs(comment);
11562
- if (!commentMs || commentMs <= lastWebhookMs) continue;
11699
+ if (!commentMs || commentMs <= startupCommentStartMs) continue;
11563
11700
  const authorId = clickUpCommentAuthorId(comment);
11564
11701
  if (authorId && (authorId === config.routing.ignoredCommentAuthorId || authorId === authorizedUserId)) continue;
11565
11702
  if (!clickUpCommentMentionsProductManager(comment, config.routing)) continue;
@@ -11586,11 +11723,11 @@ async function reconcileClickUpStartup({ config, state = {}, worktree = process.
11586
11723
  await applyClickUpBlockerTag({ clickupClient, worktree, taskId, reason: "startup_reconciliation_comments_failed", source: "startup_reconciliation_comments" });
11587
11724
  }
11588
11725
  }
11589
- const emptyPromptSessions = routed.tasks.filter((task) => task.delivered === false && task.sessionId);
11726
+ const emptyPromptSessions = routed.tasks.filter((task) => task.delivered === false && task.sessionId && task.verification !== "session_running");
11590
11727
  if (emptyPromptSessions.length > 0) {
11591
11728
  appendClickUpWebhookLocalLog(worktree, { type: "startup_reconciliation_validation_failed", tasks: emptyPromptSessions });
11592
11729
  }
11593
- clickUpWebhookLifecycleLog(worktree, { type: "startup_reconciliation_finished", ...routed });
11730
+ clickUpWebhookLifecycleLog(worktree, { type: watchdogMode ? "assignment_watchdog_finished" : "startup_reconciliation_finished", ...routed });
11594
11731
  return { ok: routed.errors === 0 && routed.undelivered === 0, ...routed, validation: { undelivered: routed.undelivered, emptyPromptSessions } };
11595
11732
  }
11596
11733
  function clickUpWebhookExpectedPath(config) {
@@ -11785,17 +11922,17 @@ function startClickUpWebhookListener({ config, state, worktree, clickupClient, o
11785
11922
  return result;
11786
11923
  }
11787
11924
  function legacyVariantPath(destinationPath) {
11788
- const parsed = path5.parse(destinationPath);
11925
+ const parsed = path6.parse(destinationPath);
11789
11926
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:TZ.]/g, "").slice(0, 14);
11790
- if (parsed.ext) return path5.join(parsed.dir, `${parsed.name}.legacy-${stamp}${parsed.ext}`);
11791
- return path5.join(parsed.dir, `${parsed.base}.legacy-${stamp}`);
11927
+ if (parsed.ext) return path6.join(parsed.dir, `${parsed.name}.legacy-${stamp}${parsed.ext}`);
11928
+ return path6.join(parsed.dir, `${parsed.base}.legacy-${stamp}`);
11792
11929
  }
11793
11930
  function normalizeWorkflowTaskPath(taskPath) {
11794
11931
  if (typeof taskPath !== "string") return { ok: false, message: "Error: task_path is required." };
11795
11932
  const trimmed = taskPath.trim();
11796
11933
  if (!trimmed) return { ok: false, message: "Error: task_path is required." };
11797
11934
  const normalized = trimmed.replace(/\\/g, "/");
11798
- if (path5.isAbsolute(trimmed)) return { ok: true, taskPath: trimmed };
11935
+ if (path6.isAbsolute(trimmed)) return { ok: true, taskPath: trimmed };
11799
11936
  if (normalized === "tasks" || normalized.startsWith("tasks/")) {
11800
11937
  return {
11801
11938
  ok: false,
@@ -11814,12 +11951,12 @@ function mergeFileIntoDestination(sourcePath, destinationPath, relativeSource, g
11814
11951
  const sourceWasTracked = isGitTracked(gitState, sourcePath);
11815
11952
  if (gitAwareMoveIfTracked(sourcePath, destinationPath, gitState)) return;
11816
11953
  if (!fs5.existsSync(destinationPath)) {
11817
- fs5.mkdirSync(path5.dirname(destinationPath), { recursive: true });
11954
+ fs5.mkdirSync(path6.dirname(destinationPath), { recursive: true });
11818
11955
  fs5.renameSync(sourcePath, destinationPath);
11819
11956
  if (sourceWasTracked) stageGitAwareMerge(sourcePath, destinationPath, gitState);
11820
11957
  return;
11821
11958
  }
11822
- const ext = path5.extname(destinationPath).toLowerCase();
11959
+ const ext = path6.extname(destinationPath).toLowerCase();
11823
11960
  if ([".yaml", ".yml", ".json"].includes(ext)) {
11824
11961
  const sourceRaw = fs5.readFileSync(sourcePath, "utf8");
11825
11962
  const destRaw = fs5.readFileSync(destinationPath, "utf8");
@@ -11854,14 +11991,14 @@ ${sourceRaw}
11854
11991
  fs5.renameSync(sourcePath, preservedPath);
11855
11992
  stageGitAwareMerge(sourcePath, preservedPath, gitState);
11856
11993
  }
11857
- function mergePathIntoDestination(sourcePath, destinationPath, relativeSource = path5.basename(sourcePath), gitState = null) {
11994
+ function mergePathIntoDestination(sourcePath, destinationPath, relativeSource = path6.basename(sourcePath), gitState = null) {
11858
11995
  if (!fs5.existsSync(sourcePath)) return;
11859
11996
  const stat = fs5.statSync(sourcePath);
11860
11997
  if (stat.isDirectory()) {
11861
11998
  const sourceWasTracked = isGitTracked(gitState, sourcePath) || hasGitTrackedChildren(gitState, sourcePath);
11862
11999
  if (gitAwareMoveIfTracked(sourcePath, destinationPath, gitState)) return;
11863
12000
  if (!fs5.existsSync(destinationPath)) {
11864
- fs5.mkdirSync(path5.dirname(destinationPath), { recursive: true });
12001
+ fs5.mkdirSync(path6.dirname(destinationPath), { recursive: true });
11865
12002
  fs5.renameSync(sourcePath, destinationPath);
11866
12003
  if (sourceWasTracked) stageGitAwareMerge(sourcePath, destinationPath, gitState);
11867
12004
  return;
@@ -11869,9 +12006,9 @@ function mergePathIntoDestination(sourcePath, destinationPath, relativeSource =
11869
12006
  fs5.mkdirSync(destinationPath, { recursive: true });
11870
12007
  for (const entry of fs5.readdirSync(sourcePath)) {
11871
12008
  mergePathIntoDestination(
11872
- path5.join(sourcePath, entry),
11873
- path5.join(destinationPath, entry),
11874
- path5.join(relativeSource, entry),
12009
+ path6.join(sourcePath, entry),
12010
+ path6.join(destinationPath, entry),
12011
+ path6.join(relativeSource, entry),
11875
12012
  gitState
11876
12013
  );
11877
12014
  }
@@ -11881,7 +12018,7 @@ function mergePathIntoDestination(sourcePath, destinationPath, relativeSource =
11881
12018
  mergeFileIntoDestination(sourcePath, destinationPath, relativeSource, gitState);
11882
12019
  }
11883
12020
  function isOptimaPluginPackageWorktree(worktree) {
11884
- const packageJsonPath = path5.join(worktree, "package.json");
12021
+ const packageJsonPath = path6.join(worktree, "package.json");
11885
12022
  if (!fs5.existsSync(packageJsonPath)) return false;
11886
12023
  try {
11887
12024
  const pkg = JSON.parse(fs5.readFileSync(packageJsonPath, "utf8"));
@@ -11893,51 +12030,51 @@ function isOptimaPluginPackageWorktree(worktree) {
11893
12030
  function migrateLegacyOptimaLayout(worktree) {
11894
12031
  const gitState = gitMigrationState(worktree);
11895
12032
  const migrations = [
11896
- [path5.join(legacyOrbitaDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path5.join(".orbita", "orbita.yaml")],
11897
- [path5.join(legacyOrbitaDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path5.join(".orbita", "staticeng.yaml")],
11898
- [path5.join(legacyOrbitaDir(worktree), ".config"), optimaLocalConfigDir(worktree), path5.join(".orbita", ".config")],
11899
- [path5.join(legacyOrbitaDir(worktree), "config"), optimaLocalConfigDir(worktree), path5.join(".orbita", "config")],
11900
- [path5.join(legacyOrbitaDir(worktree), "runtime"), path5.join(optimaLocalConfigDir(worktree), "runtime"), path5.join(".orbita", "runtime")],
11901
- [path5.join(legacyOrbitaDir(worktree), "generated"), path5.join(optimaLocalConfigDir(worktree), "generated"), path5.join(".orbita", "generated")],
12033
+ [path6.join(legacyOrbitaDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path6.join(".orbita", "orbita.yaml")],
12034
+ [path6.join(legacyOrbitaDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path6.join(".orbita", "staticeng.yaml")],
12035
+ [path6.join(legacyOrbitaDir(worktree), ".config"), optimaLocalConfigDir(worktree), path6.join(".orbita", ".config")],
12036
+ [path6.join(legacyOrbitaDir(worktree), "config"), optimaLocalConfigDir(worktree), path6.join(".orbita", "config")],
12037
+ [path6.join(legacyOrbitaDir(worktree), "runtime"), path6.join(optimaLocalConfigDir(worktree), "runtime"), path6.join(".orbita", "runtime")],
12038
+ [path6.join(legacyOrbitaDir(worktree), "generated"), path6.join(optimaLocalConfigDir(worktree), "generated"), path6.join(".orbita", "generated")],
11902
12039
  [legacyOrbitaDir(worktree), optimaDir(worktree), ".orbita"],
11903
- [path5.join(legacyStaticEngDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path5.join(".staticeng", "staticeng.yaml")],
11904
- [path5.join(legacyStaticEngDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path5.join(".staticeng", "orbita.yaml")],
11905
- [path5.join(legacyStaticEngDir(worktree), ".config"), optimaLocalConfigDir(worktree), path5.join(".staticeng", ".config")],
11906
- [path5.join(legacyStaticEngDir(worktree), "config"), optimaLocalConfigDir(worktree), path5.join(".staticeng", "config")],
11907
- [path5.join(legacyStaticEngDir(worktree), "runtime"), path5.join(optimaLocalConfigDir(worktree), "runtime"), path5.join(".staticeng", "runtime")],
11908
- [path5.join(legacyStaticEngDir(worktree), "generated"), path5.join(optimaLocalConfigDir(worktree), "generated"), path5.join(".staticeng", "generated")],
12040
+ [path6.join(legacyStaticEngDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path6.join(".staticeng", "staticeng.yaml")],
12041
+ [path6.join(legacyStaticEngDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path6.join(".staticeng", "orbita.yaml")],
12042
+ [path6.join(legacyStaticEngDir(worktree), ".config"), optimaLocalConfigDir(worktree), path6.join(".staticeng", ".config")],
12043
+ [path6.join(legacyStaticEngDir(worktree), "config"), optimaLocalConfigDir(worktree), path6.join(".staticeng", "config")],
12044
+ [path6.join(legacyStaticEngDir(worktree), "runtime"), path6.join(optimaLocalConfigDir(worktree), "runtime"), path6.join(".staticeng", "runtime")],
12045
+ [path6.join(legacyStaticEngDir(worktree), "generated"), path6.join(optimaLocalConfigDir(worktree), "generated"), path6.join(".staticeng", "generated")],
11909
12046
  [legacyStaticEngDir(worktree), optimaDir(worktree), ".staticeng"],
11910
- [path5.join(legacyNomadworkDir(worktree), "nomadworks.yaml"), repoConfigPath(worktree), path5.join(".nomadwork", "nomadworks.yaml")],
11911
- [path5.join(legacyNomadworksDir(worktree), "nomadworks.yaml"), repoConfigPath(worktree), path5.join(".nomadworks", "nomadworks.yaml")],
11912
- [path5.join(legacyNomadworkDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path5.join(".nomadwork", "staticeng.yaml")],
11913
- [path5.join(legacyNomadworksDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path5.join(".nomadworks", "staticeng.yaml")],
11914
- [path5.join(legacyNomadworkDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path5.join(".nomadwork", "orbita.yaml")],
11915
- [path5.join(legacyNomadworksDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path5.join(".nomadworks", "orbita.yaml")],
11916
- [path5.join(legacyNomadworkDir(worktree), "runtime"), path5.join(optimaLocalConfigDir(worktree), "runtime"), path5.join(".nomadwork", "runtime")],
11917
- [path5.join(legacyNomadworksDir(worktree), "runtime"), path5.join(optimaLocalConfigDir(worktree), "runtime"), path5.join(".nomadworks", "runtime")],
11918
- [path5.join(legacyNomadworkDir(worktree), "generated"), path5.join(optimaLocalConfigDir(worktree), "generated"), path5.join(".nomadwork", "generated")],
11919
- [path5.join(legacyNomadworksDir(worktree), "generated"), path5.join(optimaLocalConfigDir(worktree), "generated"), path5.join(".nomadworks", "generated")],
11920
- [path5.join(legacyNomadworkDir(worktree), "config"), optimaLocalConfigDir(worktree), path5.join(".nomadwork", "config")],
11921
- [path5.join(legacyNomadworksDir(worktree), "config"), optimaLocalConfigDir(worktree), path5.join(".nomadworks", "config")],
12047
+ [path6.join(legacyNomadworkDir(worktree), "nomadworks.yaml"), repoConfigPath(worktree), path6.join(".nomadwork", "nomadworks.yaml")],
12048
+ [path6.join(legacyNomadworksDir(worktree), "nomadworks.yaml"), repoConfigPath(worktree), path6.join(".nomadworks", "nomadworks.yaml")],
12049
+ [path6.join(legacyNomadworkDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path6.join(".nomadwork", "staticeng.yaml")],
12050
+ [path6.join(legacyNomadworksDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path6.join(".nomadworks", "staticeng.yaml")],
12051
+ [path6.join(legacyNomadworkDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path6.join(".nomadwork", "orbita.yaml")],
12052
+ [path6.join(legacyNomadworksDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path6.join(".nomadworks", "orbita.yaml")],
12053
+ [path6.join(legacyNomadworkDir(worktree), "runtime"), path6.join(optimaLocalConfigDir(worktree), "runtime"), path6.join(".nomadwork", "runtime")],
12054
+ [path6.join(legacyNomadworksDir(worktree), "runtime"), path6.join(optimaLocalConfigDir(worktree), "runtime"), path6.join(".nomadworks", "runtime")],
12055
+ [path6.join(legacyNomadworkDir(worktree), "generated"), path6.join(optimaLocalConfigDir(worktree), "generated"), path6.join(".nomadwork", "generated")],
12056
+ [path6.join(legacyNomadworksDir(worktree), "generated"), path6.join(optimaLocalConfigDir(worktree), "generated"), path6.join(".nomadworks", "generated")],
12057
+ [path6.join(legacyNomadworkDir(worktree), "config"), optimaLocalConfigDir(worktree), path6.join(".nomadwork", "config")],
12058
+ [path6.join(legacyNomadworksDir(worktree), "config"), optimaLocalConfigDir(worktree), path6.join(".nomadworks", "config")],
11922
12059
  [legacyNomadworkDir(worktree), optimaDir(worktree), ".nomadwork"],
11923
12060
  [legacyNomadworksDir(worktree), optimaDir(worktree), ".nomadworks"],
11924
- [path5.join(worktree, "tasks"), optimaTasksDir(worktree), "tasks"],
11925
- [path5.join(worktree, "evidences"), optimaEvidencesDir(worktree), "evidences"],
11926
- [path5.join(worktree, "docs", "scrs"), optimaScrsDir(worktree), path5.join("docs", "scrs")],
11927
- [path5.join(worktree, "codemap.yml"), optimaCodemapPath(worktree), "codemap.yml"],
11928
- [path5.join(worktree, "codemap.yaml"), optimaCodemapPath(worktree), "codemap.yaml"]
12061
+ [path6.join(worktree, "tasks"), optimaTasksDir(worktree), "tasks"],
12062
+ [path6.join(worktree, "evidences"), optimaEvidencesDir(worktree), "evidences"],
12063
+ [path6.join(worktree, "docs", "scrs"), optimaScrsDir(worktree), path6.join("docs", "scrs")],
12064
+ [path6.join(worktree, "codemap.yml"), optimaCodemapPath(worktree), "codemap.yml"],
12065
+ [path6.join(worktree, "codemap.yaml"), optimaCodemapPath(worktree), "codemap.yaml"]
11929
12066
  ];
11930
12067
  if (!isOptimaPluginPackageWorktree(worktree)) {
11931
- migrations.push([path5.join(worktree, "policies"), repoPoliciesDir(worktree), "policies"]);
12068
+ migrations.push([path6.join(worktree, "policies"), repoPoliciesDir(worktree), "policies"]);
11932
12069
  }
11933
12070
  for (const [source, destination, relativeSource] of migrations) {
11934
12071
  if (fs5.existsSync(source)) mergePathIntoDestination(source, destination, relativeSource, gitState);
11935
12072
  }
11936
12073
  for (const [source, destination, relativeSource] of [
11937
- [path5.join(optimaDir(worktree), "optima.yaml"), repoConfigPath(worktree), path5.join(".optima", "optima.yaml")],
11938
- [path5.join(optimaDir(worktree), "config"), optimaLocalConfigDir(worktree), path5.join(".optima", "config")],
11939
- [path5.join(optimaDir(worktree), "runtime"), path5.join(optimaLocalConfigDir(worktree), "runtime"), path5.join(".optima", "runtime")],
11940
- [path5.join(optimaDir(worktree), "generated"), path5.join(optimaLocalConfigDir(worktree), "generated"), path5.join(".optima", "generated")]
12074
+ [path6.join(optimaDir(worktree), "optima.yaml"), repoConfigPath(worktree), path6.join(".optima", "optima.yaml")],
12075
+ [path6.join(optimaDir(worktree), "config"), optimaLocalConfigDir(worktree), path6.join(".optima", "config")],
12076
+ [path6.join(optimaDir(worktree), "runtime"), path6.join(optimaLocalConfigDir(worktree), "runtime"), path6.join(".optima", "runtime")],
12077
+ [path6.join(optimaDir(worktree), "generated"), path6.join(optimaLocalConfigDir(worktree), "generated"), path6.join(".optima", "generated")]
11941
12078
  ]) {
11942
12079
  if (fs5.existsSync(source)) mergePathIntoDestination(source, destination, relativeSource, gitState);
11943
12080
  }
@@ -11986,7 +12123,7 @@ function toModelString(provider, model) {
11986
12123
  }
11987
12124
  function readTaskMetadata(taskPath, worktree) {
11988
12125
  if (!taskPath) return {};
11989
- const absoluteTaskPath = path5.isAbsolute(taskPath) ? taskPath : path5.join(worktree, taskPath);
12126
+ const absoluteTaskPath = path6.isAbsolute(taskPath) ? taskPath : path6.join(worktree, taskPath);
11990
12127
  if (!fs5.existsSync(absoluteTaskPath)) return {};
11991
12128
  try {
11992
12129
  const raw = fs5.readFileSync(absoluteTaskPath, "utf8");
@@ -12031,18 +12168,18 @@ function loadDiscussionRegistry(worktree) {
12031
12168
  }
12032
12169
  function saveDiscussionRegistry(worktree, registry) {
12033
12170
  const registryPath = runtimeDiscussionRegistryPath(worktree);
12034
- const runtimeDir = path5.dirname(registryPath);
12171
+ const runtimeDir = path6.dirname(registryPath);
12035
12172
  if (!fs5.existsSync(runtimeDir)) fs5.mkdirSync(runtimeDir, { recursive: true });
12036
12173
  fs5.writeFileSync(registryPath, JSON.stringify(registry, null, 2), "utf8");
12037
12174
  }
12038
12175
  function runtimeDiscussionsDir(worktree) {
12039
- return path5.join(optimaLocalConfigDir(worktree), "runtime", "discussions");
12176
+ return path6.join(optimaLocalConfigDir(worktree), "runtime", "discussions");
12040
12177
  }
12041
12178
  function archivedRuntimeDiscussionsDir(worktree) {
12042
- return path5.join(runtimeDiscussionsDir(worktree), "archive");
12179
+ return path6.join(runtimeDiscussionsDir(worktree), "archive");
12043
12180
  }
12044
12181
  function finalDiscussionsDir(worktree) {
12045
- return path5.join(optimaTasksDir(worktree), "discussions");
12182
+ return path6.join(optimaTasksDir(worktree), "discussions");
12046
12183
  }
12047
12184
  function nextDiscussionIdentity(worktree, title) {
12048
12185
  const discussionsDir = finalDiscussionsDir(worktree);
@@ -12053,11 +12190,11 @@ function nextDiscussionIdentity(worktree, title) {
12053
12190
  while (true) {
12054
12191
  const id = `DISCUSSION-${String(sequence).padStart(3, "0")}`;
12055
12192
  const filename = `${id}-${slugifyTitle(title)}.md`;
12056
- const summaryRelativePath = path5.join(".optima", "tasks", "discussions", filename);
12057
- const summaryAbsolutePath = path5.join(worktree, summaryRelativePath);
12193
+ const summaryRelativePath = path6.join(".optima", "tasks", "discussions", filename);
12194
+ const summaryAbsolutePath = path6.join(worktree, summaryRelativePath);
12058
12195
  const transcriptFilename = `${id}-transcript.md`;
12059
- const transcriptRelativePath = path5.join(".optima", ".config", "runtime", "discussions", transcriptFilename);
12060
- const transcriptAbsolutePath = path5.join(worktree, transcriptRelativePath);
12196
+ const transcriptRelativePath = path6.join(".optima", ".config", "runtime", "discussions", transcriptFilename);
12197
+ const transcriptAbsolutePath = path6.join(worktree, transcriptRelativePath);
12061
12198
  if (!fs5.existsSync(summaryAbsolutePath) && !fs5.existsSync(transcriptAbsolutePath)) {
12062
12199
  return {
12063
12200
  id,
@@ -12082,11 +12219,11 @@ function findDiscussionById(worktree, discussionID) {
12082
12219
  return {
12083
12220
  id: discussionID,
12084
12221
  filename,
12085
- summaryRelativePath: path5.join(".optima", "tasks", "discussions", filename),
12086
- summaryAbsolutePath: path5.join(discussionsDir, filename),
12222
+ summaryRelativePath: path6.join(".optima", "tasks", "discussions", filename),
12223
+ summaryAbsolutePath: path6.join(discussionsDir, filename),
12087
12224
  transcriptFilename,
12088
- transcriptRelativePath: path5.join(".optima", ".config", "runtime", "discussions", transcriptFilename),
12089
- transcriptAbsolutePath: path5.join(runtimeDiscussionsDir(worktree), transcriptFilename)
12225
+ transcriptRelativePath: path6.join(".optima", ".config", "runtime", "discussions", transcriptFilename),
12226
+ transcriptAbsolutePath: path6.join(runtimeDiscussionsDir(worktree), transcriptFilename)
12090
12227
  };
12091
12228
  }
12092
12229
  function parseDiscussionFile(filePath) {
@@ -12169,15 +12306,15 @@ async function appendMessageIfNeeded(client, worktree, registry, sessionID, mess
12169
12306
  });
12170
12307
  const text = extractTextParts(response.data.parts || []);
12171
12308
  if (!text) return;
12172
- appendDiscussionMessage(path5.join(worktree, discussion.transcriptPath), speaker, text, messageID);
12309
+ appendDiscussionMessage(path6.join(worktree, discussion.transcriptPath), speaker, text, messageID);
12173
12310
  discussion.appendedMessageIDs ??= [];
12174
12311
  discussion.appendedMessageIDs.push(messageID);
12175
12312
  saveDiscussionRegistry(worktree, registry);
12176
12313
  }
12177
12314
  async function summarizeDiscussionWithBA(client, worktree, discussion) {
12178
- const transcriptPath = path5.join(worktree, discussion.transcriptPath);
12179
- const summaryPath = path5.join(worktree, discussion.summaryPath);
12180
- const summaryDir = path5.dirname(summaryPath);
12315
+ const transcriptPath = path6.join(worktree, discussion.transcriptPath);
12316
+ const summaryPath = path6.join(worktree, discussion.summaryPath);
12317
+ const summaryDir = path6.dirname(summaryPath);
12181
12318
  if (!fs5.existsSync(summaryDir)) fs5.mkdirSync(summaryDir, { recursive: true });
12182
12319
  const hasExistingSummary = fs5.existsSync(summaryPath);
12183
12320
  const priorMtimeMs = hasExistingSummary ? fs5.statSync(summaryPath).mtimeMs : null;
@@ -12280,11 +12417,11 @@ async function summarizeDiscussionWithBA(client, worktree, discussion) {
12280
12417
  return { confirmation, summaryPath, transcriptPath, hasExistingSummary, priorMtimeMs };
12281
12418
  }
12282
12419
  function archiveDiscussionTranscript(worktree, transcriptRelativePath) {
12283
- const sourcePath = path5.join(worktree, transcriptRelativePath);
12420
+ const sourcePath = path6.join(worktree, transcriptRelativePath);
12284
12421
  if (!fs5.existsSync(sourcePath)) return null;
12285
12422
  const archiveDir = archivedRuntimeDiscussionsDir(worktree);
12286
12423
  if (!fs5.existsSync(archiveDir)) fs5.mkdirSync(archiveDir, { recursive: true });
12287
- const targetPath = path5.join(archiveDir, path5.basename(sourcePath));
12424
+ const targetPath = path6.join(archiveDir, path6.basename(sourcePath));
12288
12425
  fs5.renameSync(sourcePath, targetPath);
12289
12426
  return targetPath;
12290
12427
  }
@@ -12303,7 +12440,7 @@ async function finalizeClosingDiscussion(client, worktree, registry, sessionID,
12303
12440
  if (!summaryContent) {
12304
12441
  throw new Error(`Discussion summary file is empty at ${discussion.summaryPath}`);
12305
12442
  }
12306
- const transcriptPath = path5.join(worktree, discussion.transcriptPath);
12443
+ const transcriptPath = path6.join(worktree, discussion.transcriptPath);
12307
12444
  setDiscussionStatus(transcriptPath, "closed");
12308
12445
  const archivedTranscriptPath = archiveDiscussionTranscript(worktree, discussion.transcriptPath);
12309
12446
  delete registry.active[sessionID];
@@ -12311,7 +12448,7 @@ async function finalizeClosingDiscussion(client, worktree, registry, sessionID,
12311
12448
  return {
12312
12449
  confirmation,
12313
12450
  summaryPath: discussion.summaryPath,
12314
- archivedTranscriptPath: archivedTranscriptPath ? path5.relative(worktree, archivedTranscriptPath) : path5.join(".optima", ".config", "runtime", "discussions", "archive", path5.basename(discussion.transcriptPath))
12451
+ archivedTranscriptPath: archivedTranscriptPath ? path6.relative(worktree, archivedTranscriptPath) : path6.join(".optima", ".config", "runtime", "discussions", "archive", path6.basename(discussion.transcriptPath))
12315
12452
  };
12316
12453
  }
12317
12454
  function normalizeTeamMode(value) {
@@ -12383,7 +12520,7 @@ function syncGeneratedPolicies(worktree, repoCfg) {
12383
12520
  if (!fs5.existsSync(generatedDir)) fs5.mkdirSync(generatedDir, { recursive: true });
12384
12521
  const policyFiles = fs5.readdirSync(BUNDLE_POLICIES_DIR).filter((file) => file.endsWith(".md") && file !== "README.md");
12385
12522
  for (const file of policyFiles) {
12386
- const sourcePath = path5.join(BUNDLE_POLICIES_DIR, file);
12523
+ const sourcePath = path6.join(BUNDLE_POLICIES_DIR, file);
12387
12524
  const source = fs5.readFileSync(sourcePath, "utf8").trimEnd();
12388
12525
  const generated = [
12389
12526
  "<!--",
@@ -12395,18 +12532,18 @@ function syncGeneratedPolicies(worktree, repoCfg) {
12395
12532
  source,
12396
12533
  ""
12397
12534
  ].join("\n");
12398
- fs5.writeFileSync(path5.join(generatedDir, file), generated, "utf8");
12535
+ fs5.writeFileSync(path6.join(generatedDir, file), generated, "utf8");
12399
12536
  }
12400
12537
  }
12401
12538
  function ensureReadmeFile(dirPath, content) {
12402
12539
  if (!fs5.existsSync(dirPath)) fs5.mkdirSync(dirPath, { recursive: true });
12403
- const readmePath = path5.join(dirPath, "README.md");
12540
+ const readmePath = path6.join(dirPath, "README.md");
12404
12541
  if (!fs5.existsSync(readmePath)) {
12405
12542
  fs5.writeFileSync(readmePath, content, "utf8");
12406
12543
  }
12407
12544
  }
12408
12545
  function ensureFileIfMissing(filePath, content) {
12409
- if (!fs5.existsSync(path5.dirname(filePath))) fs5.mkdirSync(path5.dirname(filePath), { recursive: true });
12546
+ if (!fs5.existsSync(path6.dirname(filePath))) fs5.mkdirSync(path6.dirname(filePath), { recursive: true });
12410
12547
  if (!fs5.existsSync(filePath)) fs5.writeFileSync(filePath, content, "utf8");
12411
12548
  }
12412
12549
  function currentTasksRegistryContent() {
@@ -12493,13 +12630,13 @@ Never place implementation evidence under root \`evidences/\`.
12493
12630
  }
12494
12631
  function ensureOptimaTaskTemplates(worktree) {
12495
12632
  const tasksDir = optimaTasksDir(worktree);
12496
- ensureFileIfMissing(path5.join(tasksDir, "task-template.md"), taskTemplateContent());
12497
- ensureFileIfMissing(path5.join(tasksDir, "subtask-template.md"), subtaskTemplateContent());
12633
+ ensureFileIfMissing(path6.join(tasksDir, "task-template.md"), taskTemplateContent());
12634
+ ensureFileIfMissing(path6.join(tasksDir, "subtask-template.md"), subtaskTemplateContent());
12498
12635
  }
12499
12636
  function scaffoldOptimaConfig(worktree, teamMode = "full") {
12500
12637
  const configPath = repoConfigPath(worktree);
12501
12638
  if (fs5.existsSync(configPath)) return false;
12502
- const templatePath = path5.join(TEMPLATES_DIR, "optima.yaml.template");
12639
+ const templatePath = path6.join(TEMPLATES_DIR, "optima.yaml.template");
12503
12640
  if (!fs5.existsSync(templatePath)) return false;
12504
12641
  const agentIds = fs5.existsSync(BUNDLE_AGENTS_DIR) ? fs5.readdirSync(BUNDLE_AGENTS_DIR).filter((f) => f.endsWith(".md")).map((f) => f.replace(".md", "")) : [];
12505
12642
  let optimaConfig = fs5.readFileSync(templatePath, "utf8");
@@ -12518,9 +12655,9 @@ function scaffoldOptimaConfig(worktree, teamMode = "full") {
12518
12655
  function scaffoldOptimaRootCodemap(worktree) {
12519
12656
  const rootCodemapPath = optimaCodemapPath(worktree);
12520
12657
  if (fs5.existsSync(rootCodemapPath)) return false;
12521
- const templatePath = path5.join(TEMPLATES_DIR, "codemap.yml.template");
12658
+ const templatePath = path6.join(TEMPLATES_DIR, "codemap.yml.template");
12522
12659
  if (!fs5.existsSync(templatePath)) return false;
12523
- const codemapConfig = fs5.readFileSync(templatePath, "utf8").replace("{{projectName}}", path5.basename(worktree));
12660
+ const codemapConfig = fs5.readFileSync(templatePath, "utf8").replace("{{projectName}}", path6.basename(worktree));
12524
12661
  ensureFileIfMissing(rootCodemapPath, codemapConfig);
12525
12662
  return fs5.existsSync(rootCodemapPath);
12526
12663
  }
@@ -12529,10 +12666,10 @@ function ensureOptimaRegistries(worktree) {
12529
12666
  const scrsDir = optimaScrsDir(worktree);
12530
12667
  if (!fs5.existsSync(tasksDir)) fs5.mkdirSync(tasksDir, { recursive: true });
12531
12668
  if (!fs5.existsSync(scrsDir)) fs5.mkdirSync(scrsDir, { recursive: true });
12532
- ensureFileIfMissing(path5.join(tasksDir, "current.md"), currentTasksRegistryContent());
12533
- ensureFileIfMissing(path5.join(tasksDir, "done.md"), doneTasksRegistryContent());
12534
- ensureFileIfMissing(path5.join(scrsDir, "current.md"), currentScrRegistryContent());
12535
- ensureFileIfMissing(path5.join(scrsDir, "done.md"), doneScrRegistryContent());
12669
+ ensureFileIfMissing(path6.join(tasksDir, "current.md"), currentTasksRegistryContent());
12670
+ ensureFileIfMissing(path6.join(tasksDir, "done.md"), doneTasksRegistryContent());
12671
+ ensureFileIfMissing(path6.join(scrsDir, "current.md"), currentScrRegistryContent());
12672
+ ensureFileIfMissing(path6.join(scrsDir, "done.md"), doneScrRegistryContent());
12536
12673
  }
12537
12674
  function scaffoldOptimaReadmes(worktree) {
12538
12675
  ensureReadmeFile(repoPoliciesDir(worktree), REPO_LOCAL_POLICIES_README);
@@ -12694,12 +12831,12 @@ function shouldRegisterWorkflowProductManager(options = {}, worktree = process.c
12694
12831
  }
12695
12832
  function isClickUpDerivedWorktreeSibling(candidate, basePath) {
12696
12833
  if (typeof candidate !== "string" || typeof basePath !== "string" || !candidate.trim() || !basePath.trim()) return false;
12697
- const resolvedCandidate = path5.resolve(candidate);
12698
- const resolvedBase = path5.resolve(basePath);
12699
- const baseParent = path5.dirname(resolvedBase);
12700
- if (path5.dirname(resolvedCandidate) !== baseParent) return false;
12701
- const baseName = path5.basename(resolvedBase);
12702
- const candidateName = path5.basename(resolvedCandidate);
12834
+ const resolvedCandidate = path6.resolve(candidate);
12835
+ const resolvedBase = path6.resolve(basePath);
12836
+ const baseParent = path6.dirname(resolvedBase);
12837
+ if (path6.dirname(resolvedCandidate) !== baseParent) return false;
12838
+ const baseName = path6.basename(resolvedBase);
12839
+ const candidateName = path6.basename(resolvedCandidate);
12703
12840
  if (!candidateName.startsWith(`${baseName}-`)) return false;
12704
12841
  const branchSlug = candidateName.slice(baseName.length + 1);
12705
12842
  const parts = branchSlug.split("-").filter(Boolean);
@@ -12711,7 +12848,7 @@ function isClickUpDerivedWorktreeSibling(candidate, basePath) {
12711
12848
  if (!candidateStat.isDirectory() || candidateStat.isSymbolicLink()) return false;
12712
12849
  const realCandidate = fs5.realpathSync.native(resolvedCandidate);
12713
12850
  const realBaseParent = fs5.realpathSync.native(baseParent);
12714
- return path5.dirname(realCandidate) === realBaseParent && path5.basename(realCandidate) === candidateName;
12851
+ return path6.dirname(realCandidate) === realBaseParent && path6.basename(realCandidate) === candidateName;
12715
12852
  } catch {
12716
12853
  return false;
12717
12854
  }
@@ -12719,15 +12856,15 @@ function isClickUpDerivedWorktreeSibling(candidate, basePath) {
12719
12856
  function resolveSessionToolDirectory({ requestedDirectory, context, pluginWorktree, clickUpWebhookValidation } = {}) {
12720
12857
  const safe = safeWorktreeOrFailure(context, pluginWorktree);
12721
12858
  if (!safe.ok) return { ok: false, error: safe.message };
12722
- const requested = String(requestedDirectory || "").trim() ? path5.resolve(safe.worktree, String(requestedDirectory).trim()) : safe.worktree;
12859
+ const requested = String(requestedDirectory || "").trim() ? path6.resolve(safe.worktree, String(requestedDirectory).trim()) : safe.worktree;
12723
12860
  if (!isSafeWritableDirectory(requested)) return { ok: false, error: `Directory is not a safe writable directory: ${requested}` };
12724
12861
  if (isSameOrNestedPath(requested, safe.worktree)) return { ok: true, directory: requested, safeWorktree: safe.worktree, scope: "context_worktree" };
12725
12862
  const clickUpBasePath = clickUpWebhookValidation?.complete === true && clickUpWebhookValidation?.ok !== false ? clickUpWebhookValidation.config?.basePath : "";
12726
12863
  if (clickUpBasePath && isSameOrNestedPath(requested, clickUpBasePath)) {
12727
- return { ok: true, directory: requested, safeWorktree: safe.worktree, scope: "clickup_base_path", clickupBasePath: path5.resolve(clickUpBasePath) };
12864
+ return { ok: true, directory: requested, safeWorktree: safe.worktree, scope: "clickup_base_path", clickupBasePath: path6.resolve(clickUpBasePath) };
12728
12865
  }
12729
12866
  if (clickUpBasePath && isClickUpDerivedWorktreeSibling(requested, clickUpBasePath)) {
12730
- return { ok: true, directory: requested, safeWorktree: safe.worktree, scope: "clickup_derived_worktree", clickupBasePath: path5.resolve(clickUpBasePath) };
12867
+ return { ok: true, directory: requested, safeWorktree: safe.worktree, scope: "clickup_derived_worktree", clickupBasePath: path6.resolve(clickUpBasePath) };
12731
12868
  }
12732
12869
  return {
12733
12870
  ok: false,
@@ -12761,8 +12898,8 @@ function buildOptimaAgents(repoCfg, operatingTeamMode, worktree, debugDir, optio
12761
12898
  if (!enabled) continue;
12762
12899
  }
12763
12900
  const promptOptions = { preferCompactPromptDocs: repoCfg.features?.compact_prompt_docs !== false };
12764
- const bundledDefinition = loadAgentDefinition(path5.join(BUNDLE_AGENTS_DIR, file), worktree, promptOptions);
12765
- const repoDefinition = loadAgentDefinition(path5.join(repoAgentDefinitions, file), worktree, promptOptions) || loadAgentDefinition(path5.join(legacyAgentsDir, file), worktree, promptOptions);
12901
+ const bundledDefinition = loadAgentDefinition(path6.join(BUNDLE_AGENTS_DIR, file), worktree, promptOptions);
12902
+ const repoDefinition = loadAgentDefinition(path6.join(repoAgentDefinitions, file), worktree, promptOptions) || loadAgentDefinition(path6.join(legacyAgentsDir, file), worktree, promptOptions);
12766
12903
  const activeDefinition = repoDefinition || bundledDefinition;
12767
12904
  if (!activeDefinition) continue;
12768
12905
  const { data } = activeDefinition;
@@ -12771,7 +12908,7 @@ function buildOptimaAgents(repoCfg, operatingTeamMode, worktree, debugDir, optio
12771
12908
  if (modePromptFragment) finalPrompt = `${finalPrompt}
12772
12909
 
12773
12910
  ${modePromptFragment}`;
12774
- const additionFragment = loadMarkdownFragment(path5.join(repoAgentAdditions, file), worktree);
12911
+ const additionFragment = loadMarkdownFragment(path6.join(repoAgentAdditions, file), worktree);
12775
12912
  if (additionFragment) {
12776
12913
  finalPrompt = `${finalPrompt}
12777
12914
 
@@ -12824,7 +12961,7 @@ Use this Optima-provided fallback when the current task worktree lacks docs/core
12824
12961
  }
12825
12962
  ourAgents[id] = agentConfig;
12826
12963
  if (repoCfg.features?.debug_dumps !== false) {
12827
- const debugPath = path5.join(debugDir, `${id}.md`);
12964
+ const debugPath = path6.join(debugDir, `${id}.md`);
12828
12965
  const { prompt, ...dumpConfig } = agentConfig;
12829
12966
  const debugHeader = `---
12830
12967
  ${import_yaml3.default.stringify(dumpConfig).trim()}
@@ -12904,7 +13041,17 @@ async function OptimaPlugin(input = {}, pluginOptions = {}) {
12904
13041
  ...listenerState,
12905
13042
  listener: { bindHost: clickUpWebhookValidation.config.webhook.bindHost, bindPort: clickUpWebhookValidation.config.webhook.bindPort, startedAt: (/* @__PURE__ */ new Date()).toISOString() }
12906
13043
  }, clickUpWebhookValidation.config);
12907
- registerClickUpWebhookLifecycle({ config: clickUpWebhookValidation.config, state: activeState, worktree, clickupClient: lifecycleClickUpClient, listener: readyListener, listenerRegistry });
13044
+ const assignmentWatchdog = scheduleClickUpAssignmentWatchdog({
13045
+ config: clickUpWebhookValidation.config,
13046
+ state: activeState,
13047
+ worktree,
13048
+ clickupClient: lifecycleClickUpClient,
13049
+ openCodeClient: input.client,
13050
+ scheduler: input.assignmentWatchdogScheduler,
13051
+ intervalMs: input.assignmentWatchdogIntervalMs,
13052
+ saveState: (nextState) => writeClickUpWebhookState(worktree, nextState, clickUpWebhookValidation.config)
13053
+ });
13054
+ registerClickUpWebhookLifecycle({ config: clickUpWebhookValidation.config, state: activeState, worktree, clickupClient: lifecycleClickUpClient, listener: readyListener, listenerRegistry, assignmentWatchdog });
12908
13055
  scheduleClickUpStartupReconciliation({
12909
13056
  config: clickUpWebhookValidation.config,
12910
13057
  state: activeState,
@@ -12966,8 +13113,8 @@ async function OptimaPlugin(input = {}, pluginOptions = {}) {
12966
13113
  migrateLegacyOptimaLayout(toolWorktree);
12967
13114
  const cfgDir = optimaConfigDir(toolWorktree);
12968
13115
  if (!fs5.existsSync(cfgDir)) fs5.mkdirSync(cfgDir, { recursive: true });
12969
- const optimaTmplPath = path5.join(TEMPLATES_DIR, "optima.yaml.template");
12970
- const codemapTmplPath = path5.join(TEMPLATES_DIR, "codemap.yml.template");
13116
+ const optimaTmplPath = path6.join(TEMPLATES_DIR, "optima.yaml.template");
13117
+ const codemapTmplPath = path6.join(TEMPLATES_DIR, "codemap.yml.template");
12971
13118
  if (!fs5.existsSync(optimaTmplPath) || !fs5.existsSync(codemapTmplPath)) {
12972
13119
  return "Error: Initialization templates not found in plugin.";
12973
13120
  }
@@ -13089,14 +13236,14 @@ Restart or reload OpenCode manually if the newly scaffolded config or agents are
13089
13236
  async execute(args, context) {
13090
13237
  const safe = safeWorktreeOrFailure(context, worktree);
13091
13238
  if (!safe.ok) return safe.message;
13092
- const summaryPath = path5.resolve(safe.worktree, args.summary_path || "");
13239
+ const summaryPath = path6.resolve(safe.worktree, args.summary_path || "");
13093
13240
  if (!fs5.existsSync(summaryPath)) return `FAIL: summary_path not found: ${summaryPath}`;
13094
- const taskPath = args.task_path ? path5.resolve(safe.worktree, args.task_path) : "";
13241
+ const taskPath = args.task_path ? path6.resolve(safe.worktree, args.task_path) : "";
13095
13242
  const payload = buildClickUpSummaryPayload({
13096
13243
  summaryMarkdown: fs5.readFileSync(summaryPath, "utf8"),
13097
- summaryPath: path5.relative(safe.worktree, summaryPath),
13244
+ summaryPath: path6.relative(safe.worktree, summaryPath),
13098
13245
  taskMarkdown: taskPath && fs5.existsSync(taskPath) ? fs5.readFileSync(taskPath, "utf8") : "",
13099
- taskPath: taskPath ? path5.relative(safe.worktree, taskPath) : "",
13246
+ taskPath: taskPath ? path6.relative(safe.worktree, taskPath) : "",
13100
13247
  branch: args.branch,
13101
13248
  worktree: args.worktree,
13102
13249
  pr: args.pr
@@ -13175,12 +13322,12 @@ Restart or reload OpenCode manually if the newly scaffolded config or agents are
13175
13322
  async execute(args, context) {
13176
13323
  const safe = safeWorktreeOrFailure(context, worktree);
13177
13324
  if (!safe.ok) return safe.message;
13178
- const markdownPath = path5.resolve(safe.worktree, args.markdown_path || "");
13325
+ const markdownPath = path6.resolve(safe.worktree, args.markdown_path || "");
13179
13326
  if (!fs5.existsSync(markdownPath)) return `FAIL: markdown_path not found: ${markdownPath}`;
13180
13327
  const payload = buildClickUpCreateSubtasksPayload({
13181
13328
  parentTaskId: args.parent_task_id,
13182
13329
  markdown: fs5.readFileSync(markdownPath, "utf8"),
13183
- sourcePath: path5.relative(safe.worktree, markdownPath),
13330
+ sourcePath: path6.relative(safe.worktree, markdownPath),
13184
13331
  parentBranch: args.parent_branch,
13185
13332
  parentTaskType: args.parent_task_type || "Tarea",
13186
13333
  apply: String(args.apply || "").toLowerCase() === "true"
@@ -13379,7 +13526,7 @@ Backfilled messages: ${backfilled}`;
13379
13526
  if (!existing) {
13380
13527
  return "FAIL: No active discussion exists for this session.";
13381
13528
  }
13382
- const discussionPath = path5.join(toolWorktree, existing.transcriptPath);
13529
+ const discussionPath = path6.join(toolWorktree, existing.transcriptPath);
13383
13530
  setDiscussionStatus(discussionPath, "summarizing");
13384
13531
  existing.status = "summarizing";
13385
13532
  saveDiscussionRegistry(toolWorktree, toolRegistry);
@@ -13431,7 +13578,7 @@ Reason: ${err.message}`;
13431
13578
  try {
13432
13579
  const sessionResult = await client.session.create({
13433
13580
  query: { directory: workflowDirectory },
13434
- body: { title: `Workflow Run: ${path5.basename(workflowTaskPath)}` }
13581
+ body: { title: `Workflow Run: ${path6.basename(workflowTaskPath)}` }
13435
13582
  });
13436
13583
  const sessionId = sessionResult.data.id;
13437
13584
  activeWorkflows.set(sessionId, { pmaSessionId, taskPath: workflowTaskPath, track: workflowTrack, directory: workflowDirectory });
@@ -13560,7 +13707,7 @@ Follow-up: use optima_prompt_workflow with session_id '${sessionId}' to check in
13560
13707
  }
13561
13708
  };
13562
13709
  }
13563
- OptimaPlugin.__internals = { BUNDLE_AGENTS_DIR, BUNDLE_ASSETS_DIR, CLICKUP_DEFINITION_DOC_PARENT, activeClickUpWebhookLifecycleRegistry, cleanupManagedClickUpWebhook, deleteClickUpWebhookBestEffort, BUNDLE_POLICIES_DIR, buildClickUpApplyPayloadResult, buildClickUpCreateSubtasksPayload, buildClickUpStartTaskPayload, buildClickUpSummaryPayload, buildClickUpTransitionPayload, buildOptimaAgents, clickUpCommentLedgerKey, clickUpCommentMentionsProductManager, clickUpWebhookAuditLogDir, clickUpWebhookAuditLogPath, compactPromptPath, createClickUpApiClient, createTestClickUpApiClient, createOpenCodeSession, createOpenCodeSessionControl, deliveryEvidencePathForClickUpTask, ensureClickUpTaskWorktree, ensureClickUpTaskWorktreeForWebhook, ensureClickUpTaskWorktreeOpenChamber, ensureClickUpWebhookSubscription, handleClickUpWebhookRequest, isClickUpDerivedWorktreeSibling, isClickUpSubtaskRoute, isClickUpWebhookStateActive, isSameOrNestedPath, normalizeClickUpWebhookConfig, normalizeClickUpWebhookLogLevel, normalizeOpenCodeBaseUrl, openCodeSessionExists, promptOpenCodeSessionControl, probeOpenCodeSessionControl, readClickUpCommentLedger, readClickUpWebhookState, readOpenCodeSessionControl, readOpenCodeSessionMessages, reconcileClickUpStartup, registerOpenChamberClickUpWorktree, scheduleClickUpStartupReconciliation, syncOpenChamberWorktreeVisibility, waitForOpenCodeReadiness, recordClickUpCommentVersionProcessed, resyncClickUpWebhookForSignatureDrift, resolveIncludeFile, resolveIncludes, resolveOptimaPluginOptions, resolveSecretReference, routeClickUpWebhookEvent, sendOpenCodeSessionEvent, sendOpenCodeSessionEventDirect, summarizeOpenCodeMessages, verifyOpenCodeSessionEventDelivery, stableClickUpCommentVersionMarker, startClickUpWebhookListener, validateClickUpWebhookState, verifyClickUpSignature, writeClickUpWebhookState, decideClickUpStatusAction, deriveClickUpBranchName, deriveClickUpPendingSubtaskBranch, deriveClickUpPrTarget, deriveClickUpWorktree, determineClickUpMergeAuthority, ensureOptimaGitignoreRules, explicitSafeInputWorktree, finalApprovalAssignees, formatRepairResult, formatValidationResult, isIgnoredClickUpTaskType, isOptimaPluginPackageWorktree, isSafeWritableDirectory, loadHumansRegistry, mergeClickUpAgentMetadata, mergeClickUpSessionMetadata, migrateLegacyOptimaLayout, normalizeAgentMetadataJson, normalizeClickUpStatus, normalizeClickUpTaskType, normalizePromptResponseParts, normalizeWorkflowTaskPath, optimaRepairDependencies, parseClickUpSubtasksMarkdown, parseHumansRegistry, parseMarkdownArtifact, parseMarkdownSections, planOptimaRepair, preEstimateClickUpWork, readMarkdownArtifact, resolveHumanRoles, resolveSafeWorktree, safeWorktreeOrFailure, stripRawLogSections, validateMainWorkspaceBranchSafety, workflowFinalMessageFromPromptResponse };
13710
+ OptimaPlugin.__internals = { BUNDLE_AGENTS_DIR, BUNDLE_ASSETS_DIR, CLICKUP_DEFINITION_DOC_PARENT, activeClickUpWebhookLifecycleRegistry, cleanupManagedClickUpWebhook, deleteClickUpWebhookBestEffort, BUNDLE_POLICIES_DIR, buildClickUpApplyPayloadResult, buildClickUpCreateSubtasksPayload, buildClickUpStartTaskPayload, buildClickUpSummaryPayload, buildClickUpTransitionPayload, buildOptimaAgents, clickUpCommentLedgerKey, clickUpCommentMentionsProductManager, clickUpWebhookAuditLogDir, clickUpWebhookAuditLogPath, compactPromptPath, createClickUpApiClient, createTestClickUpApiClient, createOpenCodeSession, createOpenCodeSessionControl, deliveryEvidencePathForClickUpTask, ensureClickUpTaskWorktree, ensureClickUpTaskWorktreeForWebhook, ensureClickUpTaskWorktreeOpenChamber, ensureClickUpWebhookSubscription, handleClickUpWebhookRequest, inspectOpenCodeSessionActivity, isClickUpDerivedWorktreeSibling, isClickUpSubtaskRoute, isClickUpWebhookStateActive, isSameOrNestedPath, normalizeClickUpWebhookConfig, normalizeClickUpWebhookLogLevel, normalizeOpenCodeBaseUrl, openCodeSessionExists, promptOpenCodeSessionControl, probeOpenCodeSessionControl, readClickUpCommentLedger, readClickUpWebhookState, readOpenCodeSessionControl, readOpenCodeSessionMessages, reconcileClickUpStartup, registerOpenChamberClickUpWorktree, scheduleClickUpAssignmentWatchdog, scheduleClickUpStartupReconciliation, syncOpenChamberWorktreeVisibility, waitForOpenCodeReadiness, recordClickUpCommentVersionProcessed, resyncClickUpWebhookForSignatureDrift, resolveIncludeFile, resolveIncludes, resolveOptimaPluginOptions, resolveSecretReference, routeClickUpWebhookEvent, sendOpenCodeSessionEvent, sendOpenCodeSessionEventDirect, summarizeOpenCodeMessages, verifyOpenCodeSessionEventDelivery, stableClickUpCommentVersionMarker, startClickUpWebhookListener, validateClickUpWebhookState, verifyClickUpSignature, writeClickUpWebhookState, decideClickUpStatusAction, deriveClickUpBranchName, deriveClickUpPendingSubtaskBranch, deriveClickUpPrTarget, deriveClickUpWorktree, determineClickUpMergeAuthority, ensureOptimaGitignoreRules, explicitSafeInputWorktree, finalApprovalAssignees, formatRepairResult, formatValidationResult, isIgnoredClickUpTaskType, isOptimaPluginPackageWorktree, isSafeWritableDirectory, loadHumansRegistry, mergeClickUpAgentMetadata, mergeClickUpSessionMetadata, migrateLegacyOptimaLayout, normalizeAgentMetadataJson, normalizeClickUpStatus, normalizeClickUpTaskType, normalizePromptResponseParts, normalizeWorkflowTaskPath, optimaRepairDependencies, parseClickUpSubtasksMarkdown, parseHumansRegistry, parseMarkdownArtifact, parseMarkdownSections, planOptimaRepair, preEstimateClickUpWork, readMarkdownArtifact, resolveHumanRoles, resolveSafeWorktree, safeWorktreeOrFailure, stripRawLogSections, validateMainWorkspaceBranchSafety, workflowFinalMessageFromPromptResponse };
13564
13711
 
13565
13712
  // src/sanitize_cli.js
13566
13713
  var { migrateLegacyOptimaLayout: migrateLegacyOptimaLayout2 } = OptimaPlugin.__internals;
@@ -13616,13 +13763,13 @@ function usage() {
13616
13763
  }
13617
13764
  function expandHome(inputPath) {
13618
13765
  if (!inputPath || inputPath === "~") return os2.homedir();
13619
- if (inputPath.startsWith("~/")) return path6.join(os2.homedir(), inputPath.slice(2));
13766
+ if (inputPath.startsWith("~/")) return path7.join(os2.homedir(), inputPath.slice(2));
13620
13767
  return inputPath;
13621
13768
  }
13622
13769
  function resolveOpenCodeDbPath(inputPath = null) {
13623
13770
  const expanded = expandHome(inputPath || process.env.OPTIMA_OPENCODE_DB_PATH || DEFAULT_DB_PATH);
13624
13771
  try {
13625
- if (fs6.existsSync(expanded) && fs6.statSync(expanded).isDirectory()) return path6.join(expanded, "opencode.db");
13772
+ if (fs6.existsSync(expanded) && fs6.statSync(expanded).isDirectory()) return path7.join(expanded, "opencode.db");
13626
13773
  } catch {
13627
13774
  return expanded;
13628
13775
  }
@@ -13686,8 +13833,8 @@ function extractOpenedPathValue(value) {
13686
13833
  }
13687
13834
  function normalizePathCandidate(candidate) {
13688
13835
  const expanded = expandHome(candidate);
13689
- if (!path6.isAbsolute(expanded)) return null;
13690
- return path6.resolve(expanded);
13836
+ if (!path7.isAbsolute(expanded)) return null;
13837
+ return path7.resolve(expanded);
13691
13838
  }
13692
13839
  function discoverOpenCodePaths(dbPath) {
13693
13840
  const resolvedDb = resolveOpenCodeDbPath(dbPath);
@@ -13716,27 +13863,27 @@ function discoverOpenCodePaths(dbPath) {
13716
13863
  function collectMarkdownOverridesFrom(baseDir) {
13717
13864
  const files = [];
13718
13865
  for (const dirName of OVERRIDE_DIRS) {
13719
- const dirPath = path6.join(baseDir, dirName);
13866
+ const dirPath = path7.join(baseDir, dirName);
13720
13867
  if (!fs6.existsSync(dirPath)) continue;
13721
13868
  for (const entry of fs6.readdirSync(dirPath, { withFileTypes: true })) {
13722
13869
  if (!entry.isFile()) continue;
13723
13870
  if (!entry.name.endsWith(".md")) continue;
13724
13871
  if (entry.name.toLowerCase() === "readme.md") continue;
13725
- files.push(path6.join(dirPath, entry.name));
13872
+ files.push(path7.join(dirPath, entry.name));
13726
13873
  }
13727
13874
  }
13728
13875
  return files;
13729
13876
  }
13730
13877
  function collectOverrideFiles(worktree) {
13731
- return collectMarkdownOverridesFrom(path6.join(worktree, ".optima")).sort();
13878
+ return collectMarkdownOverridesFrom(path7.join(worktree, ".optima")).sort();
13732
13879
  }
13733
13880
  function collectPlannedOverrideFiles(worktree) {
13734
13881
  return [
13735
13882
  ...collectOverrideFiles(worktree),
13736
- ...collectMarkdownOverridesFrom(path6.join(worktree, ".staticeng")),
13737
- ...collectMarkdownOverridesFrom(path6.join(worktree, ".orbita")),
13738
- ...collectMarkdownOverridesFrom(path6.join(worktree, ".nomadwork")),
13739
- ...collectMarkdownOverridesFrom(path6.join(worktree, ".nomadworks"))
13883
+ ...collectMarkdownOverridesFrom(path7.join(worktree, ".staticeng")),
13884
+ ...collectMarkdownOverridesFrom(path7.join(worktree, ".orbita")),
13885
+ ...collectMarkdownOverridesFrom(path7.join(worktree, ".nomadwork")),
13886
+ ...collectMarkdownOverridesFrom(path7.join(worktree, ".nomadworks"))
13740
13887
  ].sort();
13741
13888
  }
13742
13889
  var CRC_TABLE = (() => {
@@ -13769,14 +13916,14 @@ function writeUInt16LE(value) {
13769
13916
  return buffer;
13770
13917
  }
13771
13918
  function createZipBackup(files, backupPath) {
13772
- fs6.mkdirSync(path6.dirname(backupPath), { recursive: true });
13919
+ fs6.mkdirSync(path7.dirname(backupPath), { recursive: true });
13773
13920
  const localParts = [];
13774
13921
  const centralParts = [];
13775
13922
  let offset = 0;
13776
13923
  const now = dosTimeDate();
13777
13924
  for (const filePath of files) {
13778
13925
  const data = fs6.readFileSync(filePath);
13779
- const name = path6.resolve(filePath).replace(/^\//, "").split(path6.sep).join("/");
13926
+ const name = path7.resolve(filePath).replace(/^\//, "").split(path7.sep).join("/");
13780
13927
  const nameBuffer = Buffer.from(name, "utf8");
13781
13928
  const crc = crc32(data);
13782
13929
  const local = Buffer.concat([
@@ -13838,15 +13985,15 @@ function validationStatus(result) {
13838
13985
  return result.ok ? "passed" : "failed";
13839
13986
  }
13840
13987
  function hasLegacyMarker(worktree) {
13841
- return fs6.existsSync(path6.join(worktree, ".staticeng")) || fs6.existsSync(path6.join(worktree, ".orbita")) || fs6.existsSync(path6.join(worktree, ".nomadwork")) || fs6.existsSync(path6.join(worktree, ".nomadworks"));
13988
+ 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"));
13842
13989
  }
13843
13990
  function rootOptimaArtifacts(worktree) {
13844
13991
  const artifacts = [
13845
- ["tasks/", path6.join(worktree, "tasks")],
13846
- ["evidences/", path6.join(worktree, "evidences")],
13847
- ["docs/scrs/", path6.join(worktree, "docs", "scrs")],
13848
- ["codemap.yml", path6.join(worktree, "codemap.yml")],
13849
- ["codemap.yaml", path6.join(worktree, "codemap.yaml")]
13992
+ ["tasks/", path7.join(worktree, "tasks")],
13993
+ ["evidences/", path7.join(worktree, "evidences")],
13994
+ ["docs/scrs/", path7.join(worktree, "docs", "scrs")],
13995
+ ["codemap.yml", path7.join(worktree, "codemap.yml")],
13996
+ ["codemap.yaml", path7.join(worktree, "codemap.yaml")]
13850
13997
  ];
13851
13998
  return artifacts.map(([display, artifactPath]) => ({ display, path: artifactPath })).filter((item) => fs6.existsSync(item.path));
13852
13999
  }
@@ -13874,7 +14021,7 @@ function planOptimaMigration(worktree, dryRun) {
13874
14021
  ...overrides.map((file) => ({
13875
14022
  category: "override",
13876
14023
  action: dryRun ? "would_remove_after_backup" : "removed_after_backup",
13877
- path: path6.relative(worktree, file).split(path6.sep).join("/"),
14024
+ path: path7.relative(worktree, file).split(path7.sep).join("/"),
13878
14025
  detail: "Remove implicit agent/policy override after host-level backup."
13879
14026
  }))
13880
14027
  ],
@@ -13922,7 +14069,7 @@ async function sanitizeHost(options = {}) {
13922
14069
  const overrides = repoStates.flatMap((state) => state.overrideFiles.map((file) => ({ repo: state.repo, file })));
13923
14070
  report.totals.overrideFiles = overrides.length;
13924
14071
  if (!dryRun && overrides.length > 0) {
13925
- const backupPath = path6.join(os2.homedir(), BACKUP_DIRNAME, `${timestamp()}.zip`);
14072
+ const backupPath = path7.join(os2.homedir(), BACKUP_DIRNAME, `${timestamp()}.zip`);
13926
14073
  try {
13927
14074
  createZipBackup(overrides.map((item) => item.file), backupPath);
13928
14075
  report.backupPath = backupPath;
@@ -13951,7 +14098,7 @@ async function sanitizeHost(options = {}) {
13951
14098
  repairActions: state.plan.actions.length,
13952
14099
  repairSkipped: state.plan.skippedRepair === true,
13953
14100
  overrideFiles: state.overrideFiles.length,
13954
- overridePaths: state.overrideFiles.map((file) => path6.relative(state.repo, file).split(path6.sep).join("/")),
14101
+ overridePaths: state.overrideFiles.map((file) => path7.relative(state.repo, file).split(path7.sep).join("/")),
13955
14102
  validation: validation ? validationStatus(validation) : "skipped",
13956
14103
  unresolved: state.plan.unresolved
13957
14104
  });