@defend-tech/opencode-optima 0.1.54 → 0.1.56

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -108,17 +108,17 @@ var require_visit = __commonJS({
108
108
  visit.BREAK = BREAK;
109
109
  visit.SKIP = SKIP;
110
110
  visit.REMOVE = REMOVE;
111
- function visit_(key, node, visitor, path3) {
112
- const ctrl = callVisitor(key, node, visitor, path3);
111
+ function visit_(key, node, visitor, path6) {
112
+ const ctrl = callVisitor(key, node, visitor, path6);
113
113
  if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
114
- replaceNode(key, path3, ctrl);
115
- return visit_(key, ctrl, visitor, path3);
114
+ replaceNode(key, path6, ctrl);
115
+ return visit_(key, ctrl, visitor, path6);
116
116
  }
117
117
  if (typeof ctrl !== "symbol") {
118
118
  if (identity.isCollection(node)) {
119
- path3 = Object.freeze(path3.concat(node));
119
+ path6 = Object.freeze(path6.concat(node));
120
120
  for (let i = 0; i < node.items.length; ++i) {
121
- const ci = visit_(i, node.items[i], visitor, path3);
121
+ const ci = visit_(i, node.items[i], visitor, path6);
122
122
  if (typeof ci === "number")
123
123
  i = ci - 1;
124
124
  else if (ci === BREAK)
@@ -129,13 +129,13 @@ var require_visit = __commonJS({
129
129
  }
130
130
  }
131
131
  } else if (identity.isPair(node)) {
132
- path3 = Object.freeze(path3.concat(node));
133
- const ck = visit_("key", node.key, visitor, path3);
132
+ path6 = Object.freeze(path6.concat(node));
133
+ const ck = visit_("key", node.key, visitor, path6);
134
134
  if (ck === BREAK)
135
135
  return BREAK;
136
136
  else if (ck === REMOVE)
137
137
  node.key = null;
138
- const cv = visit_("value", node.value, visitor, path3);
138
+ const cv = visit_("value", node.value, visitor, path6);
139
139
  if (cv === BREAK)
140
140
  return BREAK;
141
141
  else if (cv === REMOVE)
@@ -156,17 +156,17 @@ var require_visit = __commonJS({
156
156
  visitAsync.BREAK = BREAK;
157
157
  visitAsync.SKIP = SKIP;
158
158
  visitAsync.REMOVE = REMOVE;
159
- async function visitAsync_(key, node, visitor, path3) {
160
- const ctrl = await callVisitor(key, node, visitor, path3);
159
+ async function visitAsync_(key, node, visitor, path6) {
160
+ const ctrl = await callVisitor(key, node, visitor, path6);
161
161
  if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
162
- replaceNode(key, path3, ctrl);
163
- return visitAsync_(key, ctrl, visitor, path3);
162
+ replaceNode(key, path6, ctrl);
163
+ return visitAsync_(key, ctrl, visitor, path6);
164
164
  }
165
165
  if (typeof ctrl !== "symbol") {
166
166
  if (identity.isCollection(node)) {
167
- path3 = Object.freeze(path3.concat(node));
167
+ path6 = Object.freeze(path6.concat(node));
168
168
  for (let i = 0; i < node.items.length; ++i) {
169
- const ci = await visitAsync_(i, node.items[i], visitor, path3);
169
+ const ci = await visitAsync_(i, node.items[i], visitor, path6);
170
170
  if (typeof ci === "number")
171
171
  i = ci - 1;
172
172
  else if (ci === BREAK)
@@ -177,13 +177,13 @@ var require_visit = __commonJS({
177
177
  }
178
178
  }
179
179
  } else if (identity.isPair(node)) {
180
- path3 = Object.freeze(path3.concat(node));
181
- const ck = await visitAsync_("key", node.key, visitor, path3);
180
+ path6 = Object.freeze(path6.concat(node));
181
+ const ck = await visitAsync_("key", node.key, visitor, path6);
182
182
  if (ck === BREAK)
183
183
  return BREAK;
184
184
  else if (ck === REMOVE)
185
185
  node.key = null;
186
- const cv = await visitAsync_("value", node.value, visitor, path3);
186
+ const cv = await visitAsync_("value", node.value, visitor, path6);
187
187
  if (cv === BREAK)
188
188
  return BREAK;
189
189
  else if (cv === REMOVE)
@@ -210,23 +210,23 @@ var require_visit = __commonJS({
210
210
  }
211
211
  return visitor;
212
212
  }
213
- function callVisitor(key, node, visitor, path3) {
213
+ function callVisitor(key, node, visitor, path6) {
214
214
  if (typeof visitor === "function")
215
- return visitor(key, node, path3);
215
+ return visitor(key, node, path6);
216
216
  if (identity.isMap(node))
217
- return visitor.Map?.(key, node, path3);
217
+ return visitor.Map?.(key, node, path6);
218
218
  if (identity.isSeq(node))
219
- return visitor.Seq?.(key, node, path3);
219
+ return visitor.Seq?.(key, node, path6);
220
220
  if (identity.isPair(node))
221
- return visitor.Pair?.(key, node, path3);
221
+ return visitor.Pair?.(key, node, path6);
222
222
  if (identity.isScalar(node))
223
- return visitor.Scalar?.(key, node, path3);
223
+ return visitor.Scalar?.(key, node, path6);
224
224
  if (identity.isAlias(node))
225
- return visitor.Alias?.(key, node, path3);
225
+ return visitor.Alias?.(key, node, path6);
226
226
  return void 0;
227
227
  }
228
- function replaceNode(key, path3, node) {
229
- const parent = path3[path3.length - 1];
228
+ function replaceNode(key, path6, node) {
229
+ const parent = path6[path6.length - 1];
230
230
  if (identity.isCollection(parent)) {
231
231
  parent.items[key] = node;
232
232
  } else if (identity.isPair(parent)) {
@@ -632,6 +632,8 @@ var require_Alias = __commonJS({
632
632
  * instance of the `source` anchor before this node.
633
633
  */
634
634
  resolve(doc, ctx) {
635
+ if (ctx?.maxAliasCount === 0)
636
+ throw new ReferenceError("Alias resolution is disabled");
635
637
  let nodes;
636
638
  if (ctx?.aliasResolveCache) {
637
639
  nodes = ctx.aliasResolveCache;
@@ -834,10 +836,10 @@ var require_Collection = __commonJS({
834
836
  var createNode = require_createNode();
835
837
  var identity = require_identity();
836
838
  var Node = require_Node();
837
- function collectionFromPath(schema, path3, value) {
839
+ function collectionFromPath(schema, path6, value) {
838
840
  let v = value;
839
- for (let i = path3.length - 1; i >= 0; --i) {
840
- const k = path3[i];
841
+ for (let i = path6.length - 1; i >= 0; --i) {
842
+ const k = path6[i];
841
843
  if (typeof k === "number" && Number.isInteger(k) && k >= 0) {
842
844
  const a = [];
843
845
  a[k] = v;
@@ -856,7 +858,7 @@ var require_Collection = __commonJS({
856
858
  sourceObjects: /* @__PURE__ */ new Map()
857
859
  });
858
860
  }
859
- var isEmptyPath = (path3) => path3 == null || typeof path3 === "object" && !!path3[Symbol.iterator]().next().done;
861
+ var isEmptyPath = (path6) => path6 == null || typeof path6 === "object" && !!path6[Symbol.iterator]().next().done;
860
862
  var Collection = class extends Node.NodeBase {
861
863
  constructor(type, schema) {
862
864
  super(type);
@@ -886,11 +888,11 @@ var require_Collection = __commonJS({
886
888
  * be a Pair instance or a `{ key, value }` object, which may not have a key
887
889
  * that already exists in the map.
888
890
  */
889
- addIn(path3, value) {
890
- if (isEmptyPath(path3))
891
+ addIn(path6, value) {
892
+ if (isEmptyPath(path6))
891
893
  this.add(value);
892
894
  else {
893
- const [key, ...rest] = path3;
895
+ const [key, ...rest] = path6;
894
896
  const node = this.get(key, true);
895
897
  if (identity.isCollection(node))
896
898
  node.addIn(rest, value);
@@ -904,8 +906,8 @@ var require_Collection = __commonJS({
904
906
  * Removes a value from the collection.
905
907
  * @returns `true` if the item was found and removed.
906
908
  */
907
- deleteIn(path3) {
908
- const [key, ...rest] = path3;
909
+ deleteIn(path6) {
910
+ const [key, ...rest] = path6;
909
911
  if (rest.length === 0)
910
912
  return this.delete(key);
911
913
  const node = this.get(key, true);
@@ -919,8 +921,8 @@ var require_Collection = __commonJS({
919
921
  * scalar values from their surrounding node; to disable set `keepScalar` to
920
922
  * `true` (collections are always returned intact).
921
923
  */
922
- getIn(path3, keepScalar) {
923
- const [key, ...rest] = path3;
924
+ getIn(path6, keepScalar) {
925
+ const [key, ...rest] = path6;
924
926
  const node = this.get(key, true);
925
927
  if (rest.length === 0)
926
928
  return !keepScalar && identity.isScalar(node) ? node.value : node;
@@ -938,8 +940,8 @@ var require_Collection = __commonJS({
938
940
  /**
939
941
  * Checks if the collection includes a value with the key `key`.
940
942
  */
941
- hasIn(path3) {
942
- const [key, ...rest] = path3;
943
+ hasIn(path6) {
944
+ const [key, ...rest] = path6;
943
945
  if (rest.length === 0)
944
946
  return this.has(key);
945
947
  const node = this.get(key, true);
@@ -949,8 +951,8 @@ var require_Collection = __commonJS({
949
951
  * Sets a value in this collection. For `!!set`, `value` needs to be a
950
952
  * boolean to add/remove the item from the set.
951
953
  */
952
- setIn(path3, value) {
953
- const [key, ...rest] = path3;
954
+ setIn(path6, value) {
955
+ const [key, ...rest] = path6;
954
956
  if (rest.length === 0) {
955
957
  this.set(key, value);
956
958
  } else {
@@ -1431,6 +1433,7 @@ var require_stringify = __commonJS({
1431
1433
  nullStr: "null",
1432
1434
  simpleKeys: false,
1433
1435
  singleQuote: null,
1436
+ trailingComma: false,
1434
1437
  trueStr: "true",
1435
1438
  verifyAliasOrder: true
1436
1439
  }, doc.schema.toStringOptions, options);
@@ -1703,18 +1706,18 @@ var require_merge = __commonJS({
1703
1706
  };
1704
1707
  var isMergeKey = (ctx, key) => (merge.identify(key) || identity.isScalar(key) && (!key.type || key.type === Scalar.Scalar.PLAIN) && merge.identify(key.value)) && ctx?.doc.schema.tags.some((tag) => tag.tag === merge.tag && tag.default);
1705
1708
  function addMergeToJSMap(ctx, map, value) {
1706
- value = ctx && identity.isAlias(value) ? value.resolve(ctx.doc) : value;
1707
- if (identity.isSeq(value))
1708
- for (const it of value.items)
1709
+ const source = resolveAliasValue(ctx, value);
1710
+ if (identity.isSeq(source))
1711
+ for (const it of source.items)
1709
1712
  mergeValue(ctx, map, it);
1710
- else if (Array.isArray(value))
1711
- for (const it of value)
1713
+ else if (Array.isArray(source))
1714
+ for (const it of source)
1712
1715
  mergeValue(ctx, map, it);
1713
1716
  else
1714
- mergeValue(ctx, map, value);
1717
+ mergeValue(ctx, map, source);
1715
1718
  }
1716
1719
  function mergeValue(ctx, map, value) {
1717
- const source = ctx && identity.isAlias(value) ? value.resolve(ctx.doc) : value;
1720
+ const source = resolveAliasValue(ctx, value);
1718
1721
  if (!identity.isMap(source))
1719
1722
  throw new Error("Merge sources must be maps or map aliases");
1720
1723
  const srcMap = source.toJSON(null, ctx, Map);
@@ -1735,6 +1738,9 @@ var require_merge = __commonJS({
1735
1738
  }
1736
1739
  return map;
1737
1740
  }
1741
+ function resolveAliasValue(ctx, value) {
1742
+ return ctx && identity.isAlias(value) ? value.resolve(ctx.doc, ctx) : value;
1743
+ }
1738
1744
  exports.addMergeToJSMap = addMergeToJSMap;
1739
1745
  exports.isMergeKey = isMergeKey;
1740
1746
  exports.merge = merge;
@@ -1948,12 +1954,19 @@ ${indent}${line}` : "\n";
1948
1954
  if (comment)
1949
1955
  reqNewline = true;
1950
1956
  let str = stringify.stringify(item, itemCtx, () => comment = null);
1951
- if (i < items.length - 1)
1957
+ reqNewline || (reqNewline = lines.length > linesAtValue || str.includes("\n"));
1958
+ if (i < items.length - 1) {
1952
1959
  str += ",";
1960
+ } else if (ctx.options.trailingComma) {
1961
+ if (ctx.options.lineWidth > 0) {
1962
+ reqNewline || (reqNewline = lines.reduce((sum, line) => sum + line.length + 2, 2) + (str.length + 2) > ctx.options.lineWidth);
1963
+ }
1964
+ if (reqNewline) {
1965
+ str += ",";
1966
+ }
1967
+ }
1953
1968
  if (comment)
1954
1969
  str += stringifyComment.lineComment(str, itemIndent, commentString(comment));
1955
- if (!reqNewline && (lines.length > linesAtValue || str.includes("\n")))
1956
- reqNewline = true;
1957
1970
  lines.push(str);
1958
1971
  linesAtValue = lines.length;
1959
1972
  }
@@ -2365,7 +2378,7 @@ var require_stringifyNumber = __commonJS({
2365
2378
  if (!isFinite(num))
2366
2379
  return isNaN(num) ? ".nan" : num < 0 ? "-.inf" : ".inf";
2367
2380
  let n = Object.is(value, -0) ? "-0" : JSON.stringify(value);
2368
- if (!format && minFractionDigits && (!tag || tag === "tag:yaml.org,2002:float") && /^\d/.test(n)) {
2381
+ if (!format && minFractionDigits && (!tag || tag === "tag:yaml.org,2002:float") && /^-?\d/.test(n) && !n.includes("e")) {
2369
2382
  let i = n.indexOf(".");
2370
2383
  if (i < 0) {
2371
2384
  i = n.length;
@@ -3454,9 +3467,9 @@ var require_Document = __commonJS({
3454
3467
  this.contents.add(value);
3455
3468
  }
3456
3469
  /** Adds a value to the document. */
3457
- addIn(path3, value) {
3470
+ addIn(path6, value) {
3458
3471
  if (assertCollection(this.contents))
3459
- this.contents.addIn(path3, value);
3472
+ this.contents.addIn(path6, value);
3460
3473
  }
3461
3474
  /**
3462
3475
  * Create a new `Alias` node, ensuring that the target `node` has the required anchor.
@@ -3531,14 +3544,14 @@ var require_Document = __commonJS({
3531
3544
  * Removes a value from the document.
3532
3545
  * @returns `true` if the item was found and removed.
3533
3546
  */
3534
- deleteIn(path3) {
3535
- if (Collection.isEmptyPath(path3)) {
3547
+ deleteIn(path6) {
3548
+ if (Collection.isEmptyPath(path6)) {
3536
3549
  if (this.contents == null)
3537
3550
  return false;
3538
3551
  this.contents = null;
3539
3552
  return true;
3540
3553
  }
3541
- return assertCollection(this.contents) ? this.contents.deleteIn(path3) : false;
3554
+ return assertCollection(this.contents) ? this.contents.deleteIn(path6) : false;
3542
3555
  }
3543
3556
  /**
3544
3557
  * Returns item at `key`, or `undefined` if not found. By default unwraps
@@ -3553,10 +3566,10 @@ var require_Document = __commonJS({
3553
3566
  * scalar values from their surrounding node; to disable set `keepScalar` to
3554
3567
  * `true` (collections are always returned intact).
3555
3568
  */
3556
- getIn(path3, keepScalar) {
3557
- if (Collection.isEmptyPath(path3))
3569
+ getIn(path6, keepScalar) {
3570
+ if (Collection.isEmptyPath(path6))
3558
3571
  return !keepScalar && identity.isScalar(this.contents) ? this.contents.value : this.contents;
3559
- return identity.isCollection(this.contents) ? this.contents.getIn(path3, keepScalar) : void 0;
3572
+ return identity.isCollection(this.contents) ? this.contents.getIn(path6, keepScalar) : void 0;
3560
3573
  }
3561
3574
  /**
3562
3575
  * Checks if the document includes a value with the key `key`.
@@ -3567,10 +3580,10 @@ var require_Document = __commonJS({
3567
3580
  /**
3568
3581
  * Checks if the document includes a value at `path`.
3569
3582
  */
3570
- hasIn(path3) {
3571
- if (Collection.isEmptyPath(path3))
3583
+ hasIn(path6) {
3584
+ if (Collection.isEmptyPath(path6))
3572
3585
  return this.contents !== void 0;
3573
- return identity.isCollection(this.contents) ? this.contents.hasIn(path3) : false;
3586
+ return identity.isCollection(this.contents) ? this.contents.hasIn(path6) : false;
3574
3587
  }
3575
3588
  /**
3576
3589
  * Sets a value in this document. For `!!set`, `value` needs to be a
@@ -3587,13 +3600,13 @@ var require_Document = __commonJS({
3587
3600
  * Sets a value in this document. For `!!set`, `value` needs to be a
3588
3601
  * boolean to add/remove the item from the set.
3589
3602
  */
3590
- setIn(path3, value) {
3591
- if (Collection.isEmptyPath(path3)) {
3603
+ setIn(path6, value) {
3604
+ if (Collection.isEmptyPath(path6)) {
3592
3605
  this.contents = value;
3593
3606
  } else if (this.contents == null) {
3594
- this.contents = Collection.collectionFromPath(this.schema, Array.from(path3), value);
3607
+ this.contents = Collection.collectionFromPath(this.schema, Array.from(path6), value);
3595
3608
  } else if (assertCollection(this.contents)) {
3596
- this.contents.setIn(path3, value);
3609
+ this.contents.setIn(path6, value);
3597
3610
  }
3598
3611
  }
3599
3612
  /**
@@ -4737,7 +4750,7 @@ var require_resolve_flow_scalar = __commonJS({
4737
4750
  while (next === " " || next === " ")
4738
4751
  next = source[++i + 1];
4739
4752
  } else if (next === "x" || next === "u" || next === "U") {
4740
- const length = { x: 2, u: 4, U: 8 }[next];
4753
+ const length = next === "x" ? 2 : next === "u" ? 4 : 8;
4741
4754
  res += parseCharCode(source, i + 1, length, onError);
4742
4755
  i += length;
4743
4756
  } else {
@@ -4812,12 +4825,13 @@ var require_resolve_flow_scalar = __commonJS({
4812
4825
  const cc = source.substr(offset, length);
4813
4826
  const ok = cc.length === length && /^[0-9a-fA-F]+$/.test(cc);
4814
4827
  const code = ok ? parseInt(cc, 16) : NaN;
4815
- if (isNaN(code)) {
4828
+ try {
4829
+ return String.fromCodePoint(code);
4830
+ } catch {
4816
4831
  const raw = source.substr(offset - 2, length + 2);
4817
4832
  onError(offset - 2, "BAD_DQ_ESCAPE", `Invalid escape sequence ${raw}`);
4818
4833
  return raw;
4819
4834
  }
4820
- return String.fromCodePoint(code);
4821
4835
  }
4822
4836
  exports.resolveFlowScalar = resolveFlowScalar;
4823
4837
  }
@@ -4967,17 +4981,22 @@ var require_compose_node = __commonJS({
4967
4981
  case "block-map":
4968
4982
  case "block-seq":
4969
4983
  case "flow-collection":
4970
- node = composeCollection.composeCollection(CN, ctx, token, props, onError);
4971
- if (anchor)
4972
- node.anchor = anchor.source.substring(1);
4984
+ try {
4985
+ node = composeCollection.composeCollection(CN, ctx, token, props, onError);
4986
+ if (anchor)
4987
+ node.anchor = anchor.source.substring(1);
4988
+ } catch (error) {
4989
+ const message = error instanceof Error ? error.message : String(error);
4990
+ onError(token, "RESOURCE_EXHAUSTION", message);
4991
+ }
4973
4992
  break;
4974
4993
  default: {
4975
4994
  const message = token.type === "error" ? token.message : `Unsupported token (type: ${token.type})`;
4976
4995
  onError(token, "UNEXPECTED_TOKEN", message);
4977
- node = composeEmptyNode(ctx, token.offset, void 0, null, props, onError);
4978
4996
  isSrcToken = false;
4979
4997
  }
4980
4998
  }
4999
+ node ?? (node = composeEmptyNode(ctx, token.offset, void 0, null, props, onError));
4981
5000
  if (anchor && node.anchor === "")
4982
5001
  onError(anchor, "BAD_ALIAS", "Anchor cannot be an empty string");
4983
5002
  if (atKey && ctx.options.stringKeys && (!identity.isScalar(node) || typeof node.value !== "string" || node.tag && node.tag !== "tag:yaml.org,2002:str")) {
@@ -5162,8 +5181,10 @@ ${cb}` : comment;
5162
5181
  }
5163
5182
  }
5164
5183
  if (afterDoc) {
5165
- Array.prototype.push.apply(doc.errors, this.errors);
5166
- Array.prototype.push.apply(doc.warnings, this.warnings);
5184
+ for (let i = 0; i < this.errors.length; ++i)
5185
+ doc.errors.push(this.errors[i]);
5186
+ for (let i = 0; i < this.warnings.length; ++i)
5187
+ doc.warnings.push(this.warnings[i]);
5167
5188
  } else {
5168
5189
  doc.errors = this.errors;
5169
5190
  doc.warnings = this.warnings;
@@ -5545,9 +5566,9 @@ var require_cst_visit = __commonJS({
5545
5566
  visit.BREAK = BREAK;
5546
5567
  visit.SKIP = SKIP;
5547
5568
  visit.REMOVE = REMOVE;
5548
- visit.itemAtPath = (cst, path3) => {
5569
+ visit.itemAtPath = (cst, path6) => {
5549
5570
  let item = cst;
5550
- for (const [field, index] of path3) {
5571
+ for (const [field, index] of path6) {
5551
5572
  const tok = item?.[field];
5552
5573
  if (tok && "items" in tok) {
5553
5574
  item = tok.items[index];
@@ -5556,23 +5577,23 @@ var require_cst_visit = __commonJS({
5556
5577
  }
5557
5578
  return item;
5558
5579
  };
5559
- visit.parentCollection = (cst, path3) => {
5560
- const parent = visit.itemAtPath(cst, path3.slice(0, -1));
5561
- const field = path3[path3.length - 1][0];
5580
+ visit.parentCollection = (cst, path6) => {
5581
+ const parent = visit.itemAtPath(cst, path6.slice(0, -1));
5582
+ const field = path6[path6.length - 1][0];
5562
5583
  const coll = parent?.[field];
5563
5584
  if (coll && "items" in coll)
5564
5585
  return coll;
5565
5586
  throw new Error("Parent collection not found");
5566
5587
  };
5567
- function _visit(path3, item, visitor) {
5568
- let ctrl = visitor(item, path3);
5588
+ function _visit(path6, item, visitor) {
5589
+ let ctrl = visitor(item, path6);
5569
5590
  if (typeof ctrl === "symbol")
5570
5591
  return ctrl;
5571
5592
  for (const field of ["key", "value"]) {
5572
5593
  const token = item[field];
5573
5594
  if (token && "items" in token) {
5574
5595
  for (let i = 0; i < token.items.length; ++i) {
5575
- const ci = _visit(Object.freeze(path3.concat([[field, i]])), token.items[i], visitor);
5596
+ const ci = _visit(Object.freeze(path6.concat([[field, i]])), token.items[i], visitor);
5576
5597
  if (typeof ci === "number")
5577
5598
  i = ci - 1;
5578
5599
  else if (ci === BREAK)
@@ -5583,10 +5604,10 @@ var require_cst_visit = __commonJS({
5583
5604
  }
5584
5605
  }
5585
5606
  if (typeof ctrl === "function" && field === "key")
5586
- ctrl = ctrl(item, path3);
5607
+ ctrl = ctrl(item, path6);
5587
5608
  }
5588
5609
  }
5589
- return typeof ctrl === "function" ? ctrl(item, path3) : ctrl;
5610
+ return typeof ctrl === "function" ? ctrl(item, path6) : ctrl;
5590
5611
  }
5591
5612
  exports.visit = visit;
5592
5613
  }
@@ -5896,7 +5917,7 @@ var require_lexer = __commonJS({
5896
5917
  const n = (yield* this.pushCount(1)) + (yield* this.pushSpaces(true));
5897
5918
  this.indentNext = this.indentValue + 1;
5898
5919
  this.indentValue += n;
5899
- return yield* this.parseBlockStart();
5920
+ return "block-start";
5900
5921
  }
5901
5922
  return "doc";
5902
5923
  }
@@ -6195,28 +6216,38 @@ var require_lexer = __commonJS({
6195
6216
  return 0;
6196
6217
  }
6197
6218
  *pushIndicators() {
6198
- switch (this.charAt(0)) {
6199
- case "!":
6200
- return (yield* this.pushTag()) + (yield* this.pushSpaces(true)) + (yield* this.pushIndicators());
6201
- case "&":
6202
- return (yield* this.pushUntil(isNotAnchorChar)) + (yield* this.pushSpaces(true)) + (yield* this.pushIndicators());
6203
- case "-":
6204
- // this is an error
6205
- case "?":
6206
- // this is an error outside flow collections
6207
- case ":": {
6208
- const inFlow = this.flowLevel > 0;
6209
- const ch1 = this.charAt(1);
6210
- if (isEmpty(ch1) || inFlow && flowIndicatorChars.has(ch1)) {
6211
- if (!inFlow)
6212
- this.indentNext = this.indentValue + 1;
6213
- else if (this.flowKey)
6214
- this.flowKey = false;
6215
- return (yield* this.pushCount(1)) + (yield* this.pushSpaces(true)) + (yield* this.pushIndicators());
6219
+ let n = 0;
6220
+ loop: while (true) {
6221
+ switch (this.charAt(0)) {
6222
+ case "!":
6223
+ n += yield* this.pushTag();
6224
+ n += yield* this.pushSpaces(true);
6225
+ continue loop;
6226
+ case "&":
6227
+ n += yield* this.pushUntil(isNotAnchorChar);
6228
+ n += yield* this.pushSpaces(true);
6229
+ continue loop;
6230
+ case "-":
6231
+ // this is an error
6232
+ case "?":
6233
+ // this is an error outside flow collections
6234
+ case ":": {
6235
+ const inFlow = this.flowLevel > 0;
6236
+ const ch1 = this.charAt(1);
6237
+ if (isEmpty(ch1) || inFlow && flowIndicatorChars.has(ch1)) {
6238
+ if (!inFlow)
6239
+ this.indentNext = this.indentValue + 1;
6240
+ else if (this.flowKey)
6241
+ this.flowKey = false;
6242
+ n += yield* this.pushCount(1);
6243
+ n += yield* this.pushSpaces(true);
6244
+ continue loop;
6245
+ }
6216
6246
  }
6217
6247
  }
6248
+ break loop;
6218
6249
  }
6219
- return 0;
6250
+ return n;
6220
6251
  }
6221
6252
  *pushTag() {
6222
6253
  if (this.charAt(1) === "<") {
@@ -6375,6 +6406,13 @@ var require_parser = __commonJS({
6375
6406
  }
6376
6407
  return prev.splice(i, prev.length);
6377
6408
  }
6409
+ function arrayPushArray(target, source) {
6410
+ if (source.length < 1e5)
6411
+ Array.prototype.push.apply(target, source);
6412
+ else
6413
+ for (let i = 0; i < source.length; ++i)
6414
+ target.push(source[i]);
6415
+ }
6378
6416
  function fixFlowSeqItems(fc) {
6379
6417
  if (fc.start.type === "flow-seq-start") {
6380
6418
  for (const it of fc.items) {
@@ -6384,11 +6422,11 @@ var require_parser = __commonJS({
6384
6422
  delete it.key;
6385
6423
  if (isFlowToken(it.value)) {
6386
6424
  if (it.value.end)
6387
- Array.prototype.push.apply(it.value.end, it.sep);
6425
+ arrayPushArray(it.value.end, it.sep);
6388
6426
  else
6389
6427
  it.value.end = it.sep;
6390
6428
  } else
6391
- Array.prototype.push.apply(it.start, it.sep);
6429
+ arrayPushArray(it.start, it.sep);
6392
6430
  delete it.sep;
6393
6431
  }
6394
6432
  }
@@ -6743,7 +6781,7 @@ var require_parser = __commonJS({
6743
6781
  const prev = map.items[map.items.length - 2];
6744
6782
  const end = prev?.value?.end;
6745
6783
  if (Array.isArray(end)) {
6746
- Array.prototype.push.apply(end, it.start);
6784
+ arrayPushArray(end, it.start);
6747
6785
  end.push(this.sourceToken);
6748
6786
  map.items.pop();
6749
6787
  return;
@@ -6871,14 +6909,14 @@ var require_parser = __commonJS({
6871
6909
  case "scalar":
6872
6910
  case "single-quoted-scalar":
6873
6911
  case "double-quoted-scalar": {
6874
- const fs3 = this.flowScalar(this.type);
6912
+ const fs6 = this.flowScalar(this.type);
6875
6913
  if (atNextItem || it.value) {
6876
- map.items.push({ start, key: fs3, sep: [] });
6914
+ map.items.push({ start, key: fs6, sep: [] });
6877
6915
  this.onKeyLine = true;
6878
6916
  } else if (it.sep) {
6879
- this.stack.push(fs3);
6917
+ this.stack.push(fs6);
6880
6918
  } else {
6881
- Object.assign(it, { key: fs3, sep: [] });
6919
+ Object.assign(it, { key: fs6, sep: [] });
6882
6920
  this.onKeyLine = true;
6883
6921
  }
6884
6922
  return;
@@ -6931,7 +6969,7 @@ var require_parser = __commonJS({
6931
6969
  const prev = seq.items[seq.items.length - 2];
6932
6970
  const end = prev?.value?.end;
6933
6971
  if (Array.isArray(end)) {
6934
- Array.prototype.push.apply(end, it.start);
6972
+ arrayPushArray(end, it.start);
6935
6973
  end.push(this.sourceToken);
6936
6974
  seq.items.pop();
6937
6975
  return;
@@ -7006,13 +7044,13 @@ var require_parser = __commonJS({
7006
7044
  case "scalar":
7007
7045
  case "single-quoted-scalar":
7008
7046
  case "double-quoted-scalar": {
7009
- const fs3 = this.flowScalar(this.type);
7047
+ const fs6 = this.flowScalar(this.type);
7010
7048
  if (!it || it.value)
7011
- fc.items.push({ start: [], key: fs3, sep: [] });
7049
+ fc.items.push({ start: [], key: fs6, sep: [] });
7012
7050
  else if (it.sep)
7013
- this.stack.push(fs3);
7051
+ this.stack.push(fs6);
7014
7052
  else
7015
- Object.assign(it, { key: fs3, sep: [] });
7053
+ Object.assign(it, { key: fs6, sep: [] });
7016
7054
  return;
7017
7055
  }
7018
7056
  case "flow-map-end":
@@ -7550,17 +7588,17 @@ var require_ignore = __commonJS({
7550
7588
  var throwError = (message, Ctor) => {
7551
7589
  throw new Ctor(message);
7552
7590
  };
7553
- var checkPath = (path3, originalPath, doThrow) => {
7554
- if (!isString(path3)) {
7591
+ var checkPath = (path6, originalPath, doThrow) => {
7592
+ if (!isString(path6)) {
7555
7593
  return doThrow(
7556
7594
  `path must be a string, but got \`${originalPath}\``,
7557
7595
  TypeError
7558
7596
  );
7559
7597
  }
7560
- if (!path3) {
7598
+ if (!path6) {
7561
7599
  return doThrow(`path must not be empty`, TypeError);
7562
7600
  }
7563
- if (checkPath.isNotRelative(path3)) {
7601
+ if (checkPath.isNotRelative(path6)) {
7564
7602
  const r = "`path.relative()`d";
7565
7603
  return doThrow(
7566
7604
  `path should be a ${r} string, but got "${originalPath}"`,
@@ -7569,7 +7607,7 @@ var require_ignore = __commonJS({
7569
7607
  }
7570
7608
  return true;
7571
7609
  };
7572
- var isNotRelative = (path3) => REGEX_TEST_INVALID_PATH.test(path3);
7610
+ var isNotRelative = (path6) => REGEX_TEST_INVALID_PATH.test(path6);
7573
7611
  checkPath.isNotRelative = isNotRelative;
7574
7612
  checkPath.convert = (p) => p;
7575
7613
  var Ignore = class {
@@ -7628,7 +7666,7 @@ var require_ignore = __commonJS({
7628
7666
  // setting `checkUnignored` to `false` could reduce additional
7629
7667
  // path matching.
7630
7668
  // @returns {TestResult} true if a file is ignored
7631
- _testOne(path3, checkUnignored) {
7669
+ _testOne(path6, checkUnignored) {
7632
7670
  let ignored = false;
7633
7671
  let unignored = false;
7634
7672
  this._rules.forEach((rule) => {
@@ -7636,7 +7674,7 @@ var require_ignore = __commonJS({
7636
7674
  if (unignored === negative && ignored !== unignored || negative && !ignored && !unignored && !checkUnignored) {
7637
7675
  return;
7638
7676
  }
7639
- const matched = rule.regex.test(path3);
7677
+ const matched = rule.regex.test(path6);
7640
7678
  if (matched) {
7641
7679
  ignored = !negative;
7642
7680
  unignored = negative;
@@ -7649,24 +7687,24 @@ var require_ignore = __commonJS({
7649
7687
  }
7650
7688
  // @returns {TestResult}
7651
7689
  _test(originalPath, cache, checkUnignored, slices) {
7652
- const path3 = originalPath && checkPath.convert(originalPath);
7690
+ const path6 = originalPath && checkPath.convert(originalPath);
7653
7691
  checkPath(
7654
- path3,
7692
+ path6,
7655
7693
  originalPath,
7656
7694
  this._allowRelativePaths ? RETURN_FALSE : throwError
7657
7695
  );
7658
- return this._t(path3, cache, checkUnignored, slices);
7696
+ return this._t(path6, cache, checkUnignored, slices);
7659
7697
  }
7660
- _t(path3, cache, checkUnignored, slices) {
7661
- if (path3 in cache) {
7662
- return cache[path3];
7698
+ _t(path6, cache, checkUnignored, slices) {
7699
+ if (path6 in cache) {
7700
+ return cache[path6];
7663
7701
  }
7664
7702
  if (!slices) {
7665
- slices = path3.split(SLASH);
7703
+ slices = path6.split(SLASH);
7666
7704
  }
7667
7705
  slices.pop();
7668
7706
  if (!slices.length) {
7669
- return cache[path3] = this._testOne(path3, checkUnignored);
7707
+ return cache[path6] = this._testOne(path6, checkUnignored);
7670
7708
  }
7671
7709
  const parent = this._t(
7672
7710
  slices.join(SLASH) + SLASH,
@@ -7674,24 +7712,24 @@ var require_ignore = __commonJS({
7674
7712
  checkUnignored,
7675
7713
  slices
7676
7714
  );
7677
- return cache[path3] = parent.ignored ? parent : this._testOne(path3, checkUnignored);
7715
+ return cache[path6] = parent.ignored ? parent : this._testOne(path6, checkUnignored);
7678
7716
  }
7679
- ignores(path3) {
7680
- return this._test(path3, this._ignoreCache, false).ignored;
7717
+ ignores(path6) {
7718
+ return this._test(path6, this._ignoreCache, false).ignored;
7681
7719
  }
7682
7720
  createFilter() {
7683
- return (path3) => !this.ignores(path3);
7721
+ return (path6) => !this.ignores(path6);
7684
7722
  }
7685
7723
  filter(paths) {
7686
7724
  return makeArray(paths).filter(this.createFilter());
7687
7725
  }
7688
7726
  // @returns {TestResult}
7689
- test(path3) {
7690
- return this._test(path3, this._testCache, true);
7727
+ test(path6) {
7728
+ return this._test(path6, this._testCache, true);
7691
7729
  }
7692
7730
  };
7693
7731
  var factory = (options) => new Ignore(options);
7694
- var isPathValid = (path3) => checkPath(path3 && checkPath.convert(path3), path3, RETURN_FALSE);
7732
+ var isPathValid = (path6) => checkPath(path6 && checkPath.convert(path6), path6, RETURN_FALSE);
7695
7733
  factory.isPathValid = isPathValid;
7696
7734
  factory.default = factory;
7697
7735
  module.exports = factory;
@@ -7702,38 +7740,626 @@ var require_ignore = __commonJS({
7702
7740
  const makePosix = (str) => /^\\\\\?\\/.test(str) || /["<>|\u0000-\u001F]+/u.test(str) ? str : str.replace(/\\/g, "/");
7703
7741
  checkPath.convert = makePosix;
7704
7742
  const REGIX_IS_WINDOWS_PATH_ABSOLUTE = /^[a-z]:\//i;
7705
- checkPath.isNotRelative = (path3) => REGIX_IS_WINDOWS_PATH_ABSOLUTE.test(path3) || isNotRelative(path3);
7743
+ checkPath.isNotRelative = (path6) => REGIX_IS_WINDOWS_PATH_ABSOLUTE.test(path6) || isNotRelative(path6);
7706
7744
  }
7707
7745
  }
7708
7746
  });
7709
7747
 
7710
7748
  // src/index.js
7711
- var import_yaml2 = __toESM(require_dist(), 1);
7712
- var import_ignore2 = __toESM(require_ignore(), 1);
7749
+ var import_yaml3 = __toESM(require_dist(), 1);
7750
+ var import_ignore3 = __toESM(require_ignore(), 1);
7713
7751
  import crypto from "node:crypto";
7714
- import fs2 from "node:fs";
7752
+ import fs5 from "node:fs";
7715
7753
  import http from "node:http";
7716
7754
  import os from "node:os";
7717
- import path2 from "node:path";
7718
- import { execFileSync } from "node:child_process";
7755
+ import path5 from "node:path";
7719
7756
  import { fileURLToPath } from "node:url";
7720
7757
  import { tool } from "@opencode-ai/plugin/tool";
7721
7758
 
7722
- // src/validate_logic.js
7723
- var import_yaml = __toESM(require_dist(), 1);
7724
- var import_ignore = __toESM(require_ignore(), 1);
7759
+ // src/git_utils.js
7725
7760
  import fs from "node:fs";
7726
7761
  import path from "node:path";
7762
+ import { execFileSync } from "node:child_process";
7763
+ function toGitPath(worktree, targetPath) {
7764
+ const relativePath = path.relative(worktree, targetPath);
7765
+ if (!relativePath || relativePath.startsWith("..") || path.isAbsolute(relativePath)) return null;
7766
+ return relativePath.split(path.sep).join("/");
7767
+ }
7768
+ function runGit(worktree, args) {
7769
+ return execFileSync("git", args, {
7770
+ cwd: worktree,
7771
+ encoding: "utf8",
7772
+ stdio: ["ignore", "pipe", "pipe"]
7773
+ });
7774
+ }
7775
+ function sameFilesystemPath(left, right) {
7776
+ try {
7777
+ return fs.realpathSync(left) === fs.realpathSync(right);
7778
+ } catch {
7779
+ return path.resolve(left) === path.resolve(right);
7780
+ }
7781
+ }
7782
+ function gitMigrationState(worktree) {
7783
+ try {
7784
+ const root = runGit(worktree, ["rev-parse", "--show-toplevel"]).trim();
7785
+ if (!sameFilesystemPath(root, worktree)) return null;
7786
+ return { worktree };
7787
+ } catch {
7788
+ return null;
7789
+ }
7790
+ }
7791
+ function isGitTracked(gitState, targetPath) {
7792
+ if (!gitState) return false;
7793
+ const gitPath = toGitPath(gitState.worktree, targetPath);
7794
+ if (!gitPath) return false;
7795
+ try {
7796
+ runGit(gitState.worktree, ["ls-files", "--error-unmatch", "--", gitPath]);
7797
+ return true;
7798
+ } catch {
7799
+ return false;
7800
+ }
7801
+ }
7802
+ function hasGitTrackedChildren(gitState, targetPath) {
7803
+ if (!gitState) return false;
7804
+ const gitPath = toGitPath(gitState.worktree, targetPath);
7805
+ if (!gitPath) return false;
7806
+ try {
7807
+ return runGit(gitState.worktree, ["ls-files", "--", `${gitPath}/`]).trim().length > 0;
7808
+ } catch {
7809
+ return false;
7810
+ }
7811
+ }
7812
+ function gitAwareMoveIfTracked(sourcePath, destinationPath, gitState) {
7813
+ const sourceIsTracked = isGitTracked(gitState, sourcePath) || hasGitTrackedChildren(gitState, sourcePath);
7814
+ if (!gitState || !sourceIsTracked || fs.existsSync(destinationPath)) return false;
7815
+ const sourceGitPath = toGitPath(gitState.worktree, sourcePath);
7816
+ const destinationGitPath = toGitPath(gitState.worktree, destinationPath);
7817
+ if (!sourceGitPath || !destinationGitPath) return false;
7818
+ fs.mkdirSync(path.dirname(destinationPath), { recursive: true });
7819
+ try {
7820
+ runGit(gitState.worktree, ["mv", "--", sourceGitPath, destinationGitPath]);
7821
+ return true;
7822
+ } catch {
7823
+ return false;
7824
+ }
7825
+ }
7826
+ function stageGitAwareMerge(sourcePath, destinationPath, gitState) {
7827
+ if (!gitState) return;
7828
+ const sourceGitPath = toGitPath(gitState.worktree, sourcePath);
7829
+ const destinationGitPath = toGitPath(gitState.worktree, destinationPath);
7830
+ if (!sourceGitPath || !destinationGitPath) return;
7831
+ try {
7832
+ runGit(gitState.worktree, ["add", "-A", "--", sourceGitPath, destinationGitPath]);
7833
+ } catch {
7834
+ }
7835
+ }
7836
+
7837
+ // src/include_resolver.js
7838
+ import fs2 from "node:fs";
7839
+ import path2 from "node:path";
7840
+ function compactPromptPath(filePath) {
7841
+ if (!filePath.endsWith(".md") || filePath.endsWith(".prompt.md")) return null;
7842
+ return filePath.replace(/\.md$/, ".prompt.md");
7843
+ }
7844
+ function isSameOrNestedPath(candidate, root) {
7845
+ if (typeof candidate !== "string" || typeof root !== "string" || !candidate.trim() || !root.trim()) return false;
7846
+ const resolvedCandidate = path2.resolve(candidate);
7847
+ const resolvedRoot = path2.resolve(root);
7848
+ const relative = path2.relative(resolvedRoot, resolvedCandidate);
7849
+ return relative === "" || !!relative && !relative.startsWith("..") && !path2.isAbsolute(relative);
7850
+ }
7851
+ function resolveWithin(baseDir, relativePath) {
7852
+ if (!relativePath) return null;
7853
+ if (path2.isAbsolute(relativePath)) return null;
7854
+ const resolved = path2.resolve(baseDir, relativePath);
7855
+ return isSameOrNestedPath(resolved, baseDir) ? resolved : null;
7856
+ }
7857
+ function withCompactPreference(paths, options = {}) {
7858
+ if (!options.preferCompactPromptDocs) return paths;
7859
+ const compactPaths = paths.map((filePath) => filePath ? compactPromptPath(filePath) : null).filter(Boolean);
7860
+ return [...compactPaths, ...paths];
7861
+ }
7862
+ function resolveIncludeFile(includeRef, repoRoot, bundleRoot, options = {}) {
7863
+ const trimmed = String(includeRef || "").trim();
7864
+ const scopedMatch = trimmed.match(/^([a-z]+):(.*)$/i);
7865
+ const scope = scopedMatch?.[1]?.toLowerCase();
7866
+ const target = scopedMatch ? scopedMatch[2].trim() : trimmed;
7867
+ const optimaRoot = options.optimaRoot || path2.join(repoRoot, ".optima");
7868
+ const repoPolicyRoot = options.repoPolicyRoot || path2.join(optimaRoot, "policies");
7869
+ const bundlePolicyRoot = options.bundlePolicyRoot || path2.join(bundleRoot, "assets", "policies");
7870
+ if (scope === "plugin") {
7871
+ for (const filePath of withCompactPreference([resolveWithin(bundleRoot, target)], options)) {
7872
+ if (filePath && fs2.existsSync(filePath)) return filePath;
7873
+ }
7874
+ return null;
7875
+ }
7876
+ if (scope === "repo") {
7877
+ for (const filePath of withCompactPreference([resolveWithin(optimaRoot, target)], options)) {
7878
+ if (filePath && fs2.existsSync(filePath)) return filePath;
7879
+ }
7880
+ return null;
7881
+ }
7882
+ if (scope === "policy") {
7883
+ const candidates2 = withCompactPreference([
7884
+ resolveWithin(repoPolicyRoot, target),
7885
+ resolveWithin(bundlePolicyRoot, target)
7886
+ ], options);
7887
+ for (const filePath of candidates2) {
7888
+ if (filePath && fs2.existsSync(filePath)) return filePath;
7889
+ }
7890
+ return null;
7891
+ }
7892
+ const candidates = withCompactPreference([
7893
+ resolveWithin(repoRoot, target),
7894
+ resolveWithin(bundleRoot, target)
7895
+ ], options);
7896
+ for (const filePath of candidates) {
7897
+ if (filePath && fs2.existsSync(filePath)) return filePath;
7898
+ }
7899
+ return null;
7900
+ }
7901
+ function resolveIncludes(text, repoRoot, bundleRoot, options = {}) {
7902
+ const includeDepth = Number(options.includeDepth || 0);
7903
+ const maxIncludeDepth = Number(options.maxIncludeDepth || 20);
7904
+ if (includeDepth > maxIncludeDepth) {
7905
+ return "\n\n# ERROR: Include recursion limit exceeded.\n\n";
7906
+ }
7907
+ const includeRegex = /<include:(.*?)>/g;
7908
+ return String(text || "").replace(includeRegex, (match, includeRef) => {
7909
+ const filePath = resolveIncludeFile(includeRef, repoRoot, bundleRoot, options);
7910
+ if (!filePath) {
7911
+ console.warn(`[Optima] Include file not found: ${includeRef}`);
7912
+ return `
7913
+
7914
+ # ERROR: Include file not found: ${includeRef}
7915
+
7916
+ `;
7917
+ }
7918
+ const content = fs2.readFileSync(filePath, "utf8");
7919
+ return resolveIncludes(content, repoRoot, bundleRoot, { ...options, includeDepth: includeDepth + 1, maxIncludeDepth });
7920
+ });
7921
+ }
7922
+
7923
+ // src/repair.js
7924
+ var import_yaml = __toESM(require_dist(), 1);
7925
+ var import_ignore = __toESM(require_ignore(), 1);
7926
+ import fs3 from "node:fs";
7927
+ import path3 from "node:path";
7928
+ var CODEMAP_SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([
7929
+ ".js",
7930
+ ".ts",
7931
+ ".tsx",
7932
+ ".jsx",
7933
+ ".dart",
7934
+ ".py",
7935
+ ".go",
7936
+ ".rs",
7937
+ ".java",
7938
+ ".c",
7939
+ ".cpp",
7940
+ ".cs",
7941
+ ".php",
7942
+ ".rb",
7943
+ ".swift",
7944
+ ".kt",
7945
+ ".m",
7946
+ ".sh",
7947
+ ".sql",
7948
+ ".yaml",
7949
+ ".yml",
7950
+ ".json",
7951
+ ".md"
7952
+ ]);
7953
+ var LEGACY_OPERATIONAL_ROOTS = /* @__PURE__ */ new Set([
7954
+ "tasks",
7955
+ "evidences",
7956
+ ".orbita",
7957
+ ".staticeng",
7958
+ ".nomadworks",
7959
+ ".nomadwork",
7960
+ "nomadworks",
7961
+ ".codenomad"
7962
+ ]);
7963
+ var OPTIMA_OPERATIONAL_FOLDERS = [".optima", "templates", "dist"];
7964
+ function relPath(worktree, targetPath) {
7965
+ return path3.relative(worktree, targetPath).split(path3.sep).join("/") || ".";
7966
+ }
7967
+ function normalizeCodemapRelPath(relPathValue) {
7968
+ return path3.normalize(relPathValue).replace(/\\/g, "/").replace(/\/$/, "");
7969
+ }
7970
+ function firstPathSegment(relPathValue) {
7971
+ return normalizeCodemapRelPath(relPathValue).split("/").filter(Boolean)[0] || "";
7972
+ }
7973
+ function isOperationalRelPath(relPathValue) {
7974
+ if (!relPathValue) return false;
7975
+ const normalized = normalizeCodemapRelPath(relPathValue);
7976
+ const firstSegment = firstPathSegment(normalized);
7977
+ if (LEGACY_OPERATIONAL_ROOTS.has(firstSegment)) return true;
7978
+ return OPTIMA_OPERATIONAL_FOLDERS.some((folder) => normalized === folder || normalized.startsWith(`${folder}/`));
7979
+ }
7980
+ function isHiddenTree(relPathValue) {
7981
+ if (!relPathValue) return false;
7982
+ return normalizeCodemapRelPath(relPathValue).split("/").some((part) => part.startsWith("."));
7983
+ }
7984
+ function loadGitIgnoreMatcher(worktree) {
7985
+ const ig = (0, import_ignore.default)();
7986
+ ig.add(".git");
7987
+ const gitignorePath = path3.join(worktree, ".gitignore");
7988
+ if (fs3.existsSync(gitignorePath)) ig.add(fs3.readFileSync(gitignorePath, "utf8"));
7989
+ return ig;
7990
+ }
7991
+ function codemapSectionEntries(value) {
7992
+ if (Array.isArray(value)) return value;
7993
+ if (value && typeof value === "object") return Object.values(value);
7994
+ return [];
7995
+ }
7996
+ function codemapIndexedPaths(map) {
7997
+ const indexed = /* @__PURE__ */ new Set();
7998
+ for (const section of ["modules", "entrypoints", "sources_of_truth", "links", "internals"]) {
7999
+ for (const item of codemapSectionEntries(map?.[section])) {
8000
+ if (item?.path) indexed.add(normalizeCodemapRelPath(item.path));
8001
+ }
8002
+ }
8003
+ return indexed;
8004
+ }
8005
+ function readCodemap(filePath, unresolved, worktree) {
8006
+ try {
8007
+ const parsed = import_yaml.default.parse(fs3.readFileSync(filePath, "utf8"));
8008
+ if (!parsed || typeof parsed !== "object") {
8009
+ unresolved.push({ category: "codemap", path: relPath(worktree, filePath), message: "CodeMap is empty or invalid; manual repair required." });
8010
+ return null;
8011
+ }
8012
+ return parsed;
8013
+ } catch {
8014
+ unresolved.push({ category: "codemap", path: relPath(worktree, filePath), message: "CodeMap has invalid YAML; manual repair required." });
8015
+ return null;
8016
+ }
8017
+ }
8018
+ function writeCodemap(filePath, map) {
8019
+ fs3.writeFileSync(filePath, import_yaml.default.stringify(map), "utf8");
8020
+ }
8021
+ function isIgnoredPath(ig, relativePath) {
8022
+ const normalized = normalizeCodemapRelPath(relativePath);
8023
+ return Boolean(normalized) && ig.ignores(normalized);
8024
+ }
8025
+ function hasImmediateSourceFile(dirPath, ig, worktree) {
8026
+ if (!fs3.existsSync(dirPath)) return false;
8027
+ for (const item of fs3.readdirSync(dirPath, { withFileTypes: true })) {
8028
+ const childPath = path3.join(dirPath, item.name);
8029
+ const relative = path3.relative(worktree, childPath);
8030
+ if (isIgnoredPath(ig, relative) || isOperationalRelPath(relative)) continue;
8031
+ if (item.isFile() && CODEMAP_SOURCE_EXTENSIONS.has(path3.extname(item.name))) return true;
8032
+ }
8033
+ return false;
8034
+ }
8035
+ function containsSource(dirPath, ig, worktree) {
8036
+ if (!fs3.existsSync(dirPath)) return false;
8037
+ const dirRelPath = path3.relative(worktree, dirPath);
8038
+ if (isOperationalRelPath(dirRelPath) || isHiddenTree(dirRelPath)) return false;
8039
+ for (const item of fs3.readdirSync(dirPath, { withFileTypes: true })) {
8040
+ const childPath = path3.join(dirPath, item.name);
8041
+ const relative = path3.relative(worktree, childPath);
8042
+ if (isIgnoredPath(ig, relative) || isOperationalRelPath(relative) || isHiddenTree(relative)) continue;
8043
+ if (item.isFile() && CODEMAP_SOURCE_EXTENSIONS.has(path3.extname(item.name))) return true;
8044
+ if (item.isDirectory() && containsSource(childPath, ig, worktree)) return true;
8045
+ }
8046
+ return false;
8047
+ }
8048
+ function createModuleCodemap(dirPath, worktree, deps) {
8049
+ const entries = fs3.readdirSync(dirPath, { withFileTypes: true });
8050
+ const entrypoints = [];
8051
+ const internals = [];
8052
+ const relToRoot = path3.relative(dirPath, deps.optimaCodemapPath(worktree)).split(path3.sep).join("/");
8053
+ for (const item of entries) {
8054
+ if (!item.isFile() || item.name === "codemap.yml" || !CODEMAP_SOURCE_EXTENSIONS.has(path3.extname(item.name))) continue;
8055
+ const bucket = /^index\.(js|ts|tsx|jsx)$|^main\.(js|ts|tsx|jsx|py|go|rs|java)$/.test(item.name) ? entrypoints : internals;
8056
+ bucket.push({ path: item.name });
8057
+ }
8058
+ const map = { scope: "module", parent: relToRoot };
8059
+ if (entrypoints.length > 0) map.entrypoints = entrypoints;
8060
+ map.internals = internals;
8061
+ return map;
8062
+ }
8063
+ function repairSingleCodemap(codemapPath, worktree, apply, registerAction, unresolved, deps) {
8064
+ const map = readCodemap(codemapPath, unresolved, worktree);
8065
+ if (!map) return;
8066
+ const isRootMap = codemapPath === deps.optimaCodemapPath(worktree);
8067
+ const mapDir = path3.dirname(codemapPath);
8068
+ const pathBase = isRootMap ? worktree : mapDir;
8069
+ let changed = false;
8070
+ for (const section of ["modules", "entrypoints", "sources_of_truth", "links", "internals"]) {
8071
+ const originalEntries = codemapSectionEntries(map[section]);
8072
+ if (!Array.isArray(map[section]) && originalEntries.length > 0) {
8073
+ unresolved.push({ category: "codemap", path: relPath(worktree, codemapPath), message: `Section '${section}' is object-shaped; repair leaves it unchanged to avoid changing user structure.` });
8074
+ continue;
8075
+ }
8076
+ const nextEntries = [];
8077
+ for (const entry of originalEntries) {
8078
+ if (!entry?.path || entry.path.startsWith("http://") || entry.path.startsWith("https://") || path3.isAbsolute(entry.path)) {
8079
+ nextEntries.push(entry);
8080
+ continue;
8081
+ }
8082
+ const normalizedPath = normalizeCodemapRelPath(entry.path);
8083
+ const absPath = path3.join(pathBase, normalizedPath);
8084
+ if (!fs3.existsSync(absPath)) {
8085
+ registerAction({ category: "codemap", action: apply ? "removed" : "would_remove", path: relPath(worktree, codemapPath), detail: `Remove broken ${section.slice(0, -1)} reference '${entry.path}'.` });
8086
+ changed = true;
8087
+ continue;
8088
+ }
8089
+ const parts = normalizedPath.split("/").filter((part) => part && part !== ".");
8090
+ const maxParts = isRootMap ? 2 : 1;
8091
+ if (parts.length > maxParts) {
8092
+ const localPath = isRootMap ? parts.slice(0, 2).join("/") : parts[0];
8093
+ const localAbs = path3.join(pathBase, localPath);
8094
+ if (fs3.existsSync(localAbs)) {
8095
+ nextEntries.push({ ...entry, path: localPath });
8096
+ changed = true;
8097
+ registerAction({ category: "codemap", action: apply ? "updated" : "would_update", path: relPath(worktree, codemapPath), detail: `Shorten '${entry.path}' to local path '${localPath}'.` });
8098
+ continue;
8099
+ }
8100
+ unresolved.push({ category: "codemap", path: relPath(worktree, codemapPath), message: `Path '${entry.path}' violates Rule of Local Knowledge and no safe local replacement exists.` });
8101
+ nextEntries.push(entry);
8102
+ continue;
8103
+ }
8104
+ nextEntries.push(entry);
8105
+ }
8106
+ if (Array.isArray(map[section])) map[section] = nextEntries;
8107
+ }
8108
+ if (map.scope === "module" && !isOperationalRelPath(path3.relative(worktree, mapDir))) {
8109
+ const indexed = codemapIndexedPaths(map);
8110
+ const internals = Array.isArray(map.internals) ? map.internals : [];
8111
+ for (const item of fs3.readdirSync(mapDir, { withFileTypes: true })) {
8112
+ if (!item.isFile() || item.name === "codemap.yml" || !CODEMAP_SOURCE_EXTENSIONS.has(path3.extname(item.name))) continue;
8113
+ if (indexed.has(item.name)) continue;
8114
+ internals.push({ path: item.name });
8115
+ indexed.add(item.name);
8116
+ changed = true;
8117
+ registerAction({ category: "codemap", action: apply ? "updated" : "would_update", path: relPath(worktree, codemapPath), detail: `Categorize immediate source file '${item.name}' as internal.` });
8118
+ }
8119
+ if (internals.length > 0) map.internals = internals;
8120
+ }
8121
+ if (changed && apply) writeCodemap(codemapPath, map);
8122
+ }
8123
+ function repairCodemaps(worktree, apply, actions, unresolved, deps) {
8124
+ const ig = loadGitIgnoreMatcher(worktree);
8125
+ const rootCodemapPath = deps.optimaCodemapPath(worktree);
8126
+ const rootCodemapMissing = !fs3.existsSync(rootCodemapPath);
8127
+ if (rootCodemapMissing) {
8128
+ actions.push({ category: "codemap", action: apply ? "created" : "would_create", path: ".optima/codemap.yml", detail: "Create missing root CodeMap from template." });
8129
+ if (apply) deps.scaffoldOptimaRootCodemap(worktree);
8130
+ }
8131
+ if (fs3.existsSync(rootCodemapPath)) repairSingleCodemap(rootCodemapPath, worktree, apply, (action) => actions.push(action), unresolved, deps);
8132
+ const rootMap = fs3.existsSync(rootCodemapPath) ? readCodemap(rootCodemapPath, unresolved, worktree) : null;
8133
+ let rootChanged = false;
8134
+ const rootModulesRepairable = rootMap && (rootMap.modules === void 0 || Array.isArray(rootMap.modules));
8135
+ if (rootMap) {
8136
+ rootMap.scope ||= "repo";
8137
+ if (rootModulesRepairable) {
8138
+ rootMap.modules = Array.isArray(rootMap.modules) ? rootMap.modules : [];
8139
+ } else {
8140
+ unresolved.push({ category: "codemap", path: ".optima/codemap.yml", message: "Root modules section is object-shaped; repair will not add module entries to avoid changing user structure." });
8141
+ }
8142
+ }
8143
+ function walk(dirPath) {
8144
+ const relative = path3.relative(worktree, dirPath);
8145
+ if (relative && (isIgnoredPath(ig, relative) || isOperationalRelPath(relative) || isHiddenTree(relative))) return;
8146
+ const codemapPath = path3.join(dirPath, "codemap.yml");
8147
+ const hasCodemap = fs3.existsSync(codemapPath);
8148
+ const sourceDir = relative && containsSource(dirPath, ig, worktree);
8149
+ if (sourceDir && !hasCodemap && dirPath !== worktree) {
8150
+ if (hasImmediateSourceFile(dirPath, ig, worktree)) {
8151
+ actions.push({ category: "codemap", action: apply ? "created" : "would_create", path: relPath(worktree, codemapPath), detail: "Create missing module CodeMap for source directory." });
8152
+ if (apply) writeCodemap(codemapPath, createModuleCodemap(dirPath, worktree, deps));
8153
+ } else {
8154
+ unresolved.push({ category: "codemap", path: relPath(worktree, dirPath), message: "Directory contains source only in nested directories; create a local CodeMap after deciding module boundaries." });
8155
+ }
8156
+ }
8157
+ if (rootMap && rootModulesRepairable && relative && sourceDir && normalizeCodemapRelPath(relative).split("/").length === 1) {
8158
+ const modules = codemapSectionEntries(rootMap.modules);
8159
+ if (!modules.some((entry) => normalizeCodemapRelPath(entry.path) === normalizeCodemapRelPath(relative))) {
8160
+ rootMap.modules = modules;
8161
+ rootMap.modules.push({ path: normalizeCodemapRelPath(relative), summary: "Maintained source module." });
8162
+ rootChanged = true;
8163
+ actions.push({ category: "codemap", action: apply ? "updated" : "would_update", path: ".optima/codemap.yml", detail: `Register top-level source module '${normalizeCodemapRelPath(relative)}'.` });
8164
+ }
8165
+ }
8166
+ if (fs3.existsSync(codemapPath) && codemapPath !== rootCodemapPath) repairSingleCodemap(codemapPath, worktree, apply, (action) => actions.push(action), unresolved, deps);
8167
+ for (const item of fs3.readdirSync(dirPath, { withFileTypes: true })) {
8168
+ if (item.isDirectory()) walk(path3.join(dirPath, item.name));
8169
+ }
8170
+ }
8171
+ if (fs3.existsSync(worktree)) walk(worktree);
8172
+ if (rootMap && rootChanged && apply) writeCodemap(rootCodemapPath, rootMap);
8173
+ }
8174
+ function walkMarkdownFiles(dirPath) {
8175
+ if (!fs3.existsSync(dirPath)) return [];
8176
+ const files = [];
8177
+ for (const entry of fs3.readdirSync(dirPath, { withFileTypes: true })) {
8178
+ const entryPath = path3.join(dirPath, entry.name);
8179
+ if (entry.isDirectory()) {
8180
+ files.push(...walkMarkdownFiles(entryPath));
8181
+ } else if (entry.isFile() && entry.name.endsWith(".md")) {
8182
+ files.push(entryPath);
8183
+ }
8184
+ }
8185
+ return files;
8186
+ }
8187
+ function isMarkdownReferenceNormalizationExempt(line) {
8188
+ const normalized = line.toLowerCase().replace(/[`*_~]/g, "");
8189
+ const pathToken = "(?:tasks/|evidences/|docs/scrs/|codemap\\.yml|logs/|screenshots/)";
8190
+ if (new RegExp(`\\b(root|legacy)\\s+${pathToken}`).test(normalized)) return true;
8191
+ if (new RegExp(`\\b(do not|don't|never|must not|should not|avoid|forbid|prohibit)\\b[^\\n]*${pathToken}`).test(normalized)) return true;
8192
+ if (/\b(historical|problem|prohibition)\b[^\n]*(tasks\/|evidences\/|docs\/scrs\/|codemap\.yml|logs\/|screenshots\/)/.test(normalized)) return true;
8193
+ return false;
8194
+ }
8195
+ function rewriteReferenceToken(text, fromPrefix, toPrefix) {
8196
+ const escapedPrefix = fromPrefix.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
8197
+ const pattern = new RegExp("(^|[\\s([{\"'<`])" + escapedPrefix + `(?=[^\\s)\\]}>"']+)`, "g");
8198
+ return text.replace(pattern, `$1${toPrefix}`);
8199
+ }
8200
+ function rewriteOptimaMarkdownReferences(content, evidenceBasePath = null) {
8201
+ return content.split(/(\r?\n)/).map((part) => {
8202
+ if (part === "\n" || part === "\r\n" || isMarkdownReferenceNormalizationExempt(part)) return part;
8203
+ let next = part;
8204
+ next = rewriteReferenceToken(next, "tasks/", ".optima/tasks/");
8205
+ next = rewriteReferenceToken(next, "evidences/", ".optima/evidences/");
8206
+ next = rewriteReferenceToken(next, "docs/scrs/", ".optima/docs/scrs/");
8207
+ next = next.replace(/(^|[\s([{"'<`])codemap\.yml\b/g, "$1.optima/codemap.yml");
8208
+ if (evidenceBasePath) {
8209
+ next = rewriteReferenceToken(next, "logs/", `${evidenceBasePath}/logs/`);
8210
+ next = rewriteReferenceToken(next, "screenshots/", `${evidenceBasePath}/screenshots/`);
8211
+ }
8212
+ return next;
8213
+ }).join("");
8214
+ }
8215
+ function optimaEvidenceBaseForFile(worktree, filePath, deps) {
8216
+ const evidenceRoot = deps.optimaEvidencesDir(worktree);
8217
+ const relative = path3.relative(evidenceRoot, filePath).split(path3.sep).join("/");
8218
+ const [taskId] = relative.split("/");
8219
+ if (!taskId || taskId === ".." || relative.startsWith("../")) return null;
8220
+ return `.optima/evidences/${taskId}`;
8221
+ }
8222
+ function normalizeOptimaMarkdownReferences(worktree, deps) {
8223
+ const scanRoots = [
8224
+ deps.optimaTasksDir(worktree),
8225
+ deps.optimaEvidencesDir(worktree),
8226
+ deps.optimaScrsDir(worktree)
8227
+ ];
8228
+ const changed = [];
8229
+ for (const filePath of scanRoots.flatMap(walkMarkdownFiles)) {
8230
+ const raw = fs3.readFileSync(filePath, "utf8");
8231
+ const evidenceBasePath = filePath.startsWith(deps.optimaEvidencesDir(worktree) + path3.sep) ? optimaEvidenceBaseForFile(worktree, filePath, deps) : null;
8232
+ const rewritten = rewriteOptimaMarkdownReferences(raw, evidenceBasePath);
8233
+ if (rewritten !== raw) {
8234
+ fs3.writeFileSync(filePath, rewritten, "utf8");
8235
+ changed.push(relPath(worktree, filePath));
8236
+ }
8237
+ }
8238
+ return changed;
8239
+ }
8240
+ function missingOptimaGitignoreRules(worktree, deps) {
8241
+ if (!deps.isGitRepository(worktree)) return [];
8242
+ const gitignorePath = path3.join(worktree, ".gitignore");
8243
+ const existing = fs3.existsSync(gitignorePath) ? fs3.readFileSync(gitignorePath, "utf8") : "";
8244
+ const existingRules = new Set(existing.split(/\r?\n/).map((line) => line.trim()).filter(Boolean));
8245
+ return deps.optimaGitignoreRules.filter((rule) => !existingRules.has(rule));
8246
+ }
8247
+ function repairMode(args = {}) {
8248
+ const value = args.apply ?? args.mode;
8249
+ if (value === true || value === "apply") return "apply";
8250
+ return "dry-run";
8251
+ }
8252
+ function pushRepairAction(actions, category, action, pathValue, detail) {
8253
+ actions.push({ category, action, path: pathValue, detail });
8254
+ }
8255
+ function planOptimaRepair(worktree, args = {}, deps) {
8256
+ const mode = repairMode(args);
8257
+ const apply = mode === "apply";
8258
+ const actions = [];
8259
+ const unresolved = [];
8260
+ const hadOptima = fs3.existsSync(deps.optimaDir(worktree));
8261
+ const missingGitignoreRules = missingOptimaGitignoreRules(worktree, deps);
8262
+ const markdownBefore = apply ? [] : walkMarkdownFiles(deps.optimaDir(worktree)).filter((filePath) => {
8263
+ const raw = fs3.readFileSync(filePath, "utf8");
8264
+ const evidenceBasePath = filePath.startsWith(deps.optimaEvidencesDir(worktree) + path3.sep) ? optimaEvidenceBaseForFile(worktree, filePath, deps) : null;
8265
+ return rewriteOptimaMarkdownReferences(raw, evidenceBasePath) !== raw;
8266
+ }).map((filePath) => relPath(worktree, filePath));
8267
+ if (!hadOptima) pushRepairAction(actions, "operational", apply ? "created" : "would_create", ".optima/", "Create Optima operational root.");
8268
+ const legacySources = [
8269
+ [".orbita/", deps.legacyOrbitaDir(worktree)],
8270
+ [".staticeng/", deps.legacyStaticEngDir(worktree)],
8271
+ [".nomadwork/", deps.legacyNomadworkDir(worktree)],
8272
+ [".nomadworks/", deps.legacyNomadworksDir(worktree)],
8273
+ ["tasks/", path3.join(worktree, "tasks")],
8274
+ ["evidences/", path3.join(worktree, "evidences")],
8275
+ ["docs/scrs/", path3.join(worktree, "docs", "scrs")],
8276
+ ["codemap.yml", path3.join(worktree, "codemap.yml")],
8277
+ ["codemap.yaml", path3.join(worktree, "codemap.yaml")]
8278
+ ];
8279
+ if (!deps.isOptimaPluginPackageWorktree(worktree)) legacySources.push(["policies/", path3.join(worktree, "policies")]);
8280
+ for (const [display, sourcePath] of legacySources) {
8281
+ if (fs3.existsSync(sourcePath)) pushRepairAction(actions, "legacy", apply ? "migrated" : "would_migrate", display, "Move or merge legacy/root Optima artifact into .optima using preservation safeguards.");
8282
+ }
8283
+ if (apply) deps.migrateLegacyOptimaLayout(worktree);
8284
+ const configMissing = !fs3.existsSync(deps.repoConfigPath(worktree));
8285
+ if (configMissing) pushRepairAction(actions, "config", apply ? "created" : "would_create", ".optima/.config/optima.yaml", "Create missing local Optima config from template.");
8286
+ if (apply) deps.scaffoldOptimaConfig(worktree, args.team_mode || "full");
8287
+ const requiredFiles = [
8288
+ [path3.join(deps.optimaTasksDir(worktree), "current.md"), "registry", ".optima/tasks/current.md", deps.currentTasksRegistryContent()],
8289
+ [path3.join(deps.optimaTasksDir(worktree), "done.md"), "registry", ".optima/tasks/done.md", deps.doneTasksRegistryContent()],
8290
+ [path3.join(deps.optimaScrsDir(worktree), "current.md"), "registry", ".optima/docs/scrs/current.md", deps.currentScrRegistryContent()],
8291
+ [path3.join(deps.optimaScrsDir(worktree), "done.md"), "registry", ".optima/docs/scrs/done.md", deps.doneScrRegistryContent()],
8292
+ [path3.join(deps.optimaTasksDir(worktree), "task-template.md"), "template", ".optima/tasks/task-template.md", deps.taskTemplateContent()],
8293
+ [path3.join(deps.optimaTasksDir(worktree), "subtask-template.md"), "template", ".optima/tasks/subtask-template.md", deps.subtaskTemplateContent()],
8294
+ [path3.join(deps.repoPoliciesDir(worktree), "README.md"), "policy", ".optima/policies/README.md", deps.repoLocalPoliciesReadme]
8295
+ ];
8296
+ for (const [filePath, category, displayPath, content] of requiredFiles) {
8297
+ if (!fs3.existsSync(filePath)) {
8298
+ pushRepairAction(actions, category, apply ? "created" : "would_create", displayPath, "Create missing Optima scaffold file without overwriting existing content.");
8299
+ if (apply) deps.ensureFileIfMissing(filePath, content);
8300
+ }
8301
+ }
8302
+ if (apply) {
8303
+ deps.scaffoldOptimaReadmes(worktree);
8304
+ deps.ensureOptimaRegistries(worktree);
8305
+ normalizeOptimaMarkdownReferences(worktree, deps).forEach((filePath) => {
8306
+ pushRepairAction(actions, "markdown", "normalized", filePath, "Normalize Optima artifact paths in Markdown.");
8307
+ });
8308
+ } else {
8309
+ markdownBefore.forEach((filePath) => pushRepairAction(actions, "markdown", "would_normalize", filePath, "Normalize Optima artifact paths in Markdown."));
8310
+ }
8311
+ if (missingGitignoreRules.length > 0) {
8312
+ pushRepairAction(actions, "gitignore", apply ? "updated" : "would_update", ".gitignore", `Add ${missingGitignoreRules.length} Optima local/private rule(s).`);
8313
+ if (apply) deps.ensureOptimaGitignoreRules(worktree);
8314
+ }
8315
+ repairCodemaps(worktree, apply, actions, unresolved, deps);
8316
+ return { mode, actions, unresolved };
8317
+ }
8318
+ function formatRepairResult(plan, validationResult = null, formatValidationResult2 = (res) => JSON.stringify(res, null, 2)) {
8319
+ const lines = [
8320
+ `Optima repair ${plan.mode === "apply" ? "applied" : "dry-run"}.`,
8321
+ "Scope inspected: config, registries, templates, policy scaffolding, legacy/root artifact leakage, Markdown path normalization, gitignore rules, and CodeMap integrity.",
8322
+ "",
8323
+ "Planned/Applied fixes:"
8324
+ ];
8325
+ if (plan.actions.length === 0) {
8326
+ lines.push("- None");
8327
+ } else {
8328
+ for (const action of plan.actions) {
8329
+ lines.push(`- [${action.category}] ${action.action} ${action.path}: ${action.detail}`);
8330
+ }
8331
+ }
8332
+ lines.push("", "Unresolved issues:");
8333
+ if (plan.unresolved.length === 0) {
8334
+ lines.push("- None");
8335
+ } else {
8336
+ for (const issue of plan.unresolved) {
8337
+ lines.push(`- [${issue.category}] ${issue.path}: ${issue.message}`);
8338
+ }
8339
+ }
8340
+ if (validationResult) {
8341
+ lines.push("", "Validation after apply:", formatValidationResult2(validationResult));
8342
+ } else {
8343
+ lines.push("", "Validation after apply: not run in dry-run mode.");
8344
+ }
8345
+ return lines.join("\n");
8346
+ }
8347
+
8348
+ // src/validate_logic.js
8349
+ var import_yaml2 = __toESM(require_dist(), 1);
8350
+ var import_ignore2 = __toESM(require_ignore(), 1);
8351
+ import fs4 from "node:fs";
8352
+ import path4 from "node:path";
7727
8353
  async function optima_validate_logic(worktree) {
7728
- const rootCodemapPath = path.join(worktree, ".optima", "codemap.yml");
7729
- if (!fs.existsSync(rootCodemapPath)) return { ok: false, errors: [".optima/codemap.yml not found."], warnings: [] };
8354
+ const rootCodemapPath = path4.join(worktree, ".optima", "codemap.yml");
8355
+ if (!fs4.existsSync(rootCodemapPath)) return { ok: false, errors: [".optima/codemap.yml not found."], warnings: [] };
7730
8356
  const errors = [];
7731
8357
  const warnings = [];
7732
- const ig = (0, import_ignore.default)();
8358
+ const ig = (0, import_ignore2.default)();
7733
8359
  ig.add(".git");
7734
- const gitignorePath = path.join(worktree, ".gitignore");
7735
- if (fs.existsSync(gitignorePath)) {
7736
- ig.add(fs.readFileSync(gitignorePath, "utf8"));
8360
+ const gitignorePath = path4.join(worktree, ".gitignore");
8361
+ if (fs4.existsSync(gitignorePath)) {
8362
+ ig.add(fs4.readFileSync(gitignorePath, "utf8"));
7737
8363
  }
7738
8364
  const sourceExtensions = [
7739
8365
  ".js",
@@ -7771,32 +8397,32 @@ async function optima_validate_logic(worktree) {
7771
8397
  ".codenomad"
7772
8398
  ]);
7773
8399
  const operationalFolders = [".optima", "templates", "dist"];
7774
- const isHiddenTree = (relPath) => {
7775
- if (!relPath) return false;
7776
- return relPath.split(path.sep).some((part) => part.startsWith("."));
8400
+ const isHiddenTree2 = (relPath2) => {
8401
+ if (!relPath2) return false;
8402
+ return relPath2.split(path4.sep).some((part) => part.startsWith("."));
7777
8403
  };
7778
- const firstPathSegment = (relPath) => relPath.split(path.sep).filter(Boolean)[0] || "";
7779
- const isOperationalRelPath = (relPath) => {
7780
- if (!relPath) return false;
7781
- const firstSegment = firstPathSegment(relPath);
8404
+ const firstPathSegment2 = (relPath2) => relPath2.split(path4.sep).filter(Boolean)[0] || "";
8405
+ const isOperationalRelPath2 = (relPath2) => {
8406
+ if (!relPath2) return false;
8407
+ const firstSegment = firstPathSegment2(relPath2);
7782
8408
  if (legacyOperationalRoots.has(firstSegment)) return true;
7783
- return operationalFolders.some((f) => relPath === f || relPath.startsWith(f + path.sep));
8409
+ return operationalFolders.some((f) => relPath2 === f || relPath2.startsWith(f + path4.sep));
7784
8410
  };
7785
8411
  const getSectionEntries = (value) => {
7786
8412
  if (Array.isArray(value)) return value;
7787
8413
  if (value && typeof value === "object") return Object.values(value);
7788
8414
  return [];
7789
8415
  };
7790
- const normalizeRelativePath = (relPath) => path.normalize(relPath).replace(/\\/g, "/").replace(/\/$/, "");
8416
+ const normalizeRelativePath = (relPath2) => path4.normalize(relPath2).replace(/\\/g, "/").replace(/\/$/, "");
7791
8417
  const isSourceDir = (dirPath) => {
7792
- const dirRelPath = path.relative(worktree, dirPath);
7793
- if (isOperationalRelPath(dirRelPath)) return false;
7794
- const items = fs.readdirSync(dirPath, { withFileTypes: true });
8418
+ const dirRelPath = path4.relative(worktree, dirPath);
8419
+ if (isOperationalRelPath2(dirRelPath)) return false;
8420
+ const items = fs4.readdirSync(dirPath, { withFileTypes: true });
7795
8421
  for (const item of items) {
7796
- const childPath = path.join(dirPath, item.name);
7797
- const relPath = path.relative(worktree, childPath);
7798
- if (ig.ignores(relPath) || isOperationalRelPath(relPath)) continue;
7799
- if (item.isFile() && sourceExtensions.includes(path.extname(item.name))) return true;
8422
+ const childPath = path4.join(dirPath, item.name);
8423
+ const relPath2 = path4.relative(worktree, childPath);
8424
+ if (ig.ignores(relPath2) || isOperationalRelPath2(relPath2)) continue;
8425
+ if (item.isFile() && sourceExtensions.includes(path4.extname(item.name))) return true;
7800
8426
  if (item.isDirectory()) {
7801
8427
  if (isSourceDir(childPath)) return true;
7802
8428
  }
@@ -7804,10 +8430,10 @@ async function optima_validate_logic(worktree) {
7804
8430
  return false;
7805
8431
  };
7806
8432
  function validateMap(filePath) {
7807
- const content = fs.readFileSync(filePath, "utf8");
8433
+ const content = fs4.readFileSync(filePath, "utf8");
7808
8434
  let map;
7809
8435
  try {
7810
- map = import_yaml.default.parse(content);
8436
+ map = import_yaml2.default.parse(content);
7811
8437
  if (!map || typeof map !== "object") {
7812
8438
  errors.push(`${filePath}: CodeMap is empty or invalid.`);
7813
8439
  return;
@@ -7816,32 +8442,32 @@ async function optima_validate_logic(worktree) {
7816
8442
  errors.push(`${filePath}: Invalid YAML.`);
7817
8443
  return;
7818
8444
  }
7819
- const dir = path.dirname(filePath);
8445
+ const dir = path4.dirname(filePath);
7820
8446
  const pathBase = filePath === rootCodemapPath ? worktree : dir;
7821
8447
  const indexedPaths = /* @__PURE__ */ new Set();
7822
8448
  const sectionsToVerify = ["modules", "entrypoints", "sources_of_truth", "links", "internals"];
7823
8449
  for (const section of sectionsToVerify) {
7824
8450
  for (const item of getSectionEntries(map[section])) {
7825
8451
  if (item?.path) {
7826
- indexedPaths.add(path.normalize(item.path));
8452
+ indexedPaths.add(path4.normalize(item.path));
7827
8453
  if (section === "links" && (item.path.startsWith("http://") || item.path.startsWith("https://"))) {
7828
8454
  continue;
7829
8455
  }
7830
- const absPath = path.isAbsolute(item.path) ? item.path : path.join(pathBase, item.path);
7831
- if (!fs.existsSync(absPath)) {
8456
+ const absPath = path4.isAbsolute(item.path) ? item.path : path4.join(pathBase, item.path);
8457
+ if (!fs4.existsSync(absPath)) {
7832
8458
  errors.push(`${filePath}: ${section.slice(0, -1)} path does not exist: ${item.path}`);
7833
8459
  }
7834
8460
  }
7835
8461
  }
7836
8462
  }
7837
- const relDir = path.relative(worktree, dir);
7838
- const isOperational = isOperationalRelPath(relDir);
8463
+ const relDir = path4.relative(worktree, dir);
8464
+ const isOperational = isOperationalRelPath2(relDir);
7839
8465
  if (map.scope === "module" && !isOperational) {
7840
- const items = fs.readdirSync(dir, { withFileTypes: true });
8466
+ const items = fs4.readdirSync(dir, { withFileTypes: true });
7841
8467
  for (const item of items) {
7842
- if (item.isFile() && sourceExtensions.includes(path.extname(item.name))) {
8468
+ if (item.isFile() && sourceExtensions.includes(path4.extname(item.name))) {
7843
8469
  if (item.name === "codemap.yml") continue;
7844
- if (!indexedPaths.has(path.normalize(item.name))) {
8470
+ if (!indexedPaths.has(path4.normalize(item.name))) {
7845
8471
  errors.push(`${filePath}: Unindexed source file found: '${item.name}'. Every source file must be categorized in a section (e.g., 'internals').`);
7846
8472
  }
7847
8473
  }
@@ -7851,7 +8477,7 @@ async function optima_validate_logic(worktree) {
7851
8477
  for (const key of pathKeys) {
7852
8478
  for (const entry of getSectionEntries(map[key])) {
7853
8479
  if (!entry?.path || entry.path.startsWith("http://") || entry.path.startsWith("https://")) continue;
7854
- if (path.isAbsolute(entry.path)) continue;
8480
+ if (path4.isAbsolute(entry.path)) continue;
7855
8481
  const normalizedPath = normalizeRelativePath(entry.path);
7856
8482
  if (!normalizedPath || normalizedPath === ".") continue;
7857
8483
  const parts = normalizedPath.split("/").filter((p) => p && p !== ".");
@@ -7863,30 +8489,30 @@ async function optima_validate_logic(worktree) {
7863
8489
  }
7864
8490
  }
7865
8491
  const walk = (dir) => {
7866
- const relDir = path.relative(worktree, dir);
8492
+ const relDir = path4.relative(worktree, dir);
7867
8493
  if (relDir && ig.ignores(relDir)) return;
7868
- if (isOperationalRelPath(relDir)) return;
7869
- if (isHiddenTree(relDir)) return;
7870
- const hasCodemap = fs.existsSync(path.join(dir, "codemap.yml"));
7871
- const items = fs.readdirSync(dir, { withFileTypes: true });
7872
- if (!relDir.startsWith(path.join(".optima", "tasks", "done"))) {
8494
+ if (isOperationalRelPath2(relDir)) return;
8495
+ if (isHiddenTree2(relDir)) return;
8496
+ const hasCodemap = fs4.existsSync(path4.join(dir, "codemap.yml"));
8497
+ const items = fs4.readdirSync(dir, { withFileTypes: true });
8498
+ if (!relDir.startsWith(path4.join(".optima", "tasks", "done"))) {
7873
8499
  for (const item of items) {
7874
8500
  if (item.isFile() && item.name.endsWith(".md")) {
7875
- const content = fs.readFileSync(path.join(dir, item.name), "utf8");
8501
+ const content = fs4.readFileSync(path4.join(dir, item.name), "utf8");
7876
8502
  if (content.includes("[To be defined]") || content.includes("[Insert ")) {
7877
- const relFilePath = path.join(relDir, item.name);
8503
+ const relFilePath = path4.join(relDir, item.name);
7878
8504
  errors.push(`Documentation Placeholder found: '${relFilePath}' still contains [To be defined] or [Insert ...] placeholders.`);
7879
8505
  }
7880
8506
  }
7881
8507
  }
7882
8508
  }
7883
- const isOperational = isOperationalRelPath(relDir);
8509
+ const isOperational = isOperationalRelPath2(relDir);
7884
8510
  if (relDir !== "" && !hasCodemap && isSourceDir(dir) && !isOperational) {
7885
8511
  errors.push(`Missing CodeMap: Directory '${relDir}' contains source but has no codemap.yml.`);
7886
8512
  }
7887
- if (hasCodemap) validateMap(path.join(dir, "codemap.yml"));
8513
+ if (hasCodemap) validateMap(path4.join(dir, "codemap.yml"));
7888
8514
  for (const item of items) {
7889
- if (item.isDirectory()) walk(path.join(dir, item.name));
8515
+ if (item.isDirectory()) walk(path4.join(dir, item.name));
7890
8516
  }
7891
8517
  };
7892
8518
  validateMap(rootCodemapPath);
@@ -7899,12 +8525,12 @@ async function optima_validate_logic(worktree) {
7899
8525
  }
7900
8526
 
7901
8527
  // src/index.js
7902
- var PKG_ROOT = path2.resolve(path2.dirname(fileURLToPath(import.meta.url)), "..");
7903
- var BUNDLE_ASSETS_DIR = path2.join(PKG_ROOT, "assets");
7904
- var BUNDLE_AGENTS_DIR = path2.join(BUNDLE_ASSETS_DIR, "agents");
7905
- var BUNDLE_POLICIES_DIR = path2.join(BUNDLE_ASSETS_DIR, "policies");
7906
- var TEMPLATES_DIR = path2.join(PKG_ROOT, "templates");
7907
- var HUMANS_REGISTRY_PATH = path2.join(PKG_ROOT, "docs", "core", "humans.md");
8528
+ var PKG_ROOT = path5.resolve(path5.dirname(fileURLToPath(import.meta.url)), "..");
8529
+ var BUNDLE_ASSETS_DIR = path5.join(PKG_ROOT, "assets");
8530
+ var BUNDLE_AGENTS_DIR = path5.join(BUNDLE_ASSETS_DIR, "agents");
8531
+ var BUNDLE_POLICIES_DIR = path5.join(BUNDLE_ASSETS_DIR, "policies");
8532
+ var TEMPLATES_DIR = path5.join(PKG_ROOT, "templates");
8533
+ var HUMANS_REGISTRY_PATH = path5.join(PKG_ROOT, "docs", "core", "humans.md");
7908
8534
  var MANDATORY_AGENTS = /* @__PURE__ */ new Set(["product_manager", "business_analyst", "tech_lead"]);
7909
8535
  var MINI_MODE_AGENTS = /* @__PURE__ */ new Set(["product_manager", "business_analyst", "tech_lead"]);
7910
8536
  var CLICKUP_IGNORED_TASK_TYPES = ["Idea", "Backlog", "Hito", "Nota de reuni\xF3n", "Respuesta del formulario"];
@@ -8040,18 +8666,18 @@ function objectIdentity(value) {
8040
8666
  return objectIdentityMap.get(value);
8041
8667
  }
8042
8668
  function isRootDirectory(candidate) {
8043
- const resolved = path2.resolve(candidate);
8044
- return resolved === path2.parse(resolved).root;
8669
+ const resolved = path5.resolve(candidate);
8670
+ return resolved === path5.parse(resolved).root;
8045
8671
  }
8046
8672
  function isSafeWritableDirectory(candidate) {
8047
8673
  if (typeof candidate !== "string" || !candidate.trim()) return false;
8048
- if (!path2.isAbsolute(candidate)) return false;
8049
- const resolved = path2.resolve(candidate);
8674
+ if (!path5.isAbsolute(candidate)) return false;
8675
+ const resolved = path5.resolve(candidate);
8050
8676
  if (isRootDirectory(resolved)) return false;
8051
8677
  try {
8052
- const stat = fs2.statSync(resolved);
8678
+ const stat = fs5.statSync(resolved);
8053
8679
  if (!stat.isDirectory()) return false;
8054
- fs2.accessSync(resolved, fs2.constants.W_OK);
8680
+ fs5.accessSync(resolved, fs5.constants.W_OK);
8055
8681
  return true;
8056
8682
  } catch {
8057
8683
  return false;
@@ -8067,7 +8693,7 @@ function resolveSafeWorktree(context = {}, pluginWorktree = null) {
8067
8693
  ];
8068
8694
  for (const candidate of candidates) {
8069
8695
  if (typeof candidate !== "string" || !candidate.trim()) continue;
8070
- const resolved = path2.resolve(candidate);
8696
+ const resolved = path5.resolve(candidate);
8071
8697
  if (isSafeWritableDirectory(resolved)) return resolved;
8072
8698
  }
8073
8699
  throw new Error(SAFE_WORKTREE_FAILURE);
@@ -8082,13 +8708,13 @@ function safeWorktreeOrFailure(context, pluginWorktree) {
8082
8708
  function explicitSafeInputWorktree(input = {}) {
8083
8709
  for (const candidate of [input?.worktree, input?.directory]) {
8084
8710
  if (typeof candidate !== "string" || !candidate.trim()) continue;
8085
- const resolved = path2.resolve(candidate);
8711
+ const resolved = path5.resolve(candidate);
8086
8712
  if (isSafeWritableDirectory(resolved)) return resolved;
8087
8713
  }
8088
8714
  return null;
8089
8715
  }
8090
8716
  function isGitRepository(worktree) {
8091
- return fs2.existsSync(path2.join(worktree, ".git"));
8717
+ return fs5.existsSync(path5.join(worktree, ".git"));
8092
8718
  }
8093
8719
  function normalizeLooseToken(value) {
8094
8720
  return String(value ?? "").trim().normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
@@ -8122,8 +8748,8 @@ function parseHumansRegistry(markdown = "") {
8122
8748
  return roles;
8123
8749
  }
8124
8750
  function loadHumansRegistry(registryPath = HUMANS_REGISTRY_PATH) {
8125
- if (!fs2.existsSync(registryPath)) return {};
8126
- return parseHumansRegistry(fs2.readFileSync(registryPath, "utf8"));
8751
+ if (!fs5.existsSync(registryPath)) return {};
8752
+ return parseHumansRegistry(fs5.readFileSync(registryPath, "utf8"));
8127
8753
  }
8128
8754
  function resolveHumanRoles(roles = CLICKUP_FINAL_APPROVER_ROLES, registry = loadHumansRegistry()) {
8129
8755
  return [...new Set(roles.map((role) => registry[String(role ?? "").trim()] || "").filter(Boolean))];
@@ -8290,7 +8916,7 @@ function parseMarkdownArtifact(markdown = "", { requiredSections = [] } = {}) {
8290
8916
  };
8291
8917
  }
8292
8918
  function readMarkdownArtifact(filePath, options = {}) {
8293
- const markdown = fs2.readFileSync(filePath, "utf8");
8919
+ const markdown = fs5.readFileSync(filePath, "utf8");
8294
8920
  return parseMarkdownArtifact(markdown, options);
8295
8921
  }
8296
8922
  function stripRawLogSections(sections = {}) {
@@ -8576,7 +9202,7 @@ function buildClickUpSummaryPayload({ summaryMarkdown = "", summaryPath = "", ta
8576
9202
  function deriveClickUpWorktree({ baseWorktree = "", taskId, taskType, parentTaskId, subtaskId } = {}) {
8577
9203
  const branch = deriveClickUpBranchName({ taskType, parentTaskId, subtaskId, taskId });
8578
9204
  const root = baseWorktree || process.cwd();
8579
- return path2.join(path2.dirname(root), `${path2.basename(root)}-${branch.replace(/\//g, "-")}`);
9205
+ return path5.join(path5.dirname(root), `${path5.basename(root)}-${branch.replace(/\//g, "-")}`);
8580
9206
  }
8581
9207
  function clickUpCustomFieldValue(task = {}, names = []) {
8582
9208
  const fields = Array.isArray(task.custom_fields) ? task.custom_fields : [];
@@ -8600,12 +9226,12 @@ function safeExistingClickUpWorktree({ metadata = {}, branch = "" } = {}) {
8600
9226
  const taskMetadata = metadataTaskRouting(metadata);
8601
9227
  const existingWorktree = typeof taskMetadata.worktree === "string" ? taskMetadata.worktree.trim() : "";
8602
9228
  const existingBranch = typeof taskMetadata.branch === "string" ? taskMetadata.branch.trim() : "";
8603
- if (!existingWorktree || !path2.isAbsolute(existingWorktree) || !fs2.existsSync(existingWorktree)) return null;
9229
+ if (!existingWorktree || !path5.isAbsolute(existingWorktree) || !fs5.existsSync(existingWorktree)) return null;
8604
9230
  try {
8605
- const stat = fs2.statSync(existingWorktree);
9231
+ const stat = fs5.statSync(existingWorktree);
8606
9232
  if (!stat.isDirectory()) return null;
8607
9233
  if (branch && existingBranch && existingBranch !== branch) return null;
8608
- return { branch: existingBranch || branch, worktree: path2.resolve(existingWorktree), reused: true };
9234
+ return { branch: existingBranch || branch, worktree: path5.resolve(existingWorktree), reused: true };
8609
9235
  } catch {
8610
9236
  return null;
8611
9237
  }
@@ -8616,10 +9242,10 @@ function ensureClickUpTaskWorktree({ baseWorktree = "", taskId, taskType = "Tare
8616
9242
  const existing = safeExistingClickUpWorktree({ metadata: existingMetadata, branch });
8617
9243
  if (existing) return { ...existing, branch };
8618
9244
  const worktreePath = deriveClickUpWorktree({ baseWorktree, taskId, taskType, parentTaskId: effectiveParent, subtaskId });
8619
- if (fs2.existsSync(worktreePath)) return { branch, worktree: path2.resolve(worktreePath), reused: true };
9245
+ if (fs5.existsSync(worktreePath)) return { branch, worktree: path5.resolve(worktreePath), reused: true };
8620
9246
  if (allowNonGitFallback) {
8621
- fs2.mkdirSync(worktreePath, { recursive: true });
8622
- return { branch, worktree: path2.resolve(worktreePath), reused: false, fallback: "non_git" };
9247
+ fs5.mkdirSync(worktreePath, { recursive: true });
9248
+ return { branch, worktree: path5.resolve(worktreePath), reused: false, fallback: "non_git" };
8623
9249
  }
8624
9250
  const startPoint = (() => {
8625
9251
  try {
@@ -8630,7 +9256,7 @@ function ensureClickUpTaskWorktree({ baseWorktree = "", taskId, taskType = "Tare
8630
9256
  }
8631
9257
  })();
8632
9258
  runGitFn(baseWorktree, ["worktree", "add", "-b", branch, worktreePath, startPoint]);
8633
- return { branch, worktree: path2.resolve(worktreePath), reused: false, startPoint };
9259
+ return { branch, worktree: path5.resolve(worktreePath), reused: false, startPoint };
8634
9260
  }
8635
9261
  function normalizeClickUpDefinitionDocParent(parent = {}) {
8636
9262
  const docId = String(parent.doc_id || parent.docId || CLICKUP_DEFINITION_DOC_PARENT.doc_id).trim();
@@ -8765,76 +9391,10 @@ function buildClickUpTransitionPayload({ fromStatus, toStatus, validationPassed
8765
9391
  }
8766
9392
  };
8767
9393
  }
8768
- function toGitPath(worktree, targetPath) {
8769
- const relativePath = path2.relative(worktree, targetPath);
8770
- if (!relativePath || relativePath.startsWith("..") || path2.isAbsolute(relativePath)) return null;
8771
- return relativePath.split(path2.sep).join("/");
8772
- }
8773
- function runGit(worktree, args) {
8774
- return execFileSync("git", args, {
8775
- cwd: worktree,
8776
- encoding: "utf8",
8777
- stdio: ["ignore", "pipe", "pipe"]
8778
- });
8779
- }
8780
- function gitMigrationState(worktree) {
8781
- try {
8782
- const root = runGit(worktree, ["rev-parse", "--show-toplevel"]).trim();
8783
- if (path2.resolve(root) !== path2.resolve(worktree)) return null;
8784
- return { worktree };
8785
- } catch {
8786
- return null;
8787
- }
8788
- }
8789
- function isGitTracked(gitState, targetPath) {
8790
- if (!gitState) return false;
8791
- const gitPath = toGitPath(gitState.worktree, targetPath);
8792
- if (!gitPath) return false;
8793
- try {
8794
- runGit(gitState.worktree, ["ls-files", "--error-unmatch", "--", gitPath]);
8795
- return true;
8796
- } catch {
8797
- return false;
8798
- }
8799
- }
8800
- function hasGitTrackedChildren(gitState, targetPath) {
8801
- if (!gitState) return false;
8802
- const gitPath = toGitPath(gitState.worktree, targetPath);
8803
- if (!gitPath) return false;
8804
- try {
8805
- return runGit(gitState.worktree, ["ls-files", "--", `${gitPath}/`]).trim().length > 0;
8806
- } catch {
8807
- return false;
8808
- }
8809
- }
8810
- function gitAwareMoveIfTracked(sourcePath, destinationPath, gitState) {
8811
- const sourceIsTracked = isGitTracked(gitState, sourcePath) || hasGitTrackedChildren(gitState, sourcePath);
8812
- if (!gitState || !sourceIsTracked || fs2.existsSync(destinationPath)) return false;
8813
- const sourceGitPath = toGitPath(gitState.worktree, sourcePath);
8814
- const destinationGitPath = toGitPath(gitState.worktree, destinationPath);
8815
- if (!sourceGitPath || !destinationGitPath) return false;
8816
- fs2.mkdirSync(path2.dirname(destinationPath), { recursive: true });
8817
- try {
8818
- runGit(gitState.worktree, ["mv", "--", sourceGitPath, destinationGitPath]);
8819
- return true;
8820
- } catch {
8821
- return false;
8822
- }
8823
- }
8824
- function stageGitAwareMerge(sourcePath, destinationPath, gitState) {
8825
- if (!gitState || !isGitTracked(gitState, sourcePath)) return;
8826
- const sourceGitPath = toGitPath(gitState.worktree, sourcePath);
8827
- const destinationGitPath = toGitPath(gitState.worktree, destinationPath);
8828
- if (!sourceGitPath || !destinationGitPath) return;
8829
- try {
8830
- runGit(gitState.worktree, ["add", "-A", "--", sourceGitPath, destinationGitPath]);
8831
- } catch {
8832
- }
8833
- }
8834
9394
  function ensureOptimaGitignoreRules(worktree) {
8835
9395
  if (!isGitRepository(worktree)) return { touched: false, added: [] };
8836
- const gitignorePath = path2.join(worktree, ".gitignore");
8837
- const existing = fs2.existsSync(gitignorePath) ? fs2.readFileSync(gitignorePath, "utf8") : "";
9396
+ const gitignorePath = path5.join(worktree, ".gitignore");
9397
+ const existing = fs5.existsSync(gitignorePath) ? fs5.readFileSync(gitignorePath, "utf8") : "";
8838
9398
  const existingRules = new Set(existing.split(/\r?\n/).map((line) => line.trim()).filter(Boolean));
8839
9399
  const missingRules = OPTIMA_GITIGNORE_RULES.filter((rule) => !existingRules.has(rule));
8840
9400
  if (missingRules.length === 0) return { touched: false, added: [] };
@@ -8844,49 +9404,45 @@ function ensureOptimaGitignoreRules(worktree) {
8844
9404
  "# Optima local/private state",
8845
9405
  ...missingRules
8846
9406
  ].join("\n");
8847
- fs2.writeFileSync(gitignorePath, `${existing}${prefix}${separator}${block}
9407
+ fs5.writeFileSync(gitignorePath, `${existing}${prefix}${separator}${block}
8848
9408
  `, "utf8");
8849
9409
  return { touched: true, added: missingRules };
8850
9410
  }
8851
- function compactPromptPath(filePath) {
8852
- if (!filePath.endsWith(".md") || filePath.endsWith(".prompt.md")) return null;
8853
- return filePath.replace(/\.md$/, ".prompt.md");
8854
- }
8855
9411
  function optimaDir(worktree) {
8856
- return path2.join(worktree, OPTIMA_DIRNAME);
9412
+ return path5.join(worktree, OPTIMA_DIRNAME);
8857
9413
  }
8858
9414
  function optimaLocalConfigDir(worktree) {
8859
- return path2.join(optimaDir(worktree), ".config");
9415
+ return path5.join(optimaDir(worktree), ".config");
8860
9416
  }
8861
9417
  function optimaConfigDir(worktree) {
8862
9418
  return optimaLocalConfigDir(worktree);
8863
9419
  }
8864
9420
  function optimaCodemapPath(worktree) {
8865
- return path2.join(optimaDir(worktree), "codemap.yml");
9421
+ return path5.join(optimaDir(worktree), "codemap.yml");
8866
9422
  }
8867
9423
  function optimaTasksDir(worktree) {
8868
- return path2.join(optimaDir(worktree), "tasks");
9424
+ return path5.join(optimaDir(worktree), "tasks");
8869
9425
  }
8870
9426
  function optimaEvidencesDir(worktree) {
8871
- return path2.join(optimaDir(worktree), "evidences");
9427
+ return path5.join(optimaDir(worktree), "evidences");
8872
9428
  }
8873
9429
  function optimaScrsDir(worktree) {
8874
- return path2.join(optimaDir(worktree), "docs", "scrs");
9430
+ return path5.join(optimaDir(worktree), "docs", "scrs");
8875
9431
  }
8876
9432
  function legacyNomadworkDir(worktree) {
8877
- return path2.join(worktree, LEGACY_NOMADWORK_DIRNAME);
9433
+ return path5.join(worktree, LEGACY_NOMADWORK_DIRNAME);
8878
9434
  }
8879
9435
  function legacyNomadworksDir(worktree) {
8880
- return path2.join(worktree, LEGACY_NOMADWORKS_DIRNAME);
9436
+ return path5.join(worktree, LEGACY_NOMADWORKS_DIRNAME);
8881
9437
  }
8882
9438
  function legacyOrbitaDir(worktree) {
8883
- return path2.join(worktree, LEGACY_ORBITA_DIRNAME);
9439
+ return path5.join(worktree, LEGACY_ORBITA_DIRNAME);
8884
9440
  }
8885
9441
  function legacyStaticEngDir(worktree) {
8886
- return path2.join(worktree, LEGACY_STATICENG_DIRNAME);
9442
+ return path5.join(worktree, LEGACY_STATICENG_DIRNAME);
8887
9443
  }
8888
9444
  function repoConfigPath(worktree) {
8889
- return path2.join(optimaConfigDir(worktree), "optima.yaml");
9445
+ return path5.join(optimaConfigDir(worktree), "optima.yaml");
8890
9446
  }
8891
9447
  function normalizeLegacyDiscussionEntry(entry) {
8892
9448
  if (!entry || typeof entry !== "object") return entry;
@@ -8899,25 +9455,25 @@ function normalizeLegacyDiscussionEntry(entry) {
8899
9455
  return next;
8900
9456
  }
8901
9457
  function repoPoliciesDir(worktree) {
8902
- return path2.join(optimaDir(worktree), "policies");
9458
+ return path5.join(optimaDir(worktree), "policies");
8903
9459
  }
8904
9460
  function generatedPoliciesDir(worktree) {
8905
- return path2.join(optimaLocalConfigDir(worktree), "generated", "policies");
9461
+ return path5.join(optimaLocalConfigDir(worktree), "generated", "policies");
8906
9462
  }
8907
9463
  function generatedAgentsDir(worktree) {
8908
- return path2.join(optimaLocalConfigDir(worktree), "generated", "agents");
9464
+ return path5.join(optimaLocalConfigDir(worktree), "generated", "agents");
8909
9465
  }
8910
9466
  function repoAgentsDir(worktree) {
8911
- return path2.join(optimaDir(worktree), "agents");
9467
+ return path5.join(optimaDir(worktree), "agents");
8912
9468
  }
8913
9469
  function repoAgentAdditionsDir(worktree) {
8914
- return path2.join(optimaDir(worktree), "agent-additions");
9470
+ return path5.join(optimaDir(worktree), "agent-additions");
8915
9471
  }
8916
9472
  function legacyRepoAgentsDir(worktree) {
8917
- return path2.join(legacyNomadworksDir(worktree), "agents");
9473
+ return path5.join(legacyNomadworksDir(worktree), "agents");
8918
9474
  }
8919
9475
  function runtimeDiscussionRegistryPath(worktree) {
8920
- return path2.join(optimaLocalConfigDir(worktree), "runtime", "discussions.json");
9476
+ return path5.join(optimaLocalConfigDir(worktree), "runtime", "discussions.json");
8921
9477
  }
8922
9478
  function resolveConfigPath(worktree) {
8923
9479
  return repoConfigPath(worktree);
@@ -8960,32 +9516,32 @@ function mergeClickUpAgentMetadata(existing, update = {}) {
8960
9516
  return JSON.stringify(sortJsonValue(merged), null, 2);
8961
9517
  }
8962
9518
  function optimaRuntimeDir(worktree) {
8963
- return path2.join(optimaLocalConfigDir(worktree), "runtime");
9519
+ return path5.join(optimaLocalConfigDir(worktree), "runtime");
8964
9520
  }
8965
9521
  function clickUpWebhookStatePath(worktree) {
8966
- return path2.join(optimaRuntimeDir(worktree), "clickup-webhook.json");
9522
+ return path5.join(optimaRuntimeDir(worktree), "clickup-webhook.json");
8967
9523
  }
8968
9524
  function clickUpCommentLedgerPath(worktree) {
8969
- return path2.join(optimaRuntimeDir(worktree), "clickup-comment-ledger.jsonl");
9525
+ return path5.join(optimaRuntimeDir(worktree), "clickup-comment-ledger.jsonl");
8970
9526
  }
8971
9527
  function clickUpWebhookLogPath(worktree) {
8972
- return path2.join(optimaRuntimeDir(worktree), "clickup-webhook.log.jsonl");
9528
+ return path5.join(optimaRuntimeDir(worktree), "clickup-webhook.log.jsonl");
8973
9529
  }
8974
9530
  function normalizeClickUpWebhookLogLevel(value) {
8975
9531
  const level = String(value || "info").trim().toLowerCase();
8976
9532
  return CLICKUP_WEBHOOK_LOG_LEVELS.has(level) ? level : "info";
8977
9533
  }
8978
9534
  function clickUpWebhookAuditLogDir() {
8979
- const dataHome = process.env.XDG_DATA_HOME && path2.isAbsolute(process.env.XDG_DATA_HOME) ? process.env.XDG_DATA_HOME : path2.join(os.homedir(), ".local", "share", "opencode");
8980
- return path2.join(dataHome, "opencode-optima");
9535
+ 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");
9536
+ return path5.join(dataHome, "opencode-optima");
8981
9537
  }
8982
9538
  function clickUpWebhookAuditLogPath(at = /* @__PURE__ */ new Date(), logDir = clickUpWebhookAuditLogDir()) {
8983
- return path2.join(logDir, `clickup-webhook-${at.toISOString().slice(0, 10)}.jsonl`);
9539
+ return path5.join(logDir, `clickup-webhook-${at.toISOString().slice(0, 10)}.jsonl`);
8984
9540
  }
8985
9541
  function clickUpWebhookRequestFilePath(at = /* @__PURE__ */ new Date(), logDir = clickUpWebhookAuditLogDir()) {
8986
9542
  const stamp = at.toISOString().replace(/:/g, "-").replace(/\./g, "-");
8987
9543
  const shortId = crypto.randomBytes(4).toString("hex");
8988
- return path2.join(logDir, "requests", `clickup-webhook-${stamp}-${shortId}.json`);
9544
+ return path5.join(logDir, "requests", `clickup-webhook-${stamp}-${shortId}.json`);
8989
9545
  }
8990
9546
  function findOptimaPluginTupleOptions(pluginEntries = []) {
8991
9547
  if (!Array.isArray(pluginEntries)) return null;
@@ -9067,7 +9623,7 @@ function normalizeClickUpWebhookConfig(rawClickUp = null, worktree = process.cwd
9067
9623
  };
9068
9624
  const errors = [];
9069
9625
  if (!config.enabled) errors.push("clickup.enabled must be true");
9070
- if (!config.basePath || !path2.isAbsolute(config.basePath)) errors.push("clickup.base_path must be an absolute path");
9626
+ if (!config.basePath || !path5.isAbsolute(config.basePath)) errors.push("clickup.base_path must be an absolute path");
9071
9627
  if (!config.teamId) errors.push("clickup.team_id is required");
9072
9628
  if (!config.apiToken) errors.push("clickup.api_token is required");
9073
9629
  if (!config.webhook.publicUrl) errors.push("clickup.webhook.public_url is required");
@@ -9109,21 +9665,21 @@ function sanitizeClickUpWebhookState(state = {}, config = null) {
9109
9665
  }
9110
9666
  function readClickUpWebhookState(worktree, config = null) {
9111
9667
  const statePath = clickUpWebhookStatePath(worktree);
9112
- if (!fs2.existsSync(statePath)) return sanitizeClickUpWebhookState({}, config);
9668
+ if (!fs5.existsSync(statePath)) return sanitizeClickUpWebhookState({}, config);
9113
9669
  try {
9114
- return sanitizeClickUpWebhookState(JSON.parse(fs2.readFileSync(statePath, "utf8")), config);
9670
+ return sanitizeClickUpWebhookState(JSON.parse(fs5.readFileSync(statePath, "utf8")), config);
9115
9671
  } catch {
9116
9672
  return sanitizeClickUpWebhookState({}, config);
9117
9673
  }
9118
9674
  }
9119
9675
  function writeClickUpWebhookState(worktree, state, config = null) {
9120
9676
  const statePath = clickUpWebhookStatePath(worktree);
9121
- fs2.mkdirSync(path2.dirname(statePath), { recursive: true, mode: 448 });
9677
+ fs5.mkdirSync(path5.dirname(statePath), { recursive: true, mode: 448 });
9122
9678
  const next = sanitizeClickUpWebhookState(state, config);
9123
- fs2.writeFileSync(statePath, `${JSON.stringify(next, null, 2)}
9679
+ fs5.writeFileSync(statePath, `${JSON.stringify(next, null, 2)}
9124
9680
  `, { encoding: "utf8", mode: 384 });
9125
9681
  try {
9126
- fs2.chmodSync(statePath, 384);
9682
+ fs5.chmodSync(statePath, 384);
9127
9683
  } catch {
9128
9684
  }
9129
9685
  return next;
@@ -9139,7 +9695,7 @@ function isClickUpWebhookStateActive(state, config) {
9139
9695
  function expandHomePath(value = "") {
9140
9696
  const input = String(value || "").trim();
9141
9697
  if (input === "~") return os.homedir();
9142
- if (input.startsWith("~/")) return path2.join(os.homedir(), input.slice(2));
9698
+ if (input.startsWith("~/")) return path5.join(os.homedir(), input.slice(2));
9143
9699
  return input;
9144
9700
  }
9145
9701
  function resolveSecretReference(value = "") {
@@ -9149,7 +9705,7 @@ function resolveSecretReference(value = "") {
9149
9705
  const fileMatch = raw.match(/^\{file:(.+)\}$/);
9150
9706
  if (fileMatch) {
9151
9707
  try {
9152
- return fs2.readFileSync(expandHomePath(fileMatch[1]), "utf8").trim();
9708
+ return fs5.readFileSync(expandHomePath(fileMatch[1]), "utf8").trim();
9153
9709
  } catch {
9154
9710
  return "";
9155
9711
  }
@@ -9405,9 +9961,9 @@ function rememberClickUpWebhookEvent(state = {}, eventKey, limit = 200) {
9405
9961
  }
9406
9962
  function readClickUpCommentLedger(ledgerPath) {
9407
9963
  const processed = /* @__PURE__ */ new Set();
9408
- if (!ledgerPath || !fs2.existsSync(ledgerPath)) return processed;
9964
+ if (!ledgerPath || !fs5.existsSync(ledgerPath)) return processed;
9409
9965
  try {
9410
- const raw = fs2.readFileSync(ledgerPath, "utf8");
9966
+ const raw = fs5.readFileSync(ledgerPath, "utf8");
9411
9967
  for (const [index, line] of raw.split(/\r?\n/).entries()) {
9412
9968
  if (!line.trim()) continue;
9413
9969
  try {
@@ -9424,11 +9980,11 @@ function readClickUpCommentLedger(ledgerPath) {
9424
9980
  }
9425
9981
  function appendClickUpCommentLedgerEntry(ledgerPath, entry = {}) {
9426
9982
  if (!ledgerPath || !entry.key) return;
9427
- fs2.mkdirSync(path2.dirname(ledgerPath), { recursive: true, mode: 448 });
9428
- fs2.appendFileSync(ledgerPath, `${JSON.stringify(entry)}
9983
+ fs5.mkdirSync(path5.dirname(ledgerPath), { recursive: true, mode: 448 });
9984
+ fs5.appendFileSync(ledgerPath, `${JSON.stringify(entry)}
9429
9985
  `, { encoding: "utf8", mode: 384 });
9430
9986
  try {
9431
- fs2.chmodSync(ledgerPath, 384);
9987
+ fs5.chmodSync(ledgerPath, 384);
9432
9988
  } catch {
9433
9989
  }
9434
9990
  }
@@ -9830,12 +10386,170 @@ function normalizeOpenCodeSessionMessages(result) {
9830
10386
  if (Array.isArray(data?.items)) return [...data.items];
9831
10387
  return [];
9832
10388
  }
10389
+ function clampOpenCodeMessageLimit(limit) {
10390
+ const value = Number(limit);
10391
+ if (!Number.isFinite(value)) return 20;
10392
+ return Math.min(50, Math.max(1, Math.floor(value)));
10393
+ }
10394
+ function clampOpenCodeSessionText(text = "", maxLength = 12e3) {
10395
+ const value = String(text ?? "");
10396
+ return value.length > maxLength ? value.slice(0, maxLength) : value;
10397
+ }
10398
+ function hashOpenCodeSessionText(text = "") {
10399
+ return crypto.createHash("sha256").update(String(text ?? "")).digest("hex");
10400
+ }
9833
10401
  async function readOpenCodeSessionMessages(client, { sessionId, directory, limit = 20 } = {}) {
9834
10402
  if (typeof client?.session?.messages !== "function") return null;
9835
- const query = { limit };
10403
+ const query = { limit: clampOpenCodeMessageLimit(limit) };
9836
10404
  if (directory) query.directory = directory;
9837
10405
  return normalizeOpenCodeSessionMessages(await client.session.messages({ path: { id: sessionId }, query }));
9838
10406
  }
10407
+ function openCodeResultSummary(result) {
10408
+ const data = result?.data ?? result;
10409
+ return {
10410
+ type: Array.isArray(data) ? "array" : typeof data,
10411
+ id: data?.id || data?.sessionID || data?.sessionId || result?.id || result?.sessionID || result?.sessionId || null,
10412
+ keys: data && typeof data === "object" && !Array.isArray(data) ? Object.keys(data).slice(0, 20) : [],
10413
+ dataKeys: result?.data && typeof result.data === "object" && !Array.isArray(result.data) ? Object.keys(result.data).slice(0, 20) : [],
10414
+ status: result?.status || result?.response?.status || null
10415
+ };
10416
+ }
10417
+ function normalizeOpenCodeMessageRole(message = {}) {
10418
+ return message.role || message.info?.role || message.author?.role || message.type || "";
10419
+ }
10420
+ function normalizeOpenCodeMessageAgent(message = {}) {
10421
+ return message.agent || message.info?.agent || message.mode?.agent || message.author?.agent || "";
10422
+ }
10423
+ function normalizeOpenCodeMessageMode(message = {}) {
10424
+ return message.mode || message.info?.mode || message.metadata?.mode || "";
10425
+ }
10426
+ function normalizeOpenCodeMessageId(message = {}) {
10427
+ return message.id || message.messageID || message.messageId || message.info?.id || message.data?.id || null;
10428
+ }
10429
+ function summarizeOpenCodeMessages(messages = [], { snippetLength = 160, maxMessages = 50 } = {}) {
10430
+ const list = Array.isArray(messages) ? messages.slice(0, maxMessages) : [];
10431
+ const safeSnippetLength = Math.min(240, Math.max(20, Number(snippetLength) || 160));
10432
+ return list.map((message, index) => {
10433
+ const text = openCodeMessageText(message).replace(/\s+/g, " ").trim();
10434
+ return {
10435
+ index,
10436
+ id: normalizeOpenCodeMessageId(message),
10437
+ role: normalizeOpenCodeMessageRole(message),
10438
+ agent: normalizeOpenCodeMessageAgent(message),
10439
+ mode: normalizeOpenCodeMessageMode(message),
10440
+ text_length: text.length,
10441
+ text_hash: hashOpenCodeSessionText(text),
10442
+ snippet: text.length > safeSnippetLength ? `${text.slice(0, safeSnippetLength)}...` : text
10443
+ };
10444
+ });
10445
+ }
10446
+ function promptResultAssistantReturned(result) {
10447
+ const parts = normalizePromptResponseParts(result);
10448
+ const text = extractTextParts(parts);
10449
+ const data = result?.data ?? result;
10450
+ return Boolean(text || data?.role === "assistant" || data?.info?.role === "assistant");
10451
+ }
10452
+ async function createOpenCodeSessionControl(client, { directory, title, agent } = {}) {
10453
+ if (typeof client?.session?.create !== "function") throw new Error("OpenCode client does not expose session.create.");
10454
+ const body = { title };
10455
+ if (agent) body.agent = agent;
10456
+ const result = await client.session.create({ query: { directory }, body });
10457
+ const sessionId = extractOpenCodeSessionId(result);
10458
+ if (!sessionId) throw new Error("OpenCode session create response did not include a session id.");
10459
+ return {
10460
+ ok: true,
10461
+ session_id: sessionId,
10462
+ title,
10463
+ directory,
10464
+ agent: agent || null,
10465
+ result_summary: openCodeResultSummary(result)
10466
+ };
10467
+ }
10468
+ async function promptOpenCodeSessionControl(client, { sessionId, directory, text, agent, omitAgent = false, requireReadable = true } = {}) {
10469
+ if (typeof client?.session?.prompt !== "function") throw new Error("OpenCode client does not expose session.prompt.");
10470
+ if (requireReadable) await assertOpenCodeSessionReadableForDirectory(client, { sessionId, directory });
10471
+ const safeText = clampOpenCodeSessionText(text);
10472
+ const body = { parts: [{ type: "text", text: safeText }] };
10473
+ if (!omitAgent && agent) body.agent = agent;
10474
+ const result = await client.session.prompt({ path: { id: sessionId }, query: { directory }, body });
10475
+ return {
10476
+ ok: true,
10477
+ session_id: sessionId,
10478
+ directory,
10479
+ agent: omitAgent ? null : agent || null,
10480
+ omit_agent: Boolean(omitAgent),
10481
+ text_length: safeText.length,
10482
+ text_truncated: String(text ?? "").length > safeText.length,
10483
+ text_hash: hashOpenCodeSessionText(safeText),
10484
+ assistant_returned: promptResultAssistantReturned(result),
10485
+ returned_parts_count: normalizePromptResponseParts(result).length,
10486
+ result_summary: openCodeResultSummary(result)
10487
+ };
10488
+ }
10489
+ async function assertOpenCodeSessionReadableForDirectory(client, { sessionId, directory } = {}) {
10490
+ try {
10491
+ await readOpenCodeSessionMessages(client, { sessionId, directory, limit: 1 });
10492
+ return true;
10493
+ } catch (error) {
10494
+ throw new Error(`OpenCode session '${sessionId}' is not readable for the requested safe directory.`);
10495
+ }
10496
+ }
10497
+ async function readOpenCodeSessionControl(client, { sessionId, directory, limit = 20 } = {}) {
10498
+ const boundedLimit = clampOpenCodeMessageLimit(limit);
10499
+ const messages = await readOpenCodeSessionMessages(client, { sessionId, directory, limit: boundedLimit });
10500
+ if (!messages) throw new Error("OpenCode client does not expose session.messages.");
10501
+ return {
10502
+ ok: true,
10503
+ session_id: sessionId,
10504
+ directory: directory || null,
10505
+ limit: boundedLimit,
10506
+ count: messages.length,
10507
+ messages: summarizeOpenCodeMessages(messages)
10508
+ };
10509
+ }
10510
+ async function probeOpenCodeSessionControl(client, { directory, agent, omitAgentOnPrompt = false, text = "" } = {}) {
10511
+ const requestedMarker = text || `optima-session-probe-${crypto.randomUUID()}`;
10512
+ const marker = clampOpenCodeSessionText(requestedMarker);
10513
+ const create = await createOpenCodeSessionControl(client, {
10514
+ directory,
10515
+ title: `Optima session probe ${(/* @__PURE__ */ new Date()).toISOString()}`,
10516
+ agent
10517
+ });
10518
+ const prompt = await promptOpenCodeSessionControl(client, {
10519
+ sessionId: create.session_id,
10520
+ directory,
10521
+ text: marker,
10522
+ agent,
10523
+ omitAgent: omitAgentOnPrompt,
10524
+ requireReadable: false
10525
+ });
10526
+ const rawMessages = await readOpenCodeSessionMessages(client, { sessionId: create.session_id, directory, limit: 50 });
10527
+ if (!rawMessages) throw new Error("OpenCode client does not expose session.messages.");
10528
+ const fullMessageText = rawMessages.map(openCodeMessageText).join("\n");
10529
+ const messages = {
10530
+ ok: true,
10531
+ session_id: create.session_id,
10532
+ directory,
10533
+ limit: 50,
10534
+ count: rawMessages.length,
10535
+ messages: summarizeOpenCodeMessages(rawMessages)
10536
+ };
10537
+ return {
10538
+ ok: true,
10539
+ session_id: create.session_id,
10540
+ directory,
10541
+ agent: agent || null,
10542
+ omit_agent_on_prompt: Boolean(omitAgentOnPrompt),
10543
+ marker_length: marker.length,
10544
+ marker_truncated: requestedMarker.length > marker.length,
10545
+ marker_hash: hashOpenCodeSessionText(marker),
10546
+ marker_visible: fullMessageText.includes(marker),
10547
+ assistant_visible: rawMessages.some((message) => normalizeLooseToken(normalizeOpenCodeMessageRole(message)) === "assistant" || Boolean(normalizeOpenCodeMessageAgent(message) && openCodeMessageText(message))),
10548
+ create,
10549
+ prompt,
10550
+ messages
10551
+ };
10552
+ }
9839
10553
  function openCodeMessageText(message) {
9840
10554
  const parts = [message?.text, message?.content, message?.message, message?.body?.text, message?.data?.text];
9841
10555
  const partList = Array.isArray(message?.parts) ? message.parts : Array.isArray(message?.body?.parts) ? message.body.parts : [];
@@ -9986,9 +10700,9 @@ function formatClickUpWebhookPrompt({ eventType, taskId, payload, branch = "", w
9986
10700
  }
9987
10701
  function appendClickUpWebhookLocalLog(worktree, entry) {
9988
10702
  const logPath = clickUpWebhookLogPath(worktree);
9989
- fs2.mkdirSync(path2.dirname(logPath), { recursive: true });
10703
+ fs5.mkdirSync(path5.dirname(logPath), { recursive: true });
9990
10704
  const safeEntry = { ...entry, at: entry.at || (/* @__PURE__ */ new Date()).toISOString() };
9991
- fs2.appendFileSync(logPath, `${JSON.stringify(safeEntry)}
10705
+ fs5.appendFileSync(logPath, `${JSON.stringify(safeEntry)}
9992
10706
  `, "utf8");
9993
10707
  }
9994
10708
  function clickUpWebhookLifecycleLog(worktree, entry) {
@@ -10017,7 +10731,7 @@ function closeClickUpWebhookServer(server) {
10017
10731
  });
10018
10732
  }
10019
10733
  function managedClickUpWebhookKey({ worktree, state, config } = {}) {
10020
- return [path2.resolve(worktree || process.cwd()), state?.webhookId || "", config?.webhook?.publicUrl || ""].join("|");
10734
+ return [path5.resolve(worktree || process.cwd()), state?.webhookId || "", config?.webhook?.publicUrl || ""].join("|");
10021
10735
  }
10022
10736
  async function deleteClickUpWebhookBestEffort({ webhookId, clickupClient, worktree, reason = "cleanup" } = {}) {
10023
10737
  const id = String(webhookId || "").trim();
@@ -10116,13 +10830,13 @@ function writeClickUpWebhookAuditLog({ method, url, headers = {}, rawBody = "",
10116
10830
  const failed = Boolean(error || !handled?.ok || (handled?.status || 500) >= 400);
10117
10831
  if (level === "error" && !failed) return;
10118
10832
  const logDir = clickUpWebhookAuditLogDir();
10119
- fs2.mkdirSync(logDir, { recursive: true });
10833
+ fs5.mkdirSync(logDir, { recursive: true });
10120
10834
  const secretValues = [resolveSecretReference(config?.apiToken), state?.secret, config?.webhook?.secret].filter(Boolean);
10121
10835
  let requestFile;
10122
10836
  if (level === "verbose") {
10123
10837
  const absoluteRequestFile = clickUpWebhookRequestFilePath(at, logDir);
10124
- fs2.mkdirSync(path2.dirname(absoluteRequestFile), { recursive: true });
10125
- requestFile = path2.relative(logDir, absoluteRequestFile).split(path2.sep).join("/");
10838
+ fs5.mkdirSync(path5.dirname(absoluteRequestFile), { recursive: true });
10839
+ requestFile = path5.relative(logDir, absoluteRequestFile).split(path5.sep).join("/");
10126
10840
  const parsedBody = payload || (() => {
10127
10841
  try {
10128
10842
  return JSON.parse(Buffer.isBuffer(rawBody) ? rawBody.toString("utf8") : String(rawBody || ""));
@@ -10138,11 +10852,11 @@ function writeClickUpWebhookAuditLog({ method, url, headers = {}, rawBody = "",
10138
10852
  headers,
10139
10853
  body: parsedBody === void 0 ? Buffer.isBuffer(rawBody) ? rawBody.toString("utf8") : String(rawBody || "") : parsedBody
10140
10854
  }, secretValues);
10141
- fs2.writeFileSync(absoluteRequestFile, `${JSON.stringify(requestArtifact, null, 2)}
10855
+ fs5.writeFileSync(absoluteRequestFile, `${JSON.stringify(requestArtifact, null, 2)}
10142
10856
  `, "utf8");
10143
10857
  }
10144
10858
  const summary = redactClickUpWebhookAuditValue(buildClickUpWebhookAuditSummary({ method, url, config, handled, error, payload, requestFile, at }), secretValues);
10145
- fs2.appendFileSync(clickUpWebhookAuditLogPath(at, logDir), `${JSON.stringify(summary)}
10859
+ fs5.appendFileSync(clickUpWebhookAuditLogPath(at, logDir), `${JSON.stringify(summary)}
10146
10860
  `, "utf8");
10147
10861
  } catch {
10148
10862
  }
@@ -10498,7 +11212,7 @@ function clickUpListenerFingerprint({ config, state, worktree, clickupClient, op
10498
11212
  return JSON.stringify({
10499
11213
  publicUrl: config?.webhook?.publicUrl || "",
10500
11214
  path: clickUpWebhookExpectedPath(config),
10501
- worktree: path2.resolve(worktree || process.cwd()),
11215
+ worktree: path5.resolve(worktree || process.cwd()),
10502
11216
  webhookId: state?.webhookId || "",
10503
11217
  secret: state?.secret || "",
10504
11218
  events: config?.webhook?.events || [],
@@ -10595,17 +11309,17 @@ function startClickUpWebhookListener({ config, state, worktree, clickupClient, o
10595
11309
  return result;
10596
11310
  }
10597
11311
  function legacyVariantPath(destinationPath) {
10598
- const parsed = path2.parse(destinationPath);
11312
+ const parsed = path5.parse(destinationPath);
10599
11313
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:TZ.]/g, "").slice(0, 14);
10600
- if (parsed.ext) return path2.join(parsed.dir, `${parsed.name}.legacy-${stamp}${parsed.ext}`);
10601
- return path2.join(parsed.dir, `${parsed.base}.legacy-${stamp}`);
11314
+ if (parsed.ext) return path5.join(parsed.dir, `${parsed.name}.legacy-${stamp}${parsed.ext}`);
11315
+ return path5.join(parsed.dir, `${parsed.base}.legacy-${stamp}`);
10602
11316
  }
10603
11317
  function normalizeWorkflowTaskPath(taskPath) {
10604
11318
  if (typeof taskPath !== "string") return { ok: false, message: "Error: task_path is required." };
10605
11319
  const trimmed = taskPath.trim();
10606
11320
  if (!trimmed) return { ok: false, message: "Error: task_path is required." };
10607
11321
  const normalized = trimmed.replace(/\\/g, "/");
10608
- if (path2.isAbsolute(trimmed)) return { ok: true, taskPath: trimmed };
11322
+ if (path5.isAbsolute(trimmed)) return { ok: true, taskPath: trimmed };
10609
11323
  if (normalized === "tasks" || normalized.startsWith("tasks/")) {
10610
11324
  return {
10611
11325
  ok: false,
@@ -10621,76 +11335,80 @@ function normalizeWorkflowTaskPath(taskPath) {
10621
11335
  return { ok: true, taskPath: trimmed };
10622
11336
  }
10623
11337
  function mergeFileIntoDestination(sourcePath, destinationPath, relativeSource, gitState = null) {
11338
+ const sourceWasTracked = isGitTracked(gitState, sourcePath);
10624
11339
  if (gitAwareMoveIfTracked(sourcePath, destinationPath, gitState)) return;
10625
- if (!fs2.existsSync(destinationPath)) {
10626
- fs2.mkdirSync(path2.dirname(destinationPath), { recursive: true });
10627
- fs2.renameSync(sourcePath, destinationPath);
11340
+ if (!fs5.existsSync(destinationPath)) {
11341
+ fs5.mkdirSync(path5.dirname(destinationPath), { recursive: true });
11342
+ fs5.renameSync(sourcePath, destinationPath);
11343
+ if (sourceWasTracked) stageGitAwareMerge(sourcePath, destinationPath, gitState);
10628
11344
  return;
10629
11345
  }
10630
- const ext = path2.extname(destinationPath).toLowerCase();
11346
+ const ext = path5.extname(destinationPath).toLowerCase();
10631
11347
  if ([".yaml", ".yml", ".json"].includes(ext)) {
10632
- const sourceRaw = fs2.readFileSync(sourcePath, "utf8");
10633
- const destRaw = fs2.readFileSync(destinationPath, "utf8");
10634
- const parser = ext === ".json" ? JSON : import_yaml2.default;
11348
+ const sourceRaw = fs5.readFileSync(sourcePath, "utf8");
11349
+ const destRaw = fs5.readFileSync(destinationPath, "utf8");
11350
+ const parser = ext === ".json" ? JSON : import_yaml3.default;
10635
11351
  const sourceValue = parser.parse(sourceRaw) || {};
10636
11352
  const destValue = parser.parse(destRaw) || {};
10637
11353
  const merged = mergeStructuredValues(sourceValue, destValue);
10638
11354
  const serialized = ext === ".json" ? `${JSON.stringify(merged, null, 2)}
10639
- ` : import_yaml2.default.stringify(merged);
10640
- fs2.writeFileSync(destinationPath, serialized, "utf8");
10641
- fs2.unlinkSync(sourcePath);
11355
+ ` : import_yaml3.default.stringify(merged);
11356
+ fs5.writeFileSync(destinationPath, serialized, "utf8");
11357
+ fs5.unlinkSync(sourcePath);
10642
11358
  stageGitAwareMerge(sourcePath, destinationPath, gitState);
10643
11359
  return;
10644
11360
  }
10645
11361
  if (ext === ".md") {
10646
- const sourceRaw = fs2.readFileSync(sourcePath, "utf8").trimEnd();
10647
- const destRaw = fs2.readFileSync(destinationPath, "utf8").trimEnd();
11362
+ const sourceRaw = fs5.readFileSync(sourcePath, "utf8").trimEnd();
11363
+ const destRaw = fs5.readFileSync(destinationPath, "utf8").trimEnd();
10648
11364
  if (sourceRaw && !destRaw.includes(sourceRaw)) {
10649
11365
  const marker = `## Legacy Content From ${relativeSource}`;
10650
- fs2.writeFileSync(destinationPath, `${destRaw}
11366
+ fs5.writeFileSync(destinationPath, `${destRaw}
10651
11367
 
10652
11368
  ${marker}
10653
11369
 
10654
11370
  ${sourceRaw}
10655
11371
  `, "utf8");
10656
11372
  }
10657
- fs2.unlinkSync(sourcePath);
11373
+ fs5.unlinkSync(sourcePath);
10658
11374
  stageGitAwareMerge(sourcePath, destinationPath, gitState);
10659
11375
  return;
10660
11376
  }
10661
11377
  const preservedPath = legacyVariantPath(destinationPath);
10662
- fs2.renameSync(sourcePath, preservedPath);
11378
+ fs5.renameSync(sourcePath, preservedPath);
10663
11379
  stageGitAwareMerge(sourcePath, preservedPath, gitState);
10664
11380
  }
10665
- function mergePathIntoDestination(sourcePath, destinationPath, relativeSource = path2.basename(sourcePath), gitState = null) {
10666
- if (!fs2.existsSync(sourcePath)) return;
10667
- const stat = fs2.statSync(sourcePath);
11381
+ function mergePathIntoDestination(sourcePath, destinationPath, relativeSource = path5.basename(sourcePath), gitState = null) {
11382
+ if (!fs5.existsSync(sourcePath)) return;
11383
+ const stat = fs5.statSync(sourcePath);
10668
11384
  if (stat.isDirectory()) {
11385
+ const sourceWasTracked = isGitTracked(gitState, sourcePath) || hasGitTrackedChildren(gitState, sourcePath);
10669
11386
  if (gitAwareMoveIfTracked(sourcePath, destinationPath, gitState)) return;
10670
- if (!fs2.existsSync(destinationPath)) {
10671
- fs2.mkdirSync(path2.dirname(destinationPath), { recursive: true });
10672
- fs2.renameSync(sourcePath, destinationPath);
11387
+ if (!fs5.existsSync(destinationPath)) {
11388
+ fs5.mkdirSync(path5.dirname(destinationPath), { recursive: true });
11389
+ fs5.renameSync(sourcePath, destinationPath);
11390
+ if (sourceWasTracked) stageGitAwareMerge(sourcePath, destinationPath, gitState);
10673
11391
  return;
10674
11392
  }
10675
- fs2.mkdirSync(destinationPath, { recursive: true });
10676
- for (const entry of fs2.readdirSync(sourcePath)) {
11393
+ fs5.mkdirSync(destinationPath, { recursive: true });
11394
+ for (const entry of fs5.readdirSync(sourcePath)) {
10677
11395
  mergePathIntoDestination(
10678
- path2.join(sourcePath, entry),
10679
- path2.join(destinationPath, entry),
10680
- path2.join(relativeSource, entry),
11396
+ path5.join(sourcePath, entry),
11397
+ path5.join(destinationPath, entry),
11398
+ path5.join(relativeSource, entry),
10681
11399
  gitState
10682
11400
  );
10683
11401
  }
10684
- fs2.rmSync(sourcePath, { recursive: true, force: true });
11402
+ fs5.rmSync(sourcePath, { recursive: true, force: true });
10685
11403
  return;
10686
11404
  }
10687
11405
  mergeFileIntoDestination(sourcePath, destinationPath, relativeSource, gitState);
10688
11406
  }
10689
11407
  function isOptimaPluginPackageWorktree(worktree) {
10690
- const packageJsonPath = path2.join(worktree, "package.json");
10691
- if (!fs2.existsSync(packageJsonPath)) return false;
11408
+ const packageJsonPath = path5.join(worktree, "package.json");
11409
+ if (!fs5.existsSync(packageJsonPath)) return false;
10692
11410
  try {
10693
- const pkg = JSON.parse(fs2.readFileSync(packageJsonPath, "utf8"));
11411
+ const pkg = JSON.parse(fs5.readFileSync(packageJsonPath, "utf8"));
10694
11412
  return pkg?.name === "@defend-tech/opencode-optima";
10695
11413
  } catch {
10696
11414
  return false;
@@ -10699,59 +11417,59 @@ function isOptimaPluginPackageWorktree(worktree) {
10699
11417
  function migrateLegacyOptimaLayout(worktree) {
10700
11418
  const gitState = gitMigrationState(worktree);
10701
11419
  const migrations = [
10702
- [path2.join(legacyOrbitaDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path2.join(".orbita", "orbita.yaml")],
10703
- [path2.join(legacyOrbitaDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path2.join(".orbita", "staticeng.yaml")],
10704
- [path2.join(legacyOrbitaDir(worktree), ".config"), optimaLocalConfigDir(worktree), path2.join(".orbita", ".config")],
10705
- [path2.join(legacyOrbitaDir(worktree), "config"), optimaLocalConfigDir(worktree), path2.join(".orbita", "config")],
10706
- [path2.join(legacyOrbitaDir(worktree), "runtime"), path2.join(optimaLocalConfigDir(worktree), "runtime"), path2.join(".orbita", "runtime")],
10707
- [path2.join(legacyOrbitaDir(worktree), "generated"), path2.join(optimaLocalConfigDir(worktree), "generated"), path2.join(".orbita", "generated")],
11420
+ [path5.join(legacyOrbitaDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path5.join(".orbita", "orbita.yaml")],
11421
+ [path5.join(legacyOrbitaDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path5.join(".orbita", "staticeng.yaml")],
11422
+ [path5.join(legacyOrbitaDir(worktree), ".config"), optimaLocalConfigDir(worktree), path5.join(".orbita", ".config")],
11423
+ [path5.join(legacyOrbitaDir(worktree), "config"), optimaLocalConfigDir(worktree), path5.join(".orbita", "config")],
11424
+ [path5.join(legacyOrbitaDir(worktree), "runtime"), path5.join(optimaLocalConfigDir(worktree), "runtime"), path5.join(".orbita", "runtime")],
11425
+ [path5.join(legacyOrbitaDir(worktree), "generated"), path5.join(optimaLocalConfigDir(worktree), "generated"), path5.join(".orbita", "generated")],
10708
11426
  [legacyOrbitaDir(worktree), optimaDir(worktree), ".orbita"],
10709
- [path2.join(legacyStaticEngDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path2.join(".staticeng", "staticeng.yaml")],
10710
- [path2.join(legacyStaticEngDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path2.join(".staticeng", "orbita.yaml")],
10711
- [path2.join(legacyStaticEngDir(worktree), ".config"), optimaLocalConfigDir(worktree), path2.join(".staticeng", ".config")],
10712
- [path2.join(legacyStaticEngDir(worktree), "config"), optimaLocalConfigDir(worktree), path2.join(".staticeng", "config")],
10713
- [path2.join(legacyStaticEngDir(worktree), "runtime"), path2.join(optimaLocalConfigDir(worktree), "runtime"), path2.join(".staticeng", "runtime")],
10714
- [path2.join(legacyStaticEngDir(worktree), "generated"), path2.join(optimaLocalConfigDir(worktree), "generated"), path2.join(".staticeng", "generated")],
11427
+ [path5.join(legacyStaticEngDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path5.join(".staticeng", "staticeng.yaml")],
11428
+ [path5.join(legacyStaticEngDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path5.join(".staticeng", "orbita.yaml")],
11429
+ [path5.join(legacyStaticEngDir(worktree), ".config"), optimaLocalConfigDir(worktree), path5.join(".staticeng", ".config")],
11430
+ [path5.join(legacyStaticEngDir(worktree), "config"), optimaLocalConfigDir(worktree), path5.join(".staticeng", "config")],
11431
+ [path5.join(legacyStaticEngDir(worktree), "runtime"), path5.join(optimaLocalConfigDir(worktree), "runtime"), path5.join(".staticeng", "runtime")],
11432
+ [path5.join(legacyStaticEngDir(worktree), "generated"), path5.join(optimaLocalConfigDir(worktree), "generated"), path5.join(".staticeng", "generated")],
10715
11433
  [legacyStaticEngDir(worktree), optimaDir(worktree), ".staticeng"],
10716
- [path2.join(legacyNomadworkDir(worktree), "nomadworks.yaml"), repoConfigPath(worktree), path2.join(".nomadwork", "nomadworks.yaml")],
10717
- [path2.join(legacyNomadworksDir(worktree), "nomadworks.yaml"), repoConfigPath(worktree), path2.join(".nomadworks", "nomadworks.yaml")],
10718
- [path2.join(legacyNomadworkDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path2.join(".nomadwork", "staticeng.yaml")],
10719
- [path2.join(legacyNomadworksDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path2.join(".nomadworks", "staticeng.yaml")],
10720
- [path2.join(legacyNomadworkDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path2.join(".nomadwork", "orbita.yaml")],
10721
- [path2.join(legacyNomadworksDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path2.join(".nomadworks", "orbita.yaml")],
10722
- [path2.join(legacyNomadworkDir(worktree), "runtime"), path2.join(optimaLocalConfigDir(worktree), "runtime"), path2.join(".nomadwork", "runtime")],
10723
- [path2.join(legacyNomadworksDir(worktree), "runtime"), path2.join(optimaLocalConfigDir(worktree), "runtime"), path2.join(".nomadworks", "runtime")],
10724
- [path2.join(legacyNomadworkDir(worktree), "generated"), path2.join(optimaLocalConfigDir(worktree), "generated"), path2.join(".nomadwork", "generated")],
10725
- [path2.join(legacyNomadworksDir(worktree), "generated"), path2.join(optimaLocalConfigDir(worktree), "generated"), path2.join(".nomadworks", "generated")],
10726
- [path2.join(legacyNomadworkDir(worktree), "config"), optimaLocalConfigDir(worktree), path2.join(".nomadwork", "config")],
10727
- [path2.join(legacyNomadworksDir(worktree), "config"), optimaLocalConfigDir(worktree), path2.join(".nomadworks", "config")],
11434
+ [path5.join(legacyNomadworkDir(worktree), "nomadworks.yaml"), repoConfigPath(worktree), path5.join(".nomadwork", "nomadworks.yaml")],
11435
+ [path5.join(legacyNomadworksDir(worktree), "nomadworks.yaml"), repoConfigPath(worktree), path5.join(".nomadworks", "nomadworks.yaml")],
11436
+ [path5.join(legacyNomadworkDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path5.join(".nomadwork", "staticeng.yaml")],
11437
+ [path5.join(legacyNomadworksDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path5.join(".nomadworks", "staticeng.yaml")],
11438
+ [path5.join(legacyNomadworkDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path5.join(".nomadwork", "orbita.yaml")],
11439
+ [path5.join(legacyNomadworksDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path5.join(".nomadworks", "orbita.yaml")],
11440
+ [path5.join(legacyNomadworkDir(worktree), "runtime"), path5.join(optimaLocalConfigDir(worktree), "runtime"), path5.join(".nomadwork", "runtime")],
11441
+ [path5.join(legacyNomadworksDir(worktree), "runtime"), path5.join(optimaLocalConfigDir(worktree), "runtime"), path5.join(".nomadworks", "runtime")],
11442
+ [path5.join(legacyNomadworkDir(worktree), "generated"), path5.join(optimaLocalConfigDir(worktree), "generated"), path5.join(".nomadwork", "generated")],
11443
+ [path5.join(legacyNomadworksDir(worktree), "generated"), path5.join(optimaLocalConfigDir(worktree), "generated"), path5.join(".nomadworks", "generated")],
11444
+ [path5.join(legacyNomadworkDir(worktree), "config"), optimaLocalConfigDir(worktree), path5.join(".nomadwork", "config")],
11445
+ [path5.join(legacyNomadworksDir(worktree), "config"), optimaLocalConfigDir(worktree), path5.join(".nomadworks", "config")],
10728
11446
  [legacyNomadworkDir(worktree), optimaDir(worktree), ".nomadwork"],
10729
11447
  [legacyNomadworksDir(worktree), optimaDir(worktree), ".nomadworks"],
10730
- [path2.join(worktree, "tasks"), optimaTasksDir(worktree), "tasks"],
10731
- [path2.join(worktree, "evidences"), optimaEvidencesDir(worktree), "evidences"],
10732
- [path2.join(worktree, "docs", "scrs"), optimaScrsDir(worktree), path2.join("docs", "scrs")],
10733
- [path2.join(worktree, "codemap.yml"), optimaCodemapPath(worktree), "codemap.yml"],
10734
- [path2.join(worktree, "codemap.yaml"), optimaCodemapPath(worktree), "codemap.yaml"]
11448
+ [path5.join(worktree, "tasks"), optimaTasksDir(worktree), "tasks"],
11449
+ [path5.join(worktree, "evidences"), optimaEvidencesDir(worktree), "evidences"],
11450
+ [path5.join(worktree, "docs", "scrs"), optimaScrsDir(worktree), path5.join("docs", "scrs")],
11451
+ [path5.join(worktree, "codemap.yml"), optimaCodemapPath(worktree), "codemap.yml"],
11452
+ [path5.join(worktree, "codemap.yaml"), optimaCodemapPath(worktree), "codemap.yaml"]
10735
11453
  ];
10736
11454
  if (!isOptimaPluginPackageWorktree(worktree)) {
10737
- migrations.push([path2.join(worktree, "policies"), repoPoliciesDir(worktree), "policies"]);
11455
+ migrations.push([path5.join(worktree, "policies"), repoPoliciesDir(worktree), "policies"]);
10738
11456
  }
10739
11457
  for (const [source, destination, relativeSource] of migrations) {
10740
- if (fs2.existsSync(source)) mergePathIntoDestination(source, destination, relativeSource, gitState);
11458
+ if (fs5.existsSync(source)) mergePathIntoDestination(source, destination, relativeSource, gitState);
10741
11459
  }
10742
11460
  for (const [source, destination, relativeSource] of [
10743
- [path2.join(optimaDir(worktree), "optima.yaml"), repoConfigPath(worktree), path2.join(".optima", "optima.yaml")],
10744
- [path2.join(optimaDir(worktree), "config"), optimaLocalConfigDir(worktree), path2.join(".optima", "config")],
10745
- [path2.join(optimaDir(worktree), "runtime"), path2.join(optimaLocalConfigDir(worktree), "runtime"), path2.join(".optima", "runtime")],
10746
- [path2.join(optimaDir(worktree), "generated"), path2.join(optimaLocalConfigDir(worktree), "generated"), path2.join(".optima", "generated")]
11461
+ [path5.join(optimaDir(worktree), "optima.yaml"), repoConfigPath(worktree), path5.join(".optima", "optima.yaml")],
11462
+ [path5.join(optimaDir(worktree), "config"), optimaLocalConfigDir(worktree), path5.join(".optima", "config")],
11463
+ [path5.join(optimaDir(worktree), "runtime"), path5.join(optimaLocalConfigDir(worktree), "runtime"), path5.join(".optima", "runtime")],
11464
+ [path5.join(optimaDir(worktree), "generated"), path5.join(optimaLocalConfigDir(worktree), "generated"), path5.join(".optima", "generated")]
10747
11465
  ]) {
10748
- if (fs2.existsSync(source)) mergePathIntoDestination(source, destination, relativeSource, gitState);
11466
+ if (fs5.existsSync(source)) mergePathIntoDestination(source, destination, relativeSource, gitState);
10749
11467
  }
10750
11468
  }
10751
11469
  function listMarkdownFiles(dirPath) {
10752
- if (!fs2.existsSync(dirPath)) return [];
11470
+ if (!fs5.existsSync(dirPath)) return [];
10753
11471
  try {
10754
- return fs2.readdirSync(dirPath).filter((file) => file.endsWith(".md") && file.toLowerCase() !== "readme.md");
11472
+ return fs5.readdirSync(dirPath).filter((file) => file.endsWith(".md") && file.toLowerCase() !== "readme.md");
10755
11473
  } catch (e) {
10756
11474
  console.error(`[Optima] Failed to read markdown files from ${dirPath}:`, e);
10757
11475
  return [];
@@ -10761,67 +11479,6 @@ function normalizePolicyExtraction(value) {
10761
11479
  if (typeof value !== "string") return "none";
10762
11480
  return value.trim().toLowerCase() === "all" ? "all" : "none";
10763
11481
  }
10764
- function resolveIncludeFile(includeRef, repoRoot, bundleRoot, options = {}) {
10765
- const trimmed = includeRef.trim();
10766
- const scopedMatch = trimmed.match(/^([a-z]+):(.*)$/i);
10767
- const scope = scopedMatch?.[1]?.toLowerCase();
10768
- const target = scopedMatch ? scopedMatch[2].trim() : trimmed;
10769
- const resolveRelative = (baseDir, relativePath) => {
10770
- if (!relativePath) return null;
10771
- return path2.isAbsolute(relativePath) ? relativePath : path2.join(baseDir, relativePath);
10772
- };
10773
- const withCompactPreference = (paths) => {
10774
- if (!options.preferCompactPromptDocs) return paths;
10775
- const compactPaths = paths.map((filePath) => filePath ? compactPromptPath(filePath) : null).filter(Boolean);
10776
- return [...compactPaths, ...paths];
10777
- };
10778
- if (scope === "plugin") {
10779
- for (const filePath of withCompactPreference([resolveRelative(bundleRoot, target)])) {
10780
- if (filePath && fs2.existsSync(filePath)) return filePath;
10781
- }
10782
- return null;
10783
- }
10784
- if (scope === "repo") {
10785
- for (const filePath of withCompactPreference([resolveRelative(optimaDir(repoRoot), target)])) {
10786
- if (filePath && fs2.existsSync(filePath)) return filePath;
10787
- }
10788
- return null;
10789
- }
10790
- if (scope === "policy") {
10791
- const candidates2 = withCompactPreference([
10792
- resolveRelative(repoPoliciesDir(repoRoot), target),
10793
- resolveRelative(BUNDLE_POLICIES_DIR, target)
10794
- ]);
10795
- for (const filePath of candidates2) {
10796
- if (filePath && fs2.existsSync(filePath)) return filePath;
10797
- }
10798
- return null;
10799
- }
10800
- const candidates = withCompactPreference([
10801
- resolveRelative(repoRoot, target),
10802
- resolveRelative(bundleRoot, target)
10803
- ]);
10804
- for (const filePath of candidates) {
10805
- if (filePath && fs2.existsSync(filePath)) return filePath;
10806
- }
10807
- return null;
10808
- }
10809
- function resolveIncludes(text, repoRoot, bundleRoot, options = {}) {
10810
- const includeRegex = /<include:(.*?)>/g;
10811
- return text.replace(includeRegex, (match, includeRef) => {
10812
- const filePath = resolveIncludeFile(includeRef, repoRoot, bundleRoot, options);
10813
- if (!filePath) {
10814
- console.warn(`[Optima] Include file not found: ${includeRef}`);
10815
- return `
10816
-
10817
- # ERROR: Include file not found: ${includeRef}
10818
-
10819
- `;
10820
- }
10821
- const content = fs2.readFileSync(filePath, "utf8");
10822
- return resolveIncludes(content, repoRoot, bundleRoot, options);
10823
- });
10824
- }
10825
11482
  function parseFrontmatter(mdText) {
10826
11483
  const lines = mdText.split(/\r?\n/);
10827
11484
  if (lines[0]?.trim() !== "---") return { data: {}, body: mdText };
@@ -10836,7 +11493,7 @@ function parseFrontmatter(mdText) {
10836
11493
  const fmText = lines.slice(1, end).join("\n");
10837
11494
  const body = lines.slice(end + 1).join("\n");
10838
11495
  try {
10839
- return { data: import_yaml2.default.parse(fmText) || {}, body };
11496
+ return { data: import_yaml3.default.parse(fmText) || {}, body };
10840
11497
  } catch {
10841
11498
  return { data: {}, body };
10842
11499
  }
@@ -10853,10 +11510,10 @@ function toModelString(provider, model) {
10853
11510
  }
10854
11511
  function readTaskMetadata(taskPath, worktree) {
10855
11512
  if (!taskPath) return {};
10856
- const absoluteTaskPath = path2.isAbsolute(taskPath) ? taskPath : path2.join(worktree, taskPath);
10857
- if (!fs2.existsSync(absoluteTaskPath)) return {};
11513
+ const absoluteTaskPath = path5.isAbsolute(taskPath) ? taskPath : path5.join(worktree, taskPath);
11514
+ if (!fs5.existsSync(absoluteTaskPath)) return {};
10858
11515
  try {
10859
- const raw = fs2.readFileSync(absoluteTaskPath, "utf8");
11516
+ const raw = fs5.readFileSync(absoluteTaskPath, "utf8");
10860
11517
  const { data } = parseFrontmatter(raw);
10861
11518
  return {
10862
11519
  complexity: typeof data.complexity === "string" ? data.complexity.trim().toLowerCase() : void 0,
@@ -10881,11 +11538,11 @@ function slugifyTitle(input) {
10881
11538
  }
10882
11539
  function loadDiscussionRegistry(worktree) {
10883
11540
  const registryPath = runtimeDiscussionRegistryPath(worktree);
10884
- if (!fs2.existsSync(registryPath)) {
11541
+ if (!fs5.existsSync(registryPath)) {
10885
11542
  return { version: 1, active: {} };
10886
11543
  }
10887
11544
  try {
10888
- const parsed = JSON.parse(fs2.readFileSync(registryPath, "utf8"));
11545
+ const parsed = JSON.parse(fs5.readFileSync(registryPath, "utf8"));
10889
11546
  const registry = {
10890
11547
  version: 1,
10891
11548
  active: Object.fromEntries(Object.entries(parsed.active || {}).map(([key, value]) => [key, normalizeLegacyDiscussionEntry(value)]))
@@ -10898,34 +11555,34 @@ function loadDiscussionRegistry(worktree) {
10898
11555
  }
10899
11556
  function saveDiscussionRegistry(worktree, registry) {
10900
11557
  const registryPath = runtimeDiscussionRegistryPath(worktree);
10901
- const runtimeDir = path2.dirname(registryPath);
10902
- if (!fs2.existsSync(runtimeDir)) fs2.mkdirSync(runtimeDir, { recursive: true });
10903
- fs2.writeFileSync(registryPath, JSON.stringify(registry, null, 2), "utf8");
11558
+ const runtimeDir = path5.dirname(registryPath);
11559
+ if (!fs5.existsSync(runtimeDir)) fs5.mkdirSync(runtimeDir, { recursive: true });
11560
+ fs5.writeFileSync(registryPath, JSON.stringify(registry, null, 2), "utf8");
10904
11561
  }
10905
11562
  function runtimeDiscussionsDir(worktree) {
10906
- return path2.join(optimaLocalConfigDir(worktree), "runtime", "discussions");
11563
+ return path5.join(optimaLocalConfigDir(worktree), "runtime", "discussions");
10907
11564
  }
10908
11565
  function archivedRuntimeDiscussionsDir(worktree) {
10909
- return path2.join(runtimeDiscussionsDir(worktree), "archive");
11566
+ return path5.join(runtimeDiscussionsDir(worktree), "archive");
10910
11567
  }
10911
11568
  function finalDiscussionsDir(worktree) {
10912
- return path2.join(optimaTasksDir(worktree), "discussions");
11569
+ return path5.join(optimaTasksDir(worktree), "discussions");
10913
11570
  }
10914
11571
  function nextDiscussionIdentity(worktree, title) {
10915
11572
  const discussionsDir = finalDiscussionsDir(worktree);
10916
11573
  const runtimeDir = runtimeDiscussionsDir(worktree);
10917
- if (!fs2.existsSync(discussionsDir)) fs2.mkdirSync(discussionsDir, { recursive: true });
10918
- if (!fs2.existsSync(runtimeDir)) fs2.mkdirSync(runtimeDir, { recursive: true });
11574
+ if (!fs5.existsSync(discussionsDir)) fs5.mkdirSync(discussionsDir, { recursive: true });
11575
+ if (!fs5.existsSync(runtimeDir)) fs5.mkdirSync(runtimeDir, { recursive: true });
10919
11576
  let sequence = 1;
10920
11577
  while (true) {
10921
11578
  const id = `DISCUSSION-${String(sequence).padStart(3, "0")}`;
10922
11579
  const filename = `${id}-${slugifyTitle(title)}.md`;
10923
- const summaryRelativePath = path2.join(".optima", "tasks", "discussions", filename);
10924
- const summaryAbsolutePath = path2.join(worktree, summaryRelativePath);
11580
+ const summaryRelativePath = path5.join(".optima", "tasks", "discussions", filename);
11581
+ const summaryAbsolutePath = path5.join(worktree, summaryRelativePath);
10925
11582
  const transcriptFilename = `${id}-transcript.md`;
10926
- const transcriptRelativePath = path2.join(".optima", ".config", "runtime", "discussions", transcriptFilename);
10927
- const transcriptAbsolutePath = path2.join(worktree, transcriptRelativePath);
10928
- if (!fs2.existsSync(summaryAbsolutePath) && !fs2.existsSync(transcriptAbsolutePath)) {
11583
+ const transcriptRelativePath = path5.join(".optima", ".config", "runtime", "discussions", transcriptFilename);
11584
+ const transcriptAbsolutePath = path5.join(worktree, transcriptRelativePath);
11585
+ if (!fs5.existsSync(summaryAbsolutePath) && !fs5.existsSync(transcriptAbsolutePath)) {
10929
11586
  return {
10930
11587
  id,
10931
11588
  filename,
@@ -10941,37 +11598,37 @@ function nextDiscussionIdentity(worktree, title) {
10941
11598
  }
10942
11599
  function findDiscussionById(worktree, discussionID) {
10943
11600
  const discussionsDir = finalDiscussionsDir(worktree);
10944
- if (!fs2.existsSync(discussionsDir)) return null;
10945
- const entries = fs2.readdirSync(discussionsDir).filter((name) => name.startsWith(`${discussionID}-`) && name.endsWith(".md"));
11601
+ if (!fs5.existsSync(discussionsDir)) return null;
11602
+ const entries = fs5.readdirSync(discussionsDir).filter((name) => name.startsWith(`${discussionID}-`) && name.endsWith(".md"));
10946
11603
  if (entries.length === 0) return null;
10947
11604
  const filename = entries.sort()[0];
10948
11605
  const transcriptFilename = `${discussionID}-transcript.md`;
10949
11606
  return {
10950
11607
  id: discussionID,
10951
11608
  filename,
10952
- summaryRelativePath: path2.join(".optima", "tasks", "discussions", filename),
10953
- summaryAbsolutePath: path2.join(discussionsDir, filename),
11609
+ summaryRelativePath: path5.join(".optima", "tasks", "discussions", filename),
11610
+ summaryAbsolutePath: path5.join(discussionsDir, filename),
10954
11611
  transcriptFilename,
10955
- transcriptRelativePath: path2.join(".optima", ".config", "runtime", "discussions", transcriptFilename),
10956
- transcriptAbsolutePath: path2.join(runtimeDiscussionsDir(worktree), transcriptFilename)
11612
+ transcriptRelativePath: path5.join(".optima", ".config", "runtime", "discussions", transcriptFilename),
11613
+ transcriptAbsolutePath: path5.join(runtimeDiscussionsDir(worktree), transcriptFilename)
10957
11614
  };
10958
11615
  }
10959
11616
  function parseDiscussionFile(filePath) {
10960
- const raw = fs2.readFileSync(filePath, "utf8");
11617
+ const raw = fs5.readFileSync(filePath, "utf8");
10961
11618
  const { data, body } = parseFrontmatter(raw);
10962
11619
  return { data, body: body.trimStart() };
10963
11620
  }
10964
11621
  function writeDiscussionFile(filePath, frontmatter, body) {
10965
11622
  const serialized = `---
10966
- ${import_yaml2.default.stringify(frontmatter).trim()}
11623
+ ${import_yaml3.default.stringify(frontmatter).trim()}
10967
11624
  ---
10968
11625
 
10969
11626
  ${body.trimEnd()}
10970
11627
  `;
10971
- fs2.writeFileSync(filePath, serialized, "utf8");
11628
+ fs5.writeFileSync(filePath, serialized, "utf8");
10972
11629
  }
10973
11630
  function setDiscussionStatus(filePath, status) {
10974
- if (!fs2.existsSync(filePath)) return;
11631
+ if (!fs5.existsSync(filePath)) return;
10975
11632
  const { data, body } = parseDiscussionFile(filePath);
10976
11633
  writeDiscussionFile(filePath, { ...data, status }, body);
10977
11634
  }
@@ -11036,18 +11693,18 @@ async function appendMessageIfNeeded(client, worktree, registry, sessionID, mess
11036
11693
  });
11037
11694
  const text = extractTextParts(response.data.parts || []);
11038
11695
  if (!text) return;
11039
- appendDiscussionMessage(path2.join(worktree, discussion.transcriptPath), speaker, text, messageID);
11696
+ appendDiscussionMessage(path5.join(worktree, discussion.transcriptPath), speaker, text, messageID);
11040
11697
  discussion.appendedMessageIDs ??= [];
11041
11698
  discussion.appendedMessageIDs.push(messageID);
11042
11699
  saveDiscussionRegistry(worktree, registry);
11043
11700
  }
11044
11701
  async function summarizeDiscussionWithBA(client, worktree, discussion) {
11045
- const transcriptPath = path2.join(worktree, discussion.transcriptPath);
11046
- const summaryPath = path2.join(worktree, discussion.summaryPath);
11047
- const summaryDir = path2.dirname(summaryPath);
11048
- if (!fs2.existsSync(summaryDir)) fs2.mkdirSync(summaryDir, { recursive: true });
11049
- const hasExistingSummary = fs2.existsSync(summaryPath);
11050
- const priorMtimeMs = hasExistingSummary ? fs2.statSync(summaryPath).mtimeMs : null;
11702
+ const transcriptPath = path5.join(worktree, discussion.transcriptPath);
11703
+ const summaryPath = path5.join(worktree, discussion.summaryPath);
11704
+ const summaryDir = path5.dirname(summaryPath);
11705
+ if (!fs5.existsSync(summaryDir)) fs5.mkdirSync(summaryDir, { recursive: true });
11706
+ const hasExistingSummary = fs5.existsSync(summaryPath);
11707
+ const priorMtimeMs = hasExistingSummary ? fs5.statSync(summaryPath).mtimeMs : null;
11051
11708
  const summarizerSession = await client.session.create({
11052
11709
  body: { title: `Discussion Summary: ${discussion.id}` }
11053
11710
  });
@@ -11147,30 +11804,30 @@ async function summarizeDiscussionWithBA(client, worktree, discussion) {
11147
11804
  return { confirmation, summaryPath, transcriptPath, hasExistingSummary, priorMtimeMs };
11148
11805
  }
11149
11806
  function archiveDiscussionTranscript(worktree, transcriptRelativePath) {
11150
- const sourcePath = path2.join(worktree, transcriptRelativePath);
11151
- if (!fs2.existsSync(sourcePath)) return null;
11807
+ const sourcePath = path5.join(worktree, transcriptRelativePath);
11808
+ if (!fs5.existsSync(sourcePath)) return null;
11152
11809
  const archiveDir = archivedRuntimeDiscussionsDir(worktree);
11153
- if (!fs2.existsSync(archiveDir)) fs2.mkdirSync(archiveDir, { recursive: true });
11154
- const targetPath = path2.join(archiveDir, path2.basename(sourcePath));
11155
- fs2.renameSync(sourcePath, targetPath);
11810
+ if (!fs5.existsSync(archiveDir)) fs5.mkdirSync(archiveDir, { recursive: true });
11811
+ const targetPath = path5.join(archiveDir, path5.basename(sourcePath));
11812
+ fs5.renameSync(sourcePath, targetPath);
11156
11813
  return targetPath;
11157
11814
  }
11158
11815
  async function finalizeClosingDiscussion(client, worktree, registry, sessionID, discussion) {
11159
11816
  const { confirmation, summaryPath, hasExistingSummary, priorMtimeMs } = await summarizeDiscussionWithBA(client, worktree, discussion);
11160
- if (!fs2.existsSync(summaryPath)) {
11817
+ if (!fs5.existsSync(summaryPath)) {
11161
11818
  throw new Error(`Discussion summary was not written to ${discussion.summaryPath}`);
11162
11819
  }
11163
11820
  if (hasExistingSummary) {
11164
- const currentMtimeMs = fs2.statSync(summaryPath).mtimeMs;
11821
+ const currentMtimeMs = fs5.statSync(summaryPath).mtimeMs;
11165
11822
  if (currentMtimeMs <= priorMtimeMs) {
11166
11823
  throw new Error(`Discussion summary file was not updated at ${discussion.summaryPath}`);
11167
11824
  }
11168
11825
  }
11169
- const summaryContent = fs2.readFileSync(summaryPath, "utf8").trim();
11826
+ const summaryContent = fs5.readFileSync(summaryPath, "utf8").trim();
11170
11827
  if (!summaryContent) {
11171
11828
  throw new Error(`Discussion summary file is empty at ${discussion.summaryPath}`);
11172
11829
  }
11173
- const transcriptPath = path2.join(worktree, discussion.transcriptPath);
11830
+ const transcriptPath = path5.join(worktree, discussion.transcriptPath);
11174
11831
  setDiscussionStatus(transcriptPath, "closed");
11175
11832
  const archivedTranscriptPath = archiveDiscussionTranscript(worktree, discussion.transcriptPath);
11176
11833
  delete registry.active[sessionID];
@@ -11178,7 +11835,7 @@ async function finalizeClosingDiscussion(client, worktree, registry, sessionID,
11178
11835
  return {
11179
11836
  confirmation,
11180
11837
  summaryPath: discussion.summaryPath,
11181
- archivedTranscriptPath: archivedTranscriptPath ? path2.relative(worktree, archivedTranscriptPath) : path2.join(".optima", ".config", "runtime", "discussions", "archive", path2.basename(discussion.transcriptPath))
11838
+ archivedTranscriptPath: archivedTranscriptPath ? path5.relative(worktree, archivedTranscriptPath) : path5.join(".optima", ".config", "runtime", "discussions", "archive", path5.basename(discussion.transcriptPath))
11182
11839
  };
11183
11840
  }
11184
11841
  function normalizeTeamMode(value) {
@@ -11217,13 +11874,13 @@ function getOperatingTeamMode(repoCfg) {
11217
11874
  }
11218
11875
  function readResolvedFile(relativePath, worktree, options = {}) {
11219
11876
  const filePath = resolveIncludeFile(`plugin:${relativePath}`, worktree, PKG_ROOT, options);
11220
- if (!filePath || !fs2.existsSync(filePath)) return "";
11221
- return resolveIncludes(fs2.readFileSync(filePath, "utf8"), worktree, PKG_ROOT, options).trim();
11877
+ if (!filePath || !fs5.existsSync(filePath)) return "";
11878
+ return resolveIncludes(fs5.readFileSync(filePath, "utf8"), worktree, PKG_ROOT, options).trim();
11222
11879
  }
11223
11880
  function loadMarkdownFragment(filePath, worktree) {
11224
- if (!fs2.existsSync(filePath)) return "";
11881
+ if (!fs5.existsSync(filePath)) return "";
11225
11882
  try {
11226
- const raw = fs2.readFileSync(filePath, "utf8");
11883
+ const raw = fs5.readFileSync(filePath, "utf8");
11227
11884
  const { body } = parseFrontmatter(raw);
11228
11885
  return resolveIncludes(body.trim(), worktree, PKG_ROOT);
11229
11886
  } catch (e) {
@@ -11232,9 +11889,9 @@ function loadMarkdownFragment(filePath, worktree) {
11232
11889
  }
11233
11890
  }
11234
11891
  function loadAgentDefinition(filePath, worktree, options = {}) {
11235
- if (!fs2.existsSync(filePath)) return null;
11892
+ if (!fs5.existsSync(filePath)) return null;
11236
11893
  try {
11237
- const rawContent = fs2.readFileSync(filePath, "utf8");
11894
+ const rawContent = fs5.readFileSync(filePath, "utf8");
11238
11895
  const { data, body } = parseFrontmatter(rawContent);
11239
11896
  const prompt = resolveIncludes(body.trim(), worktree, PKG_ROOT, options);
11240
11897
  return { data, prompt };
@@ -11245,13 +11902,13 @@ function loadAgentDefinition(filePath, worktree, options = {}) {
11245
11902
  }
11246
11903
  function syncGeneratedPolicies(worktree, repoCfg) {
11247
11904
  if (repoCfg.policies?.extract_defaults !== "all") return;
11248
- if (!fs2.existsSync(BUNDLE_POLICIES_DIR)) return;
11905
+ if (!fs5.existsSync(BUNDLE_POLICIES_DIR)) return;
11249
11906
  const generatedDir = generatedPoliciesDir(worktree);
11250
- if (!fs2.existsSync(generatedDir)) fs2.mkdirSync(generatedDir, { recursive: true });
11251
- const policyFiles = fs2.readdirSync(BUNDLE_POLICIES_DIR).filter((file) => file.endsWith(".md") && file !== "README.md");
11907
+ if (!fs5.existsSync(generatedDir)) fs5.mkdirSync(generatedDir, { recursive: true });
11908
+ const policyFiles = fs5.readdirSync(BUNDLE_POLICIES_DIR).filter((file) => file.endsWith(".md") && file !== "README.md");
11252
11909
  for (const file of policyFiles) {
11253
- const sourcePath = path2.join(BUNDLE_POLICIES_DIR, file);
11254
- const source = fs2.readFileSync(sourcePath, "utf8").trimEnd();
11910
+ const sourcePath = path5.join(BUNDLE_POLICIES_DIR, file);
11911
+ const source = fs5.readFileSync(sourcePath, "utf8").trimEnd();
11255
11912
  const generated = [
11256
11913
  "<!--",
11257
11914
  "Generated from Optima plugin defaults.",
@@ -11262,19 +11919,31 @@ function syncGeneratedPolicies(worktree, repoCfg) {
11262
11919
  source,
11263
11920
  ""
11264
11921
  ].join("\n");
11265
- fs2.writeFileSync(path2.join(generatedDir, file), generated, "utf8");
11922
+ fs5.writeFileSync(path5.join(generatedDir, file), generated, "utf8");
11266
11923
  }
11267
11924
  }
11268
11925
  function ensureReadmeFile(dirPath, content) {
11269
- if (!fs2.existsSync(dirPath)) fs2.mkdirSync(dirPath, { recursive: true });
11270
- const readmePath = path2.join(dirPath, "README.md");
11271
- if (!fs2.existsSync(readmePath)) {
11272
- fs2.writeFileSync(readmePath, content, "utf8");
11926
+ if (!fs5.existsSync(dirPath)) fs5.mkdirSync(dirPath, { recursive: true });
11927
+ const readmePath = path5.join(dirPath, "README.md");
11928
+ if (!fs5.existsSync(readmePath)) {
11929
+ fs5.writeFileSync(readmePath, content, "utf8");
11273
11930
  }
11274
11931
  }
11275
11932
  function ensureFileIfMissing(filePath, content) {
11276
- if (!fs2.existsSync(path2.dirname(filePath))) fs2.mkdirSync(path2.dirname(filePath), { recursive: true });
11277
- if (!fs2.existsSync(filePath)) fs2.writeFileSync(filePath, content, "utf8");
11933
+ if (!fs5.existsSync(path5.dirname(filePath))) fs5.mkdirSync(path5.dirname(filePath), { recursive: true });
11934
+ if (!fs5.existsSync(filePath)) fs5.writeFileSync(filePath, content, "utf8");
11935
+ }
11936
+ function currentTasksRegistryContent() {
11937
+ return "# Current Tasks (Backlog)\n\n## \u{1F4AC} Active Discussions\n- (None)\n\n## \u{1F680} Active\n- (None)\n\n## \u{1F4CB} Todo\n- (None)\n\n## \u{1F6D1} Blocked\n- (None)\n";
11938
+ }
11939
+ function doneTasksRegistryContent() {
11940
+ return "# Completed Tasks (Registry)\n\n| Date | Task ID | SCR ID | Commit | Summary |\n| :--- | :--- | :--- | :--- | :--- |\n";
11941
+ }
11942
+ function currentScrRegistryContent() {
11943
+ return "# Current Spec Change Requests (Backlog)\n\n## \u{1F680} Active/Review\n- (None)\n\n## \u{1F4CB} Approved (Ready for Implementation)\n- (None)\n\n## \u{1F4A1} Proposed\n- (None)\n";
11944
+ }
11945
+ function doneScrRegistryContent() {
11946
+ return "# Implemented Spec Change Requests\n\n| Date | SCR ID | Title | Related Feature | Task ID |\n| :--- | :--- | :--- | :--- | :--- |\n";
11278
11947
  }
11279
11948
  function taskTemplateContent() {
11280
11949
  return `---
@@ -11348,19 +12017,58 @@ Never place implementation evidence under root \`evidences/\`.
11348
12017
  }
11349
12018
  function ensureOptimaTaskTemplates(worktree) {
11350
12019
  const tasksDir = optimaTasksDir(worktree);
11351
- ensureFileIfMissing(path2.join(tasksDir, "task-template.md"), taskTemplateContent());
11352
- ensureFileIfMissing(path2.join(tasksDir, "subtask-template.md"), subtaskTemplateContent());
12020
+ ensureFileIfMissing(path5.join(tasksDir, "task-template.md"), taskTemplateContent());
12021
+ ensureFileIfMissing(path5.join(tasksDir, "subtask-template.md"), subtaskTemplateContent());
12022
+ }
12023
+ function scaffoldOptimaConfig(worktree, teamMode = "full") {
12024
+ const configPath = repoConfigPath(worktree);
12025
+ if (fs5.existsSync(configPath)) return false;
12026
+ const templatePath = path5.join(TEMPLATES_DIR, "optima.yaml.template");
12027
+ if (!fs5.existsSync(templatePath)) return false;
12028
+ const agentIds = fs5.existsSync(BUNDLE_AGENTS_DIR) ? fs5.readdirSync(BUNDLE_AGENTS_DIR).filter((f) => f.endsWith(".md")).map((f) => f.replace(".md", "")) : [];
12029
+ let optimaConfig = fs5.readFileSync(templatePath, "utf8");
12030
+ optimaConfig = optimaConfig.replace("{{teamMode}}", normalizeTeamMode(teamMode));
12031
+ let agentsSection = "";
12032
+ for (const id of agentIds) {
12033
+ const enabled = isAgentEnabledForTeamMode(id, normalizeTeamMode(teamMode)) ? "true" : "false";
12034
+ agentsSection += ` ${id}:
12035
+ enabled: ${enabled}
12036
+ `;
12037
+ }
12038
+ optimaConfig = optimaConfig.replace(/^agents:/m, "agents:\n" + agentsSection);
12039
+ ensureFileIfMissing(configPath, optimaConfig);
12040
+ return fs5.existsSync(configPath);
12041
+ }
12042
+ function scaffoldOptimaRootCodemap(worktree) {
12043
+ const rootCodemapPath = optimaCodemapPath(worktree);
12044
+ if (fs5.existsSync(rootCodemapPath)) return false;
12045
+ const templatePath = path5.join(TEMPLATES_DIR, "codemap.yml.template");
12046
+ if (!fs5.existsSync(templatePath)) return false;
12047
+ const codemapConfig = fs5.readFileSync(templatePath, "utf8").replace("{{projectName}}", path5.basename(worktree));
12048
+ ensureFileIfMissing(rootCodemapPath, codemapConfig);
12049
+ return fs5.existsSync(rootCodemapPath);
12050
+ }
12051
+ function ensureOptimaRegistries(worktree) {
12052
+ const tasksDir = optimaTasksDir(worktree);
12053
+ const scrsDir = optimaScrsDir(worktree);
12054
+ if (!fs5.existsSync(tasksDir)) fs5.mkdirSync(tasksDir, { recursive: true });
12055
+ if (!fs5.existsSync(scrsDir)) fs5.mkdirSync(scrsDir, { recursive: true });
12056
+ ensureFileIfMissing(path5.join(tasksDir, "current.md"), currentTasksRegistryContent());
12057
+ ensureFileIfMissing(path5.join(tasksDir, "done.md"), doneTasksRegistryContent());
12058
+ ensureFileIfMissing(path5.join(scrsDir, "current.md"), currentScrRegistryContent());
12059
+ ensureFileIfMissing(path5.join(scrsDir, "done.md"), doneScrRegistryContent());
11353
12060
  }
11354
12061
  function scaffoldOptimaReadmes(worktree) {
11355
12062
  ensureReadmeFile(repoPoliciesDir(worktree), REPO_LOCAL_POLICIES_README);
11356
12063
  ensureReadmeFile(repoAgentsDir(worktree), [
11357
12064
  "# Repository Agents",
11358
12065
  "",
11359
- "Place full repository-local agent definitions here.",
12066
+ "Place full repository-local agent definitions here only when explicitly requested by the user.",
11360
12067
  "",
11361
- "- Use `.optima/agents/<agent>.md` to override a bundled agent's full base definition.",
11362
- "- Use `.optima/agents/<agent>.md` to define a brand new custom repository agent.",
11363
- "- Files in this folder are treated as full agent definitions.",
12068
+ "- Use `.optima/agents/<agent>.md` only to intentionally override a bundled agent's full base definition.",
12069
+ "- Use `.optima/agents/<agent>.md` only to define a brand new custom repository agent.",
12070
+ "- Files in this folder are treated as full agent definitions and block bundled prompt updates for that agent.",
12071
+ "- Prefer `.optima/agent-additions/<agent>.md` for normal repository-specific guidance.",
11364
12072
  "- `README.md` is ignored by agent discovery.",
11365
12073
  "",
11366
12074
  "## Include Types Available In Custom Agents",
@@ -11454,6 +12162,38 @@ function scaffoldOptimaReadmes(worktree) {
11454
12162
  ].join("\n"));
11455
12163
  ensureOptimaTaskTemplates(worktree);
11456
12164
  }
12165
+ function optimaRepairDependencies() {
12166
+ return {
12167
+ currentScrRegistryContent,
12168
+ currentTasksRegistryContent,
12169
+ doneScrRegistryContent,
12170
+ doneTasksRegistryContent,
12171
+ ensureFileIfMissing,
12172
+ ensureOptimaGitignoreRules,
12173
+ ensureOptimaRegistries,
12174
+ isGitRepository,
12175
+ isOptimaPluginPackageWorktree,
12176
+ legacyNomadworkDir,
12177
+ legacyNomadworksDir,
12178
+ legacyOrbitaDir,
12179
+ legacyStaticEngDir,
12180
+ migrateLegacyOptimaLayout,
12181
+ optimaCodemapPath,
12182
+ optimaDir,
12183
+ optimaEvidencesDir,
12184
+ optimaGitignoreRules: OPTIMA_GITIGNORE_RULES,
12185
+ optimaScrsDir,
12186
+ optimaTasksDir,
12187
+ repoConfigPath,
12188
+ repoLocalPoliciesReadme: REPO_LOCAL_POLICIES_README,
12189
+ repoPoliciesDir,
12190
+ scaffoldOptimaConfig,
12191
+ scaffoldOptimaReadmes,
12192
+ scaffoldOptimaRootCodemap,
12193
+ subtaskTemplateContent,
12194
+ taskTemplateContent
12195
+ };
12196
+ }
11457
12197
  function getModePromptFragment(agentId, operatingTeamMode, worktree) {
11458
12198
  const fragmentMap = {
11459
12199
  product_manager: {
@@ -11469,18 +12209,26 @@ function getModePromptFragment(agentId, operatingTeamMode, worktree) {
11469
12209
  if (!fragmentPath) return "";
11470
12210
  return readResolvedFile(fragmentPath, worktree, { preferCompactPromptDocs: true });
11471
12211
  }
11472
- function isSameOrNestedPath(candidate, root) {
11473
- if (typeof candidate !== "string" || typeof root !== "string" || !candidate.trim() || !root.trim()) return false;
11474
- const resolvedCandidate = path2.resolve(candidate);
11475
- const resolvedRoot = path2.resolve(root);
11476
- const relative = path2.relative(resolvedRoot, resolvedCandidate);
11477
- return relative === "" || !!relative && !relative.startsWith("..") && !path2.isAbsolute(relative);
11478
- }
11479
12212
  function shouldRegisterWorkflowProductManager(options = {}, worktree = process.cwd()) {
11480
12213
  if (options.clickUpWebhookActive === true) return true;
11481
12214
  const validation = options.clickUpWebhookValidation;
11482
12215
  return validation?.complete === true && validation?.ok !== false && isSameOrNestedPath(worktree, validation.config?.basePath);
11483
12216
  }
12217
+ function resolveSessionToolDirectory({ requestedDirectory, context, pluginWorktree, clickUpWebhookValidation } = {}) {
12218
+ const safe = safeWorktreeOrFailure(context, pluginWorktree);
12219
+ if (!safe.ok) return { ok: false, error: safe.message };
12220
+ const requested = String(requestedDirectory || "").trim() ? path5.resolve(safe.worktree, String(requestedDirectory).trim()) : safe.worktree;
12221
+ if (!isSafeWritableDirectory(requested)) return { ok: false, error: `Directory is not a safe writable directory: ${requested}` };
12222
+ if (isSameOrNestedPath(requested, safe.worktree)) return { ok: true, directory: requested, safeWorktree: safe.worktree, scope: "context_worktree" };
12223
+ const clickUpBasePath = clickUpWebhookValidation?.complete === true && clickUpWebhookValidation?.ok !== false ? clickUpWebhookValidation.config?.basePath : "";
12224
+ if (clickUpBasePath && isSameOrNestedPath(requested, clickUpBasePath)) {
12225
+ return { ok: true, directory: requested, safeWorktree: safe.worktree, scope: "clickup_base_path", clickupBasePath: path5.resolve(clickUpBasePath) };
12226
+ }
12227
+ return {
12228
+ ok: false,
12229
+ error: `Directory '${requested}' is outside the safe worktree '${safe.worktree}' and configured ClickUp base path.`
12230
+ };
12231
+ }
11484
12232
  function buildOptimaAgents(repoCfg, operatingTeamMode, worktree, debugDir, options = {}) {
11485
12233
  const optimaActive = repoCfg && repoCfg.enabled === true;
11486
12234
  const clickUpWebhookActive = shouldRegisterWorkflowProductManager(options, worktree);
@@ -11508,8 +12256,8 @@ function buildOptimaAgents(repoCfg, operatingTeamMode, worktree, debugDir, optio
11508
12256
  if (!enabled) continue;
11509
12257
  }
11510
12258
  const promptOptions = { preferCompactPromptDocs: repoCfg.features?.compact_prompt_docs !== false };
11511
- const bundledDefinition = loadAgentDefinition(path2.join(BUNDLE_AGENTS_DIR, file), worktree, promptOptions);
11512
- const repoDefinition = loadAgentDefinition(path2.join(repoAgentDefinitions, file), worktree, promptOptions) || loadAgentDefinition(path2.join(legacyAgentsDir, file), worktree, promptOptions);
12259
+ const bundledDefinition = loadAgentDefinition(path5.join(BUNDLE_AGENTS_DIR, file), worktree, promptOptions);
12260
+ const repoDefinition = loadAgentDefinition(path5.join(repoAgentDefinitions, file), worktree, promptOptions) || loadAgentDefinition(path5.join(legacyAgentsDir, file), worktree, promptOptions);
11513
12261
  const activeDefinition = repoDefinition || bundledDefinition;
11514
12262
  if (!activeDefinition) continue;
11515
12263
  const { data } = activeDefinition;
@@ -11518,7 +12266,7 @@ function buildOptimaAgents(repoCfg, operatingTeamMode, worktree, debugDir, optio
11518
12266
  if (modePromptFragment) finalPrompt = `${finalPrompt}
11519
12267
 
11520
12268
  ${modePromptFragment}`;
11521
- const additionFragment = loadMarkdownFragment(path2.join(repoAgentAdditions, file), worktree);
12269
+ const additionFragment = loadMarkdownFragment(path5.join(repoAgentAdditions, file), worktree);
11522
12270
  if (additionFragment) {
11523
12271
  finalPrompt = `${finalPrompt}
11524
12272
 
@@ -11571,14 +12319,14 @@ Use this Optima-provided fallback when the current task worktree lacks docs/core
11571
12319
  }
11572
12320
  ourAgents[id] = agentConfig;
11573
12321
  if (repoCfg.features?.debug_dumps !== false) {
11574
- const debugPath = path2.join(debugDir, `${id}.md`);
12322
+ const debugPath = path5.join(debugDir, `${id}.md`);
11575
12323
  const { prompt, ...dumpConfig } = agentConfig;
11576
12324
  const debugHeader = `---
11577
- ${import_yaml2.default.stringify(dumpConfig).trim()}
12325
+ ${import_yaml3.default.stringify(dumpConfig).trim()}
11578
12326
  ---`;
11579
12327
  try {
11580
- if (!fs2.existsSync(debugDir)) fs2.mkdirSync(debugDir, { recursive: true });
11581
- fs2.writeFileSync(debugPath, `${debugHeader}
12328
+ if (!fs5.existsSync(debugDir)) fs5.mkdirSync(debugDir, { recursive: true });
12329
+ fs5.writeFileSync(debugPath, `${debugHeader}
11582
12330
 
11583
12331
  ${prompt}`, "utf8");
11584
12332
  } catch (e) {
@@ -11602,9 +12350,9 @@ async function OptimaPlugin(input = {}, pluginOptions = {}) {
11602
12350
  const configPath = resolveConfigPath(worktree);
11603
12351
  const discussionRegistry = loadDiscussionRegistry(worktree);
11604
12352
  let repoCfg = { agents: {}, defaults: {}, features: {} };
11605
- if (fs2.existsSync(configPath)) {
12353
+ if (fs5.existsSync(configPath)) {
11606
12354
  try {
11607
- repoCfg = import_yaml2.default.parse(fs2.readFileSync(configPath, "utf8")) || repoCfg;
12355
+ repoCfg = import_yaml3.default.parse(fs5.readFileSync(configPath, "utf8")) || repoCfg;
11608
12356
  } catch (e) {
11609
12357
  console.error(`[Optima] Failed to parse config at ${configPath}:`, e);
11610
12358
  }
@@ -11711,54 +12459,16 @@ async function OptimaPlugin(input = {}, pluginOptions = {}) {
11711
12459
  }
11712
12460
  migrateLegacyOptimaLayout(toolWorktree);
11713
12461
  const cfgDir = optimaConfigDir(toolWorktree);
11714
- if (!fs2.existsSync(cfgDir)) fs2.mkdirSync(cfgDir, { recursive: true });
11715
- const agentIds = fs2.existsSync(BUNDLE_AGENTS_DIR) ? fs2.readdirSync(BUNDLE_AGENTS_DIR).filter((f) => f.endsWith(".md")).map((f) => f.replace(".md", "")) : [];
11716
- const optimaTmplPath = path2.join(TEMPLATES_DIR, "optima.yaml.template");
11717
- const codemapTmplPath = path2.join(TEMPLATES_DIR, "codemap.yml.template");
11718
- if (!fs2.existsSync(optimaTmplPath) || !fs2.existsSync(codemapTmplPath)) {
12462
+ if (!fs5.existsSync(cfgDir)) fs5.mkdirSync(cfgDir, { recursive: true });
12463
+ const optimaTmplPath = path5.join(TEMPLATES_DIR, "optima.yaml.template");
12464
+ const codemapTmplPath = path5.join(TEMPLATES_DIR, "codemap.yml.template");
12465
+ if (!fs5.existsSync(optimaTmplPath) || !fs5.existsSync(codemapTmplPath)) {
11719
12466
  return "Error: Initialization templates not found in plugin.";
11720
12467
  }
11721
- let optimaConfig = fs2.readFileSync(optimaTmplPath, "utf8");
11722
- optimaConfig = optimaConfig.replace("{{teamMode}}", requestedTeamMode);
11723
- let agentsSection = "";
11724
- for (const id of agentIds) {
11725
- const enabled = isAgentEnabledForTeamMode(id, requestedTeamMode) ? "true" : "false";
11726
- agentsSection += ` ${id}:
11727
- enabled: ${enabled}
11728
- `;
11729
- }
11730
- optimaConfig = optimaConfig.replace(/^agents:/m, "agents:\n" + agentsSection);
11731
- let codemapConfig = fs2.readFileSync(codemapTmplPath, "utf8");
11732
- codemapConfig = codemapConfig.replace("{{projectName}}", path2.basename(toolWorktree));
11733
- const cfgFilePath = repoConfigPath(toolWorktree);
11734
- const rootCodemapPath = optimaCodemapPath(toolWorktree);
11735
- if (!fs2.existsSync(cfgFilePath)) {
11736
- fs2.writeFileSync(cfgFilePath, optimaConfig, "utf8");
11737
- }
11738
- if (!fs2.existsSync(rootCodemapPath)) {
11739
- fs2.writeFileSync(rootCodemapPath, codemapConfig, "utf8");
11740
- }
12468
+ scaffoldOptimaConfig(toolWorktree, requestedTeamMode);
12469
+ scaffoldOptimaRootCodemap(toolWorktree);
11741
12470
  scaffoldOptimaReadmes(toolWorktree);
11742
- const tasksDir = optimaTasksDir(toolWorktree);
11743
- const scrsDir = optimaScrsDir(toolWorktree);
11744
- if (!fs2.existsSync(tasksDir)) fs2.mkdirSync(tasksDir, { recursive: true });
11745
- if (!fs2.existsSync(scrsDir)) fs2.mkdirSync(scrsDir, { recursive: true });
11746
- const currentPath = path2.join(tasksDir, "current.md");
11747
- const donePath = path2.join(tasksDir, "done.md");
11748
- const scrsCurrentPath = path2.join(scrsDir, "current.md");
11749
- const scrsDonePath = path2.join(scrsDir, "done.md");
11750
- if (!fs2.existsSync(currentPath)) {
11751
- fs2.writeFileSync(currentPath, "# Current Tasks (Backlog)\n\n## \u{1F4AC} Active Discussions\n- (None)\n\n## \u{1F680} Active\n- (None)\n\n## \u{1F4CB} Todo\n- (None)\n\n## \u{1F6D1} Blocked\n- (None)\n", "utf8");
11752
- }
11753
- if (!fs2.existsSync(donePath)) {
11754
- fs2.writeFileSync(donePath, "# Completed Tasks (Registry)\n\n| Date | Task ID | SCR ID | Commit | Summary |\n| :--- | :--- | :--- | :--- | :--- |\n", "utf8");
11755
- }
11756
- if (!fs2.existsSync(scrsCurrentPath)) {
11757
- fs2.writeFileSync(scrsCurrentPath, "# Current Spec Change Requests (Backlog)\n\n## \u{1F680} Active/Review\n- (None)\n\n## \u{1F4CB} Approved (Ready for Implementation)\n- (None)\n\n## \u{1F4A1} Proposed\n- (None)\n", "utf8");
11758
- }
11759
- if (!fs2.existsSync(scrsDonePath)) {
11760
- fs2.writeFileSync(scrsDonePath, "# Implemented Spec Change Requests\n\n| Date | SCR ID | Title | Related Feature | Task ID |\n| :--- | :--- | :--- | :--- | :--- |\n", "utf8");
11761
- }
12471
+ ensureOptimaRegistries(toolWorktree);
11762
12472
  const gitignoreResult = ensureOptimaGitignoreRules(toolWorktree);
11763
12473
  const gitignoreNote = gitignoreResult.added.length > 0 ? ` Added ${gitignoreResult.added.length} Optima local/private .gitignore rule(s).` : "";
11764
12474
  const initSummary = `Optima initialized in '${requestedTeamMode}' team mode: .optima/.config/optima.yaml, repo policy/agent folders, registries, and .optima/codemap.yml created.${gitignoreNote}`;
@@ -11767,6 +12477,100 @@ async function OptimaPlugin(input = {}, pluginOptions = {}) {
11767
12477
  Restart or reload OpenCode manually if the newly scaffolded config or agents are not visible in this session. Optima did not dispose or reload the active OpenCode instance automatically to avoid aborting the current session.`;
11768
12478
  }
11769
12479
  }),
12480
+ optima_session_create: tool({
12481
+ description: "Create an OpenCode session through the installed structured SDK shape",
12482
+ args: {
12483
+ directory: tool.schema.string().describe("Project directory for the OpenCode session"),
12484
+ title: tool.schema.string().describe("Session title"),
12485
+ agent: tool.schema.string().describe("Optional agent id for session creation")
12486
+ },
12487
+ async execute(args, context) {
12488
+ try {
12489
+ const directory = resolveSessionToolDirectory({ requestedDirectory: args.directory, context, pluginWorktree: worktree, clickUpWebhookValidation });
12490
+ if (!directory.ok) return JSON.stringify({ ok: false, error: directory.error }, null, 2);
12491
+ const result = await createOpenCodeSessionControl(input.client, {
12492
+ directory: directory.directory,
12493
+ title: args.title,
12494
+ agent: args.agent
12495
+ });
12496
+ return JSON.stringify(result, null, 2);
12497
+ } catch (error) {
12498
+ return JSON.stringify({ ok: false, error: error.message }, null, 2);
12499
+ }
12500
+ }
12501
+ }),
12502
+ optima_session_prompt: tool({
12503
+ description: "Prompt an existing OpenCode session through the installed structured SDK shape",
12504
+ args: {
12505
+ session_id: tool.schema.string().describe("OpenCode session id"),
12506
+ directory: tool.schema.string().describe("Project directory for the OpenCode session"),
12507
+ text: tool.schema.string().describe("Text prompt to send"),
12508
+ agent: tool.schema.string().describe("Optional agent id for the prompt body"),
12509
+ omit_agent: tool.schema.string().describe("Set to 'true' to omit agent from the prompt body")
12510
+ },
12511
+ async execute(args, context) {
12512
+ try {
12513
+ const directory = resolveSessionToolDirectory({ requestedDirectory: args.directory, context, pluginWorktree: worktree, clickUpWebhookValidation });
12514
+ if (!directory.ok) return JSON.stringify({ ok: false, error: directory.error }, null, 2);
12515
+ const result = await promptOpenCodeSessionControl(input.client, {
12516
+ sessionId: args.session_id,
12517
+ directory: directory.directory,
12518
+ text: args.text,
12519
+ agent: args.agent,
12520
+ omitAgent: String(args.omit_agent || "").toLowerCase() === "true"
12521
+ });
12522
+ return JSON.stringify(result, null, 2);
12523
+ } catch (error) {
12524
+ return JSON.stringify({ ok: false, error: error.message }, null, 2);
12525
+ }
12526
+ }
12527
+ }),
12528
+ optima_session_messages: tool({
12529
+ description: "Read and summarize OpenCode session messages through the installed structured SDK shape",
12530
+ args: {
12531
+ session_id: tool.schema.string().describe("OpenCode session id"),
12532
+ directory: tool.schema.string().describe("Optional project directory for the OpenCode session"),
12533
+ limit: tool.schema.number().describe("Optional message limit")
12534
+ },
12535
+ async execute(args, context) {
12536
+ try {
12537
+ const directory = resolveSessionToolDirectory({ requestedDirectory: args.directory, context, pluginWorktree: worktree, clickUpWebhookValidation });
12538
+ if (!directory.ok) return JSON.stringify({ ok: false, error: directory.error }, null, 2);
12539
+ const result = await readOpenCodeSessionControl(input.client, {
12540
+ sessionId: args.session_id,
12541
+ directory: directory.directory,
12542
+ limit: args.limit
12543
+ });
12544
+ return JSON.stringify(result, null, 2);
12545
+ } catch (error) {
12546
+ return JSON.stringify({ ok: false, error: error.message }, null, 2);
12547
+ }
12548
+ }
12549
+ }),
12550
+ optima_session_probe: tool({
12551
+ description: "Create, prompt, and read an OpenCode session without touching ClickUp state",
12552
+ args: {
12553
+ directory: tool.schema.string().describe("Project directory for the OpenCode session"),
12554
+ agent: tool.schema.string().describe("Optional agent id to probe"),
12555
+ omit_agent_on_prompt: tool.schema.string().describe("Set to 'true' to omit agent from the prompt body"),
12556
+ text: tool.schema.string().describe("Optional marker text to send")
12557
+ },
12558
+ async execute(args, context) {
12559
+ try {
12560
+ const directory = resolveSessionToolDirectory({ requestedDirectory: args.directory, context, pluginWorktree: worktree, clickUpWebhookValidation });
12561
+ if (!directory.ok) return JSON.stringify({ ok: false, error: directory.error }, null, 2);
12562
+ const result = await probeOpenCodeSessionControl(input.client, {
12563
+ directory: directory.directory,
12564
+ agent: args.agent,
12565
+ omitAgentOnPrompt: String(args.omit_agent_on_prompt || "").toLowerCase() === "true",
12566
+ text: args.text
12567
+ });
12568
+ return JSON.stringify(result, null, 2);
12569
+ } catch (error) {
12570
+ return JSON.stringify({ ok: false, error: error.message }, null, 2);
12571
+ }
12572
+ }
12573
+ }),
11770
12574
  optima_clickup_sync_summary: tool({
11771
12575
  description: "Generate a dry-run ClickUp summary/comment payload from Optima Markdown task and evidence artifacts",
11772
12576
  args: {
@@ -11779,14 +12583,14 @@ Restart or reload OpenCode manually if the newly scaffolded config or agents are
11779
12583
  async execute(args, context) {
11780
12584
  const safe = safeWorktreeOrFailure(context, worktree);
11781
12585
  if (!safe.ok) return safe.message;
11782
- const summaryPath = path2.resolve(safe.worktree, args.summary_path || "");
11783
- if (!fs2.existsSync(summaryPath)) return `FAIL: summary_path not found: ${summaryPath}`;
11784
- const taskPath = args.task_path ? path2.resolve(safe.worktree, args.task_path) : "";
12586
+ const summaryPath = path5.resolve(safe.worktree, args.summary_path || "");
12587
+ if (!fs5.existsSync(summaryPath)) return `FAIL: summary_path not found: ${summaryPath}`;
12588
+ const taskPath = args.task_path ? path5.resolve(safe.worktree, args.task_path) : "";
11785
12589
  const payload = buildClickUpSummaryPayload({
11786
- summaryMarkdown: fs2.readFileSync(summaryPath, "utf8"),
11787
- summaryPath: path2.relative(safe.worktree, summaryPath),
11788
- taskMarkdown: taskPath && fs2.existsSync(taskPath) ? fs2.readFileSync(taskPath, "utf8") : "",
11789
- taskPath: taskPath ? path2.relative(safe.worktree, taskPath) : "",
12590
+ summaryMarkdown: fs5.readFileSync(summaryPath, "utf8"),
12591
+ summaryPath: path5.relative(safe.worktree, summaryPath),
12592
+ taskMarkdown: taskPath && fs5.existsSync(taskPath) ? fs5.readFileSync(taskPath, "utf8") : "",
12593
+ taskPath: taskPath ? path5.relative(safe.worktree, taskPath) : "",
11790
12594
  branch: args.branch,
11791
12595
  worktree: args.worktree,
11792
12596
  pr: args.pr
@@ -11865,12 +12669,12 @@ Restart or reload OpenCode manually if the newly scaffolded config or agents are
11865
12669
  async execute(args, context) {
11866
12670
  const safe = safeWorktreeOrFailure(context, worktree);
11867
12671
  if (!safe.ok) return safe.message;
11868
- const markdownPath = path2.resolve(safe.worktree, args.markdown_path || "");
11869
- if (!fs2.existsSync(markdownPath)) return `FAIL: markdown_path not found: ${markdownPath}`;
12672
+ const markdownPath = path5.resolve(safe.worktree, args.markdown_path || "");
12673
+ if (!fs5.existsSync(markdownPath)) return `FAIL: markdown_path not found: ${markdownPath}`;
11870
12674
  const payload = buildClickUpCreateSubtasksPayload({
11871
12675
  parentTaskId: args.parent_task_id,
11872
- markdown: fs2.readFileSync(markdownPath, "utf8"),
11873
- sourcePath: path2.relative(safe.worktree, markdownPath),
12676
+ markdown: fs5.readFileSync(markdownPath, "utf8"),
12677
+ sourcePath: path5.relative(safe.worktree, markdownPath),
11874
12678
  parentBranch: args.parent_branch,
11875
12679
  parentTaskType: args.parent_task_type || "Tarea",
11876
12680
  apply: String(args.apply || "").toLowerCase() === "true"
@@ -11902,6 +12706,21 @@ Restart or reload OpenCode manually if the newly scaffolded config or agents are
11902
12706
  return formatValidationResult(res);
11903
12707
  }
11904
12708
  }),
12709
+ optima_repair: tool({
12710
+ description: "Inspect and repair Optima operational errors across config, registries, templates, policies, legacy artifacts, Markdown paths, gitignore rules, and CodeMaps. Dry-run by default; set apply true to mutate safely.",
12711
+ args: {
12712
+ apply: tool.schema.boolean().optional().describe("Set true to apply deterministic Optima metadata repairs. Defaults to false dry-run."),
12713
+ mode: tool.schema.string().optional().describe("Optional mode: 'dry-run' or 'apply'. Dry-run is the default."),
12714
+ team_mode: tool.schema.string().optional().describe("Team mode for a newly created config when missing: mini or full. Defaults to full.")
12715
+ },
12716
+ async execute(args, context) {
12717
+ const safe = safeWorktreeOrFailure(context, worktree);
12718
+ if (!safe.ok) return safe.message;
12719
+ const plan = planOptimaRepair(safe.worktree, args, optimaRepairDependencies());
12720
+ const validationResult = plan.mode === "apply" ? await optima_validate_logic(safe.worktree) : null;
12721
+ return formatRepairResult(plan, validationResult, formatValidationResult);
12722
+ }
12723
+ }),
11905
12724
  optima_start_discussion: tool({
11906
12725
  description: "Start an automatic discussion transcript for this session",
11907
12726
  args: {
@@ -12054,7 +12873,7 @@ Backfilled messages: ${backfilled}`;
12054
12873
  if (!existing) {
12055
12874
  return "FAIL: No active discussion exists for this session.";
12056
12875
  }
12057
- const discussionPath = path2.join(toolWorktree, existing.transcriptPath);
12876
+ const discussionPath = path5.join(toolWorktree, existing.transcriptPath);
12058
12877
  setDiscussionStatus(discussionPath, "summarizing");
12059
12878
  existing.status = "summarizing";
12060
12879
  saveDiscussionRegistry(toolWorktree, toolRegistry);
@@ -12106,7 +12925,7 @@ Reason: ${err.message}`;
12106
12925
  try {
12107
12926
  const sessionResult = await client.session.create({
12108
12927
  query: { directory: workflowDirectory },
12109
- body: { title: `Workflow Run: ${path2.basename(workflowTaskPath)}` }
12928
+ body: { title: `Workflow Run: ${path5.basename(workflowTaskPath)}` }
12110
12929
  });
12111
12930
  const sessionId = sessionResult.data.id;
12112
12931
  activeWorkflows.set(sessionId, { pmaSessionId, taskPath: workflowTaskPath, track: workflowTrack, directory: workflowDirectory });
@@ -12235,7 +13054,7 @@ Follow-up: use optima_prompt_workflow with session_id '${sessionId}' to check in
12235
13054
  }
12236
13055
  };
12237
13056
  }
12238
- 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, createClickUpApiClient, createOpenCodeSession, deliveryEvidencePathForClickUpTask, ensureClickUpTaskWorktree, ensureClickUpWebhookSubscription, handleClickUpWebhookRequest, isClickUpWebhookStateActive, normalizeClickUpWebhookConfig, normalizeClickUpWebhookLogLevel, normalizeOpenCodeBaseUrl, openCodeSessionExists, readClickUpCommentLedger, readClickUpWebhookState, readOpenCodeSessionMessages, reconcileClickUpStartup, scheduleClickUpStartupReconciliation, waitForOpenCodeReadiness, recordClickUpCommentVersionProcessed, resyncClickUpWebhookForSignatureDrift, resolveOptimaPluginOptions, resolveSecretReference, routeClickUpWebhookEvent, sendOpenCodeSessionEvent, sendOpenCodeSessionEventDirect, verifyOpenCodeSessionEventDelivery, stableClickUpCommentVersionMarker, startClickUpWebhookListener, validateClickUpWebhookState, verifyClickUpSignature, writeClickUpWebhookState, decideClickUpStatusAction, deriveClickUpBranchName, deriveClickUpPendingSubtaskBranch, deriveClickUpPrTarget, deriveClickUpWorktree, determineClickUpMergeAuthority, ensureOptimaGitignoreRules, explicitSafeInputWorktree, finalApprovalAssignees, formatValidationResult, isIgnoredClickUpTaskType, isOptimaPluginPackageWorktree, isSafeWritableDirectory, loadHumansRegistry, mergeClickUpAgentMetadata, mergeClickUpSessionMetadata, migrateLegacyOptimaLayout, normalizeAgentMetadataJson, normalizeClickUpStatus, normalizeClickUpTaskType, normalizePromptResponseParts, normalizeWorkflowTaskPath, parseClickUpSubtasksMarkdown, parseHumansRegistry, parseMarkdownArtifact, parseMarkdownSections, preEstimateClickUpWork, readMarkdownArtifact, resolveHumanRoles, resolveSafeWorktree, safeWorktreeOrFailure, stripRawLogSections, validateMainWorkspaceBranchSafety, workflowFinalMessageFromPromptResponse };
13057
+ 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, createOpenCodeSession, createOpenCodeSessionControl, deliveryEvidencePathForClickUpTask, ensureClickUpTaskWorktree, ensureClickUpWebhookSubscription, handleClickUpWebhookRequest, isClickUpWebhookStateActive, isSameOrNestedPath, normalizeClickUpWebhookConfig, normalizeClickUpWebhookLogLevel, normalizeOpenCodeBaseUrl, openCodeSessionExists, promptOpenCodeSessionControl, probeOpenCodeSessionControl, readClickUpCommentLedger, readClickUpWebhookState, readOpenCodeSessionControl, readOpenCodeSessionMessages, reconcileClickUpStartup, scheduleClickUpStartupReconciliation, 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 };
12239
13058
  export {
12240
13059
  OptimaPlugin as default
12241
13060
  };