@defend-tech/opencode-optima 0.1.55 → 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
  }
@@ -10144,9 +10700,9 @@ function formatClickUpWebhookPrompt({ eventType, taskId, payload, branch = "", w
10144
10700
  }
10145
10701
  function appendClickUpWebhookLocalLog(worktree, entry) {
10146
10702
  const logPath = clickUpWebhookLogPath(worktree);
10147
- fs2.mkdirSync(path2.dirname(logPath), { recursive: true });
10703
+ fs5.mkdirSync(path5.dirname(logPath), { recursive: true });
10148
10704
  const safeEntry = { ...entry, at: entry.at || (/* @__PURE__ */ new Date()).toISOString() };
10149
- fs2.appendFileSync(logPath, `${JSON.stringify(safeEntry)}
10705
+ fs5.appendFileSync(logPath, `${JSON.stringify(safeEntry)}
10150
10706
  `, "utf8");
10151
10707
  }
10152
10708
  function clickUpWebhookLifecycleLog(worktree, entry) {
@@ -10175,7 +10731,7 @@ function closeClickUpWebhookServer(server) {
10175
10731
  });
10176
10732
  }
10177
10733
  function managedClickUpWebhookKey({ worktree, state, config } = {}) {
10178
- 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("|");
10179
10735
  }
10180
10736
  async function deleteClickUpWebhookBestEffort({ webhookId, clickupClient, worktree, reason = "cleanup" } = {}) {
10181
10737
  const id = String(webhookId || "").trim();
@@ -10274,13 +10830,13 @@ function writeClickUpWebhookAuditLog({ method, url, headers = {}, rawBody = "",
10274
10830
  const failed = Boolean(error || !handled?.ok || (handled?.status || 500) >= 400);
10275
10831
  if (level === "error" && !failed) return;
10276
10832
  const logDir = clickUpWebhookAuditLogDir();
10277
- fs2.mkdirSync(logDir, { recursive: true });
10833
+ fs5.mkdirSync(logDir, { recursive: true });
10278
10834
  const secretValues = [resolveSecretReference(config?.apiToken), state?.secret, config?.webhook?.secret].filter(Boolean);
10279
10835
  let requestFile;
10280
10836
  if (level === "verbose") {
10281
10837
  const absoluteRequestFile = clickUpWebhookRequestFilePath(at, logDir);
10282
- fs2.mkdirSync(path2.dirname(absoluteRequestFile), { recursive: true });
10283
- 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("/");
10284
10840
  const parsedBody = payload || (() => {
10285
10841
  try {
10286
10842
  return JSON.parse(Buffer.isBuffer(rawBody) ? rawBody.toString("utf8") : String(rawBody || ""));
@@ -10296,11 +10852,11 @@ function writeClickUpWebhookAuditLog({ method, url, headers = {}, rawBody = "",
10296
10852
  headers,
10297
10853
  body: parsedBody === void 0 ? Buffer.isBuffer(rawBody) ? rawBody.toString("utf8") : String(rawBody || "") : parsedBody
10298
10854
  }, secretValues);
10299
- fs2.writeFileSync(absoluteRequestFile, `${JSON.stringify(requestArtifact, null, 2)}
10855
+ fs5.writeFileSync(absoluteRequestFile, `${JSON.stringify(requestArtifact, null, 2)}
10300
10856
  `, "utf8");
10301
10857
  }
10302
10858
  const summary = redactClickUpWebhookAuditValue(buildClickUpWebhookAuditSummary({ method, url, config, handled, error, payload, requestFile, at }), secretValues);
10303
- fs2.appendFileSync(clickUpWebhookAuditLogPath(at, logDir), `${JSON.stringify(summary)}
10859
+ fs5.appendFileSync(clickUpWebhookAuditLogPath(at, logDir), `${JSON.stringify(summary)}
10304
10860
  `, "utf8");
10305
10861
  } catch {
10306
10862
  }
@@ -10656,7 +11212,7 @@ function clickUpListenerFingerprint({ config, state, worktree, clickupClient, op
10656
11212
  return JSON.stringify({
10657
11213
  publicUrl: config?.webhook?.publicUrl || "",
10658
11214
  path: clickUpWebhookExpectedPath(config),
10659
- worktree: path2.resolve(worktree || process.cwd()),
11215
+ worktree: path5.resolve(worktree || process.cwd()),
10660
11216
  webhookId: state?.webhookId || "",
10661
11217
  secret: state?.secret || "",
10662
11218
  events: config?.webhook?.events || [],
@@ -10753,17 +11309,17 @@ function startClickUpWebhookListener({ config, state, worktree, clickupClient, o
10753
11309
  return result;
10754
11310
  }
10755
11311
  function legacyVariantPath(destinationPath) {
10756
- const parsed = path2.parse(destinationPath);
11312
+ const parsed = path5.parse(destinationPath);
10757
11313
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:TZ.]/g, "").slice(0, 14);
10758
- if (parsed.ext) return path2.join(parsed.dir, `${parsed.name}.legacy-${stamp}${parsed.ext}`);
10759
- 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}`);
10760
11316
  }
10761
11317
  function normalizeWorkflowTaskPath(taskPath) {
10762
11318
  if (typeof taskPath !== "string") return { ok: false, message: "Error: task_path is required." };
10763
11319
  const trimmed = taskPath.trim();
10764
11320
  if (!trimmed) return { ok: false, message: "Error: task_path is required." };
10765
11321
  const normalized = trimmed.replace(/\\/g, "/");
10766
- if (path2.isAbsolute(trimmed)) return { ok: true, taskPath: trimmed };
11322
+ if (path5.isAbsolute(trimmed)) return { ok: true, taskPath: trimmed };
10767
11323
  if (normalized === "tasks" || normalized.startsWith("tasks/")) {
10768
11324
  return {
10769
11325
  ok: false,
@@ -10779,76 +11335,80 @@ function normalizeWorkflowTaskPath(taskPath) {
10779
11335
  return { ok: true, taskPath: trimmed };
10780
11336
  }
10781
11337
  function mergeFileIntoDestination(sourcePath, destinationPath, relativeSource, gitState = null) {
11338
+ const sourceWasTracked = isGitTracked(gitState, sourcePath);
10782
11339
  if (gitAwareMoveIfTracked(sourcePath, destinationPath, gitState)) return;
10783
- if (!fs2.existsSync(destinationPath)) {
10784
- fs2.mkdirSync(path2.dirname(destinationPath), { recursive: true });
10785
- 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);
10786
11344
  return;
10787
11345
  }
10788
- const ext = path2.extname(destinationPath).toLowerCase();
11346
+ const ext = path5.extname(destinationPath).toLowerCase();
10789
11347
  if ([".yaml", ".yml", ".json"].includes(ext)) {
10790
- const sourceRaw = fs2.readFileSync(sourcePath, "utf8");
10791
- const destRaw = fs2.readFileSync(destinationPath, "utf8");
10792
- 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;
10793
11351
  const sourceValue = parser.parse(sourceRaw) || {};
10794
11352
  const destValue = parser.parse(destRaw) || {};
10795
11353
  const merged = mergeStructuredValues(sourceValue, destValue);
10796
11354
  const serialized = ext === ".json" ? `${JSON.stringify(merged, null, 2)}
10797
- ` : import_yaml2.default.stringify(merged);
10798
- fs2.writeFileSync(destinationPath, serialized, "utf8");
10799
- fs2.unlinkSync(sourcePath);
11355
+ ` : import_yaml3.default.stringify(merged);
11356
+ fs5.writeFileSync(destinationPath, serialized, "utf8");
11357
+ fs5.unlinkSync(sourcePath);
10800
11358
  stageGitAwareMerge(sourcePath, destinationPath, gitState);
10801
11359
  return;
10802
11360
  }
10803
11361
  if (ext === ".md") {
10804
- const sourceRaw = fs2.readFileSync(sourcePath, "utf8").trimEnd();
10805
- const destRaw = fs2.readFileSync(destinationPath, "utf8").trimEnd();
11362
+ const sourceRaw = fs5.readFileSync(sourcePath, "utf8").trimEnd();
11363
+ const destRaw = fs5.readFileSync(destinationPath, "utf8").trimEnd();
10806
11364
  if (sourceRaw && !destRaw.includes(sourceRaw)) {
10807
11365
  const marker = `## Legacy Content From ${relativeSource}`;
10808
- fs2.writeFileSync(destinationPath, `${destRaw}
11366
+ fs5.writeFileSync(destinationPath, `${destRaw}
10809
11367
 
10810
11368
  ${marker}
10811
11369
 
10812
11370
  ${sourceRaw}
10813
11371
  `, "utf8");
10814
11372
  }
10815
- fs2.unlinkSync(sourcePath);
11373
+ fs5.unlinkSync(sourcePath);
10816
11374
  stageGitAwareMerge(sourcePath, destinationPath, gitState);
10817
11375
  return;
10818
11376
  }
10819
11377
  const preservedPath = legacyVariantPath(destinationPath);
10820
- fs2.renameSync(sourcePath, preservedPath);
11378
+ fs5.renameSync(sourcePath, preservedPath);
10821
11379
  stageGitAwareMerge(sourcePath, preservedPath, gitState);
10822
11380
  }
10823
- function mergePathIntoDestination(sourcePath, destinationPath, relativeSource = path2.basename(sourcePath), gitState = null) {
10824
- if (!fs2.existsSync(sourcePath)) return;
10825
- 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);
10826
11384
  if (stat.isDirectory()) {
11385
+ const sourceWasTracked = isGitTracked(gitState, sourcePath) || hasGitTrackedChildren(gitState, sourcePath);
10827
11386
  if (gitAwareMoveIfTracked(sourcePath, destinationPath, gitState)) return;
10828
- if (!fs2.existsSync(destinationPath)) {
10829
- fs2.mkdirSync(path2.dirname(destinationPath), { recursive: true });
10830
- 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);
10831
11391
  return;
10832
11392
  }
10833
- fs2.mkdirSync(destinationPath, { recursive: true });
10834
- for (const entry of fs2.readdirSync(sourcePath)) {
11393
+ fs5.mkdirSync(destinationPath, { recursive: true });
11394
+ for (const entry of fs5.readdirSync(sourcePath)) {
10835
11395
  mergePathIntoDestination(
10836
- path2.join(sourcePath, entry),
10837
- path2.join(destinationPath, entry),
10838
- path2.join(relativeSource, entry),
11396
+ path5.join(sourcePath, entry),
11397
+ path5.join(destinationPath, entry),
11398
+ path5.join(relativeSource, entry),
10839
11399
  gitState
10840
11400
  );
10841
11401
  }
10842
- fs2.rmSync(sourcePath, { recursive: true, force: true });
11402
+ fs5.rmSync(sourcePath, { recursive: true, force: true });
10843
11403
  return;
10844
11404
  }
10845
11405
  mergeFileIntoDestination(sourcePath, destinationPath, relativeSource, gitState);
10846
11406
  }
10847
11407
  function isOptimaPluginPackageWorktree(worktree) {
10848
- const packageJsonPath = path2.join(worktree, "package.json");
10849
- if (!fs2.existsSync(packageJsonPath)) return false;
11408
+ const packageJsonPath = path5.join(worktree, "package.json");
11409
+ if (!fs5.existsSync(packageJsonPath)) return false;
10850
11410
  try {
10851
- const pkg = JSON.parse(fs2.readFileSync(packageJsonPath, "utf8"));
11411
+ const pkg = JSON.parse(fs5.readFileSync(packageJsonPath, "utf8"));
10852
11412
  return pkg?.name === "@defend-tech/opencode-optima";
10853
11413
  } catch {
10854
11414
  return false;
@@ -10857,59 +11417,59 @@ function isOptimaPluginPackageWorktree(worktree) {
10857
11417
  function migrateLegacyOptimaLayout(worktree) {
10858
11418
  const gitState = gitMigrationState(worktree);
10859
11419
  const migrations = [
10860
- [path2.join(legacyOrbitaDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path2.join(".orbita", "orbita.yaml")],
10861
- [path2.join(legacyOrbitaDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path2.join(".orbita", "staticeng.yaml")],
10862
- [path2.join(legacyOrbitaDir(worktree), ".config"), optimaLocalConfigDir(worktree), path2.join(".orbita", ".config")],
10863
- [path2.join(legacyOrbitaDir(worktree), "config"), optimaLocalConfigDir(worktree), path2.join(".orbita", "config")],
10864
- [path2.join(legacyOrbitaDir(worktree), "runtime"), path2.join(optimaLocalConfigDir(worktree), "runtime"), path2.join(".orbita", "runtime")],
10865
- [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")],
10866
11426
  [legacyOrbitaDir(worktree), optimaDir(worktree), ".orbita"],
10867
- [path2.join(legacyStaticEngDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path2.join(".staticeng", "staticeng.yaml")],
10868
- [path2.join(legacyStaticEngDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path2.join(".staticeng", "orbita.yaml")],
10869
- [path2.join(legacyStaticEngDir(worktree), ".config"), optimaLocalConfigDir(worktree), path2.join(".staticeng", ".config")],
10870
- [path2.join(legacyStaticEngDir(worktree), "config"), optimaLocalConfigDir(worktree), path2.join(".staticeng", "config")],
10871
- [path2.join(legacyStaticEngDir(worktree), "runtime"), path2.join(optimaLocalConfigDir(worktree), "runtime"), path2.join(".staticeng", "runtime")],
10872
- [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")],
10873
11433
  [legacyStaticEngDir(worktree), optimaDir(worktree), ".staticeng"],
10874
- [path2.join(legacyNomadworkDir(worktree), "nomadworks.yaml"), repoConfigPath(worktree), path2.join(".nomadwork", "nomadworks.yaml")],
10875
- [path2.join(legacyNomadworksDir(worktree), "nomadworks.yaml"), repoConfigPath(worktree), path2.join(".nomadworks", "nomadworks.yaml")],
10876
- [path2.join(legacyNomadworkDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path2.join(".nomadwork", "staticeng.yaml")],
10877
- [path2.join(legacyNomadworksDir(worktree), "staticeng.yaml"), repoConfigPath(worktree), path2.join(".nomadworks", "staticeng.yaml")],
10878
- [path2.join(legacyNomadworkDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path2.join(".nomadwork", "orbita.yaml")],
10879
- [path2.join(legacyNomadworksDir(worktree), "orbita.yaml"), repoConfigPath(worktree), path2.join(".nomadworks", "orbita.yaml")],
10880
- [path2.join(legacyNomadworkDir(worktree), "runtime"), path2.join(optimaLocalConfigDir(worktree), "runtime"), path2.join(".nomadwork", "runtime")],
10881
- [path2.join(legacyNomadworksDir(worktree), "runtime"), path2.join(optimaLocalConfigDir(worktree), "runtime"), path2.join(".nomadworks", "runtime")],
10882
- [path2.join(legacyNomadworkDir(worktree), "generated"), path2.join(optimaLocalConfigDir(worktree), "generated"), path2.join(".nomadwork", "generated")],
10883
- [path2.join(legacyNomadworksDir(worktree), "generated"), path2.join(optimaLocalConfigDir(worktree), "generated"), path2.join(".nomadworks", "generated")],
10884
- [path2.join(legacyNomadworkDir(worktree), "config"), optimaLocalConfigDir(worktree), path2.join(".nomadwork", "config")],
10885
- [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")],
10886
11446
  [legacyNomadworkDir(worktree), optimaDir(worktree), ".nomadwork"],
10887
11447
  [legacyNomadworksDir(worktree), optimaDir(worktree), ".nomadworks"],
10888
- [path2.join(worktree, "tasks"), optimaTasksDir(worktree), "tasks"],
10889
- [path2.join(worktree, "evidences"), optimaEvidencesDir(worktree), "evidences"],
10890
- [path2.join(worktree, "docs", "scrs"), optimaScrsDir(worktree), path2.join("docs", "scrs")],
10891
- [path2.join(worktree, "codemap.yml"), optimaCodemapPath(worktree), "codemap.yml"],
10892
- [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"]
10893
11453
  ];
10894
11454
  if (!isOptimaPluginPackageWorktree(worktree)) {
10895
- migrations.push([path2.join(worktree, "policies"), repoPoliciesDir(worktree), "policies"]);
11455
+ migrations.push([path5.join(worktree, "policies"), repoPoliciesDir(worktree), "policies"]);
10896
11456
  }
10897
11457
  for (const [source, destination, relativeSource] of migrations) {
10898
- if (fs2.existsSync(source)) mergePathIntoDestination(source, destination, relativeSource, gitState);
11458
+ if (fs5.existsSync(source)) mergePathIntoDestination(source, destination, relativeSource, gitState);
10899
11459
  }
10900
11460
  for (const [source, destination, relativeSource] of [
10901
- [path2.join(optimaDir(worktree), "optima.yaml"), repoConfigPath(worktree), path2.join(".optima", "optima.yaml")],
10902
- [path2.join(optimaDir(worktree), "config"), optimaLocalConfigDir(worktree), path2.join(".optima", "config")],
10903
- [path2.join(optimaDir(worktree), "runtime"), path2.join(optimaLocalConfigDir(worktree), "runtime"), path2.join(".optima", "runtime")],
10904
- [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")]
10905
11465
  ]) {
10906
- if (fs2.existsSync(source)) mergePathIntoDestination(source, destination, relativeSource, gitState);
11466
+ if (fs5.existsSync(source)) mergePathIntoDestination(source, destination, relativeSource, gitState);
10907
11467
  }
10908
11468
  }
10909
11469
  function listMarkdownFiles(dirPath) {
10910
- if (!fs2.existsSync(dirPath)) return [];
11470
+ if (!fs5.existsSync(dirPath)) return [];
10911
11471
  try {
10912
- 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");
10913
11473
  } catch (e) {
10914
11474
  console.error(`[Optima] Failed to read markdown files from ${dirPath}:`, e);
10915
11475
  return [];
@@ -10919,67 +11479,6 @@ function normalizePolicyExtraction(value) {
10919
11479
  if (typeof value !== "string") return "none";
10920
11480
  return value.trim().toLowerCase() === "all" ? "all" : "none";
10921
11481
  }
10922
- function resolveIncludeFile(includeRef, repoRoot, bundleRoot, options = {}) {
10923
- const trimmed = includeRef.trim();
10924
- const scopedMatch = trimmed.match(/^([a-z]+):(.*)$/i);
10925
- const scope = scopedMatch?.[1]?.toLowerCase();
10926
- const target = scopedMatch ? scopedMatch[2].trim() : trimmed;
10927
- const resolveRelative = (baseDir, relativePath) => {
10928
- if (!relativePath) return null;
10929
- return path2.isAbsolute(relativePath) ? relativePath : path2.join(baseDir, relativePath);
10930
- };
10931
- const withCompactPreference = (paths) => {
10932
- if (!options.preferCompactPromptDocs) return paths;
10933
- const compactPaths = paths.map((filePath) => filePath ? compactPromptPath(filePath) : null).filter(Boolean);
10934
- return [...compactPaths, ...paths];
10935
- };
10936
- if (scope === "plugin") {
10937
- for (const filePath of withCompactPreference([resolveRelative(bundleRoot, target)])) {
10938
- if (filePath && fs2.existsSync(filePath)) return filePath;
10939
- }
10940
- return null;
10941
- }
10942
- if (scope === "repo") {
10943
- for (const filePath of withCompactPreference([resolveRelative(optimaDir(repoRoot), target)])) {
10944
- if (filePath && fs2.existsSync(filePath)) return filePath;
10945
- }
10946
- return null;
10947
- }
10948
- if (scope === "policy") {
10949
- const candidates2 = withCompactPreference([
10950
- resolveRelative(repoPoliciesDir(repoRoot), target),
10951
- resolveRelative(BUNDLE_POLICIES_DIR, target)
10952
- ]);
10953
- for (const filePath of candidates2) {
10954
- if (filePath && fs2.existsSync(filePath)) return filePath;
10955
- }
10956
- return null;
10957
- }
10958
- const candidates = withCompactPreference([
10959
- resolveRelative(repoRoot, target),
10960
- resolveRelative(bundleRoot, target)
10961
- ]);
10962
- for (const filePath of candidates) {
10963
- if (filePath && fs2.existsSync(filePath)) return filePath;
10964
- }
10965
- return null;
10966
- }
10967
- function resolveIncludes(text, repoRoot, bundleRoot, options = {}) {
10968
- const includeRegex = /<include:(.*?)>/g;
10969
- return text.replace(includeRegex, (match, includeRef) => {
10970
- const filePath = resolveIncludeFile(includeRef, repoRoot, bundleRoot, options);
10971
- if (!filePath) {
10972
- console.warn(`[Optima] Include file not found: ${includeRef}`);
10973
- return `
10974
-
10975
- # ERROR: Include file not found: ${includeRef}
10976
-
10977
- `;
10978
- }
10979
- const content = fs2.readFileSync(filePath, "utf8");
10980
- return resolveIncludes(content, repoRoot, bundleRoot, options);
10981
- });
10982
- }
10983
11482
  function parseFrontmatter(mdText) {
10984
11483
  const lines = mdText.split(/\r?\n/);
10985
11484
  if (lines[0]?.trim() !== "---") return { data: {}, body: mdText };
@@ -10994,7 +11493,7 @@ function parseFrontmatter(mdText) {
10994
11493
  const fmText = lines.slice(1, end).join("\n");
10995
11494
  const body = lines.slice(end + 1).join("\n");
10996
11495
  try {
10997
- return { data: import_yaml2.default.parse(fmText) || {}, body };
11496
+ return { data: import_yaml3.default.parse(fmText) || {}, body };
10998
11497
  } catch {
10999
11498
  return { data: {}, body };
11000
11499
  }
@@ -11011,10 +11510,10 @@ function toModelString(provider, model) {
11011
11510
  }
11012
11511
  function readTaskMetadata(taskPath, worktree) {
11013
11512
  if (!taskPath) return {};
11014
- const absoluteTaskPath = path2.isAbsolute(taskPath) ? taskPath : path2.join(worktree, taskPath);
11015
- if (!fs2.existsSync(absoluteTaskPath)) return {};
11513
+ const absoluteTaskPath = path5.isAbsolute(taskPath) ? taskPath : path5.join(worktree, taskPath);
11514
+ if (!fs5.existsSync(absoluteTaskPath)) return {};
11016
11515
  try {
11017
- const raw = fs2.readFileSync(absoluteTaskPath, "utf8");
11516
+ const raw = fs5.readFileSync(absoluteTaskPath, "utf8");
11018
11517
  const { data } = parseFrontmatter(raw);
11019
11518
  return {
11020
11519
  complexity: typeof data.complexity === "string" ? data.complexity.trim().toLowerCase() : void 0,
@@ -11039,11 +11538,11 @@ function slugifyTitle(input) {
11039
11538
  }
11040
11539
  function loadDiscussionRegistry(worktree) {
11041
11540
  const registryPath = runtimeDiscussionRegistryPath(worktree);
11042
- if (!fs2.existsSync(registryPath)) {
11541
+ if (!fs5.existsSync(registryPath)) {
11043
11542
  return { version: 1, active: {} };
11044
11543
  }
11045
11544
  try {
11046
- const parsed = JSON.parse(fs2.readFileSync(registryPath, "utf8"));
11545
+ const parsed = JSON.parse(fs5.readFileSync(registryPath, "utf8"));
11047
11546
  const registry = {
11048
11547
  version: 1,
11049
11548
  active: Object.fromEntries(Object.entries(parsed.active || {}).map(([key, value]) => [key, normalizeLegacyDiscussionEntry(value)]))
@@ -11056,34 +11555,34 @@ function loadDiscussionRegistry(worktree) {
11056
11555
  }
11057
11556
  function saveDiscussionRegistry(worktree, registry) {
11058
11557
  const registryPath = runtimeDiscussionRegistryPath(worktree);
11059
- const runtimeDir = path2.dirname(registryPath);
11060
- if (!fs2.existsSync(runtimeDir)) fs2.mkdirSync(runtimeDir, { recursive: true });
11061
- 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");
11062
11561
  }
11063
11562
  function runtimeDiscussionsDir(worktree) {
11064
- return path2.join(optimaLocalConfigDir(worktree), "runtime", "discussions");
11563
+ return path5.join(optimaLocalConfigDir(worktree), "runtime", "discussions");
11065
11564
  }
11066
11565
  function archivedRuntimeDiscussionsDir(worktree) {
11067
- return path2.join(runtimeDiscussionsDir(worktree), "archive");
11566
+ return path5.join(runtimeDiscussionsDir(worktree), "archive");
11068
11567
  }
11069
11568
  function finalDiscussionsDir(worktree) {
11070
- return path2.join(optimaTasksDir(worktree), "discussions");
11569
+ return path5.join(optimaTasksDir(worktree), "discussions");
11071
11570
  }
11072
11571
  function nextDiscussionIdentity(worktree, title) {
11073
11572
  const discussionsDir = finalDiscussionsDir(worktree);
11074
11573
  const runtimeDir = runtimeDiscussionsDir(worktree);
11075
- if (!fs2.existsSync(discussionsDir)) fs2.mkdirSync(discussionsDir, { recursive: true });
11076
- 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 });
11077
11576
  let sequence = 1;
11078
11577
  while (true) {
11079
11578
  const id = `DISCUSSION-${String(sequence).padStart(3, "0")}`;
11080
11579
  const filename = `${id}-${slugifyTitle(title)}.md`;
11081
- const summaryRelativePath = path2.join(".optima", "tasks", "discussions", filename);
11082
- const summaryAbsolutePath = path2.join(worktree, summaryRelativePath);
11580
+ const summaryRelativePath = path5.join(".optima", "tasks", "discussions", filename);
11581
+ const summaryAbsolutePath = path5.join(worktree, summaryRelativePath);
11083
11582
  const transcriptFilename = `${id}-transcript.md`;
11084
- const transcriptRelativePath = path2.join(".optima", ".config", "runtime", "discussions", transcriptFilename);
11085
- const transcriptAbsolutePath = path2.join(worktree, transcriptRelativePath);
11086
- 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)) {
11087
11586
  return {
11088
11587
  id,
11089
11588
  filename,
@@ -11099,37 +11598,37 @@ function nextDiscussionIdentity(worktree, title) {
11099
11598
  }
11100
11599
  function findDiscussionById(worktree, discussionID) {
11101
11600
  const discussionsDir = finalDiscussionsDir(worktree);
11102
- if (!fs2.existsSync(discussionsDir)) return null;
11103
- 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"));
11104
11603
  if (entries.length === 0) return null;
11105
11604
  const filename = entries.sort()[0];
11106
11605
  const transcriptFilename = `${discussionID}-transcript.md`;
11107
11606
  return {
11108
11607
  id: discussionID,
11109
11608
  filename,
11110
- summaryRelativePath: path2.join(".optima", "tasks", "discussions", filename),
11111
- summaryAbsolutePath: path2.join(discussionsDir, filename),
11609
+ summaryRelativePath: path5.join(".optima", "tasks", "discussions", filename),
11610
+ summaryAbsolutePath: path5.join(discussionsDir, filename),
11112
11611
  transcriptFilename,
11113
- transcriptRelativePath: path2.join(".optima", ".config", "runtime", "discussions", transcriptFilename),
11114
- transcriptAbsolutePath: path2.join(runtimeDiscussionsDir(worktree), transcriptFilename)
11612
+ transcriptRelativePath: path5.join(".optima", ".config", "runtime", "discussions", transcriptFilename),
11613
+ transcriptAbsolutePath: path5.join(runtimeDiscussionsDir(worktree), transcriptFilename)
11115
11614
  };
11116
11615
  }
11117
11616
  function parseDiscussionFile(filePath) {
11118
- const raw = fs2.readFileSync(filePath, "utf8");
11617
+ const raw = fs5.readFileSync(filePath, "utf8");
11119
11618
  const { data, body } = parseFrontmatter(raw);
11120
11619
  return { data, body: body.trimStart() };
11121
11620
  }
11122
11621
  function writeDiscussionFile(filePath, frontmatter, body) {
11123
11622
  const serialized = `---
11124
- ${import_yaml2.default.stringify(frontmatter).trim()}
11623
+ ${import_yaml3.default.stringify(frontmatter).trim()}
11125
11624
  ---
11126
11625
 
11127
11626
  ${body.trimEnd()}
11128
11627
  `;
11129
- fs2.writeFileSync(filePath, serialized, "utf8");
11628
+ fs5.writeFileSync(filePath, serialized, "utf8");
11130
11629
  }
11131
11630
  function setDiscussionStatus(filePath, status) {
11132
- if (!fs2.existsSync(filePath)) return;
11631
+ if (!fs5.existsSync(filePath)) return;
11133
11632
  const { data, body } = parseDiscussionFile(filePath);
11134
11633
  writeDiscussionFile(filePath, { ...data, status }, body);
11135
11634
  }
@@ -11194,18 +11693,18 @@ async function appendMessageIfNeeded(client, worktree, registry, sessionID, mess
11194
11693
  });
11195
11694
  const text = extractTextParts(response.data.parts || []);
11196
11695
  if (!text) return;
11197
- appendDiscussionMessage(path2.join(worktree, discussion.transcriptPath), speaker, text, messageID);
11696
+ appendDiscussionMessage(path5.join(worktree, discussion.transcriptPath), speaker, text, messageID);
11198
11697
  discussion.appendedMessageIDs ??= [];
11199
11698
  discussion.appendedMessageIDs.push(messageID);
11200
11699
  saveDiscussionRegistry(worktree, registry);
11201
11700
  }
11202
11701
  async function summarizeDiscussionWithBA(client, worktree, discussion) {
11203
- const transcriptPath = path2.join(worktree, discussion.transcriptPath);
11204
- const summaryPath = path2.join(worktree, discussion.summaryPath);
11205
- const summaryDir = path2.dirname(summaryPath);
11206
- if (!fs2.existsSync(summaryDir)) fs2.mkdirSync(summaryDir, { recursive: true });
11207
- const hasExistingSummary = fs2.existsSync(summaryPath);
11208
- 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;
11209
11708
  const summarizerSession = await client.session.create({
11210
11709
  body: { title: `Discussion Summary: ${discussion.id}` }
11211
11710
  });
@@ -11305,30 +11804,30 @@ async function summarizeDiscussionWithBA(client, worktree, discussion) {
11305
11804
  return { confirmation, summaryPath, transcriptPath, hasExistingSummary, priorMtimeMs };
11306
11805
  }
11307
11806
  function archiveDiscussionTranscript(worktree, transcriptRelativePath) {
11308
- const sourcePath = path2.join(worktree, transcriptRelativePath);
11309
- if (!fs2.existsSync(sourcePath)) return null;
11807
+ const sourcePath = path5.join(worktree, transcriptRelativePath);
11808
+ if (!fs5.existsSync(sourcePath)) return null;
11310
11809
  const archiveDir = archivedRuntimeDiscussionsDir(worktree);
11311
- if (!fs2.existsSync(archiveDir)) fs2.mkdirSync(archiveDir, { recursive: true });
11312
- const targetPath = path2.join(archiveDir, path2.basename(sourcePath));
11313
- 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);
11314
11813
  return targetPath;
11315
11814
  }
11316
11815
  async function finalizeClosingDiscussion(client, worktree, registry, sessionID, discussion) {
11317
11816
  const { confirmation, summaryPath, hasExistingSummary, priorMtimeMs } = await summarizeDiscussionWithBA(client, worktree, discussion);
11318
- if (!fs2.existsSync(summaryPath)) {
11817
+ if (!fs5.existsSync(summaryPath)) {
11319
11818
  throw new Error(`Discussion summary was not written to ${discussion.summaryPath}`);
11320
11819
  }
11321
11820
  if (hasExistingSummary) {
11322
- const currentMtimeMs = fs2.statSync(summaryPath).mtimeMs;
11821
+ const currentMtimeMs = fs5.statSync(summaryPath).mtimeMs;
11323
11822
  if (currentMtimeMs <= priorMtimeMs) {
11324
11823
  throw new Error(`Discussion summary file was not updated at ${discussion.summaryPath}`);
11325
11824
  }
11326
11825
  }
11327
- const summaryContent = fs2.readFileSync(summaryPath, "utf8").trim();
11826
+ const summaryContent = fs5.readFileSync(summaryPath, "utf8").trim();
11328
11827
  if (!summaryContent) {
11329
11828
  throw new Error(`Discussion summary file is empty at ${discussion.summaryPath}`);
11330
11829
  }
11331
- const transcriptPath = path2.join(worktree, discussion.transcriptPath);
11830
+ const transcriptPath = path5.join(worktree, discussion.transcriptPath);
11332
11831
  setDiscussionStatus(transcriptPath, "closed");
11333
11832
  const archivedTranscriptPath = archiveDiscussionTranscript(worktree, discussion.transcriptPath);
11334
11833
  delete registry.active[sessionID];
@@ -11336,7 +11835,7 @@ async function finalizeClosingDiscussion(client, worktree, registry, sessionID,
11336
11835
  return {
11337
11836
  confirmation,
11338
11837
  summaryPath: discussion.summaryPath,
11339
- 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))
11340
11839
  };
11341
11840
  }
11342
11841
  function normalizeTeamMode(value) {
@@ -11375,13 +11874,13 @@ function getOperatingTeamMode(repoCfg) {
11375
11874
  }
11376
11875
  function readResolvedFile(relativePath, worktree, options = {}) {
11377
11876
  const filePath = resolveIncludeFile(`plugin:${relativePath}`, worktree, PKG_ROOT, options);
11378
- if (!filePath || !fs2.existsSync(filePath)) return "";
11379
- 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();
11380
11879
  }
11381
11880
  function loadMarkdownFragment(filePath, worktree) {
11382
- if (!fs2.existsSync(filePath)) return "";
11881
+ if (!fs5.existsSync(filePath)) return "";
11383
11882
  try {
11384
- const raw = fs2.readFileSync(filePath, "utf8");
11883
+ const raw = fs5.readFileSync(filePath, "utf8");
11385
11884
  const { body } = parseFrontmatter(raw);
11386
11885
  return resolveIncludes(body.trim(), worktree, PKG_ROOT);
11387
11886
  } catch (e) {
@@ -11390,9 +11889,9 @@ function loadMarkdownFragment(filePath, worktree) {
11390
11889
  }
11391
11890
  }
11392
11891
  function loadAgentDefinition(filePath, worktree, options = {}) {
11393
- if (!fs2.existsSync(filePath)) return null;
11892
+ if (!fs5.existsSync(filePath)) return null;
11394
11893
  try {
11395
- const rawContent = fs2.readFileSync(filePath, "utf8");
11894
+ const rawContent = fs5.readFileSync(filePath, "utf8");
11396
11895
  const { data, body } = parseFrontmatter(rawContent);
11397
11896
  const prompt = resolveIncludes(body.trim(), worktree, PKG_ROOT, options);
11398
11897
  return { data, prompt };
@@ -11403,13 +11902,13 @@ function loadAgentDefinition(filePath, worktree, options = {}) {
11403
11902
  }
11404
11903
  function syncGeneratedPolicies(worktree, repoCfg) {
11405
11904
  if (repoCfg.policies?.extract_defaults !== "all") return;
11406
- if (!fs2.existsSync(BUNDLE_POLICIES_DIR)) return;
11905
+ if (!fs5.existsSync(BUNDLE_POLICIES_DIR)) return;
11407
11906
  const generatedDir = generatedPoliciesDir(worktree);
11408
- if (!fs2.existsSync(generatedDir)) fs2.mkdirSync(generatedDir, { recursive: true });
11409
- 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");
11410
11909
  for (const file of policyFiles) {
11411
- const sourcePath = path2.join(BUNDLE_POLICIES_DIR, file);
11412
- const source = fs2.readFileSync(sourcePath, "utf8").trimEnd();
11910
+ const sourcePath = path5.join(BUNDLE_POLICIES_DIR, file);
11911
+ const source = fs5.readFileSync(sourcePath, "utf8").trimEnd();
11413
11912
  const generated = [
11414
11913
  "<!--",
11415
11914
  "Generated from Optima plugin defaults.",
@@ -11420,19 +11919,31 @@ function syncGeneratedPolicies(worktree, repoCfg) {
11420
11919
  source,
11421
11920
  ""
11422
11921
  ].join("\n");
11423
- fs2.writeFileSync(path2.join(generatedDir, file), generated, "utf8");
11922
+ fs5.writeFileSync(path5.join(generatedDir, file), generated, "utf8");
11424
11923
  }
11425
11924
  }
11426
11925
  function ensureReadmeFile(dirPath, content) {
11427
- if (!fs2.existsSync(dirPath)) fs2.mkdirSync(dirPath, { recursive: true });
11428
- const readmePath = path2.join(dirPath, "README.md");
11429
- if (!fs2.existsSync(readmePath)) {
11430
- 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");
11431
11930
  }
11432
11931
  }
11433
11932
  function ensureFileIfMissing(filePath, content) {
11434
- if (!fs2.existsSync(path2.dirname(filePath))) fs2.mkdirSync(path2.dirname(filePath), { recursive: true });
11435
- 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";
11436
11947
  }
11437
11948
  function taskTemplateContent() {
11438
11949
  return `---
@@ -11506,19 +12017,58 @@ Never place implementation evidence under root \`evidences/\`.
11506
12017
  }
11507
12018
  function ensureOptimaTaskTemplates(worktree) {
11508
12019
  const tasksDir = optimaTasksDir(worktree);
11509
- ensureFileIfMissing(path2.join(tasksDir, "task-template.md"), taskTemplateContent());
11510
- 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());
11511
12060
  }
11512
12061
  function scaffoldOptimaReadmes(worktree) {
11513
12062
  ensureReadmeFile(repoPoliciesDir(worktree), REPO_LOCAL_POLICIES_README);
11514
12063
  ensureReadmeFile(repoAgentsDir(worktree), [
11515
12064
  "# Repository Agents",
11516
12065
  "",
11517
- "Place full repository-local agent definitions here.",
12066
+ "Place full repository-local agent definitions here only when explicitly requested by the user.",
11518
12067
  "",
11519
- "- Use `.optima/agents/<agent>.md` to override a bundled agent's full base definition.",
11520
- "- Use `.optima/agents/<agent>.md` to define a brand new custom repository agent.",
11521
- "- 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.",
11522
12072
  "- `README.md` is ignored by agent discovery.",
11523
12073
  "",
11524
12074
  "## Include Types Available In Custom Agents",
@@ -11612,6 +12162,38 @@ function scaffoldOptimaReadmes(worktree) {
11612
12162
  ].join("\n"));
11613
12163
  ensureOptimaTaskTemplates(worktree);
11614
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
+ }
11615
12197
  function getModePromptFragment(agentId, operatingTeamMode, worktree) {
11616
12198
  const fragmentMap = {
11617
12199
  product_manager: {
@@ -11627,13 +12209,6 @@ function getModePromptFragment(agentId, operatingTeamMode, worktree) {
11627
12209
  if (!fragmentPath) return "";
11628
12210
  return readResolvedFile(fragmentPath, worktree, { preferCompactPromptDocs: true });
11629
12211
  }
11630
- function isSameOrNestedPath(candidate, root) {
11631
- if (typeof candidate !== "string" || typeof root !== "string" || !candidate.trim() || !root.trim()) return false;
11632
- const resolvedCandidate = path2.resolve(candidate);
11633
- const resolvedRoot = path2.resolve(root);
11634
- const relative = path2.relative(resolvedRoot, resolvedCandidate);
11635
- return relative === "" || !!relative && !relative.startsWith("..") && !path2.isAbsolute(relative);
11636
- }
11637
12212
  function shouldRegisterWorkflowProductManager(options = {}, worktree = process.cwd()) {
11638
12213
  if (options.clickUpWebhookActive === true) return true;
11639
12214
  const validation = options.clickUpWebhookValidation;
@@ -11642,12 +12217,12 @@ function shouldRegisterWorkflowProductManager(options = {}, worktree = process.c
11642
12217
  function resolveSessionToolDirectory({ requestedDirectory, context, pluginWorktree, clickUpWebhookValidation } = {}) {
11643
12218
  const safe = safeWorktreeOrFailure(context, pluginWorktree);
11644
12219
  if (!safe.ok) return { ok: false, error: safe.message };
11645
- const requested = String(requestedDirectory || "").trim() ? path2.resolve(safe.worktree, String(requestedDirectory).trim()) : safe.worktree;
12220
+ const requested = String(requestedDirectory || "").trim() ? path5.resolve(safe.worktree, String(requestedDirectory).trim()) : safe.worktree;
11646
12221
  if (!isSafeWritableDirectory(requested)) return { ok: false, error: `Directory is not a safe writable directory: ${requested}` };
11647
12222
  if (isSameOrNestedPath(requested, safe.worktree)) return { ok: true, directory: requested, safeWorktree: safe.worktree, scope: "context_worktree" };
11648
12223
  const clickUpBasePath = clickUpWebhookValidation?.complete === true && clickUpWebhookValidation?.ok !== false ? clickUpWebhookValidation.config?.basePath : "";
11649
12224
  if (clickUpBasePath && isSameOrNestedPath(requested, clickUpBasePath)) {
11650
- return { ok: true, directory: requested, safeWorktree: safe.worktree, scope: "clickup_base_path", clickupBasePath: path2.resolve(clickUpBasePath) };
12225
+ return { ok: true, directory: requested, safeWorktree: safe.worktree, scope: "clickup_base_path", clickupBasePath: path5.resolve(clickUpBasePath) };
11651
12226
  }
11652
12227
  return {
11653
12228
  ok: false,
@@ -11681,8 +12256,8 @@ function buildOptimaAgents(repoCfg, operatingTeamMode, worktree, debugDir, optio
11681
12256
  if (!enabled) continue;
11682
12257
  }
11683
12258
  const promptOptions = { preferCompactPromptDocs: repoCfg.features?.compact_prompt_docs !== false };
11684
- const bundledDefinition = loadAgentDefinition(path2.join(BUNDLE_AGENTS_DIR, file), worktree, promptOptions);
11685
- 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);
11686
12261
  const activeDefinition = repoDefinition || bundledDefinition;
11687
12262
  if (!activeDefinition) continue;
11688
12263
  const { data } = activeDefinition;
@@ -11691,7 +12266,7 @@ function buildOptimaAgents(repoCfg, operatingTeamMode, worktree, debugDir, optio
11691
12266
  if (modePromptFragment) finalPrompt = `${finalPrompt}
11692
12267
 
11693
12268
  ${modePromptFragment}`;
11694
- const additionFragment = loadMarkdownFragment(path2.join(repoAgentAdditions, file), worktree);
12269
+ const additionFragment = loadMarkdownFragment(path5.join(repoAgentAdditions, file), worktree);
11695
12270
  if (additionFragment) {
11696
12271
  finalPrompt = `${finalPrompt}
11697
12272
 
@@ -11744,14 +12319,14 @@ Use this Optima-provided fallback when the current task worktree lacks docs/core
11744
12319
  }
11745
12320
  ourAgents[id] = agentConfig;
11746
12321
  if (repoCfg.features?.debug_dumps !== false) {
11747
- const debugPath = path2.join(debugDir, `${id}.md`);
12322
+ const debugPath = path5.join(debugDir, `${id}.md`);
11748
12323
  const { prompt, ...dumpConfig } = agentConfig;
11749
12324
  const debugHeader = `---
11750
- ${import_yaml2.default.stringify(dumpConfig).trim()}
12325
+ ${import_yaml3.default.stringify(dumpConfig).trim()}
11751
12326
  ---`;
11752
12327
  try {
11753
- if (!fs2.existsSync(debugDir)) fs2.mkdirSync(debugDir, { recursive: true });
11754
- fs2.writeFileSync(debugPath, `${debugHeader}
12328
+ if (!fs5.existsSync(debugDir)) fs5.mkdirSync(debugDir, { recursive: true });
12329
+ fs5.writeFileSync(debugPath, `${debugHeader}
11755
12330
 
11756
12331
  ${prompt}`, "utf8");
11757
12332
  } catch (e) {
@@ -11775,9 +12350,9 @@ async function OptimaPlugin(input = {}, pluginOptions = {}) {
11775
12350
  const configPath = resolveConfigPath(worktree);
11776
12351
  const discussionRegistry = loadDiscussionRegistry(worktree);
11777
12352
  let repoCfg = { agents: {}, defaults: {}, features: {} };
11778
- if (fs2.existsSync(configPath)) {
12353
+ if (fs5.existsSync(configPath)) {
11779
12354
  try {
11780
- repoCfg = import_yaml2.default.parse(fs2.readFileSync(configPath, "utf8")) || repoCfg;
12355
+ repoCfg = import_yaml3.default.parse(fs5.readFileSync(configPath, "utf8")) || repoCfg;
11781
12356
  } catch (e) {
11782
12357
  console.error(`[Optima] Failed to parse config at ${configPath}:`, e);
11783
12358
  }
@@ -11884,54 +12459,16 @@ async function OptimaPlugin(input = {}, pluginOptions = {}) {
11884
12459
  }
11885
12460
  migrateLegacyOptimaLayout(toolWorktree);
11886
12461
  const cfgDir = optimaConfigDir(toolWorktree);
11887
- if (!fs2.existsSync(cfgDir)) fs2.mkdirSync(cfgDir, { recursive: true });
11888
- const agentIds = fs2.existsSync(BUNDLE_AGENTS_DIR) ? fs2.readdirSync(BUNDLE_AGENTS_DIR).filter((f) => f.endsWith(".md")).map((f) => f.replace(".md", "")) : [];
11889
- const optimaTmplPath = path2.join(TEMPLATES_DIR, "optima.yaml.template");
11890
- const codemapTmplPath = path2.join(TEMPLATES_DIR, "codemap.yml.template");
11891
- 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)) {
11892
12466
  return "Error: Initialization templates not found in plugin.";
11893
12467
  }
11894
- let optimaConfig = fs2.readFileSync(optimaTmplPath, "utf8");
11895
- optimaConfig = optimaConfig.replace("{{teamMode}}", requestedTeamMode);
11896
- let agentsSection = "";
11897
- for (const id of agentIds) {
11898
- const enabled = isAgentEnabledForTeamMode(id, requestedTeamMode) ? "true" : "false";
11899
- agentsSection += ` ${id}:
11900
- enabled: ${enabled}
11901
- `;
11902
- }
11903
- optimaConfig = optimaConfig.replace(/^agents:/m, "agents:\n" + agentsSection);
11904
- let codemapConfig = fs2.readFileSync(codemapTmplPath, "utf8");
11905
- codemapConfig = codemapConfig.replace("{{projectName}}", path2.basename(toolWorktree));
11906
- const cfgFilePath = repoConfigPath(toolWorktree);
11907
- const rootCodemapPath = optimaCodemapPath(toolWorktree);
11908
- if (!fs2.existsSync(cfgFilePath)) {
11909
- fs2.writeFileSync(cfgFilePath, optimaConfig, "utf8");
11910
- }
11911
- if (!fs2.existsSync(rootCodemapPath)) {
11912
- fs2.writeFileSync(rootCodemapPath, codemapConfig, "utf8");
11913
- }
12468
+ scaffoldOptimaConfig(toolWorktree, requestedTeamMode);
12469
+ scaffoldOptimaRootCodemap(toolWorktree);
11914
12470
  scaffoldOptimaReadmes(toolWorktree);
11915
- const tasksDir = optimaTasksDir(toolWorktree);
11916
- const scrsDir = optimaScrsDir(toolWorktree);
11917
- if (!fs2.existsSync(tasksDir)) fs2.mkdirSync(tasksDir, { recursive: true });
11918
- if (!fs2.existsSync(scrsDir)) fs2.mkdirSync(scrsDir, { recursive: true });
11919
- const currentPath = path2.join(tasksDir, "current.md");
11920
- const donePath = path2.join(tasksDir, "done.md");
11921
- const scrsCurrentPath = path2.join(scrsDir, "current.md");
11922
- const scrsDonePath = path2.join(scrsDir, "done.md");
11923
- if (!fs2.existsSync(currentPath)) {
11924
- 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");
11925
- }
11926
- if (!fs2.existsSync(donePath)) {
11927
- fs2.writeFileSync(donePath, "# Completed Tasks (Registry)\n\n| Date | Task ID | SCR ID | Commit | Summary |\n| :--- | :--- | :--- | :--- | :--- |\n", "utf8");
11928
- }
11929
- if (!fs2.existsSync(scrsCurrentPath)) {
11930
- 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");
11931
- }
11932
- if (!fs2.existsSync(scrsDonePath)) {
11933
- fs2.writeFileSync(scrsDonePath, "# Implemented Spec Change Requests\n\n| Date | SCR ID | Title | Related Feature | Task ID |\n| :--- | :--- | :--- | :--- | :--- |\n", "utf8");
11934
- }
12471
+ ensureOptimaRegistries(toolWorktree);
11935
12472
  const gitignoreResult = ensureOptimaGitignoreRules(toolWorktree);
11936
12473
  const gitignoreNote = gitignoreResult.added.length > 0 ? ` Added ${gitignoreResult.added.length} Optima local/private .gitignore rule(s).` : "";
11937
12474
  const initSummary = `Optima initialized in '${requestedTeamMode}' team mode: .optima/.config/optima.yaml, repo policy/agent folders, registries, and .optima/codemap.yml created.${gitignoreNote}`;
@@ -12046,14 +12583,14 @@ Restart or reload OpenCode manually if the newly scaffolded config or agents are
12046
12583
  async execute(args, context) {
12047
12584
  const safe = safeWorktreeOrFailure(context, worktree);
12048
12585
  if (!safe.ok) return safe.message;
12049
- const summaryPath = path2.resolve(safe.worktree, args.summary_path || "");
12050
- if (!fs2.existsSync(summaryPath)) return `FAIL: summary_path not found: ${summaryPath}`;
12051
- 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) : "";
12052
12589
  const payload = buildClickUpSummaryPayload({
12053
- summaryMarkdown: fs2.readFileSync(summaryPath, "utf8"),
12054
- summaryPath: path2.relative(safe.worktree, summaryPath),
12055
- taskMarkdown: taskPath && fs2.existsSync(taskPath) ? fs2.readFileSync(taskPath, "utf8") : "",
12056
- 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) : "",
12057
12594
  branch: args.branch,
12058
12595
  worktree: args.worktree,
12059
12596
  pr: args.pr
@@ -12132,12 +12669,12 @@ Restart or reload OpenCode manually if the newly scaffolded config or agents are
12132
12669
  async execute(args, context) {
12133
12670
  const safe = safeWorktreeOrFailure(context, worktree);
12134
12671
  if (!safe.ok) return safe.message;
12135
- const markdownPath = path2.resolve(safe.worktree, args.markdown_path || "");
12136
- 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}`;
12137
12674
  const payload = buildClickUpCreateSubtasksPayload({
12138
12675
  parentTaskId: args.parent_task_id,
12139
- markdown: fs2.readFileSync(markdownPath, "utf8"),
12140
- sourcePath: path2.relative(safe.worktree, markdownPath),
12676
+ markdown: fs5.readFileSync(markdownPath, "utf8"),
12677
+ sourcePath: path5.relative(safe.worktree, markdownPath),
12141
12678
  parentBranch: args.parent_branch,
12142
12679
  parentTaskType: args.parent_task_type || "Tarea",
12143
12680
  apply: String(args.apply || "").toLowerCase() === "true"
@@ -12169,6 +12706,21 @@ Restart or reload OpenCode manually if the newly scaffolded config or agents are
12169
12706
  return formatValidationResult(res);
12170
12707
  }
12171
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
+ }),
12172
12724
  optima_start_discussion: tool({
12173
12725
  description: "Start an automatic discussion transcript for this session",
12174
12726
  args: {
@@ -12321,7 +12873,7 @@ Backfilled messages: ${backfilled}`;
12321
12873
  if (!existing) {
12322
12874
  return "FAIL: No active discussion exists for this session.";
12323
12875
  }
12324
- const discussionPath = path2.join(toolWorktree, existing.transcriptPath);
12876
+ const discussionPath = path5.join(toolWorktree, existing.transcriptPath);
12325
12877
  setDiscussionStatus(discussionPath, "summarizing");
12326
12878
  existing.status = "summarizing";
12327
12879
  saveDiscussionRegistry(toolWorktree, toolRegistry);
@@ -12373,7 +12925,7 @@ Reason: ${err.message}`;
12373
12925
  try {
12374
12926
  const sessionResult = await client.session.create({
12375
12927
  query: { directory: workflowDirectory },
12376
- body: { title: `Workflow Run: ${path2.basename(workflowTaskPath)}` }
12928
+ body: { title: `Workflow Run: ${path5.basename(workflowTaskPath)}` }
12377
12929
  });
12378
12930
  const sessionId = sessionResult.data.id;
12379
12931
  activeWorkflows.set(sessionId, { pmaSessionId, taskPath: workflowTaskPath, track: workflowTrack, directory: workflowDirectory });
@@ -12502,7 +13054,7 @@ Follow-up: use optima_prompt_workflow with session_id '${sessionId}' to check in
12502
13054
  }
12503
13055
  };
12504
13056
  }
12505
- 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, createOpenCodeSessionControl, deliveryEvidencePathForClickUpTask, ensureClickUpTaskWorktree, ensureClickUpWebhookSubscription, handleClickUpWebhookRequest, isClickUpWebhookStateActive, normalizeClickUpWebhookConfig, normalizeClickUpWebhookLogLevel, normalizeOpenCodeBaseUrl, openCodeSessionExists, promptOpenCodeSessionControl, probeOpenCodeSessionControl, readClickUpCommentLedger, readClickUpWebhookState, readOpenCodeSessionControl, readOpenCodeSessionMessages, reconcileClickUpStartup, scheduleClickUpStartupReconciliation, waitForOpenCodeReadiness, recordClickUpCommentVersionProcessed, resyncClickUpWebhookForSignatureDrift, resolveOptimaPluginOptions, resolveSecretReference, routeClickUpWebhookEvent, sendOpenCodeSessionEvent, sendOpenCodeSessionEventDirect, summarizeOpenCodeMessages, 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 };
12506
13058
  export {
12507
13059
  OptimaPlugin as default
12508
13060
  };