@docyrus/docyrus 0.0.40 → 0.0.41

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/main.js CHANGED
@@ -111,17 +111,17 @@ var require_visit = __commonJS({
111
111
  visit2.BREAK = BREAK;
112
112
  visit2.SKIP = SKIP2;
113
113
  visit2.REMOVE = REMOVE;
114
- function visit_(key, node2, visitor, path3) {
115
- const ctrl = callVisitor(key, node2, visitor, path3);
114
+ function visit_(key, node2, visitor, path7) {
115
+ const ctrl = callVisitor(key, node2, visitor, path7);
116
116
  if (identity3.isNode(ctrl) || identity3.isPair(ctrl)) {
117
- replaceNode(key, path3, ctrl);
118
- return visit_(key, ctrl, visitor, path3);
117
+ replaceNode(key, path7, ctrl);
118
+ return visit_(key, ctrl, visitor, path7);
119
119
  }
120
120
  if (typeof ctrl !== "symbol") {
121
121
  if (identity3.isCollection(node2)) {
122
- path3 = Object.freeze(path3.concat(node2));
122
+ path7 = Object.freeze(path7.concat(node2));
123
123
  for (let i2 = 0; i2 < node2.items.length; ++i2) {
124
- const ci = visit_(i2, node2.items[i2], visitor, path3);
124
+ const ci = visit_(i2, node2.items[i2], visitor, path7);
125
125
  if (typeof ci === "number")
126
126
  i2 = ci - 1;
127
127
  else if (ci === BREAK)
@@ -132,13 +132,13 @@ var require_visit = __commonJS({
132
132
  }
133
133
  }
134
134
  } else if (identity3.isPair(node2)) {
135
- path3 = Object.freeze(path3.concat(node2));
136
- const ck = visit_("key", node2.key, visitor, path3);
135
+ path7 = Object.freeze(path7.concat(node2));
136
+ const ck = visit_("key", node2.key, visitor, path7);
137
137
  if (ck === BREAK)
138
138
  return BREAK;
139
139
  else if (ck === REMOVE)
140
140
  node2.key = null;
141
- const cv = visit_("value", node2.value, visitor, path3);
141
+ const cv = visit_("value", node2.value, visitor, path7);
142
142
  if (cv === BREAK)
143
143
  return BREAK;
144
144
  else if (cv === REMOVE)
@@ -159,17 +159,17 @@ var require_visit = __commonJS({
159
159
  visitAsync.BREAK = BREAK;
160
160
  visitAsync.SKIP = SKIP2;
161
161
  visitAsync.REMOVE = REMOVE;
162
- async function visitAsync_(key, node2, visitor, path3) {
163
- const ctrl = await callVisitor(key, node2, visitor, path3);
162
+ async function visitAsync_(key, node2, visitor, path7) {
163
+ const ctrl = await callVisitor(key, node2, visitor, path7);
164
164
  if (identity3.isNode(ctrl) || identity3.isPair(ctrl)) {
165
- replaceNode(key, path3, ctrl);
166
- return visitAsync_(key, ctrl, visitor, path3);
165
+ replaceNode(key, path7, ctrl);
166
+ return visitAsync_(key, ctrl, visitor, path7);
167
167
  }
168
168
  if (typeof ctrl !== "symbol") {
169
169
  if (identity3.isCollection(node2)) {
170
- path3 = Object.freeze(path3.concat(node2));
170
+ path7 = Object.freeze(path7.concat(node2));
171
171
  for (let i2 = 0; i2 < node2.items.length; ++i2) {
172
- const ci = await visitAsync_(i2, node2.items[i2], visitor, path3);
172
+ const ci = await visitAsync_(i2, node2.items[i2], visitor, path7);
173
173
  if (typeof ci === "number")
174
174
  i2 = ci - 1;
175
175
  else if (ci === BREAK)
@@ -180,13 +180,13 @@ var require_visit = __commonJS({
180
180
  }
181
181
  }
182
182
  } else if (identity3.isPair(node2)) {
183
- path3 = Object.freeze(path3.concat(node2));
184
- const ck = await visitAsync_("key", node2.key, visitor, path3);
183
+ path7 = Object.freeze(path7.concat(node2));
184
+ const ck = await visitAsync_("key", node2.key, visitor, path7);
185
185
  if (ck === BREAK)
186
186
  return BREAK;
187
187
  else if (ck === REMOVE)
188
188
  node2.key = null;
189
- const cv = await visitAsync_("value", node2.value, visitor, path3);
189
+ const cv = await visitAsync_("value", node2.value, visitor, path7);
190
190
  if (cv === BREAK)
191
191
  return BREAK;
192
192
  else if (cv === REMOVE)
@@ -213,23 +213,23 @@ var require_visit = __commonJS({
213
213
  }
214
214
  return visitor;
215
215
  }
216
- function callVisitor(key, node2, visitor, path3) {
216
+ function callVisitor(key, node2, visitor, path7) {
217
217
  if (typeof visitor === "function")
218
- return visitor(key, node2, path3);
218
+ return visitor(key, node2, path7);
219
219
  if (identity3.isMap(node2))
220
- return visitor.Map?.(key, node2, path3);
220
+ return visitor.Map?.(key, node2, path7);
221
221
  if (identity3.isSeq(node2))
222
- return visitor.Seq?.(key, node2, path3);
222
+ return visitor.Seq?.(key, node2, path7);
223
223
  if (identity3.isPair(node2))
224
- return visitor.Pair?.(key, node2, path3);
224
+ return visitor.Pair?.(key, node2, path7);
225
225
  if (identity3.isScalar(node2))
226
- return visitor.Scalar?.(key, node2, path3);
226
+ return visitor.Scalar?.(key, node2, path7);
227
227
  if (identity3.isAlias(node2))
228
- return visitor.Alias?.(key, node2, path3);
228
+ return visitor.Alias?.(key, node2, path7);
229
229
  return void 0;
230
230
  }
231
- function replaceNode(key, path3, node2) {
232
- const parent = path3[path3.length - 1];
231
+ function replaceNode(key, path7, node2) {
232
+ const parent = path7[path7.length - 1];
233
233
  if (identity3.isCollection(parent)) {
234
234
  parent.items[key] = node2;
235
235
  } else if (identity3.isPair(parent)) {
@@ -837,10 +837,10 @@ var require_Collection = __commonJS({
837
837
  var createNode = require_createNode();
838
838
  var identity3 = require_identity();
839
839
  var Node2 = require_Node();
840
- function collectionFromPath(schema, path3, value2) {
840
+ function collectionFromPath(schema, path7, value2) {
841
841
  let v = value2;
842
- for (let i2 = path3.length - 1; i2 >= 0; --i2) {
843
- const k = path3[i2];
842
+ for (let i2 = path7.length - 1; i2 >= 0; --i2) {
843
+ const k = path7[i2];
844
844
  if (typeof k === "number" && Number.isInteger(k) && k >= 0) {
845
845
  const a = [];
846
846
  a[k] = v;
@@ -859,7 +859,7 @@ var require_Collection = __commonJS({
859
859
  sourceObjects: /* @__PURE__ */ new Map()
860
860
  });
861
861
  }
862
- var isEmptyPath = (path3) => path3 == null || typeof path3 === "object" && !!path3[Symbol.iterator]().next().done;
862
+ var isEmptyPath = (path7) => path7 == null || typeof path7 === "object" && !!path7[Symbol.iterator]().next().done;
863
863
  var Collection = class extends Node2.NodeBase {
864
864
  constructor(type, schema) {
865
865
  super(type);
@@ -889,11 +889,11 @@ var require_Collection = __commonJS({
889
889
  * be a Pair instance or a `{ key, value }` object, which may not have a key
890
890
  * that already exists in the map.
891
891
  */
892
- addIn(path3, value2) {
893
- if (isEmptyPath(path3))
892
+ addIn(path7, value2) {
893
+ if (isEmptyPath(path7))
894
894
  this.add(value2);
895
895
  else {
896
- const [key, ...rest] = path3;
896
+ const [key, ...rest] = path7;
897
897
  const node2 = this.get(key, true);
898
898
  if (identity3.isCollection(node2))
899
899
  node2.addIn(rest, value2);
@@ -907,8 +907,8 @@ var require_Collection = __commonJS({
907
907
  * Removes a value from the collection.
908
908
  * @returns `true` if the item was found and removed.
909
909
  */
910
- deleteIn(path3) {
911
- const [key, ...rest] = path3;
910
+ deleteIn(path7) {
911
+ const [key, ...rest] = path7;
912
912
  if (rest.length === 0)
913
913
  return this.delete(key);
914
914
  const node2 = this.get(key, true);
@@ -922,8 +922,8 @@ var require_Collection = __commonJS({
922
922
  * scalar values from their surrounding node; to disable set `keepScalar` to
923
923
  * `true` (collections are always returned intact).
924
924
  */
925
- getIn(path3, keepScalar) {
926
- const [key, ...rest] = path3;
925
+ getIn(path7, keepScalar) {
926
+ const [key, ...rest] = path7;
927
927
  const node2 = this.get(key, true);
928
928
  if (rest.length === 0)
929
929
  return !keepScalar && identity3.isScalar(node2) ? node2.value : node2;
@@ -941,8 +941,8 @@ var require_Collection = __commonJS({
941
941
  /**
942
942
  * Checks if the collection includes a value with the key `key`.
943
943
  */
944
- hasIn(path3) {
945
- const [key, ...rest] = path3;
944
+ hasIn(path7) {
945
+ const [key, ...rest] = path7;
946
946
  if (rest.length === 0)
947
947
  return this.has(key);
948
948
  const node2 = this.get(key, true);
@@ -952,8 +952,8 @@ var require_Collection = __commonJS({
952
952
  * Sets a value in this collection. For `!!set`, `value` needs to be a
953
953
  * boolean to add/remove the item from the set.
954
954
  */
955
- setIn(path3, value2) {
956
- const [key, ...rest] = path3;
955
+ setIn(path7, value2) {
956
+ const [key, ...rest] = path7;
957
957
  if (rest.length === 0) {
958
958
  this.set(key, value2);
959
959
  } else {
@@ -3465,9 +3465,9 @@ var require_Document = __commonJS({
3465
3465
  this.contents.add(value2);
3466
3466
  }
3467
3467
  /** Adds a value to the document. */
3468
- addIn(path3, value2) {
3468
+ addIn(path7, value2) {
3469
3469
  if (assertCollection(this.contents))
3470
- this.contents.addIn(path3, value2);
3470
+ this.contents.addIn(path7, value2);
3471
3471
  }
3472
3472
  /**
3473
3473
  * Create a new `Alias` node, ensuring that the target `node` has the required anchor.
@@ -3542,14 +3542,14 @@ var require_Document = __commonJS({
3542
3542
  * Removes a value from the document.
3543
3543
  * @returns `true` if the item was found and removed.
3544
3544
  */
3545
- deleteIn(path3) {
3546
- if (Collection.isEmptyPath(path3)) {
3545
+ deleteIn(path7) {
3546
+ if (Collection.isEmptyPath(path7)) {
3547
3547
  if (this.contents == null)
3548
3548
  return false;
3549
3549
  this.contents = null;
3550
3550
  return true;
3551
3551
  }
3552
- return assertCollection(this.contents) ? this.contents.deleteIn(path3) : false;
3552
+ return assertCollection(this.contents) ? this.contents.deleteIn(path7) : false;
3553
3553
  }
3554
3554
  /**
3555
3555
  * Returns item at `key`, or `undefined` if not found. By default unwraps
@@ -3564,10 +3564,10 @@ var require_Document = __commonJS({
3564
3564
  * scalar values from their surrounding node; to disable set `keepScalar` to
3565
3565
  * `true` (collections are always returned intact).
3566
3566
  */
3567
- getIn(path3, keepScalar) {
3568
- if (Collection.isEmptyPath(path3))
3567
+ getIn(path7, keepScalar) {
3568
+ if (Collection.isEmptyPath(path7))
3569
3569
  return !keepScalar && identity3.isScalar(this.contents) ? this.contents.value : this.contents;
3570
- return identity3.isCollection(this.contents) ? this.contents.getIn(path3, keepScalar) : void 0;
3570
+ return identity3.isCollection(this.contents) ? this.contents.getIn(path7, keepScalar) : void 0;
3571
3571
  }
3572
3572
  /**
3573
3573
  * Checks if the document includes a value with the key `key`.
@@ -3578,10 +3578,10 @@ var require_Document = __commonJS({
3578
3578
  /**
3579
3579
  * Checks if the document includes a value at `path`.
3580
3580
  */
3581
- hasIn(path3) {
3582
- if (Collection.isEmptyPath(path3))
3581
+ hasIn(path7) {
3582
+ if (Collection.isEmptyPath(path7))
3583
3583
  return this.contents !== void 0;
3584
- return identity3.isCollection(this.contents) ? this.contents.hasIn(path3) : false;
3584
+ return identity3.isCollection(this.contents) ? this.contents.hasIn(path7) : false;
3585
3585
  }
3586
3586
  /**
3587
3587
  * Sets a value in this document. For `!!set`, `value` needs to be a
@@ -3598,13 +3598,13 @@ var require_Document = __commonJS({
3598
3598
  * Sets a value in this document. For `!!set`, `value` needs to be a
3599
3599
  * boolean to add/remove the item from the set.
3600
3600
  */
3601
- setIn(path3, value2) {
3602
- if (Collection.isEmptyPath(path3)) {
3601
+ setIn(path7, value2) {
3602
+ if (Collection.isEmptyPath(path7)) {
3603
3603
  this.contents = value2;
3604
3604
  } else if (this.contents == null) {
3605
- this.contents = Collection.collectionFromPath(this.schema, Array.from(path3), value2);
3605
+ this.contents = Collection.collectionFromPath(this.schema, Array.from(path7), value2);
3606
3606
  } else if (assertCollection(this.contents)) {
3607
- this.contents.setIn(path3, value2);
3607
+ this.contents.setIn(path7, value2);
3608
3608
  }
3609
3609
  }
3610
3610
  /**
@@ -5561,9 +5561,9 @@ var require_cst_visit = __commonJS({
5561
5561
  visit2.BREAK = BREAK;
5562
5562
  visit2.SKIP = SKIP2;
5563
5563
  visit2.REMOVE = REMOVE;
5564
- visit2.itemAtPath = (cst, path3) => {
5564
+ visit2.itemAtPath = (cst, path7) => {
5565
5565
  let item = cst;
5566
- for (const [field, index2] of path3) {
5566
+ for (const [field, index2] of path7) {
5567
5567
  const tok = item?.[field];
5568
5568
  if (tok && "items" in tok) {
5569
5569
  item = tok.items[index2];
@@ -5572,23 +5572,23 @@ var require_cst_visit = __commonJS({
5572
5572
  }
5573
5573
  return item;
5574
5574
  };
5575
- visit2.parentCollection = (cst, path3) => {
5576
- const parent = visit2.itemAtPath(cst, path3.slice(0, -1));
5577
- const field = path3[path3.length - 1][0];
5575
+ visit2.parentCollection = (cst, path7) => {
5576
+ const parent = visit2.itemAtPath(cst, path7.slice(0, -1));
5577
+ const field = path7[path7.length - 1][0];
5578
5578
  const coll = parent?.[field];
5579
5579
  if (coll && "items" in coll)
5580
5580
  return coll;
5581
5581
  throw new Error("Parent collection not found");
5582
5582
  };
5583
- function _visit(path3, item, visitor) {
5584
- let ctrl = visitor(item, path3);
5583
+ function _visit(path7, item, visitor) {
5584
+ let ctrl = visitor(item, path7);
5585
5585
  if (typeof ctrl === "symbol")
5586
5586
  return ctrl;
5587
5587
  for (const field of ["key", "value"]) {
5588
5588
  const token = item[field];
5589
5589
  if (token && "items" in token) {
5590
5590
  for (let i2 = 0; i2 < token.items.length; ++i2) {
5591
- const ci = _visit(Object.freeze(path3.concat([[field, i2]])), token.items[i2], visitor);
5591
+ const ci = _visit(Object.freeze(path7.concat([[field, i2]])), token.items[i2], visitor);
5592
5592
  if (typeof ci === "number")
5593
5593
  i2 = ci - 1;
5594
5594
  else if (ci === BREAK)
@@ -5599,10 +5599,10 @@ var require_cst_visit = __commonJS({
5599
5599
  }
5600
5600
  }
5601
5601
  if (typeof ctrl === "function" && field === "key")
5602
- ctrl = ctrl(item, path3);
5602
+ ctrl = ctrl(item, path7);
5603
5603
  }
5604
5604
  }
5605
- return typeof ctrl === "function" ? ctrl(item, path3) : ctrl;
5605
+ return typeof ctrl === "function" ? ctrl(item, path7) : ctrl;
5606
5606
  }
5607
5607
  exports2.visit = visit2;
5608
5608
  }
@@ -6887,14 +6887,14 @@ var require_parser = __commonJS({
6887
6887
  case "scalar":
6888
6888
  case "single-quoted-scalar":
6889
6889
  case "double-quoted-scalar": {
6890
- const fs4 = this.flowScalar(this.type);
6890
+ const fs7 = this.flowScalar(this.type);
6891
6891
  if (atNextItem || it.value) {
6892
- map2.items.push({ start: start2, key: fs4, sep: [] });
6892
+ map2.items.push({ start: start2, key: fs7, sep: [] });
6893
6893
  this.onKeyLine = true;
6894
6894
  } else if (it.sep) {
6895
- this.stack.push(fs4);
6895
+ this.stack.push(fs7);
6896
6896
  } else {
6897
- Object.assign(it, { key: fs4, sep: [] });
6897
+ Object.assign(it, { key: fs7, sep: [] });
6898
6898
  this.onKeyLine = true;
6899
6899
  }
6900
6900
  return;
@@ -7022,13 +7022,13 @@ var require_parser = __commonJS({
7022
7022
  case "scalar":
7023
7023
  case "single-quoted-scalar":
7024
7024
  case "double-quoted-scalar": {
7025
- const fs4 = this.flowScalar(this.type);
7025
+ const fs7 = this.flowScalar(this.type);
7026
7026
  if (!it || it.value)
7027
- fc.items.push({ start: [], key: fs4, sep: [] });
7027
+ fc.items.push({ start: [], key: fs7, sep: [] });
7028
7028
  else if (it.sep)
7029
- this.stack.push(fs4);
7029
+ this.stack.push(fs7);
7030
7030
  else
7031
- Object.assign(it, { key: fs4, sep: [] });
7031
+ Object.assign(it, { key: fs7, sep: [] });
7032
7032
  return;
7033
7033
  }
7034
7034
  case "flow-map-end":
@@ -10529,8 +10529,8 @@ var require_utils = __commonJS({
10529
10529
  }
10530
10530
  return ind;
10531
10531
  }
10532
- function removeDotSegments(path3) {
10533
- let input = path3;
10532
+ function removeDotSegments(path7) {
10533
+ let input = path7;
10534
10534
  const output = [];
10535
10535
  let nextSlash = -1;
10536
10536
  let len = 0;
@@ -10729,8 +10729,8 @@ var require_schemes = __commonJS({
10729
10729
  wsComponent.secure = void 0;
10730
10730
  }
10731
10731
  if (wsComponent.resourceName) {
10732
- const [path3, query] = wsComponent.resourceName.split("?");
10733
- wsComponent.path = path3 && path3 !== "/" ? path3 : void 0;
10732
+ const [path7, query] = wsComponent.resourceName.split("?");
10733
+ wsComponent.path = path7 && path7 !== "/" ? path7 : void 0;
10734
10734
  wsComponent.query = query;
10735
10735
  wsComponent.resourceName = void 0;
10736
10736
  }
@@ -14092,12 +14092,12 @@ var require_dist2 = __commonJS({
14092
14092
  throw new Error(`Unknown format "${name2}"`);
14093
14093
  return f;
14094
14094
  };
14095
- function addFormats(ajv, list4, fs4, exportName) {
14095
+ function addFormats(ajv, list4, fs7, exportName) {
14096
14096
  var _a2;
14097
14097
  var _b;
14098
14098
  (_a2 = (_b = ajv.opts.code).formats) !== null && _a2 !== void 0 ? _a2 : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
14099
14099
  for (const f of list4)
14100
- ajv.addFormat(f, fs4[f]);
14100
+ ajv.addFormat(f, fs7[f]);
14101
14101
  }
14102
14102
  module2.exports = exports2 = formatsPlugin;
14103
14103
  Object.defineProperty(exports2, "__esModule", { value: true });
@@ -61639,15 +61639,15 @@ var require_route = __commonJS({
61639
61639
  };
61640
61640
  }
61641
61641
  function wrapConversion(toModel, graph) {
61642
- const path3 = [graph[toModel].parent, toModel];
61642
+ const path7 = [graph[toModel].parent, toModel];
61643
61643
  let fn = conversions[graph[toModel].parent][toModel];
61644
61644
  let cur = graph[toModel].parent;
61645
61645
  while (graph[cur].parent) {
61646
- path3.unshift(graph[cur].parent);
61646
+ path7.unshift(graph[cur].parent);
61647
61647
  fn = link3(conversions[graph[cur].parent][cur], fn);
61648
61648
  cur = graph[cur].parent;
61649
61649
  }
61650
- fn.conversion = path3;
61650
+ fn.conversion = path7;
61651
61651
  return fn;
61652
61652
  }
61653
61653
  module2.exports = function(fromModel) {
@@ -76272,11 +76272,11 @@ var require_commonjs3 = __commonJS({
76272
76272
  return (f) => f.length === len && f !== "." && f !== "..";
76273
76273
  };
76274
76274
  var defaultPlatform = typeof process === "object" && process ? typeof process.env === "object" && process.env && process.env.__MINIMATCH_TESTING_PLATFORM__ || process.platform : "posix";
76275
- var path3 = {
76275
+ var path7 = {
76276
76276
  win32: { sep: "\\" },
76277
76277
  posix: { sep: "/" }
76278
76278
  };
76279
- exports2.sep = defaultPlatform === "win32" ? path3.win32.sep : path3.posix.sep;
76279
+ exports2.sep = defaultPlatform === "win32" ? path7.win32.sep : path7.posix.sep;
76280
76280
  exports2.minimatch.sep = exports2.sep;
76281
76281
  exports2.GLOBSTAR = /* @__PURE__ */ Symbol("globstar **");
76282
76282
  exports2.minimatch.GLOBSTAR = exports2.GLOBSTAR;
@@ -77046,8 +77046,8 @@ var require_commonjs3 = __commonJS({
77046
77046
  var require_lib4 = __commonJS({
77047
77047
  "../../node_modules/.pnpm/ignore-walk@8.0.0/node_modules/ignore-walk/lib/index.js"(exports2, module2) {
77048
77048
  "use strict";
77049
- var fs4 = require("fs");
77050
- var path3 = require("path");
77049
+ var fs7 = require("fs");
77050
+ var path7 = require("path");
77051
77051
  var EE = require("events").EventEmitter;
77052
77052
  var Minimatch = require_commonjs3().Minimatch;
77053
77053
  var Walker = class _Walker extends EE {
@@ -77056,7 +77056,7 @@ var require_lib4 = __commonJS({
77056
77056
  super(opts);
77057
77057
  this.isSymbolicLink = opts.isSymbolicLink;
77058
77058
  this.path = opts.path || process.cwd();
77059
- this.basename = path3.basename(this.path);
77059
+ this.basename = path7.basename(this.path);
77060
77060
  this.ignoreFiles = opts.ignoreFiles || [".ignore"];
77061
77061
  this.ignoreRules = {};
77062
77062
  this.parent = opts.parent || null;
@@ -77089,7 +77089,7 @@ var require_lib4 = __commonJS({
77089
77089
  return ret;
77090
77090
  }
77091
77091
  start() {
77092
- fs4.readdir(this.path, (er, entries) => er ? this.emit("error", er) : this.onReaddir(entries));
77092
+ fs7.readdir(this.path, (er, entries) => er ? this.emit("error", er) : this.onReaddir(entries));
77093
77093
  return this;
77094
77094
  }
77095
77095
  isIgnoreFile(e) {
@@ -77122,8 +77122,8 @@ var require_lib4 = __commonJS({
77122
77122
  newIg.forEach((e) => this.addIgnoreFile(e, then));
77123
77123
  }
77124
77124
  addIgnoreFile(file2, then) {
77125
- const ig = path3.resolve(this.path, file2);
77126
- fs4.readFile(ig, "utf8", (er, data) => er ? this.emit("error", er) : this.onReadIgnoreFile(file2, data, then));
77125
+ const ig = path7.resolve(this.path, file2);
77126
+ fs7.readFile(ig, "utf8", (er, data) => er ? this.emit("error", er) : this.onReadIgnoreFile(file2, data, then));
77127
77127
  }
77128
77128
  onReadIgnoreFile(file2, data, then) {
77129
77129
  const mmopt = {
@@ -77178,13 +77178,13 @@ var require_lib4 = __commonJS({
77178
77178
  }
77179
77179
  stat({ entry, file: file2, dir }, then) {
77180
77180
  const abs = this.path + "/" + entry;
77181
- fs4.lstat(abs, (lstatErr, lstatResult) => {
77181
+ fs7.lstat(abs, (lstatErr, lstatResult) => {
77182
77182
  if (lstatErr) {
77183
77183
  this.emit("error", lstatErr);
77184
77184
  } else {
77185
77185
  const isSymbolicLink = lstatResult.isSymbolicLink();
77186
77186
  if (this.follow && isSymbolicLink) {
77187
- fs4.stat(abs, (statErr, statResult) => {
77187
+ fs7.stat(abs, (statErr, statResult) => {
77188
77188
  if (statErr) {
77189
77189
  this.emit("error", statErr);
77190
77190
  } else {
@@ -77240,19 +77240,19 @@ var require_lib4 = __commonJS({
77240
77240
  };
77241
77241
  var WalkerSync = class _WalkerSync extends Walker {
77242
77242
  start() {
77243
- this.onReaddir(fs4.readdirSync(this.path));
77243
+ this.onReaddir(fs7.readdirSync(this.path));
77244
77244
  return this;
77245
77245
  }
77246
77246
  addIgnoreFile(file2, then) {
77247
- const ig = path3.resolve(this.path, file2);
77248
- this.onReadIgnoreFile(file2, fs4.readFileSync(ig, "utf8"), then);
77247
+ const ig = path7.resolve(this.path, file2);
77248
+ this.onReadIgnoreFile(file2, fs7.readFileSync(ig, "utf8"), then);
77249
77249
  }
77250
77250
  stat({ entry, file: file2, dir }, then) {
77251
77251
  const abs = this.path + "/" + entry;
77252
- let st = fs4.lstatSync(abs);
77252
+ let st = fs7.lstatSync(abs);
77253
77253
  const isSymbolicLink = st.isSymbolicLink();
77254
77254
  if (this.follow && isSymbolicLink) {
77255
- st = fs4.statSync(abs);
77255
+ st = fs7.statSync(abs);
77256
77256
  }
77257
77257
  this.onstat({ st, entry, file: file2, dir, isSymbolicLink }, then);
77258
77258
  }
@@ -85621,8 +85621,8 @@ function assertNonEmpty(part, name2) {
85621
85621
  throw new Error("`" + name2 + "` cannot be empty");
85622
85622
  }
85623
85623
  }
85624
- function assertPath(path3, name2) {
85625
- if (!path3) {
85624
+ function assertPath(path7, name2) {
85625
+ if (!path7) {
85626
85626
  throw new Error("Setting `" + name2 + "` requires `path` to be set too");
85627
85627
  }
85628
85628
  }
@@ -85808,13 +85808,13 @@ var init_lib10 = __esm({
85808
85808
  * @returns {undefined}
85809
85809
  * Nothing.
85810
85810
  */
85811
- set path(path3) {
85812
- if (isUrl(path3)) {
85813
- path3 = (0, import_node_url.fileURLToPath)(path3);
85811
+ set path(path7) {
85812
+ if (isUrl(path7)) {
85813
+ path7 = (0, import_node_url.fileURLToPath)(path7);
85814
85814
  }
85815
- assertNonEmpty(path3, "path");
85816
- if (this.path !== path3) {
85817
- this.history.push(path3);
85815
+ assertNonEmpty(path7, "path");
85816
+ if (this.path !== path7) {
85817
+ this.history.push(path7);
85818
85818
  }
85819
85819
  }
85820
85820
  /**
@@ -88691,14 +88691,14 @@ var require_util3 = __commonJS({
88691
88691
  }
88692
88692
  const port = url2.port != null ? url2.port : url2.protocol === "https:" ? 443 : 80;
88693
88693
  let origin = url2.origin != null ? url2.origin : `${url2.protocol || ""}//${url2.hostname || ""}:${port}`;
88694
- let path3 = url2.path != null ? url2.path : `${url2.pathname || ""}${url2.search || ""}`;
88694
+ let path7 = url2.path != null ? url2.path : `${url2.pathname || ""}${url2.search || ""}`;
88695
88695
  if (origin[origin.length - 1] === "/") {
88696
88696
  origin = origin.slice(0, origin.length - 1);
88697
88697
  }
88698
- if (path3 && path3[0] !== "/") {
88699
- path3 = `/${path3}`;
88698
+ if (path7 && path7[0] !== "/") {
88699
+ path7 = `/${path7}`;
88700
88700
  }
88701
- return new URL(`${origin}${path3}`);
88701
+ return new URL(`${origin}${path7}`);
88702
88702
  }
88703
88703
  if (!isHttpOrHttpsPrefixed(url2.origin || url2.protocol)) {
88704
88704
  throw new InvalidArgumentError("Invalid URL protocol: the URL must start with `http:` or `https:`.");
@@ -89503,9 +89503,9 @@ var require_diagnostics = __commonJS({
89503
89503
  "undici:client:sendHeaders",
89504
89504
  (evt) => {
89505
89505
  const {
89506
- request: { method, path: path3, origin }
89506
+ request: { method, path: path7, origin }
89507
89507
  } = evt;
89508
- debugLog("sending request to %s %s%s", method, origin, path3);
89508
+ debugLog("sending request to %s %s%s", method, origin, path7);
89509
89509
  }
89510
89510
  );
89511
89511
  }
@@ -89523,14 +89523,14 @@ var require_diagnostics = __commonJS({
89523
89523
  "undici:request:headers",
89524
89524
  (evt) => {
89525
89525
  const {
89526
- request: { method, path: path3, origin },
89526
+ request: { method, path: path7, origin },
89527
89527
  response: { statusCode }
89528
89528
  } = evt;
89529
89529
  debugLog(
89530
89530
  "received response to %s %s%s - HTTP %d",
89531
89531
  method,
89532
89532
  origin,
89533
- path3,
89533
+ path7,
89534
89534
  statusCode
89535
89535
  );
89536
89536
  }
@@ -89539,23 +89539,23 @@ var require_diagnostics = __commonJS({
89539
89539
  "undici:request:trailers",
89540
89540
  (evt) => {
89541
89541
  const {
89542
- request: { method, path: path3, origin }
89542
+ request: { method, path: path7, origin }
89543
89543
  } = evt;
89544
- debugLog("trailers received from %s %s%s", method, origin, path3);
89544
+ debugLog("trailers received from %s %s%s", method, origin, path7);
89545
89545
  }
89546
89546
  );
89547
89547
  diagnosticsChannel.subscribe(
89548
89548
  "undici:request:error",
89549
89549
  (evt) => {
89550
89550
  const {
89551
- request: { method, path: path3, origin },
89551
+ request: { method, path: path7, origin },
89552
89552
  error: error48
89553
89553
  } = evt;
89554
89554
  debugLog(
89555
89555
  "request to %s %s%s errored - %s",
89556
89556
  method,
89557
89557
  origin,
89558
- path3,
89558
+ path7,
89559
89559
  error48.message
89560
89560
  );
89561
89561
  }
@@ -89655,7 +89655,7 @@ var require_request = __commonJS({
89655
89655
  var kHandler = /* @__PURE__ */ Symbol("handler");
89656
89656
  var Request = class {
89657
89657
  constructor(origin, {
89658
- path: path3,
89658
+ path: path7,
89659
89659
  method,
89660
89660
  body: body2,
89661
89661
  headers,
@@ -89671,11 +89671,11 @@ var require_request = __commonJS({
89671
89671
  throwOnError,
89672
89672
  maxRedirections
89673
89673
  }, handler2) {
89674
- if (typeof path3 !== "string") {
89674
+ if (typeof path7 !== "string") {
89675
89675
  throw new InvalidArgumentError("path must be a string");
89676
- } else if (path3[0] !== "/" && !(path3.startsWith("http://") || path3.startsWith("https://")) && method !== "CONNECT") {
89676
+ } else if (path7[0] !== "/" && !(path7.startsWith("http://") || path7.startsWith("https://")) && method !== "CONNECT") {
89677
89677
  throw new InvalidArgumentError("path must be an absolute URL or start with a slash");
89678
- } else if (invalidPathRegex.test(path3)) {
89678
+ } else if (invalidPathRegex.test(path7)) {
89679
89679
  throw new InvalidArgumentError("invalid request path");
89680
89680
  }
89681
89681
  if (typeof method !== "string") {
@@ -89743,7 +89743,7 @@ var require_request = __commonJS({
89743
89743
  this.completed = false;
89744
89744
  this.aborted = false;
89745
89745
  this.upgrade = upgrade || null;
89746
- this.path = query ? serializePathWithQuery(path3, query) : path3;
89746
+ this.path = query ? serializePathWithQuery(path7, query) : path7;
89747
89747
  this.origin = origin;
89748
89748
  this.protocol = getProtocolFromUrlString(origin);
89749
89749
  this.idempotent = idempotent == null ? method === "HEAD" || method === "GET" : idempotent;
@@ -94760,7 +94760,7 @@ var require_client_h1 = __commonJS({
94760
94760
  return method !== "GET" && method !== "HEAD" && method !== "OPTIONS" && method !== "TRACE" && method !== "CONNECT";
94761
94761
  }
94762
94762
  function writeH1(client, request) {
94763
- const { method, path: path3, host, upgrade, blocking, reset } = request;
94763
+ const { method, path: path7, host, upgrade, blocking, reset } = request;
94764
94764
  let { body: body2, headers, contentLength } = request;
94765
94765
  const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH" || method === "QUERY" || method === "PROPFIND" || method === "PROPPATCH";
94766
94766
  if (util2.isFormDataLike(body2)) {
@@ -94826,7 +94826,7 @@ var require_client_h1 = __commonJS({
94826
94826
  if (blocking) {
94827
94827
  socket[kBlocking] = true;
94828
94828
  }
94829
- let header = `${method} ${path3} HTTP/1.1\r
94829
+ let header = `${method} ${path7} HTTP/1.1\r
94830
94830
  `;
94831
94831
  if (typeof host === "string") {
94832
94832
  header += `host: ${host}\r
@@ -95479,7 +95479,7 @@ var require_client_h2 = __commonJS({
95479
95479
  function writeH2(client, request) {
95480
95480
  const requestTimeout = request.bodyTimeout ?? client[kBodyTimeout];
95481
95481
  const session = client[kHTTP2Session];
95482
- const { method, path: path3, host, upgrade, expectContinue, signal, protocol, headers: reqHeaders } = request;
95482
+ const { method, path: path7, host, upgrade, expectContinue, signal, protocol, headers: reqHeaders } = request;
95483
95483
  let { body: body2 } = request;
95484
95484
  if (upgrade != null && upgrade !== "websocket") {
95485
95485
  util2.errorRequest(client, request, new InvalidArgumentError(`Custom upgrade "${upgrade}" not supported over HTTP/2`));
@@ -95547,7 +95547,7 @@ var require_client_h2 = __commonJS({
95547
95547
  }
95548
95548
  headers[HTTP2_HEADER_METHOD] = "CONNECT";
95549
95549
  headers[HTTP2_HEADER_PROTOCOL] = "websocket";
95550
- headers[HTTP2_HEADER_PATH] = path3;
95550
+ headers[HTTP2_HEADER_PATH] = path7;
95551
95551
  if (protocol === "ws:" || protocol === "wss:") {
95552
95552
  headers[HTTP2_HEADER_SCHEME] = protocol === "ws:" ? "http" : "https";
95553
95553
  } else {
@@ -95588,7 +95588,7 @@ var require_client_h2 = __commonJS({
95588
95588
  stream.setTimeout(requestTimeout);
95589
95589
  return true;
95590
95590
  }
95591
- headers[HTTP2_HEADER_PATH] = path3;
95591
+ headers[HTTP2_HEADER_PATH] = path7;
95592
95592
  headers[HTTP2_HEADER_SCHEME] = protocol === "http:" ? "http" : "https";
95593
95593
  const expectsPayload = method === "PUT" || method === "POST" || method === "PATCH";
95594
95594
  if (body2 && typeof body2.read === "function") {
@@ -97212,10 +97212,10 @@ var require_proxy_agent = __commonJS({
97212
97212
  };
97213
97213
  const {
97214
97214
  origin,
97215
- path: path3 = "/",
97215
+ path: path7 = "/",
97216
97216
  headers = {}
97217
97217
  } = opts;
97218
- opts.path = origin + path3;
97218
+ opts.path = origin + path7;
97219
97219
  if (!("host" in headers) && !("Host" in headers)) {
97220
97220
  const { host } = new URL(origin);
97221
97221
  headers.host = host;
@@ -99256,20 +99256,20 @@ var require_mock_utils = __commonJS({
99256
99256
  }
99257
99257
  return normalizedQp;
99258
99258
  }
99259
- function safeUrl(path3) {
99260
- if (typeof path3 !== "string") {
99261
- return path3;
99259
+ function safeUrl(path7) {
99260
+ if (typeof path7 !== "string") {
99261
+ return path7;
99262
99262
  }
99263
- const pathSegments = path3.split("?", 3);
99263
+ const pathSegments = path7.split("?", 3);
99264
99264
  if (pathSegments.length !== 2) {
99265
- return path3;
99265
+ return path7;
99266
99266
  }
99267
99267
  const qp = new URLSearchParams(pathSegments.pop());
99268
99268
  qp.sort();
99269
99269
  return [...pathSegments, qp.toString()].join("?");
99270
99270
  }
99271
- function matchKey(mockDispatch2, { path: path3, method, body: body2, headers }) {
99272
- const pathMatch = matchValue(mockDispatch2.path, path3);
99271
+ function matchKey(mockDispatch2, { path: path7, method, body: body2, headers }) {
99272
+ const pathMatch = matchValue(mockDispatch2.path, path7);
99273
99273
  const methodMatch = matchValue(mockDispatch2.method, method);
99274
99274
  const bodyMatch = typeof mockDispatch2.body !== "undefined" ? matchValue(mockDispatch2.body, body2) : true;
99275
99275
  const headersMatch = matchHeaders(mockDispatch2, headers);
@@ -99294,8 +99294,8 @@ var require_mock_utils = __commonJS({
99294
99294
  const basePath = key.query ? serializePathWithQuery(key.path, key.query) : key.path;
99295
99295
  const resolvedPath = typeof basePath === "string" ? safeUrl(basePath) : basePath;
99296
99296
  const resolvedPathWithoutTrailingSlash = removeTrailingSlash(resolvedPath);
99297
- let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path3, ignoreTrailingSlash }) => {
99298
- return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(path3)), resolvedPathWithoutTrailingSlash) : matchValue(safeUrl(path3), resolvedPath);
99297
+ let matchedMockDispatches = mockDispatches.filter(({ consumed }) => !consumed).filter(({ path: path7, ignoreTrailingSlash }) => {
99298
+ return ignoreTrailingSlash ? matchValue(removeTrailingSlash(safeUrl(path7)), resolvedPathWithoutTrailingSlash) : matchValue(safeUrl(path7), resolvedPath);
99299
99299
  });
99300
99300
  if (matchedMockDispatches.length === 0) {
99301
99301
  throw new MockNotMatchedError(`Mock dispatch not matched for path '${resolvedPath}'`);
@@ -99333,19 +99333,19 @@ var require_mock_utils = __commonJS({
99333
99333
  mockDispatches.splice(index2, 1);
99334
99334
  }
99335
99335
  }
99336
- function removeTrailingSlash(path3) {
99337
- while (path3.endsWith("/")) {
99338
- path3 = path3.slice(0, -1);
99336
+ function removeTrailingSlash(path7) {
99337
+ while (path7.endsWith("/")) {
99338
+ path7 = path7.slice(0, -1);
99339
99339
  }
99340
- if (path3.length === 0) {
99341
- path3 = "/";
99340
+ if (path7.length === 0) {
99341
+ path7 = "/";
99342
99342
  }
99343
- return path3;
99343
+ return path7;
99344
99344
  }
99345
99345
  function buildKey(opts) {
99346
- const { path: path3, method, body: body2, headers, query } = opts;
99346
+ const { path: path7, method, body: body2, headers, query } = opts;
99347
99347
  return {
99348
- path: path3,
99348
+ path: path7,
99349
99349
  method,
99350
99350
  body: body2,
99351
99351
  headers,
@@ -100032,10 +100032,10 @@ var require_pending_interceptors_formatter = __commonJS({
100032
100032
  }
100033
100033
  format(pendingInterceptors) {
100034
100034
  const withPrettyHeaders = pendingInterceptors.map(
100035
- ({ method, path: path3, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
100035
+ ({ method, path: path7, data: { statusCode }, persist, times, timesInvoked, origin }) => ({
100036
100036
  Method: method,
100037
100037
  Origin: origin,
100038
- Path: path3,
100038
+ Path: path7,
100039
100039
  "Status code": statusCode,
100040
100040
  Persistent: persist ? PERSISTENT : NOT_PERSISTENT,
100041
100041
  Invocations: timesInvoked,
@@ -100117,9 +100117,9 @@ var require_mock_agent = __commonJS({
100117
100117
  const acceptNonStandardSearchParameters = this[kMockAgentAcceptsNonStandardSearchParameters];
100118
100118
  const dispatchOpts = { ...opts };
100119
100119
  if (acceptNonStandardSearchParameters && dispatchOpts.path) {
100120
- const [path3, searchParams] = dispatchOpts.path.split("?");
100120
+ const [path7, searchParams] = dispatchOpts.path.split("?");
100121
100121
  const normalizedSearchParams = normalizeSearchParams(searchParams, acceptNonStandardSearchParameters);
100122
- dispatchOpts.path = `${path3}?${normalizedSearchParams}`;
100122
+ dispatchOpts.path = `${path7}?${normalizedSearchParams}`;
100123
100123
  }
100124
100124
  return this[kAgent].dispatch(dispatchOpts, handler2);
100125
100125
  }
@@ -100247,8 +100247,8 @@ var require_snapshot_utils = __commonJS({
100247
100247
  match: new Set(matchHeaders.map((header) => caseSensitive ? header : header.toLowerCase()))
100248
100248
  };
100249
100249
  }
100250
- var crypto = runtimeFeatures.has("crypto") ? require("node:crypto") : null;
100251
- var hashId = crypto?.hash ? (value2) => crypto.hash("sha256", value2, "base64url") : (value2) => Buffer.from(value2).toString("base64url");
100250
+ var crypto2 = runtimeFeatures.has("crypto") ? require("node:crypto") : null;
100251
+ var hashId = crypto2?.hash ? (value2) => crypto2.hash("sha256", value2, "base64url") : (value2) => Buffer.from(value2).toString("base64url");
100252
100252
  function isUndiciHeaders(headers) {
100253
100253
  return Array.isArray(headers) && (headers.length & 1) === 0;
100254
100254
  }
@@ -100520,12 +100520,12 @@ var require_snapshot_recorder = __commonJS({
100520
100520
  * @return {Promise<void>} - Resolves when snapshots are loaded
100521
100521
  */
100522
100522
  async loadSnapshots(filePath) {
100523
- const path3 = filePath || this.#snapshotPath;
100524
- if (!path3) {
100523
+ const path7 = filePath || this.#snapshotPath;
100524
+ if (!path7) {
100525
100525
  throw new InvalidArgumentError("Snapshot path is required");
100526
100526
  }
100527
100527
  try {
100528
- const data = await readFile17(resolve2(path3), "utf8");
100528
+ const data = await readFile17(resolve2(path7), "utf8");
100529
100529
  const parsed = JSON.parse(data);
100530
100530
  if (Array.isArray(parsed)) {
100531
100531
  this.#snapshots.clear();
@@ -100539,7 +100539,7 @@ var require_snapshot_recorder = __commonJS({
100539
100539
  if (error48.code === "ENOENT") {
100540
100540
  this.#snapshots.clear();
100541
100541
  } else {
100542
- throw new UndiciError(`Failed to load snapshots from ${path3}`, { cause: error48 });
100542
+ throw new UndiciError(`Failed to load snapshots from ${path7}`, { cause: error48 });
100543
100543
  }
100544
100544
  }
100545
100545
  }
@@ -100550,11 +100550,11 @@ var require_snapshot_recorder = __commonJS({
100550
100550
  * @returns {Promise<void>} - Resolves when snapshots are saved
100551
100551
  */
100552
100552
  async saveSnapshots(filePath) {
100553
- const path3 = filePath || this.#snapshotPath;
100554
- if (!path3) {
100553
+ const path7 = filePath || this.#snapshotPath;
100554
+ if (!path7) {
100555
100555
  throw new InvalidArgumentError("Snapshot path is required");
100556
100556
  }
100557
- const resolvedPath = resolve2(path3);
100557
+ const resolvedPath = resolve2(path7);
100558
100558
  await mkdir10(dirname13(resolvedPath), { recursive: true });
100559
100559
  const data = Array.from(this.#snapshots.entries()).map(([hash3, snapshot]) => ({
100560
100560
  hash: hash3,
@@ -101179,15 +101179,15 @@ var require_redirect_handler = __commonJS({
101179
101179
  return;
101180
101180
  }
101181
101181
  const { origin, pathname, search: search2 } = util2.parseURL(new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin)));
101182
- const path3 = search2 ? `${pathname}${search2}` : pathname;
101183
- const redirectUrlString = `${origin}${path3}`;
101182
+ const path7 = search2 ? `${pathname}${search2}` : pathname;
101183
+ const redirectUrlString = `${origin}${path7}`;
101184
101184
  for (const historyUrl of this.history) {
101185
101185
  if (historyUrl.toString() === redirectUrlString) {
101186
101186
  throw new InvalidArgumentError(`Redirect loop detected. Cannot redirect to ${origin}. This typically happens when using a Client or Pool with cross-origin redirects. Use an Agent for cross-origin redirects.`);
101187
101187
  }
101188
101188
  }
101189
101189
  this.opts.headers = cleanRequestHeaders(this.opts.headers, statusCode === 303, this.opts.origin !== origin);
101190
- this.opts.path = path3;
101190
+ this.opts.path = path7;
101191
101191
  this.opts.origin = origin;
101192
101192
  this.opts.query = null;
101193
101193
  }
@@ -106050,10 +106050,10 @@ var require_subresource_integrity = __commonJS({
106050
106050
  var assert4 = require("node:assert");
106051
106051
  var { runtimeFeatures } = require_runtime_features();
106052
106052
  var validSRIHashAlgorithmTokenSet = /* @__PURE__ */ new Map([["sha256", 0], ["sha384", 1], ["sha512", 2]]);
106053
- var crypto;
106053
+ var crypto2;
106054
106054
  if (runtimeFeatures.has("crypto")) {
106055
- crypto = require("node:crypto");
106056
- const cryptoHashes = crypto.getHashes();
106055
+ crypto2 = require("node:crypto");
106056
+ const cryptoHashes = crypto2.getHashes();
106057
106057
  if (cryptoHashes.length === 0) {
106058
106058
  validSRIHashAlgorithmTokenSet.clear();
106059
106059
  }
@@ -106143,7 +106143,7 @@ var require_subresource_integrity = __commonJS({
106143
106143
  return result;
106144
106144
  }
106145
106145
  var applyAlgorithmToBytes = (algorithm, bytes) => {
106146
- return crypto.hash(algorithm, bytes, "base64");
106146
+ return crypto2.hash(algorithm, bytes, "base64");
106147
106147
  };
106148
106148
  function caseSensitiveMatch(actualValue, expectedValue) {
106149
106149
  let actualValueLength = actualValue.length;
@@ -108064,9 +108064,9 @@ var require_util6 = __commonJS({
108064
108064
  }
108065
108065
  }
108066
108066
  }
108067
- function validateCookiePath(path3) {
108068
- for (let i2 = 0; i2 < path3.length; ++i2) {
108069
- const code = path3.charCodeAt(i2);
108067
+ function validateCookiePath(path7) {
108068
+ for (let i2 = 0; i2 < path7.length; ++i2) {
108069
+ const code = path7.charCodeAt(i2);
108070
108070
  if (code < 32 || // exclude CTLs (0-31)
108071
108071
  code === 127 || // DEL
108072
108072
  code === 59) {
@@ -109064,7 +109064,7 @@ var require_connection = __commonJS({
109064
109064
  var { WebsocketFrameSend } = require_frame();
109065
109065
  var assert4 = require("node:assert");
109066
109066
  var { runtimeFeatures } = require_runtime_features();
109067
- var crypto = runtimeFeatures.has("crypto") ? require("node:crypto") : null;
109067
+ var crypto2 = runtimeFeatures.has("crypto") ? require("node:crypto") : null;
109068
109068
  var warningEmitted = false;
109069
109069
  function establishWebSocketConnection(url2, protocols, client, handler2, options2) {
109070
109070
  const requestURL = url2;
@@ -109084,7 +109084,7 @@ var require_connection = __commonJS({
109084
109084
  const headersList = getHeadersList(new Headers(options2.headers));
109085
109085
  request.headersList = headersList;
109086
109086
  }
109087
- const keyValue = crypto.randomBytes(16).toString("base64");
109087
+ const keyValue = crypto2.randomBytes(16).toString("base64");
109088
109088
  request.headersList.append("sec-websocket-key", keyValue, true);
109089
109089
  request.headersList.append("sec-websocket-version", "13", true);
109090
109090
  for (const protocol of protocols) {
@@ -109124,7 +109124,7 @@ var require_connection = __commonJS({
109124
109124
  return;
109125
109125
  }
109126
109126
  const secWSAccept = response.headersList.get("Sec-WebSocket-Accept");
109127
- const digest = crypto.hash("sha1", keyValue + uid, "base64");
109127
+ const digest = crypto2.hash("sha1", keyValue + uid, "base64");
109128
109128
  if (secWSAccept !== digest) {
109129
109129
  failWebsocketConnection(handler2, 1002, "Incorrect hash received in Sec-WebSocket-Accept header.");
109130
109130
  return;
@@ -111177,11 +111177,11 @@ var require_undici = __commonJS({
111177
111177
  if (typeof opts.path !== "string") {
111178
111178
  throw new InvalidArgumentError("invalid opts.path");
111179
111179
  }
111180
- let path3 = opts.path;
111180
+ let path7 = opts.path;
111181
111181
  if (!opts.path.startsWith("/")) {
111182
- path3 = `/${path3}`;
111182
+ path7 = `/${path7}`;
111183
111183
  }
111184
- url2 = new URL(util2.parseOrigin(url2).origin + path3);
111184
+ url2 = new URL(util2.parseOrigin(url2).origin + path7);
111185
111185
  } else {
111186
111186
  if (!opts) {
111187
111187
  opts = typeof url2 === "object" ? url2 : {};
@@ -112065,10 +112065,10 @@ function mergeDefs(...defs) {
112065
112065
  function cloneDef(schema) {
112066
112066
  return mergeDefs(schema._zod.def);
112067
112067
  }
112068
- function getElementAtPath(obj, path3) {
112069
- if (!path3)
112068
+ function getElementAtPath(obj, path7) {
112069
+ if (!path7)
112070
112070
  return obj;
112071
- return path3.reduce((acc, key) => acc?.[key], obj);
112071
+ return path7.reduce((acc, key) => acc?.[key], obj);
112072
112072
  }
112073
112073
  function promiseAllObject(promisesObj) {
112074
112074
  const keys = Object.keys(promisesObj);
@@ -112451,11 +112451,11 @@ function aborted(x, startIndex = 0) {
112451
112451
  }
112452
112452
  return false;
112453
112453
  }
112454
- function prefixIssues(path3, issues) {
112454
+ function prefixIssues(path7, issues) {
112455
112455
  return issues.map((iss) => {
112456
112456
  var _a2;
112457
112457
  (_a2 = iss).path ?? (_a2.path = []);
112458
- iss.path.unshift(path3);
112458
+ iss.path.unshift(path7);
112459
112459
  return iss;
112460
112460
  });
112461
112461
  }
@@ -112638,7 +112638,7 @@ function formatError(error48, mapper = (issue2) => issue2.message) {
112638
112638
  }
112639
112639
  function treeifyError(error48, mapper = (issue2) => issue2.message) {
112640
112640
  const result = { errors: [] };
112641
- const processError = (error49, path3 = []) => {
112641
+ const processError = (error49, path7 = []) => {
112642
112642
  var _a2, _b;
112643
112643
  for (const issue2 of error49.issues) {
112644
112644
  if (issue2.code === "invalid_union" && issue2.errors.length) {
@@ -112648,7 +112648,7 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
112648
112648
  } else if (issue2.code === "invalid_element") {
112649
112649
  processError({ issues: issue2.issues }, issue2.path);
112650
112650
  } else {
112651
- const fullpath = [...path3, ...issue2.path];
112651
+ const fullpath = [...path7, ...issue2.path];
112652
112652
  if (fullpath.length === 0) {
112653
112653
  result.errors.push(mapper(issue2));
112654
112654
  continue;
@@ -112680,8 +112680,8 @@ function treeifyError(error48, mapper = (issue2) => issue2.message) {
112680
112680
  }
112681
112681
  function toDotPath(_path) {
112682
112682
  const segs = [];
112683
- const path3 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
112684
- for (const seg of path3) {
112683
+ const path7 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
112684
+ for (const seg of path7) {
112685
112685
  if (typeof seg === "number")
112686
112686
  segs.push(`[${seg}]`);
112687
112687
  else if (typeof seg === "symbol")
@@ -124658,13 +124658,13 @@ function resolveRef(ref, ctx) {
124658
124658
  if (!ref.startsWith("#")) {
124659
124659
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
124660
124660
  }
124661
- const path3 = ref.slice(1).split("/").filter(Boolean);
124662
- if (path3.length === 0) {
124661
+ const path7 = ref.slice(1).split("/").filter(Boolean);
124662
+ if (path7.length === 0) {
124663
124663
  return ctx.rootSchema;
124664
124664
  }
124665
124665
  const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
124666
- if (path3[0] === defsKey) {
124667
- const key = path3[1];
124666
+ if (path7[0] === defsKey) {
124667
+ const key = path7[1];
124668
124668
  if (!key || !ctx.defs[key]) {
124669
124669
  throw new Error(`Reference not found: ${ref}`);
124670
124670
  }
@@ -125504,26 +125504,26 @@ function applyReplacer(root, replacer) {
125504
125504
  if (replacedRoot === void 0) return transformChildren(root, replacer, []);
125505
125505
  return transformChildren(normalizeValue(replacedRoot), replacer, []);
125506
125506
  }
125507
- function transformChildren(value2, replacer, path3) {
125508
- if (isJsonObject(value2)) return transformObject(value2, replacer, path3);
125509
- if (isJsonArray(value2)) return transformArray(value2, replacer, path3);
125507
+ function transformChildren(value2, replacer, path7) {
125508
+ if (isJsonObject(value2)) return transformObject(value2, replacer, path7);
125509
+ if (isJsonArray(value2)) return transformArray(value2, replacer, path7);
125510
125510
  return value2;
125511
125511
  }
125512
- function transformObject(obj, replacer, path3) {
125512
+ function transformObject(obj, replacer, path7) {
125513
125513
  const result = {};
125514
125514
  for (const [key, value2] of Object.entries(obj)) {
125515
- const childPath = [...path3, key];
125515
+ const childPath = [...path7, key];
125516
125516
  const replacedValue = replacer(key, value2, childPath);
125517
125517
  if (replacedValue === void 0) continue;
125518
125518
  result[key] = transformChildren(normalizeValue(replacedValue), replacer, childPath);
125519
125519
  }
125520
125520
  return result;
125521
125521
  }
125522
- function transformArray(arr, replacer, path3) {
125522
+ function transformArray(arr, replacer, path7) {
125523
125523
  const result = [];
125524
125524
  for (let i2 = 0; i2 < arr.length; i2++) {
125525
125525
  const value2 = arr[i2];
125526
- const childPath = [...path3, i2];
125526
+ const childPath = [...path7, i2];
125527
125527
  const replacedValue = replacer(String(i2), value2, childPath);
125528
125528
  if (replacedValue === void 0) continue;
125529
125529
  const normalizedValue = normalizeValue(replacedValue);
@@ -125591,33 +125591,33 @@ function columnarTable(items) {
125591
125591
  const keys = [...new Set(items.flatMap(Object.keys))];
125592
125592
  return table(keys, items.map((item) => keys.map((k) => String(item[k] ?? ""))));
125593
125593
  }
125594
- function formatMarkdown(value2, path3 = []) {
125594
+ function formatMarkdown(value2, path7 = []) {
125595
125595
  if (isScalar(value2)) {
125596
- if (path3.length === 0)
125596
+ if (path7.length === 0)
125597
125597
  return String(value2);
125598
- return `## ${path3.join(".")}
125598
+ return `## ${path7.join(".")}
125599
125599
 
125600
125600
  ${String(value2)}`;
125601
125601
  }
125602
125602
  if (Array.isArray(value2)) {
125603
125603
  if (isArrayOfObjects2(value2)) {
125604
125604
  const table2 = columnarTable(value2);
125605
- if (path3.length === 0)
125605
+ if (path7.length === 0)
125606
125606
  return table2;
125607
- return `## ${path3.join(".")}
125607
+ return `## ${path7.join(".")}
125608
125608
 
125609
125609
  ${table2}`;
125610
125610
  }
125611
- return formatMarkdown(String(value2), path3);
125611
+ return formatMarkdown(String(value2), path7);
125612
125612
  }
125613
125613
  const obj = value2;
125614
125614
  const entries = Object.entries(obj);
125615
- if (path3.length === 0 && isFlat(obj))
125615
+ if (path7.length === 0 && isFlat(obj))
125616
125616
  return kvTable(obj);
125617
- const needsHeadings = path3.length > 0 || entries.length > 1 || entries.some(([, v]) => !isScalar(v));
125617
+ const needsHeadings = path7.length > 0 || entries.length > 1 || entries.some(([, v]) => !isScalar(v));
125618
125618
  if (needsHeadings) {
125619
125619
  const sections = entries.map(([key, val]) => {
125620
- const childPath = [...path3, key];
125620
+ const childPath = [...path7, key];
125621
125621
  if (isScalar(val))
125622
125622
  return `## ${childPath.join(".")}
125623
125623
 
@@ -126231,8 +126231,8 @@ function getErrorMap2() {
126231
126231
 
126232
126232
  // ../../node_modules/.pnpm/zod@4.3.6/node_modules/zod/v3/helpers/parseUtil.js
126233
126233
  var makeIssue = (params) => {
126234
- const { data, path: path3, errorMaps, issueData } = params;
126235
- const fullPath = [...path3, ...issueData.path || []];
126234
+ const { data, path: path7, errorMaps, issueData } = params;
126235
+ const fullPath = [...path7, ...issueData.path || []];
126236
126236
  const fullIssue = {
126237
126237
  ...issueData,
126238
126238
  path: fullPath
@@ -126347,11 +126347,11 @@ var errorUtil;
126347
126347
 
126348
126348
  // ../../node_modules/.pnpm/zod@4.3.6/node_modules/zod/v3/types.js
126349
126349
  var ParseInputLazyPath = class {
126350
- constructor(parent, value2, path3, key) {
126350
+ constructor(parent, value2, path7, key) {
126351
126351
  this._cachedPath = [];
126352
126352
  this.parent = parent;
126353
126353
  this.data = value2;
126354
- this._path = path3;
126354
+ this._path = path7;
126355
126355
  this._key = key;
126356
126356
  }
126357
126357
  get path() {
@@ -135486,12 +135486,12 @@ function isAsyncGenerator(value2) {
135486
135486
  function collectTools(commands, prefix) {
135487
135487
  const result = [];
135488
135488
  for (const [name2, entry] of commands) {
135489
- const path3 = [...prefix, name2];
135489
+ const path7 = [...prefix, name2];
135490
135490
  if ("_group" in entry && entry._group)
135491
- result.push(...collectTools(entry.commands, path3));
135491
+ result.push(...collectTools(entry.commands, path7));
135492
135492
  else {
135493
135493
  result.push({
135494
- name: path3.join("_"),
135494
+ name: path7.join("_"),
135495
135495
  description: entry.description,
135496
135496
  inputSchema: buildToolSchema(entry.args, entry.options),
135497
135497
  command: entry
@@ -136636,7 +136636,7 @@ async function serveImpl(name2, commands, argv, options2 = {}) {
136636
136636
  exit2(1);
136637
136637
  return;
136638
136638
  }
136639
- const { command, path: path3, rest } = effective;
136639
+ const { command, path: path7, rest } = effective;
136640
136640
  try {
136641
136641
  const { args: args2, options: parsedOptions } = parse3(rest, {
136642
136642
  alias: command.alias,
@@ -136662,7 +136662,7 @@ async function serveImpl(name2, commands, argv, options2 = {}) {
136662
136662
  if (isAsyncGenerator2(result)) {
136663
136663
  await handleStreaming(result, {
136664
136664
  name: name2,
136665
- path: path3,
136665
+ path: path7,
136666
136666
  start: start2,
136667
136667
  format: format2,
136668
136668
  formatExplicit,
@@ -136683,7 +136683,7 @@ async function serveImpl(name2, commands, argv, options2 = {}) {
136683
136683
  ok: true,
136684
136684
  data: awaited.data,
136685
136685
  meta: {
136686
- command: path3,
136686
+ command: path7,
136687
136687
  duration: `${Math.round(performance.now() - start2)}ms`,
136688
136688
  ...cta ? { cta } : void 0
136689
136689
  }
@@ -136697,7 +136697,7 @@ async function serveImpl(name2, commands, argv, options2 = {}) {
136697
136697
  ...awaited.retryable !== void 0 ? { retryable: awaited.retryable } : void 0
136698
136698
  },
136699
136699
  meta: {
136700
- command: path3,
136700
+ command: path7,
136701
136701
  duration: `${Math.round(performance.now() - start2)}ms`,
136702
136702
  ...cta ? { cta } : void 0
136703
136703
  }
@@ -136709,7 +136709,7 @@ async function serveImpl(name2, commands, argv, options2 = {}) {
136709
136709
  ok: true,
136710
136710
  data: awaited,
136711
136711
  meta: {
136712
- command: path3,
136712
+ command: path7,
136713
136713
  duration: `${Math.round(performance.now() - start2)}ms`
136714
136714
  }
136715
136715
  });
@@ -136724,12 +136724,12 @@ async function serveImpl(name2, commands, argv, options2 = {}) {
136724
136724
  ...error48 instanceof ValidationError ? { fieldErrors: error48.fieldErrors } : void 0
136725
136725
  },
136726
136726
  meta: {
136727
- command: path3,
136727
+ command: path7,
136728
136728
  duration: `${Math.round(performance.now() - start2)}ms`
136729
136729
  }
136730
136730
  };
136731
136731
  if (human && !formatExplicit && error48 instanceof ValidationError) {
136732
- writeln(formatHumanValidationError(name2, path3, command, error48));
136732
+ writeln(formatHumanValidationError(name2, path7, command, error48));
136733
136733
  exit2(1);
136734
136734
  return;
136735
136735
  }
@@ -136737,13 +136737,13 @@ async function serveImpl(name2, commands, argv, options2 = {}) {
136737
136737
  exit2(1);
136738
136738
  }
136739
136739
  }
136740
- function formatHumanValidationError(cli2, path3, command, error48) {
136740
+ function formatHumanValidationError(cli2, path7, command, error48) {
136741
136741
  const lines = [];
136742
136742
  for (const fe of error48.fieldErrors)
136743
136743
  lines.push(`Error: missing required argument <${fe.path}>`);
136744
136744
  lines.push("See below for usage.");
136745
136745
  lines.push("");
136746
- lines.push(formatCommand(path3 === cli2 ? cli2 : `${cli2} ${path3}`, {
136746
+ lines.push(formatCommand(path7 === cli2 ? cli2 : `${cli2} ${path7}`, {
136747
136747
  alias: command.alias,
136748
136748
  description: command.description,
136749
136749
  args: command.args,
@@ -136760,7 +136760,7 @@ function resolveCommand(commands, tokens) {
136760
136760
  if (!first || !commands.has(first))
136761
136761
  return { error: first ?? "(none)", path: "" };
136762
136762
  let entry = commands.get(first);
136763
- const path3 = [first];
136763
+ const path7 = [first];
136764
136764
  let remaining = rest;
136765
136765
  let inheritedOutputPolicy;
136766
136766
  while (isGroup(entry)) {
@@ -136770,22 +136770,22 @@ function resolveCommand(commands, tokens) {
136770
136770
  if (!next)
136771
136771
  return {
136772
136772
  help: true,
136773
- path: path3.join(" "),
136773
+ path: path7.join(" "),
136774
136774
  description: entry.description,
136775
136775
  commands: entry.commands
136776
136776
  };
136777
136777
  const child = entry.commands.get(next);
136778
136778
  if (!child) {
136779
- return { error: next, path: path3.join(" ") };
136779
+ return { error: next, path: path7.join(" ") };
136780
136780
  }
136781
- path3.push(next);
136781
+ path7.push(next);
136782
136782
  remaining = remaining.slice(1);
136783
136783
  entry = child;
136784
136784
  }
136785
136785
  const outputPolicy = entry.outputPolicy ?? inheritedOutputPolicy;
136786
136786
  return {
136787
136787
  command: entry,
136788
- path: path3.join(" "),
136788
+ path: path7.join(" "),
136789
136789
  rest: remaining,
136790
136790
  ...outputPolicy ? { outputPolicy } : void 0
136791
136791
  };
@@ -137050,11 +137050,11 @@ function buildManifest(commands, prefix = []) {
137050
137050
  function collectCommands(commands, prefix) {
137051
137051
  const result = [];
137052
137052
  for (const [name2, entry] of commands) {
137053
- const path3 = [...prefix, name2];
137053
+ const path7 = [...prefix, name2];
137054
137054
  if (isGroup(entry)) {
137055
- result.push(...collectCommands(entry.commands, path3));
137055
+ result.push(...collectCommands(entry.commands, path7));
137056
137056
  } else {
137057
- const cmd = { name: path3.join(" ") };
137057
+ const cmd = { name: path7.join(" ") };
137058
137058
  if (entry.description)
137059
137059
  cmd.description = entry.description;
137060
137060
  const inputSchema = buildInputSchema(entry.args, entry.env, entry.options);
@@ -137072,7 +137072,7 @@ function collectCommands(commands, prefix) {
137072
137072
  }
137073
137073
  const examples = formatExamples(entry.examples);
137074
137074
  if (examples) {
137075
- const cmdName = path3.join(" ");
137075
+ const cmdName = path7.join(" ");
137076
137076
  cmd.examples = examples.map((e) => ({
137077
137077
  ...e,
137078
137078
  command: e.command ? `${cmdName} ${e.command}` : cmdName
@@ -137086,13 +137086,13 @@ function collectCommands(commands, prefix) {
137086
137086
  function collectSkillCommands(commands, prefix, groups) {
137087
137087
  const result = [];
137088
137088
  for (const [name2, entry] of commands) {
137089
- const path3 = [...prefix, name2];
137089
+ const path7 = [...prefix, name2];
137090
137090
  if (isGroup(entry)) {
137091
137091
  if (entry.description)
137092
- groups.set(path3.join(" "), entry.description);
137093
- result.push(...collectSkillCommands(entry.commands, path3, groups));
137092
+ groups.set(path7.join(" "), entry.description);
137093
+ result.push(...collectSkillCommands(entry.commands, path7, groups));
137094
137094
  } else {
137095
- const cmd = { name: path3.join(" ") };
137095
+ const cmd = { name: path7.join(" ") };
137096
137096
  if (entry.description)
137097
137097
  cmd.description = entry.description;
137098
137098
  if (entry.args)
@@ -137107,7 +137107,7 @@ function collectSkillCommands(commands, prefix, groups) {
137107
137107
  cmd.output = entry.output;
137108
137108
  const examples = formatExamples(entry.examples);
137109
137109
  if (examples) {
137110
- const cmdName = path3.join(" ");
137110
+ const cmdName = path7.join(" ");
137111
137111
  cmd.examples = examples.map((e) => ({
137112
137112
  ...e,
137113
137113
  command: e.command ? `${cmdName} ${e.command}` : cmdName
@@ -137151,7 +137151,7 @@ function buildInputSchema(args2, env2, options2) {
137151
137151
  // package.json
137152
137152
  var package_default = {
137153
137153
  name: "@docyrus/docyrus",
137154
- version: "0.0.40",
137154
+ version: "0.0.41",
137155
137155
  private: false,
137156
137156
  description: "Docyrus API CLI",
137157
137157
  main: "./main.js",
@@ -137396,7 +137396,7 @@ function createActionCli(dependencies) {
137396
137396
  const apiClient = dependencies.createApiClient(apiBaseUrl);
137397
137397
  const { appSlug, actionKey } = context.args;
137398
137398
  const body2 = context.options.params ? parseJsonParams(context.options.params) : {};
137399
- const path3 = `/v1/apps/${encodeURIComponent(appSlug)}/actions/${encodeURIComponent(actionKey)}/run`;
137399
+ const path7 = `/v1/apps/${encodeURIComponent(appSlug)}/actions/${encodeURIComponent(actionKey)}/run`;
137400
137400
  const headers = {};
137401
137401
  if (context.options.connectionId) {
137402
137402
  headers["x-connection-id"] = context.options.connectionId;
@@ -137411,7 +137411,7 @@ function createActionCli(dependencies) {
137411
137411
  payload: {
137412
137412
  dryRun: true,
137413
137413
  method: "POST",
137414
- path: path3,
137414
+ path: path7,
137415
137415
  headers: Object.keys(headers).length > 0 ? headers : void 0,
137416
137416
  body: body2
137417
137417
  }
@@ -137419,7 +137419,7 @@ function createActionCli(dependencies) {
137419
137419
  }
137420
137420
  const response = await apiClient.request({
137421
137421
  method: "POST",
137422
- path: path3,
137422
+ path: path7,
137423
137423
  headers: Object.keys(headers).length > 0 ? headers : void 0,
137424
137424
  body: body2
137425
137425
  });
@@ -137641,10 +137641,10 @@ function createAiCli(dependencies) {
137641
137641
  const deploymentId = context.options.deploymentId?.trim() || void 0;
137642
137642
  const apiBaseUrl = await dependencies.environmentConfigService.getActiveApiBaseUrl();
137643
137643
  const apiClient = dependencies.createApiClient(apiBaseUrl);
137644
- const path3 = deploymentId ? `/ai/agents/${agentId}/deployments/${deploymentId}/chat` : `/ai/agents/${agentId}/chat`;
137644
+ const path7 = deploymentId ? `/ai/agents/${agentId}/deployments/${deploymentId}/chat` : `/ai/agents/${agentId}/chat`;
137645
137645
  const response = await apiClient.request({
137646
137646
  method: "POST",
137647
- path: path3,
137647
+ path: path7,
137648
137648
  body: {
137649
137649
  messages: [
137650
137650
  {
@@ -138624,7 +138624,7 @@ async function readDataInput(params) {
138624
138624
  data,
138625
138625
  fromFile,
138626
138626
  readStdin: readStdin2 = readStdinText,
138627
- readFileFn = async (path3, encoding) => await (0, import_promises2.readFile)(path3, encoding)
138627
+ readFileFn = async (path7, encoding) => await (0, import_promises2.readFile)(path7, encoding)
138628
138628
  } = params;
138629
138629
  const trimmedData = data?.trim();
138630
138630
  const trimmedFromFile = fromFile?.trim();
@@ -139321,8 +139321,8 @@ function getEntities(document4) {
139321
139321
  }
139322
139322
  function extractNamespaces(paths) {
139323
139323
  const namespaces = /* @__PURE__ */ new Set();
139324
- for (const path3 of Object.keys(paths)) {
139325
- const segments = path3.split("/").map((item) => item.trim()).filter((item) => item.length > 0);
139324
+ for (const path7 of Object.keys(paths)) {
139325
+ const segments = path7.split("/").map((item) => item.trim()).filter((item) => item.length > 0);
139326
139326
  if (segments.length === 0) {
139327
139327
  continue;
139328
139328
  }
@@ -139344,8 +139344,8 @@ function getPathOperation(pathItem, method) {
139344
139344
  function toEndpointMethodEntries(paths, pathFilter) {
139345
139345
  const entries = [];
139346
139346
  const sortedPaths = Object.keys(paths).filter(pathFilter).sort((left, right) => left.localeCompare(right));
139347
- for (const path3 of sortedPaths) {
139348
- const pathItem = paths[path3];
139347
+ for (const path7 of sortedPaths) {
139348
+ const pathItem = paths[path7];
139349
139349
  if (!isRecord2(pathItem)) {
139350
139350
  continue;
139351
139351
  }
@@ -139358,7 +139358,7 @@ function toEndpointMethodEntries(paths, pathFilter) {
139358
139358
  const summaryValue = operation.summary;
139359
139359
  const description = typeof descriptionValue === "string" ? descriptionValue : typeof summaryValue === "string" ? summaryValue : void 0;
139360
139360
  entries.push({
139361
- path: toOutputPath(path3),
139361
+ path: toOutputPath(path7),
139362
139362
  method,
139363
139363
  description
139364
139364
  });
@@ -139484,7 +139484,7 @@ function createDiscoverCli(dependencies) {
139484
139484
  const candidates = buildPathCandidates(context.args.prefix);
139485
139485
  const endpoints = toEndpointMethodEntries(
139486
139486
  paths,
139487
- (path3) => candidates.some((candidate) => path3.startsWith(candidate))
139487
+ (path7) => candidates.some((candidate) => path7.startsWith(candidate))
139488
139488
  );
139489
139489
  return await injectContext({
139490
139490
  apiBaseUrl,
@@ -139581,7 +139581,7 @@ function createDiscoverCli(dependencies) {
139581
139581
  const loweredTerm = term.toLowerCase();
139582
139582
  const matchingEndpoints = toEndpointMethodEntries(
139583
139583
  pathMap,
139584
- (path3) => path3.toLowerCase().includes(loweredTerm)
139584
+ (path7) => path7.toLowerCase().includes(loweredTerm)
139585
139585
  );
139586
139586
  const matchingEntities = entityNames.filter((entityName) => entityName.toLowerCase().includes(loweredTerm));
139587
139587
  return {
@@ -139795,8 +139795,8 @@ function createEnvCli(dependencies) {
139795
139795
  }
139796
139796
 
139797
139797
  // src/commands/knowledgeCommands.ts
139798
- var import_node_crypto4 = require("node:crypto");
139799
- var import_node_path18 = require("node:path");
139798
+ var import_node_crypto6 = require("node:crypto");
139799
+ var import_node_path20 = require("node:path");
139800
139800
  init_graph();
139801
139801
 
139802
139802
  // src/knowledge/query.ts
@@ -142100,11 +142100,11 @@ var Module2 = (() => {
142100
142100
  throw toThrow;
142101
142101
  }, "quit_");
142102
142102
  var scriptDirectory = "";
142103
- function locateFile(path3) {
142103
+ function locateFile(path7) {
142104
142104
  if (Module["locateFile"]) {
142105
- return Module["locateFile"](path3, scriptDirectory);
142105
+ return Module["locateFile"](path7, scriptDirectory);
142106
142106
  }
142107
- return scriptDirectory + path3;
142107
+ return scriptDirectory + path7;
142108
142108
  }
142109
142109
  __name(locateFile, "locateFile");
142110
142110
  var readAsync, readBinary;
@@ -144019,6 +144019,9 @@ function extractName(node2) {
144019
144019
  const nameNode = node2.childForFieldName("name");
144020
144020
  return nameNode ? nameNode.text : null;
144021
144021
  }
144022
+ function isSyntaxNode(node2) {
144023
+ return node2 !== null;
144024
+ }
144022
144025
  function firstLine(text3) {
144023
144026
  const newLineIndex = text3.indexOf("\n");
144024
144027
  return newLineIndex === -1 ? text3 : text3.slice(0, newLineIndex);
@@ -144052,7 +144055,7 @@ function extractTsSymbols(tree) {
144052
144055
  continue;
144053
144056
  }
144054
144057
  if (node2.type === "export_statement") {
144055
- node2 = node2.namedChildren.find((child) => child.type === "function_declaration" || child.type === "generator_function_declaration" || child.type === "class_declaration" || child.type === "abstract_class_declaration" || child.type === "lexical_declaration" || child.type === "type_alias_declaration" || child.type === "interface_declaration") || node2;
144058
+ node2 = node2.namedChildren.find((child) => isSyntaxNode(child) && (child.type === "function_declaration" || child.type === "generator_function_declaration" || child.type === "class_declaration" || child.type === "abstract_class_declaration" || child.type === "lexical_declaration" || child.type === "type_alias_declaration" || child.type === "interface_declaration")) || node2;
144056
144059
  }
144057
144060
  const startLine = node2.startPosition.row + 1;
144058
144061
  const endLine = node2.endPosition.row + 1;
@@ -144088,6 +144091,9 @@ function extractTsSymbols(tree) {
144088
144091
  }
144089
144092
  if (node2.type === "lexical_declaration") {
144090
144093
  for (const declaration of node2.namedChildren) {
144094
+ if (!declaration) {
144095
+ continue;
144096
+ }
144091
144097
  if (declaration.type !== "variable_declarator") {
144092
144098
  continue;
144093
144099
  }
@@ -144464,6 +144470,9 @@ function cFieldName(declarator) {
144464
144470
  }
144465
144471
  function collectFieldsFromList(fieldList, structName, symbols) {
144466
144472
  for (const field of fieldList.namedChildren) {
144473
+ if (!field) {
144474
+ continue;
144475
+ }
144467
144476
  if (field.type !== "field_declaration") {
144468
144477
  continue;
144469
144478
  }
@@ -144483,8 +144492,14 @@ function collectFieldsFromList(fieldList, structName, symbols) {
144483
144492
  continue;
144484
144493
  }
144485
144494
  for (const inner of field.namedChildren) {
144495
+ if (!inner) {
144496
+ continue;
144497
+ }
144486
144498
  if ((inner.type === "union_specifier" || inner.type === "struct_specifier") && !extractName(inner)) {
144487
144499
  for (const nested of inner.namedChildren) {
144500
+ if (!nested) {
144501
+ continue;
144502
+ }
144488
144503
  if (nested.type === "field_declaration_list") {
144489
144504
  collectFieldsFromList(nested, structName, symbols);
144490
144505
  }
@@ -144495,6 +144510,9 @@ function collectFieldsFromList(fieldList, structName, symbols) {
144495
144510
  }
144496
144511
  function collectCStructFields(structNode, structName, symbols) {
144497
144512
  for (const child of structNode.namedChildren) {
144513
+ if (!child) {
144514
+ continue;
144515
+ }
144498
144516
  if (child.type === "field_declaration_list") {
144499
144517
  collectFieldsFromList(child, structName, symbols);
144500
144518
  }
@@ -144502,10 +144520,16 @@ function collectCStructFields(structNode, structName, symbols) {
144502
144520
  }
144503
144521
  function collectCEnumMembers(enumSpecifier, symbols, enumName) {
144504
144522
  for (const child of enumSpecifier.namedChildren) {
144523
+ if (!child) {
144524
+ continue;
144525
+ }
144505
144526
  if (child.type !== "enumerator_list") {
144506
144527
  continue;
144507
144528
  }
144508
144529
  for (const enumerator of child.namedChildren) {
144530
+ if (!enumerator) {
144531
+ continue;
144532
+ }
144509
144533
  if (enumerator.type !== "enumerator") {
144510
144534
  continue;
144511
144535
  }
@@ -144571,6 +144595,9 @@ function collectCNodes(parent, symbols) {
144571
144595
  symbols.push({ name: name2, kind: "type", startLine, endLine, signature: firstLine(node2.text) });
144572
144596
  }
144573
144597
  for (const child of node2.namedChildren) {
144598
+ if (!child) {
144599
+ continue;
144600
+ }
144574
144601
  if (child.type === "enum_specifier") {
144575
144602
  collectCEnumMembers(child, symbols, name2 || extractName(child) || void 0);
144576
144603
  } else if (child.type === "struct_specifier" && name2) {
@@ -145550,9 +145577,9 @@ function shouldUseKnowledgeColors() {
145550
145577
  }
145551
145578
 
145552
145579
  // src/knowledge/init.ts
145553
- var import_node_fs8 = require("node:fs");
145554
- var import_promises12 = require("node:fs/promises");
145555
- var import_node_path16 = require("node:path");
145580
+ var import_node_fs10 = require("node:fs");
145581
+ var import_promises14 = require("node:fs/promises");
145582
+ var import_node_path18 = require("node:path");
145556
145583
  init_graph();
145557
145584
 
145558
145585
  // src/knowledge/bootstrap.ts
@@ -145964,6 +145991,754 @@ async function generateInitialKnowledge(params) {
145964
145991
  };
145965
145992
  }
145966
145993
 
145994
+ // src/project-plan/graph.ts
145995
+ var import_node_crypto5 = require("node:crypto");
145996
+ var import_node_fs9 = require("node:fs");
145997
+ var import_promises13 = __toESM(require("node:fs/promises"));
145998
+ var import_node_path17 = __toESM(require("node:path"));
145999
+ init_graph();
146000
+
146001
+ // src/project-plan/localTodos.ts
146002
+ var import_node_crypto4 = __toESM(require("node:crypto"));
146003
+ var import_node_fs8 = require("node:fs");
146004
+ var import_promises12 = __toESM(require("node:fs/promises"));
146005
+ var import_node_path16 = __toESM(require("node:path"));
146006
+ var TODO_DIR_NAME = ".pi/todos";
146007
+ var TODO_PATH_ENV = "PI_TODO_PATH";
146008
+ function resolveTodosDirectory(root) {
146009
+ const overridePath = process.env[TODO_PATH_ENV]?.trim();
146010
+ if (overridePath) {
146011
+ return import_node_path16.default.resolve(root, overridePath);
146012
+ }
146013
+ return import_node_path16.default.resolve(root, TODO_DIR_NAME);
146014
+ }
146015
+ function getTodoFilePath(todosDir, id) {
146016
+ return import_node_path16.default.join(todosDir, `${id}.md`);
146017
+ }
146018
+ function splitFrontMatter(content3) {
146019
+ if (!content3.startsWith("{")) {
146020
+ return {
146021
+ frontMatter: "",
146022
+ body: content3
146023
+ };
146024
+ }
146025
+ let depth = 0;
146026
+ let inString = false;
146027
+ let escaped = false;
146028
+ let endIndex = -1;
146029
+ for (let index2 = 0; index2 < content3.length; index2 += 1) {
146030
+ const char = content3[index2];
146031
+ if (inString) {
146032
+ if (escaped) {
146033
+ escaped = false;
146034
+ continue;
146035
+ }
146036
+ if (char === "\\") {
146037
+ escaped = true;
146038
+ continue;
146039
+ }
146040
+ if (char === '"') {
146041
+ inString = false;
146042
+ }
146043
+ continue;
146044
+ }
146045
+ if (char === '"') {
146046
+ inString = true;
146047
+ continue;
146048
+ }
146049
+ if (char === "{") {
146050
+ depth += 1;
146051
+ continue;
146052
+ }
146053
+ if (char === "}") {
146054
+ depth -= 1;
146055
+ if (depth === 0) {
146056
+ endIndex = index2;
146057
+ break;
146058
+ }
146059
+ }
146060
+ }
146061
+ if (endIndex === -1) {
146062
+ return {
146063
+ frontMatter: "",
146064
+ body: content3
146065
+ };
146066
+ }
146067
+ return {
146068
+ frontMatter: content3.slice(0, endIndex + 1),
146069
+ body: content3.slice(endIndex + 1).replace(/^\r?\n+/u, "")
146070
+ };
146071
+ }
146072
+ function parseLocalTodoFrontMatter(frontMatter, idFallback) {
146073
+ const base = {
146074
+ id: idFallback,
146075
+ title: "",
146076
+ tags: [],
146077
+ status: "open",
146078
+ created_at: ""
146079
+ };
146080
+ if (!frontMatter.trim()) {
146081
+ return base;
146082
+ }
146083
+ try {
146084
+ const parsed = JSON.parse(frontMatter);
146085
+ return {
146086
+ id: typeof parsed.id === "string" && parsed.id.trim() ? parsed.id.trim() : idFallback,
146087
+ title: typeof parsed.title === "string" ? parsed.title : "",
146088
+ tags: Array.isArray(parsed.tags) ? parsed.tags.filter((value2) => typeof value2 === "string") : [],
146089
+ status: typeof parsed.status === "string" && parsed.status.trim() ? parsed.status.trim() : "open",
146090
+ created_at: typeof parsed.created_at === "string" ? parsed.created_at : "",
146091
+ assigned_to_session: typeof parsed.assigned_to_session === "string" && parsed.assigned_to_session.trim() ? parsed.assigned_to_session.trim() : void 0,
146092
+ parent_task_id: typeof parsed.parent_task_id === "string" && parsed.parent_task_id.trim() ? parsed.parent_task_id.trim() : void 0
146093
+ };
146094
+ } catch {
146095
+ return base;
146096
+ }
146097
+ }
146098
+ function serializeLocalTodo(record2) {
146099
+ const frontMatter = JSON.stringify(
146100
+ {
146101
+ id: record2.id,
146102
+ title: record2.title,
146103
+ tags: record2.tags,
146104
+ status: record2.status,
146105
+ created_at: record2.created_at,
146106
+ assigned_to_session: record2.assigned_to_session || void 0,
146107
+ parent_task_id: record2.parent_task_id || void 0
146108
+ },
146109
+ null,
146110
+ 2
146111
+ );
146112
+ const trimmedBody = record2.body.trim();
146113
+ return trimmedBody ? `${frontMatter}
146114
+
146115
+ ${trimmedBody}
146116
+ ` : `${frontMatter}
146117
+ `;
146118
+ }
146119
+ async function generateTodoId(todosDir) {
146120
+ for (let attempt = 0; attempt < 10; attempt += 1) {
146121
+ const id = import_node_crypto4.default.randomBytes(4).toString("hex");
146122
+ if (!(0, import_node_fs8.existsSync)(getTodoFilePath(todosDir, id))) {
146123
+ return id;
146124
+ }
146125
+ }
146126
+ throw new Error("Failed to generate linked todo id.");
146127
+ }
146128
+ async function listLinkedTodosByTask(root) {
146129
+ const todosDir = resolveTodosDirectory(root);
146130
+ const result = /* @__PURE__ */ new Map();
146131
+ let entries = [];
146132
+ try {
146133
+ entries = await import_promises12.default.readdir(todosDir);
146134
+ } catch {
146135
+ return result;
146136
+ }
146137
+ for (const entry of entries) {
146138
+ if (!entry.endsWith(".md")) {
146139
+ continue;
146140
+ }
146141
+ const id = entry.slice(0, -3);
146142
+ const filePath = getTodoFilePath(todosDir, id);
146143
+ try {
146144
+ const raw = await import_promises12.default.readFile(filePath, "utf8");
146145
+ const { frontMatter } = splitFrontMatter(raw);
146146
+ const parsed = parseLocalTodoFrontMatter(frontMatter, id);
146147
+ if (!parsed.parent_task_id) {
146148
+ continue;
146149
+ }
146150
+ const existing = result.get(parsed.parent_task_id) || [];
146151
+ existing.push({
146152
+ id,
146153
+ title: parsed.title,
146154
+ status: parsed.status,
146155
+ filePath: import_node_path16.default.relative(root, filePath),
146156
+ parentTaskId: parsed.parent_task_id
146157
+ });
146158
+ result.set(parsed.parent_task_id, existing);
146159
+ } catch {
146160
+ }
146161
+ }
146162
+ for (const linkedTodos of result.values()) {
146163
+ linkedTodos.sort((left, right) => left.title.localeCompare(right.title) || left.id.localeCompare(right.id));
146164
+ }
146165
+ return result;
146166
+ }
146167
+ async function createLinkedTodo(params) {
146168
+ const todosDir = resolveTodosDirectory(params.root);
146169
+ await import_promises12.default.mkdir(todosDir, {
146170
+ recursive: true
146171
+ });
146172
+ const id = await generateTodoId(todosDir);
146173
+ const filePath = getTodoFilePath(todosDir, id);
146174
+ const todo = {
146175
+ id,
146176
+ title: params.title,
146177
+ tags: [],
146178
+ status: "open",
146179
+ created_at: (/* @__PURE__ */ new Date()).toISOString(),
146180
+ parent_task_id: params.parentTaskId,
146181
+ body: params.body ?? ""
146182
+ };
146183
+ await import_promises12.default.writeFile(filePath, serializeLocalTodo(todo), "utf8");
146184
+ return {
146185
+ id,
146186
+ title: todo.title,
146187
+ status: todo.status,
146188
+ filePath: import_node_path16.default.relative(params.root, filePath),
146189
+ parentTaskId: params.parentTaskId
146190
+ };
146191
+ }
146192
+
146193
+ // src/project-plan/types.ts
146194
+ var PROJECT_TASK_TYPES = [
146195
+ "bug-fix",
146196
+ "new-implementation",
146197
+ "api-test",
146198
+ "browser-automation-test",
146199
+ "work"
146200
+ ];
146201
+ var PROJECT_TASK_ASSIGNEES = [
146202
+ "agent",
146203
+ "user"
146204
+ ];
146205
+ var PROJECT_TASK_STATUSES = [
146206
+ "planned",
146207
+ "in_progress",
146208
+ "blocked",
146209
+ "done"
146210
+ ];
146211
+
146212
+ // src/project-plan/graph.ts
146213
+ var PROJECT_PLAN_DIR_SEGMENTS = ["docyrus", "project-plan"];
146214
+ var PROJECT_PLAN_JSON_FILE_NAME = "project-plan.json";
146215
+ var PROJECT_PLAN_MARKDOWN_FILE_NAME = "PROJECT_PLAN.md";
146216
+ var DEFAULT_ROUTE_TARGETS = {
146217
+ features: {
146218
+ heading: "Features",
146219
+ filePathSuffix: "docyrus/knowledge/features/features.md"
146220
+ },
146221
+ testing: {
146222
+ heading: "Testing",
146223
+ filePathSuffix: "docyrus/knowledge/testing/testing.md"
146224
+ },
146225
+ architecture: {
146226
+ heading: "Architecture",
146227
+ filePathSuffix: "docyrus/knowledge/architecture/architecture.md"
146228
+ },
146229
+ workflows: {
146230
+ heading: "Workflows",
146231
+ filePathSuffix: "docyrus/knowledge/workflows/workflows.md"
146232
+ }
146233
+ };
146234
+ function isRecord3(value2) {
146235
+ return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
146236
+ }
146237
+ function isNonEmptyString(value2) {
146238
+ return typeof value2 === "string" && value2.trim().length > 0;
146239
+ }
146240
+ function normalizeStringArray(value2) {
146241
+ if (!Array.isArray(value2)) {
146242
+ return [];
146243
+ }
146244
+ return value2.filter((item) => typeof item === "string").map((item) => item.trim()).filter(Boolean);
146245
+ }
146246
+ function slugify2(value2) {
146247
+ const slug = value2.toLowerCase().replace(/[^a-z0-9]+/gu, "-").replace(/^-+|-+$/gu, "").slice(0, 80);
146248
+ return slug || "item";
146249
+ }
146250
+ function hashParts(parts2) {
146251
+ return (0, import_node_crypto5.createHash)("sha1").update(parts2.join("::")).digest("hex").slice(0, 12);
146252
+ }
146253
+ function normalizeFeatureId(sectionId, slug) {
146254
+ return `feature-${hashParts([sectionId, slug])}`;
146255
+ }
146256
+ function normalizeTaskId(featureId, type, title) {
146257
+ return `task-${hashParts([featureId, type, slugify2(title)])}`;
146258
+ }
146259
+ function compareStrings(left, right) {
146260
+ return left.localeCompare(right);
146261
+ }
146262
+ function sortGraph(graph) {
146263
+ return {
146264
+ version: 1,
146265
+ sections: [...graph.sections].sort((left, right) => compareStrings(left.sectionId, right.sectionId)),
146266
+ features: [...graph.features].sort((left, right) => {
146267
+ return compareStrings(left.sectionId, right.sectionId) || compareStrings(left.title, right.title) || compareStrings(left.id, right.id);
146268
+ }),
146269
+ tasks: [...graph.tasks].sort((left, right) => {
146270
+ return compareStrings(left.sectionId, right.sectionId) || compareStrings(left.featureId, right.featureId) || compareStrings(left.title, right.title) || compareStrings(left.id, right.id);
146271
+ })
146272
+ };
146273
+ }
146274
+ function resolveProjectPlanDirectory(root) {
146275
+ return import_node_path17.default.join(root, ...PROJECT_PLAN_DIR_SEGMENTS);
146276
+ }
146277
+ function resolveProjectPlanGraphPath(root) {
146278
+ return import_node_path17.default.join(resolveProjectPlanDirectory(root), PROJECT_PLAN_JSON_FILE_NAME);
146279
+ }
146280
+ function resolveProjectPlanMarkdownPath(root) {
146281
+ return import_node_path17.default.join(resolveProjectPlanDirectory(root), PROJECT_PLAN_MARKDOWN_FILE_NAME);
146282
+ }
146283
+ function createEmptyProjectPlanGraph() {
146284
+ return {
146285
+ version: 1,
146286
+ sections: [],
146287
+ features: [],
146288
+ tasks: []
146289
+ };
146290
+ }
146291
+ async function readKnowledgeSections(root) {
146292
+ const knowledgeDir = import_node_path17.default.join(root, "docyrus", "knowledge");
146293
+ if (!(0, import_node_fs9.existsSync)(knowledgeDir)) {
146294
+ return [];
146295
+ }
146296
+ return flattenSections(await loadAllSections(knowledgeDir));
146297
+ }
146298
+ function parseProjectPlanGraph(rawValue) {
146299
+ if (!isRecord3(rawValue)) {
146300
+ return createEmptyProjectPlanGraph();
146301
+ }
146302
+ const sections = Array.isArray(rawValue.sections) ? rawValue.sections.filter((value2) => isRecord3(value2)).map((value2) => ({
146303
+ sectionId: isNonEmptyString(value2.sectionId) ? value2.sectionId.trim() : ""
146304
+ })).filter((value2) => value2.sectionId.length > 0) : [];
146305
+ const features = Array.isArray(rawValue.features) ? rawValue.features.filter((value2) => isRecord3(value2)).map((value2) => ({
146306
+ id: isNonEmptyString(value2.id) ? value2.id.trim() : "",
146307
+ title: isNonEmptyString(value2.title) ? value2.title.trim() : "",
146308
+ slug: isNonEmptyString(value2.slug) ? value2.slug.trim() : "",
146309
+ summary: typeof value2.summary === "string" ? value2.summary.trim() : "",
146310
+ sectionId: isNonEmptyString(value2.sectionId) ? value2.sectionId.trim() : ""
146311
+ })).filter((value2) => value2.id.length > 0) : [];
146312
+ const tasks = Array.isArray(rawValue.tasks) ? rawValue.tasks.filter((value2) => isRecord3(value2)).map((value2) => ({
146313
+ id: isNonEmptyString(value2.id) ? value2.id.trim() : "",
146314
+ title: isNonEmptyString(value2.title) ? value2.title.trim() : "",
146315
+ summary: typeof value2.summary === "string" ? value2.summary.trim() : "",
146316
+ type: typeof value2.type === "string" ? value2.type : "work",
146317
+ assignee: typeof value2.assignee === "string" ? value2.assignee : "agent",
146318
+ status: typeof value2.status === "string" ? value2.status : "planned",
146319
+ acceptanceCriteria: normalizeStringArray(value2.acceptanceCriteria),
146320
+ featureId: isNonEmptyString(value2.featureId) ? value2.featureId.trim() : "",
146321
+ sectionId: isNonEmptyString(value2.sectionId) ? value2.sectionId.trim() : ""
146322
+ })).filter((value2) => value2.id.length > 0) : [];
146323
+ return sortGraph({
146324
+ version: 1,
146325
+ sections,
146326
+ features,
146327
+ tasks
146328
+ });
146329
+ }
146330
+ async function readProjectPlanGraph(root) {
146331
+ const graphPath = resolveProjectPlanGraphPath(root);
146332
+ if (!(0, import_node_fs9.existsSync)(graphPath)) {
146333
+ return createEmptyProjectPlanGraph();
146334
+ }
146335
+ const raw = await import_promises13.default.readFile(graphPath, "utf8");
146336
+ return parseProjectPlanGraph(JSON.parse(raw));
146337
+ }
146338
+ function deriveFeatureStatus(tasks) {
146339
+ if (tasks.length === 0) {
146340
+ return "planned";
146341
+ }
146342
+ if (tasks.every((task) => task.status === "done")) {
146343
+ return "done";
146344
+ }
146345
+ if (tasks.some((task) => task.status === "in_progress")) {
146346
+ return "in_progress";
146347
+ }
146348
+ if (tasks.some((task) => task.status === "blocked")) {
146349
+ return "blocked";
146350
+ }
146351
+ return "planned";
146352
+ }
146353
+ function deriveSectionStatus(features) {
146354
+ if (features.length === 0) {
146355
+ return "planned";
146356
+ }
146357
+ if (features.every((feature) => feature.status === "done")) {
146358
+ return "done";
146359
+ }
146360
+ if (features.some((feature) => feature.status === "in_progress")) {
146361
+ return "in_progress";
146362
+ }
146363
+ if (features.some((feature) => feature.status === "blocked")) {
146364
+ return "blocked";
146365
+ }
146366
+ return "planned";
146367
+ }
146368
+ function findKnowledgeSectionTitle(knowledgeSections, sectionId) {
146369
+ const section2 = knowledgeSections.find((item) => item.id === sectionId);
146370
+ if (!section2) {
146371
+ return {
146372
+ heading: sectionId,
146373
+ filePath: ""
146374
+ };
146375
+ }
146376
+ return {
146377
+ heading: section2.heading,
146378
+ filePath: section2.filePath
146379
+ };
146380
+ }
146381
+ async function buildProjectPlanHierarchy(root, graph) {
146382
+ const knowledgeSections = await readKnowledgeSections(root);
146383
+ const currentGraph = graph ?? await readProjectPlanGraph(root);
146384
+ const linkedTodos = await listLinkedTodosByTask(root);
146385
+ const featureMap = /* @__PURE__ */ new Map();
146386
+ for (const feature of currentGraph.features) {
146387
+ const featureTasks = currentGraph.tasks.filter((task) => task.featureId === feature.id).map((task) => {
146388
+ const taskLinkedTodos = linkedTodos.get(task.id) || [];
146389
+ return {
146390
+ ...task,
146391
+ linkedTodos: taskLinkedTodos,
146392
+ linkedTodoCount: taskLinkedTodos.length
146393
+ };
146394
+ });
146395
+ featureMap.set(feature.id, {
146396
+ ...feature,
146397
+ status: deriveFeatureStatus(featureTasks),
146398
+ taskCount: featureTasks.length,
146399
+ tasks: featureTasks
146400
+ });
146401
+ }
146402
+ const sections = currentGraph.sections.map((section2) => {
146403
+ const features = currentGraph.features.filter((feature) => feature.sectionId === section2.sectionId).map((feature) => featureMap.get(feature.id)).filter((feature) => Boolean(feature));
146404
+ const knowledgeMetadata = findKnowledgeSectionTitle(knowledgeSections, section2.sectionId);
146405
+ const taskCount = features.reduce((count, feature) => count + feature.taskCount, 0);
146406
+ return {
146407
+ sectionId: section2.sectionId,
146408
+ heading: knowledgeMetadata.heading,
146409
+ filePath: knowledgeMetadata.filePath,
146410
+ status: deriveSectionStatus(features),
146411
+ featureCount: features.length,
146412
+ taskCount,
146413
+ features
146414
+ };
146415
+ });
146416
+ return {
146417
+ sections
146418
+ };
146419
+ }
146420
+ function formatAcceptanceCriteria(criteria) {
146421
+ if (criteria.length === 0) {
146422
+ return ["- None yet"];
146423
+ }
146424
+ return criteria.map((item) => `- ${item}`);
146425
+ }
146426
+ async function renderProjectPlanMarkdown(root, graph) {
146427
+ const hierarchy = await buildProjectPlanHierarchy(root, graph);
146428
+ const lines = [
146429
+ "# Project Plan",
146430
+ "",
146431
+ "This file is derived from `docyrus/project-plan/project-plan.json`.",
146432
+ ""
146433
+ ];
146434
+ const populatedSections = hierarchy.sections.filter((section2) => section2.features.length > 0);
146435
+ if (populatedSections.length === 0) {
146436
+ lines.push("No planned features or tasks yet.");
146437
+ lines.push("");
146438
+ return `${lines.join("\n")}`;
146439
+ }
146440
+ for (const section2 of populatedSections) {
146441
+ lines.push(`## ${section2.heading}`);
146442
+ lines.push("");
146443
+ lines.push(`- Section ID: \`${section2.sectionId}\``);
146444
+ lines.push(`- Status: \`${section2.status}\``);
146445
+ lines.push(`- Features: ${section2.featureCount}`);
146446
+ lines.push(`- Tasks: ${section2.taskCount}`);
146447
+ lines.push("");
146448
+ for (const feature of section2.features) {
146449
+ lines.push(`### ${feature.title}`);
146450
+ lines.push("");
146451
+ lines.push(`- Feature ID: \`${feature.id}\``);
146452
+ lines.push(`- Status: \`${feature.status}\``);
146453
+ lines.push(`- Slug: \`${feature.slug}\``);
146454
+ if (feature.summary) {
146455
+ lines.push(`- Summary: ${feature.summary}`);
146456
+ }
146457
+ lines.push("");
146458
+ for (const task of feature.tasks) {
146459
+ lines.push(`#### ${task.title}`);
146460
+ lines.push("");
146461
+ lines.push(`- Task ID: \`${task.id}\``);
146462
+ lines.push(`- Type: \`${task.type}\``);
146463
+ lines.push(`- Assignee: \`${task.assignee}\``);
146464
+ lines.push(`- Status: \`${task.status}\``);
146465
+ if (task.summary) {
146466
+ lines.push(`- Summary: ${task.summary}`);
146467
+ }
146468
+ lines.push("- Acceptance Criteria:");
146469
+ lines.push(...formatAcceptanceCriteria(task.acceptanceCriteria));
146470
+ lines.push("");
146471
+ }
146472
+ }
146473
+ }
146474
+ return `${lines.join("\n").trimEnd()}
146475
+ `;
146476
+ }
146477
+ async function writeProjectPlanFiles(root, graph) {
146478
+ const graphPath = resolveProjectPlanGraphPath(root);
146479
+ const markdownPath = resolveProjectPlanMarkdownPath(root);
146480
+ await import_promises13.default.mkdir(import_node_path17.default.dirname(graphPath), {
146481
+ recursive: true
146482
+ });
146483
+ const sortedGraph = sortGraph(graph);
146484
+ await import_promises13.default.writeFile(graphPath, `${JSON.stringify(sortedGraph, null, 2)}
146485
+ `, "utf8");
146486
+ await import_promises13.default.writeFile(markdownPath, await renderProjectPlanMarkdown(root, sortedGraph), "utf8");
146487
+ return {
146488
+ graph: sortedGraph,
146489
+ graphPath,
146490
+ markdownPath
146491
+ };
146492
+ }
146493
+ function buildProjectPlanCheckError(code, message, target) {
146494
+ return {
146495
+ code,
146496
+ message,
146497
+ target
146498
+ };
146499
+ }
146500
+ async function validateProjectPlanGraph(root, graph) {
146501
+ const currentGraph = graph ?? await readProjectPlanGraph(root);
146502
+ const errors = [];
146503
+ const knowledgeSections = await readKnowledgeSections(root);
146504
+ const knowledgeSectionIds = new Set(knowledgeSections.map((section2) => section2.id));
146505
+ const sectionIds = /* @__PURE__ */ new Set();
146506
+ const featureIds = /* @__PURE__ */ new Set();
146507
+ const featureMap = /* @__PURE__ */ new Map();
146508
+ for (const section2 of currentGraph.sections) {
146509
+ if (!section2.sectionId) {
146510
+ errors.push(buildProjectPlanCheckError("section_missing_id", "Project plan section is missing `sectionId`."));
146511
+ continue;
146512
+ }
146513
+ if (sectionIds.has(section2.sectionId)) {
146514
+ errors.push(buildProjectPlanCheckError("duplicate_section", `Duplicate section id "${section2.sectionId}"`, section2.sectionId));
146515
+ continue;
146516
+ }
146517
+ sectionIds.add(section2.sectionId);
146518
+ if (!knowledgeSectionIds.has(section2.sectionId)) {
146519
+ errors.push(buildProjectPlanCheckError(
146520
+ "unknown_knowledge_section",
146521
+ `Project plan section "${section2.sectionId}" does not exist in docyrus/knowledge.`,
146522
+ section2.sectionId
146523
+ ));
146524
+ }
146525
+ }
146526
+ const allowedTypes = new Set(PROJECT_TASK_TYPES);
146527
+ const allowedAssignees = new Set(PROJECT_TASK_ASSIGNEES);
146528
+ const allowedStatuses = new Set(PROJECT_TASK_STATUSES);
146529
+ for (const feature of currentGraph.features) {
146530
+ if (!feature.id) {
146531
+ errors.push(buildProjectPlanCheckError("feature_missing_id", "Project plan feature is missing `id`."));
146532
+ continue;
146533
+ }
146534
+ if (featureIds.has(feature.id)) {
146535
+ errors.push(buildProjectPlanCheckError("duplicate_feature", `Duplicate feature id "${feature.id}"`, feature.id));
146536
+ continue;
146537
+ }
146538
+ featureIds.add(feature.id);
146539
+ featureMap.set(feature.id, feature);
146540
+ if (!feature.sectionId) {
146541
+ errors.push(buildProjectPlanCheckError("feature_missing_section", `Feature "${feature.id}" is missing \`sectionId\`.`, feature.id));
146542
+ continue;
146543
+ }
146544
+ if (!sectionIds.has(feature.sectionId)) {
146545
+ errors.push(buildProjectPlanCheckError(
146546
+ "feature_unknown_section",
146547
+ `Feature "${feature.id}" references unknown section "${feature.sectionId}".`,
146548
+ feature.id
146549
+ ));
146550
+ }
146551
+ if (!feature.title.trim()) {
146552
+ errors.push(buildProjectPlanCheckError("feature_missing_title", `Feature "${feature.id}" is missing a title.`, feature.id));
146553
+ }
146554
+ if (!feature.slug.trim()) {
146555
+ errors.push(buildProjectPlanCheckError("feature_missing_slug", `Feature "${feature.id}" is missing a slug.`, feature.id));
146556
+ }
146557
+ }
146558
+ const taskIds = /* @__PURE__ */ new Set();
146559
+ for (const task of currentGraph.tasks) {
146560
+ if (!task.id) {
146561
+ errors.push(buildProjectPlanCheckError("task_missing_id", "Project plan task is missing `id`."));
146562
+ continue;
146563
+ }
146564
+ if (taskIds.has(task.id)) {
146565
+ errors.push(buildProjectPlanCheckError("duplicate_task", `Duplicate task id "${task.id}"`, task.id));
146566
+ continue;
146567
+ }
146568
+ taskIds.add(task.id);
146569
+ const feature = featureMap.get(task.featureId);
146570
+ if (!feature) {
146571
+ errors.push(buildProjectPlanCheckError(
146572
+ "task_unknown_feature",
146573
+ `Task "${task.id}" references unknown feature "${task.featureId}".`,
146574
+ task.id
146575
+ ));
146576
+ continue;
146577
+ }
146578
+ if (!task.title.trim()) {
146579
+ errors.push(buildProjectPlanCheckError("task_missing_title", `Task "${task.id}" is missing a title.`, task.id));
146580
+ }
146581
+ if (!allowedTypes.has(task.type)) {
146582
+ errors.push(buildProjectPlanCheckError(
146583
+ "task_invalid_type",
146584
+ `Task "${task.id}" has invalid type "${task.type}".`,
146585
+ task.id
146586
+ ));
146587
+ }
146588
+ if (!allowedAssignees.has(task.assignee)) {
146589
+ errors.push(buildProjectPlanCheckError(
146590
+ "task_invalid_assignee",
146591
+ `Task "${task.id}" has invalid assignee "${task.assignee}".`,
146592
+ task.id
146593
+ ));
146594
+ }
146595
+ if (!allowedStatuses.has(task.status)) {
146596
+ errors.push(buildProjectPlanCheckError(
146597
+ "task_invalid_status",
146598
+ `Task "${task.id}" has invalid status "${task.status}".`,
146599
+ task.id
146600
+ ));
146601
+ }
146602
+ if (!sectionIds.has(task.sectionId)) {
146603
+ errors.push(buildProjectPlanCheckError(
146604
+ "task_unknown_section",
146605
+ `Task "${task.id}" references unknown section "${task.sectionId}".`,
146606
+ task.id
146607
+ ));
146608
+ }
146609
+ if (task.sectionId !== feature.sectionId) {
146610
+ errors.push(buildProjectPlanCheckError(
146611
+ "task_section_mismatch",
146612
+ `Task "${task.id}" section "${task.sectionId}" does not match feature "${feature.id}" section "${feature.sectionId}".`,
146613
+ task.id
146614
+ ));
146615
+ }
146616
+ }
146617
+ return {
146618
+ ok: errors.length === 0,
146619
+ errors
146620
+ };
146621
+ }
146622
+ async function resolveKnowledgeSectionIds(root) {
146623
+ const sections = await readKnowledgeSections(root);
146624
+ return sections.map((section2) => section2.id).sort(compareStrings);
146625
+ }
146626
+ async function syncProjectPlanSectionsFromKnowledge(root) {
146627
+ const currentGraph = await readProjectPlanGraph(root);
146628
+ const knowledgeSectionIds = await resolveKnowledgeSectionIds(root);
146629
+ const syncedGraph = {
146630
+ ...currentGraph,
146631
+ sections: knowledgeSectionIds.map((sectionId) => ({
146632
+ sectionId
146633
+ }))
146634
+ };
146635
+ return writeProjectPlanFiles(root, syncedGraph);
146636
+ }
146637
+ async function ensureProjectPlanGraph(root) {
146638
+ const graphPath = resolveProjectPlanGraphPath(root);
146639
+ if (!(0, import_node_fs9.existsSync)(graphPath)) {
146640
+ return syncProjectPlanSectionsFromKnowledge(root);
146641
+ }
146642
+ const graph = await readProjectPlanGraph(root);
146643
+ return writeProjectPlanFiles(root, graph);
146644
+ }
146645
+ async function upsertProjectPlanFeature(params) {
146646
+ const state = await ensureProjectPlanGraph(params.root);
146647
+ const slug = slugify2(params.slug?.trim() || params.title);
146648
+ const featureId = params.featureId?.trim() || normalizeFeatureId(params.sectionId, slug);
146649
+ const graph = state.graph;
146650
+ const existing = graph.features.find((feature) => feature.id === featureId) || graph.features.find((feature) => feature.sectionId === params.sectionId && feature.slug === slug);
146651
+ const nextFeature = {
146652
+ id: existing?.id || featureId,
146653
+ title: params.title.trim(),
146654
+ slug,
146655
+ summary: params.summary?.trim() || "",
146656
+ sectionId: params.sectionId
146657
+ };
146658
+ const nextFeatures = existing ? graph.features.map((feature) => feature.id === existing.id ? nextFeature : feature) : [...graph.features, nextFeature];
146659
+ await writeProjectPlanFiles(params.root, {
146660
+ ...graph,
146661
+ features: nextFeatures
146662
+ });
146663
+ return nextFeature;
146664
+ }
146665
+ async function getProjectPlanTask(params) {
146666
+ const graph = await readProjectPlanGraph(params.root);
146667
+ const linkedTodos = await listLinkedTodosByTask(params.root);
146668
+ const task = graph.tasks.find((item) => item.id === params.taskId);
146669
+ if (!task) {
146670
+ return null;
146671
+ }
146672
+ const taskLinkedTodos = linkedTodos.get(task.id) || [];
146673
+ return {
146674
+ ...task,
146675
+ linkedTodos: taskLinkedTodos,
146676
+ linkedTodoCount: taskLinkedTodos.length
146677
+ };
146678
+ }
146679
+ async function upsertProjectPlanTask(params) {
146680
+ const state = await ensureProjectPlanGraph(params.root);
146681
+ const graph = state.graph;
146682
+ const feature = graph.features.find((item) => item.id === params.featureId);
146683
+ if (!feature) {
146684
+ throw new Error(`Feature "${params.featureId}" not found.`);
146685
+ }
146686
+ const sectionId = params.sectionId?.trim() || feature.sectionId;
146687
+ const taskId = params.taskId?.trim() || normalizeTaskId(feature.id, params.type, params.title);
146688
+ const existing = graph.tasks.find((task) => task.id === taskId) || graph.tasks.find((task) => task.featureId === feature.id && task.type === params.type && task.title === params.title.trim());
146689
+ const nextTask = {
146690
+ id: existing?.id || taskId,
146691
+ title: params.title.trim(),
146692
+ summary: params.summary?.trim() || "",
146693
+ type: params.type,
146694
+ assignee: params.assignee,
146695
+ status: params.status || "planned",
146696
+ acceptanceCriteria: [...new Set((params.acceptanceCriteria || []).map((item) => item.trim()).filter(Boolean))],
146697
+ featureId: feature.id,
146698
+ sectionId
146699
+ };
146700
+ const nextTasks = existing ? graph.tasks.map((task) => task.id === existing.id ? nextTask : task) : [...graph.tasks, nextTask];
146701
+ await writeProjectPlanFiles(params.root, {
146702
+ ...graph,
146703
+ tasks: nextTasks
146704
+ });
146705
+ return nextTask;
146706
+ }
146707
+ async function updateProjectPlanTaskStatus(params) {
146708
+ const graph = await readProjectPlanGraph(params.root);
146709
+ const task = graph.tasks.find((item) => item.id === params.taskId);
146710
+ if (!task) {
146711
+ throw new Error(`Task "${params.taskId}" not found.`);
146712
+ }
146713
+ const nextTask = {
146714
+ ...task,
146715
+ status: params.status
146716
+ };
146717
+ await writeProjectPlanFiles(params.root, {
146718
+ ...graph,
146719
+ tasks: graph.tasks.map((item) => item.id === task.id ? nextTask : item)
146720
+ });
146721
+ return nextTask;
146722
+ }
146723
+ async function resolveDefaultProjectPlanRoutes(root) {
146724
+ const sections = await readKnowledgeSections(root);
146725
+ const resolveRoute = (key) => {
146726
+ const candidate = sections.find((section2) => {
146727
+ return section2.heading === DEFAULT_ROUTE_TARGETS[key].heading && section2.filePath === DEFAULT_ROUTE_TARGETS[key].filePathSuffix && section2.depth === 1;
146728
+ }) || sections.find((section2) => section2.heading === DEFAULT_ROUTE_TARGETS[key].heading);
146729
+ if (!candidate) {
146730
+ throw new Error(`Unable to resolve the default knowledge section for ${key}.`);
146731
+ }
146732
+ return candidate.id;
146733
+ };
146734
+ return {
146735
+ featuresSectionId: resolveRoute("features"),
146736
+ testingSectionId: resolveRoute("testing"),
146737
+ architectureSectionId: resolveRoute("architecture"),
146738
+ workflowsSectionId: resolveRoute("workflows")
146739
+ };
146740
+ }
146741
+
145967
146742
  // src/knowledge/init.ts
145968
146743
  var MARKER_BEGIN = "%% docyrus-knowledge:begin %%";
145969
146744
  var MARKER_END = "%% docyrus-knowledge:end %%";
@@ -145975,60 +146750,60 @@ ${content3}${content3.endsWith("\n") ? "" : "\n"}${MARKER_END}
145975
146750
  `;
145976
146751
  }
145977
146752
  async function ensureDirectory(pathValue) {
145978
- await (0, import_promises12.mkdir)(pathValue, {
146753
+ await (0, import_promises14.mkdir)(pathValue, {
145979
146754
  recursive: true,
145980
146755
  mode: 493
145981
146756
  });
145982
146757
  }
145983
146758
  async function writeIfMissing(filePath, content3) {
145984
- if ((0, import_node_fs8.existsSync)(filePath)) {
146759
+ if ((0, import_node_fs10.existsSync)(filePath)) {
145985
146760
  return "kept";
145986
146761
  }
145987
- await ensureDirectory((0, import_node_path16.dirname)(filePath));
145988
- await (0, import_promises12.writeFile)(filePath, content3, "utf8");
146762
+ await ensureDirectory((0, import_node_path18.dirname)(filePath));
146763
+ await (0, import_promises14.writeFile)(filePath, content3, "utf8");
145989
146764
  return "created";
145990
146765
  }
145991
146766
  async function writeOrUpdate(filePath, content3) {
145992
- if (!(0, import_node_fs8.existsSync)(filePath)) {
145993
- await ensureDirectory((0, import_node_path16.dirname)(filePath));
145994
- await (0, import_promises12.writeFile)(filePath, content3, "utf8");
146767
+ if (!(0, import_node_fs10.existsSync)(filePath)) {
146768
+ await ensureDirectory((0, import_node_path18.dirname)(filePath));
146769
+ await (0, import_promises14.writeFile)(filePath, content3, "utf8");
145995
146770
  return "created";
145996
146771
  }
145997
- const current = await (0, import_promises12.readFile)(filePath, "utf8");
146772
+ const current = await (0, import_promises14.readFile)(filePath, "utf8");
145998
146773
  if (current === content3) {
145999
146774
  return "kept";
146000
146775
  }
146001
- await ensureDirectory((0, import_node_path16.dirname)(filePath));
146002
- await (0, import_promises12.writeFile)(filePath, content3, "utf8");
146776
+ await ensureDirectory((0, import_node_path18.dirname)(filePath));
146777
+ await (0, import_promises14.writeFile)(filePath, content3, "utf8");
146003
146778
  return "updated";
146004
146779
  }
146005
146780
  async function upsertManagedBlock(filePath, content3) {
146006
146781
  const wrapped = wrapManagedBlock(content3);
146007
- if (!(0, import_node_fs8.existsSync)(filePath)) {
146008
- await ensureDirectory((0, import_node_path16.dirname)(filePath));
146009
- await (0, import_promises12.writeFile)(filePath, wrapped, "utf8");
146782
+ if (!(0, import_node_fs10.existsSync)(filePath)) {
146783
+ await ensureDirectory((0, import_node_path18.dirname)(filePath));
146784
+ await (0, import_promises14.writeFile)(filePath, wrapped, "utf8");
146010
146785
  return "created";
146011
146786
  }
146012
- const current = await (0, import_promises12.readFile)(filePath, "utf8");
146787
+ const current = await (0, import_promises14.readFile)(filePath, "utf8");
146013
146788
  const beginIndex = current.indexOf(MARKER_BEGIN);
146014
146789
  const endIndex = current.indexOf(MARKER_END);
146015
146790
  if (beginIndex !== -1 && endIndex !== -1 && endIndex > beginIndex) {
146016
146791
  const replaceEnd = current[endIndex + MARKER_END.length] === "\n" ? endIndex + MARKER_END.length + 1 : endIndex + MARKER_END.length;
146017
146792
  const updated = `${current.slice(0, beginIndex)}${wrapped}${current.slice(replaceEnd)}`;
146018
- await (0, import_promises12.writeFile)(filePath, updated, "utf8");
146793
+ await (0, import_promises14.writeFile)(filePath, updated, "utf8");
146019
146794
  return "updated";
146020
146795
  }
146021
146796
  const separator = current.endsWith("\n") ? "\n" : "\n\n";
146022
- await (0, import_promises12.writeFile)(filePath, `${current}${separator}${wrapped}`, "utf8");
146797
+ await (0, import_promises14.writeFile)(filePath, `${current}${separator}${wrapped}`, "utf8");
146023
146798
  return "appended";
146024
146799
  }
146025
146800
  function normalizeObject(value2) {
146026
146801
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2) ? { ...value2 } : {};
146027
146802
  }
146028
146803
  async function updateJsonFile(filePath, updater) {
146029
- const current = (0, import_node_fs8.existsSync)(filePath) ? normalizeObject(JSON.parse((0, import_node_fs8.readFileSync)(filePath, "utf8"))) : {};
146030
- await ensureDirectory((0, import_node_path16.dirname)(filePath));
146031
- await (0, import_promises12.writeFile)(filePath, `${JSON.stringify(updater(current), null, 2)}
146804
+ const current = (0, import_node_fs10.existsSync)(filePath) ? normalizeObject(JSON.parse((0, import_node_fs10.readFileSync)(filePath, "utf8"))) : {};
146805
+ await ensureDirectory((0, import_node_path18.dirname)(filePath));
146806
+ await (0, import_promises14.writeFile)(filePath, `${JSON.stringify(updater(current), null, 2)}
146032
146807
  `, "utf8");
146033
146808
  }
146034
146809
  function wrapHookBlock(content3) {
@@ -146038,17 +146813,17 @@ ${content3}${content3.endsWith("\n") ? "" : "\n"}${HOOK_MARKER_END}
146038
146813
  }
146039
146814
  async function upsertShellHook(filePath, content3, shellHeader) {
146040
146815
  const wrapped = wrapHookBlock(content3);
146041
- if (!(0, import_node_fs8.existsSync)(filePath)) {
146042
- await ensureDirectory((0, import_node_path16.dirname)(filePath));
146816
+ if (!(0, import_node_fs10.existsSync)(filePath)) {
146817
+ await ensureDirectory((0, import_node_path18.dirname)(filePath));
146043
146818
  const initial = `${shellHeader || ""}${wrapped}`;
146044
- await (0, import_promises12.writeFile)(filePath, initial, {
146819
+ await (0, import_promises14.writeFile)(filePath, initial, {
146045
146820
  encoding: "utf8",
146046
146821
  mode: 493
146047
146822
  });
146048
- await (0, import_promises12.chmod)(filePath, 493);
146823
+ await (0, import_promises14.chmod)(filePath, 493);
146049
146824
  return "created";
146050
146825
  }
146051
- const current = await (0, import_promises12.readFile)(filePath, "utf8");
146826
+ const current = await (0, import_promises14.readFile)(filePath, "utf8");
146052
146827
  const beginIndex = current.indexOf(HOOK_MARKER_BEGIN);
146053
146828
  const endIndex = current.indexOf(HOOK_MARKER_END);
146054
146829
  if (beginIndex !== -1 && endIndex !== -1 && endIndex > beginIndex) {
@@ -146057,13 +146832,13 @@ async function upsertShellHook(filePath, content3, shellHeader) {
146057
146832
  if (nextContent === current) {
146058
146833
  return "kept";
146059
146834
  }
146060
- await (0, import_promises12.writeFile)(filePath, nextContent, "utf8");
146061
- await (0, import_promises12.chmod)(filePath, 493);
146835
+ await (0, import_promises14.writeFile)(filePath, nextContent, "utf8");
146836
+ await (0, import_promises14.chmod)(filePath, 493);
146062
146837
  return "updated";
146063
146838
  }
146064
146839
  const separator = current.endsWith("\n") ? "\n" : "\n\n";
146065
- await (0, import_promises12.writeFile)(filePath, `${current}${separator}${wrapped}`, "utf8");
146066
- await (0, import_promises12.chmod)(filePath, 493);
146840
+ await (0, import_promises14.writeFile)(filePath, `${current}${separator}${wrapped}`, "utf8");
146841
+ await (0, import_promises14.chmod)(filePath, 493);
146067
146842
  return "appended";
146068
146843
  }
146069
146844
  function buildKnowledgeDocumentTemplate() {
@@ -146157,33 +146932,34 @@ function syncCursorHooks(settings, commandPrefix) {
146157
146932
  };
146158
146933
  }
146159
146934
  async function initializeKnowledgeRepo(params) {
146160
- const root = (0, import_node_path16.resolve)(params.root || process.cwd());
146935
+ const root = (0, import_node_path18.resolve)(params.root || process.cwd());
146161
146936
  const knowledgeDir = getKnowledgeDirectory(root);
146162
- const knowledgeFile = (0, import_node_path16.join)(knowledgeDir, "knowledge.md");
146937
+ const knowledgeFile = (0, import_node_path18.join)(knowledgeDir, "knowledge.md");
146163
146938
  await ensureDirectory(knowledgeDir);
146164
146939
  const knowledgeFileStatus = await writeIfMissing(knowledgeFile, `${buildKnowledgeDocumentTemplate()}
146165
146940
  `);
146166
- const agentsStatus = await upsertManagedBlock((0, import_node_path16.join)(root, "AGENTS.md"), buildAgentsTemplate(params.commandPrefix));
146167
- const claudeStatus = await upsertManagedBlock((0, import_node_path16.join)(root, "CLAUDE.md"), buildAgentsTemplate(params.commandPrefix));
146168
- const cursorRulesStatus = await writeOrUpdate((0, import_node_path16.join)(root, ".cursor", "rules", "docyrus-knowledge.md"), `${buildCursorRulesTemplate(params.commandPrefix)}
146941
+ const agentsStatus = await upsertManagedBlock((0, import_node_path18.join)(root, "AGENTS.md"), buildAgentsTemplate(params.commandPrefix));
146942
+ const claudeStatus = await upsertManagedBlock((0, import_node_path18.join)(root, "CLAUDE.md"), buildAgentsTemplate(params.commandPrefix));
146943
+ const cursorRulesStatus = await writeOrUpdate((0, import_node_path18.join)(root, ".cursor", "rules", "docyrus-knowledge.md"), `${buildCursorRulesTemplate(params.commandPrefix)}
146169
146944
  `);
146170
146945
  const bootstrap = (await generateInitialKnowledge({
146171
146946
  root,
146172
146947
  brief: params.brief
146173
146948
  })).files;
146174
- await updateJsonFile((0, import_node_path16.join)(root, ".claude", "settings.json"), (value2) => syncClaudeHooks(value2, params.commandPrefix));
146175
- await updateJsonFile((0, import_node_path16.join)(root, ".cursor", "hooks.json"), (value2) => syncCursorHooks(value2, params.commandPrefix));
146949
+ const projectPlan = await syncProjectPlanSectionsFromKnowledge(root);
146950
+ await updateJsonFile((0, import_node_path18.join)(root, ".claude", "settings.json"), (value2) => syncClaudeHooks(value2, params.commandPrefix));
146951
+ await updateJsonFile((0, import_node_path18.join)(root, ".cursor", "hooks.json"), (value2) => syncCursorHooks(value2, params.commandPrefix));
146176
146952
  let huskyHookStatus;
146177
- const huskyDir = (0, import_node_path16.join)(root, ".husky");
146178
- if ((0, import_node_fs8.existsSync)(huskyDir)) {
146179
- const huskyHookPath = (0, import_node_path16.join)(huskyDir, "pre-commit");
146180
- const huskyHeader = (0, import_node_fs8.existsSync)((0, import_node_path16.join)(huskyDir, "_", "h")) ? '#!/usr/bin/env sh\n. "$(dirname -- "$0")/_/h"\n\n' : void 0;
146953
+ const huskyDir = (0, import_node_path18.join)(root, ".husky");
146954
+ if ((0, import_node_fs10.existsSync)(huskyDir)) {
146955
+ const huskyHookPath = (0, import_node_path18.join)(huskyDir, "pre-commit");
146956
+ const huskyHeader = (0, import_node_fs10.existsSync)((0, import_node_path18.join)(huskyDir, "_", "h")) ? '#!/usr/bin/env sh\n. "$(dirname -- "$0")/_/h"\n\n' : void 0;
146181
146957
  huskyHookStatus = await upsertShellHook(huskyHookPath, `${params.commandPrefix} knowledge pre-commit
146182
146958
  `, huskyHeader);
146183
146959
  }
146184
146960
  let gitHookStatus;
146185
146961
  if (!huskyHookStatus && params.installGitHook) {
146186
- const gitHookPath = (0, import_node_path16.join)(root, ".git", "hooks", "pre-commit");
146962
+ const gitHookPath = (0, import_node_path18.join)(root, ".git", "hooks", "pre-commit");
146187
146963
  gitHookStatus = await upsertShellHook(gitHookPath, `${params.commandPrefix} knowledge pre-commit
146188
146964
  `, "#!/usr/bin/env sh\n\n");
146189
146965
  }
@@ -146191,6 +146967,8 @@ async function initializeKnowledgeRepo(params) {
146191
146967
  root,
146192
146968
  knowledgeDir,
146193
146969
  knowledgeFile,
146970
+ projectPlanGraphPath: projectPlan.graphPath,
146971
+ projectPlanMarkdownPath: projectPlan.markdownPath,
146194
146972
  agentsStatus,
146195
146973
  claudeStatus,
146196
146974
  cursorRulesStatus,
@@ -146205,9 +146983,9 @@ async function initializeKnowledgeRepo(params) {
146205
146983
  init_graph();
146206
146984
 
146207
146985
  // src/knowledge/validation.ts
146208
- var import_node_fs9 = require("node:fs");
146209
- var import_promises13 = require("node:fs/promises");
146210
- var import_node_path17 = require("node:path");
146986
+ var import_node_fs11 = require("node:fs");
146987
+ var import_promises15 = require("node:fs/promises");
146988
+ var import_node_path19 = require("node:path");
146211
146989
  init_graph();
146212
146990
  var MAX_BODY_LENGTH = 250;
146213
146991
  function bodyTextLength(body2) {
@@ -146240,15 +147018,15 @@ async function tryResolveSourceRef(target, projectRoot) {
146240
147018
  const hashIndex = target.indexOf("#");
146241
147019
  const filePart = hashIndex === -1 ? target : target.slice(0, hashIndex);
146242
147020
  const symbolPart = hashIndex === -1 ? "" : target.slice(hashIndex + 1);
146243
- const extension2 = (0, import_node_path17.extname)(filePart);
147021
+ const extension2 = (0, import_node_path19.extname)(filePart);
146244
147022
  if (!SOURCE_EXTENSIONS.has(extension2)) {
146245
147023
  if (extension2 && hashIndex !== -1) {
146246
147024
  return `broken link [[${target}]] - unsupported file extension "${extension2}"`;
146247
147025
  }
146248
147026
  return `broken link [[${target}]] - no matching section found`;
146249
147027
  }
146250
- const absolutePath = (0, import_node_path17.join)(projectRoot, filePart);
146251
- if (!(0, import_node_fs9.existsSync)(absolutePath)) {
147028
+ const absolutePath = (0, import_node_path19.join)(projectRoot, filePart);
147029
+ if (!(0, import_node_fs11.existsSync)(absolutePath)) {
146252
147030
  return `broken link [[${target}]] - file "${filePart}" not found`;
146253
147031
  }
146254
147032
  if (!symbolPart) {
@@ -146265,7 +147043,7 @@ async function tryResolveSourceRef(target, projectRoot) {
146265
147043
  }
146266
147044
  async function checkKnowledgeMarkdown(knowledgeDir) {
146267
147045
  clearSymbolCache();
146268
- const projectRoot = (0, import_node_path17.dirname)((0, import_node_path17.dirname)(knowledgeDir));
147046
+ const projectRoot = (0, import_node_path19.dirname)((0, import_node_path19.dirname)(knowledgeDir));
146269
147047
  const files = await listKnowledgeFiles(knowledgeDir);
146270
147048
  const sections = await loadAllSections(knowledgeDir);
146271
147049
  const flat = flattenSections(sections);
@@ -146274,9 +147052,9 @@ async function checkKnowledgeMarkdown(knowledgeDir) {
146274
147052
  const fileIndex = buildFileIndex(sections);
146275
147053
  const errors = [];
146276
147054
  for (const filePath of files) {
146277
- const content3 = await (0, import_promises13.readFile)(filePath, "utf8");
147055
+ const content3 = await (0, import_promises15.readFile)(filePath, "utf8");
146278
147056
  const refs = extractRefs(filePath, content3, projectRoot);
146279
- const displayPath = (0, import_node_path17.relative)(process.cwd(), filePath);
147057
+ const displayPath = (0, import_node_path19.relative)(process.cwd(), filePath);
146280
147058
  for (const ref of refs) {
146281
147059
  const resolved = resolveRef2(ref.target, sectionIds, fileIndex, canonicalSectionIds);
146282
147060
  if (resolved.ambiguous) {
@@ -146308,7 +147086,7 @@ async function checkKnowledgeMarkdown(knowledgeDir) {
146308
147086
  };
146309
147087
  }
146310
147088
  async function checkKnowledgeCodeRefs(knowledgeDir) {
146311
- const projectRoot = (0, import_node_path17.dirname)((0, import_node_path17.dirname)(knowledgeDir));
147089
+ const projectRoot = (0, import_node_path19.dirname)((0, import_node_path19.dirname)(knowledgeDir));
146312
147090
  const sections = await loadAllSections(knowledgeDir);
146313
147091
  const flat = flattenSections(sections);
146314
147092
  const sectionIds = new Set(flat.map((section2) => section2.id.toLowerCase()));
@@ -146320,7 +147098,7 @@ async function checkKnowledgeCodeRefs(knowledgeDir) {
146320
147098
  for (const ref of scan.refs) {
146321
147099
  const resolved = resolveRef2(ref.target, sectionIds, fileIndex, canonicalSectionIds);
146322
147100
  mentionedSections.add(resolved.resolved.toLowerCase());
146323
- const displayPath = (0, import_node_path17.relative)(process.cwd(), (0, import_node_path17.join)(projectRoot, ref.file));
147101
+ const displayPath = (0, import_node_path19.relative)(process.cwd(), (0, import_node_path19.join)(projectRoot, ref.file));
146324
147102
  if (resolved.ambiguous) {
146325
147103
  errors.push({
146326
147104
  file: displayPath,
@@ -146340,12 +147118,12 @@ async function checkKnowledgeCodeRefs(knowledgeDir) {
146340
147118
  }
146341
147119
  }
146342
147120
  for (const filePath of await listKnowledgeFiles(knowledgeDir)) {
146343
- const content3 = await (0, import_promises13.readFile)(filePath, "utf8");
147121
+ const content3 = await (0, import_promises15.readFile)(filePath, "utf8");
146344
147122
  if (!parseFrontmatter(content3).requireCodeMention) {
146345
147123
  continue;
146346
147124
  }
146347
147125
  const leafSections = flattenSections(parseSections(filePath, content3, projectRoot)).filter((section2) => section2.children.length === 0);
146348
- const displayPath = (0, import_node_path17.relative)(process.cwd(), filePath);
147126
+ const displayPath = (0, import_node_path19.relative)(process.cwd(), filePath);
146349
147127
  for (const section2 of leafSections) {
146350
147128
  if (!mentionedSections.has(section2.id.toLowerCase())) {
146351
147129
  errors.push({
@@ -146369,7 +147147,7 @@ async function checkKnowledgeIndex(knowledgeDir) {
146369
147147
  const name2 = pathValue.includes("/") ? pathValue.slice(pathValue.lastIndexOf("/") + 1) : pathValue;
146370
147148
  if (!name2.endsWith(".md")) {
146371
147149
  errors.push({
146372
- dir: `${(0, import_node_path17.basename)(knowledgeDir)}/`,
147150
+ dir: `${(0, import_node_path19.basename)(knowledgeDir)}/`,
146373
147151
  message: `"${pathValue}" is not a .md file - only markdown files belong in docyrus/knowledge/`
146374
147152
  });
146375
147153
  }
@@ -146383,7 +147161,7 @@ async function checkKnowledgeIndex(knowledgeDir) {
146383
147161
  }
146384
147162
  }
146385
147163
  for (const dir of dirs) {
146386
- const dirName = dir === "" ? (0, import_node_path17.basename)(knowledgeDir) : dir.split("/").pop() || (0, import_node_path17.basename)(knowledgeDir);
147164
+ const dirName = dir === "" ? (0, import_node_path19.basename)(knowledgeDir) : dir.split("/").pop() || (0, import_node_path19.basename)(knowledgeDir);
146387
147165
  const indexFileName = dirName.endsWith(".md") ? dirName : `${dirName}.md`;
146388
147166
  const indexRelPath = dir === "" ? indexFileName : `${dir}/${indexFileName}`;
146389
147167
  const prefix = dir === "" ? "" : `${dir}/`;
@@ -146392,11 +147170,11 @@ async function checkKnowledgeIndex(knowledgeDir) {
146392
147170
  if (children.length === 0) {
146393
147171
  continue;
146394
147172
  }
146395
- const indexFullPath = (0, import_node_path17.join)(knowledgeDir, indexRelPath);
146396
- const displayDir = dir === "" ? `${(0, import_node_path17.basename)(knowledgeDir)}/` : `${dir}/`;
147173
+ const indexFullPath = (0, import_node_path19.join)(knowledgeDir, indexRelPath);
147174
+ const displayDir = dir === "" ? `${(0, import_node_path19.basename)(knowledgeDir)}/` : `${dir}/`;
146397
147175
  let content3;
146398
147176
  try {
146399
- content3 = await (0, import_promises13.readFile)(indexFullPath, "utf8");
147177
+ content3 = await (0, import_promises15.readFile)(indexFullPath, "utf8");
146400
147178
  } catch {
146401
147179
  errors.push({
146402
147180
  dir: displayDir,
@@ -146432,12 +147210,12 @@ ${indexSnippet(missing)}`,
146432
147210
  return errors;
146433
147211
  }
146434
147212
  async function checkKnowledgeSections(knowledgeDir) {
146435
- const projectRoot = (0, import_node_path17.dirname)((0, import_node_path17.dirname)(knowledgeDir));
147213
+ const projectRoot = (0, import_node_path19.dirname)((0, import_node_path19.dirname)(knowledgeDir));
146436
147214
  const errors = [];
146437
147215
  for (const filePath of await listKnowledgeFiles(knowledgeDir)) {
146438
- const content3 = await (0, import_promises13.readFile)(filePath, "utf8");
147216
+ const content3 = await (0, import_promises15.readFile)(filePath, "utf8");
146439
147217
  const sections = flattenSections(parseSections(filePath, content3, projectRoot));
146440
- const displayPath = (0, import_node_path17.relative)(process.cwd(), filePath);
147218
+ const displayPath = (0, import_node_path19.relative)(process.cwd(), filePath);
146441
147219
  for (const section2 of sections) {
146442
147220
  if (!section2.firstParagraph) {
146443
147221
  errors.push({
@@ -146492,7 +147270,7 @@ function formatKnowledgeIndexErrors(errors, styler) {
146492
147270
 
146493
147271
  // src/knowledge/audit.ts
146494
147272
  var import_node_child_process4 = require("node:child_process");
146495
- var import_node_fs10 = require("node:fs");
147273
+ var import_node_fs12 = require("node:fs");
146496
147274
  init_graph();
146497
147275
  function runGit(projectRoot, args2) {
146498
147276
  return new Promise((resolve2) => {
@@ -146627,7 +147405,7 @@ async function analyzeKnowledgeImpacts(params) {
146627
147405
  const changedFiles = await getChangedFiles(params.projectRoot, params.mode);
146628
147406
  const knowledgeChangedFiles = changedFiles.filter((filePath) => filePath.startsWith("docyrus/knowledge/"));
146629
147407
  const diffStats = await getDiffStats(params.projectRoot, params.mode);
146630
- if (!params.knowledgeDir || !(0, import_node_fs10.existsSync)(params.knowledgeDir)) {
147408
+ if (!params.knowledgeDir || !(0, import_node_fs12.existsSync)(params.knowledgeDir)) {
146631
147409
  return {
146632
147410
  ok: true,
146633
147411
  mode: params.mode,
@@ -146733,7 +147511,7 @@ async function analyzeKnowledgeImpacts(params) {
146733
147511
  };
146734
147512
  }
146735
147513
  async function analyzeKnowledgeDoctor(params) {
146736
- if (!params.knowledgeDir || !(0, import_node_fs10.existsSync)(params.knowledgeDir)) {
147514
+ if (!params.knowledgeDir || !(0, import_node_fs12.existsSync)(params.knowledgeDir)) {
146737
147515
  return {
146738
147516
  ok: false,
146739
147517
  warnings: [{
@@ -146893,7 +147671,8 @@ async function getStopReason(knowledgeDir) {
146893
147671
  const code = await checkKnowledgeCodeRefs(knowledgeDir);
146894
147672
  const indexErrors = await checkKnowledgeIndex(knowledgeDir);
146895
147673
  const sectionErrors = await checkKnowledgeSections(knowledgeDir);
146896
- const totalErrors = markdown.errors.length + code.errors.length + indexErrors.length + sectionErrors.length;
147674
+ const projectPlanErrors = await validateProjectPlanGraph(process.cwd());
147675
+ const totalErrors = markdown.errors.length + code.errors.length + indexErrors.length + sectionErrors.length + projectPlanErrors.errors.length;
146897
147676
  const audit = await analyzeKnowledgeImpacts({
146898
147677
  projectRoot: process.cwd(),
146899
147678
  knowledgeDir,
@@ -146906,6 +147685,9 @@ async function getStopReason(knowledgeDir) {
146906
147685
  if (totalErrors > 0) {
146907
147686
  parts2.push(`docyrus knowledge check failed with ${totalErrors} error${totalErrors === 1 ? "" : "s"}.`);
146908
147687
  }
147688
+ for (const error48 of projectPlanErrors.errors) {
147689
+ parts2.push(error48.message);
147690
+ }
146909
147691
  for (const error48 of audit.blockingErrors) {
146910
147692
  parts2.push(error48.message);
146911
147693
  }
@@ -147055,6 +147837,7 @@ function createKnowledgeCli(dependencies) {
147055
147837
  maybePrintHuman(context, [
147056
147838
  `Knowledge graph ready at ${result.knowledgeDir}`,
147057
147839
  `knowledge.md: ${result.knowledgeFileStatus}`,
147840
+ `project-plan: ${result.projectPlanGraphPath}`,
147058
147841
  `AGENTS.md: ${result.agentsStatus}`,
147059
147842
  `CLAUDE.md: ${result.claudeStatus}`,
147060
147843
  `.cursor/rules/docyrus-knowledge.md: ${result.cursorRulesStatus}`,
@@ -147082,8 +147865,10 @@ function createKnowledgeCli(dependencies) {
147082
147865
  root: process.cwd(),
147083
147866
  brief: context.args.brief
147084
147867
  });
147868
+ const projectPlan = await syncProjectPlanSectionsFromKnowledge(process.cwd());
147085
147869
  maybePrintHuman(context, [
147086
- `Generated starter knowledge under ${(0, import_node_path18.join)(process.cwd(), "docyrus", "knowledge")}`,
147870
+ `Generated starter knowledge under ${(0, import_node_path20.join)(process.cwd(), "docyrus", "knowledge")}`,
147871
+ `project-plan: ${projectPlan.graphPath}`,
147087
147872
  `root: ${result.files.rootKnowledgeStatus}`,
147088
147873
  `architecture: ${result.files.architectureStatus}`,
147089
147874
  `features: ${result.files.featuresStatus}`,
@@ -147108,17 +147893,19 @@ function createKnowledgeCli(dependencies) {
147108
147893
  const codeRefs = await checkKnowledgeCodeRefs(knowledgeContext.knowledgeDir);
147109
147894
  const indexErrors = await checkKnowledgeIndex(knowledgeContext.knowledgeDir);
147110
147895
  const sectionErrors = await checkKnowledgeSections(knowledgeContext.knowledgeDir);
147896
+ const projectPlan = await validateProjectPlanGraph(process.cwd());
147111
147897
  const fileStats = { ...markdown.files };
147112
147898
  for (const [extension2, count] of Object.entries(codeRefs.files)) {
147113
147899
  fileStats[extension2] = (fileStats[extension2] || 0) + count;
147114
147900
  }
147115
- const totalErrors = markdown.errors.length + codeRefs.errors.length + indexErrors.length + sectionErrors.length;
147901
+ const totalErrors = markdown.errors.length + codeRefs.errors.length + indexErrors.length + sectionErrors.length + projectPlan.errors.length;
147116
147902
  const human = [
147117
147903
  formatKnowledgeFileStats(fileStats, knowledgeContext.styler),
147118
147904
  ...formatKnowledgeCheckErrors(markdown.errors, knowledgeContext.styler),
147119
147905
  ...formatKnowledgeCheckErrors(codeRefs.errors, knowledgeContext.styler),
147120
147906
  ...formatKnowledgeIndexErrors(indexErrors, knowledgeContext.styler),
147121
147907
  ...formatKnowledgeCheckErrors(sectionErrors, knowledgeContext.styler),
147908
+ ...projectPlan.errors.map((error48) => `- ${knowledgeContext.styler.cyan("docyrus/project-plan/project-plan.json")}: ${knowledgeContext.styler.red(error48.message)}`),
147122
147909
  totalErrors === 0 ? knowledgeContext.styler.green("All knowledge checks passed") : knowledgeContext.styler.red(`${totalErrors} error${totalErrors === 1 ? "" : "s"} found`)
147123
147910
  ].join("\n");
147124
147911
  maybePrintHuman(context, human);
@@ -147131,7 +147918,8 @@ function createKnowledgeCli(dependencies) {
147131
147918
  markdown: markdown.errors,
147132
147919
  codeRefs: codeRefs.errors,
147133
147920
  index: indexErrors,
147134
- sections: sectionErrors
147921
+ sections: sectionErrors,
147922
+ projectPlan: projectPlan.errors
147135
147923
  },
147136
147924
  files: fileStats,
147137
147925
  ok: totalErrors === 0
@@ -147456,9 +148244,10 @@ function createKnowledgeCli(dependencies) {
147456
148244
  markdown: await checkKnowledgeMarkdown(knowledgeContext.knowledgeDir),
147457
148245
  codeRefs: await checkKnowledgeCodeRefs(knowledgeContext.knowledgeDir),
147458
148246
  index: await checkKnowledgeIndex(knowledgeContext.knowledgeDir),
147459
- sections: await checkKnowledgeSections(knowledgeContext.knowledgeDir)
148247
+ sections: await checkKnowledgeSections(knowledgeContext.knowledgeDir),
148248
+ projectPlan: await validateProjectPlanGraph(process.cwd())
147460
148249
  } : null;
147461
- const blockingCheckErrors = checkResult ? checkResult.markdown.errors.length + checkResult.codeRefs.errors.length + checkResult.index.length + checkResult.sections.length : 0;
148250
+ const blockingCheckErrors = checkResult ? checkResult.markdown.errors.length + checkResult.codeRefs.errors.length + checkResult.index.length + checkResult.sections.length + checkResult.projectPlan.errors.length : 0;
147462
148251
  const ok3 = blockingCheckErrors === 0 && audit.blockingErrors.length === 0;
147463
148252
  const payload = {
147464
148253
  ok: ok3,
@@ -147466,7 +148255,8 @@ function createKnowledgeCli(dependencies) {
147466
148255
  markdown: checkResult.markdown.errors,
147467
148256
  codeRefs: checkResult.codeRefs.errors,
147468
148257
  index: checkResult.index,
147469
- sections: checkResult.sections
148258
+ sections: checkResult.sections,
148259
+ projectPlan: checkResult.projectPlan.errors
147470
148260
  } : null,
147471
148261
  audit
147472
148262
  };
@@ -147540,8 +148330,10 @@ function createKnowledgeCli(dependencies) {
147540
148330
  brief: context.args.brief,
147541
148331
  targetSectionIds: sectionIds
147542
148332
  });
148333
+ const projectPlan = await syncProjectPlanSectionsFromKnowledge(process.cwd());
147543
148334
  maybePrintHuman(context, [
147544
148335
  `Refreshed managed knowledge files.`,
148336
+ `project-plan: ${projectPlan.graphPath}`,
147545
148337
  `Targets: ${sectionIds.length > 0 ? sectionIds.join(", ") : "all starter files"}`,
147546
148338
  `root: ${result.files.rootKnowledgeStatus}`,
147547
148339
  `architecture: ${result.files.architectureStatus}`,
@@ -147555,6 +148347,8 @@ function createKnowledgeCli(dependencies) {
147555
148347
  authStore: dependencies.authStore,
147556
148348
  payload: {
147557
148349
  ...result,
148350
+ projectPlanGraphPath: projectPlan.graphPath,
148351
+ projectPlanMarkdownPath: projectPlan.markdownPath,
147558
148352
  targetSectionIds: sectionIds
147559
148353
  }
147560
148354
  });
@@ -147602,7 +148396,7 @@ function createKnowledgeCli(dependencies) {
147602
148396
  settingsRootPath: dependencies.settingsPaths.rootPath
147603
148397
  });
147604
148398
  const payload = {
147605
- id: (0, import_node_crypto4.randomUUID)(),
148399
+ id: (0, import_node_crypto6.randomUUID)(),
147606
148400
  projectRoot,
147607
148401
  knowledgeDir,
147608
148402
  settingsScope: dependencies.settingsPaths.scope,
@@ -147647,9 +148441,617 @@ function createKnowledgeCli(dependencies) {
147647
148441
  return knowledgeCli;
147648
148442
  }
147649
148443
 
148444
+ // src/commands/projectPlanCommands.ts
148445
+ var import_node_fs14 = require("node:fs");
148446
+ var import_node_path22 = __toESM(require("node:path"));
148447
+ init_graph();
148448
+
148449
+ // src/project-plan/artifactSync.ts
148450
+ var import_node_fs13 = require("node:fs");
148451
+ var import_promises16 = __toESM(require("node:fs/promises"));
148452
+ var import_node_path21 = __toESM(require("node:path"));
148453
+ var PLAN_FILE_NAME = "PLAN.md";
148454
+ var ARCHITECT_PLAN_JSON_FILE_NAME = "data-sources.plan.json";
148455
+ function normalizeMarkdownSectionName(value2) {
148456
+ return value2.trim().toLowerCase().replace(/\s+/gu, " ");
148457
+ }
148458
+ function parseBulletValue(line) {
148459
+ const trimmed = line.trim();
148460
+ if (!trimmed) {
148461
+ return null;
148462
+ }
148463
+ if (/^[-*]\s+/u.test(trimmed)) {
148464
+ return trimmed.replace(/^[-*]\s+/u, "").trim() || null;
148465
+ }
148466
+ if (/^\d+\.\s+/u.test(trimmed)) {
148467
+ return trimmed.replace(/^\d+\.\s+/u, "").trim() || null;
148468
+ }
148469
+ return null;
148470
+ }
148471
+ function parseMarkdownPlan(markdown) {
148472
+ const buckets = {
148473
+ summary: [],
148474
+ implementationChanges: [],
148475
+ testPlan: [],
148476
+ assumptions: []
148477
+ };
148478
+ let current = null;
148479
+ for (const rawLine of markdown.split(/\r?\n/gu)) {
148480
+ const line = rawLine.trim();
148481
+ if (!line) {
148482
+ continue;
148483
+ }
148484
+ if (line.startsWith("## ")) {
148485
+ const heading2 = normalizeMarkdownSectionName(line.slice(3));
148486
+ current = heading2 === "summary" ? "summary" : heading2 === "implementation changes" ? "implementationChanges" : heading2 === "test plan" ? "testPlan" : heading2 === "assumptions" ? "assumptions" : null;
148487
+ continue;
148488
+ }
148489
+ if (!current) {
148490
+ continue;
148491
+ }
148492
+ const parsedBullet = parseBulletValue(line);
148493
+ buckets[current].push(parsedBullet || line);
148494
+ }
148495
+ return buckets;
148496
+ }
148497
+ function classifyImplementationTaskType(taskText, fallbackTitle) {
148498
+ const text3 = `${fallbackTitle} ${taskText}`.toLowerCase();
148499
+ if (/(bug|fix|issue|regression|error|failure)/u.test(text3)) {
148500
+ return "bug-fix";
148501
+ }
148502
+ if (/(crud|query|list|create|update|delete|docyrus|api)/u.test(text3)) {
148503
+ return "work";
148504
+ }
148505
+ return "new-implementation";
148506
+ }
148507
+ function classifyTestTaskType(taskText) {
148508
+ const text3 = taskText.toLowerCase();
148509
+ if (/(browser|playwright|page|ui|journey|flow|automation)/u.test(text3)) {
148510
+ return "browser-automation-test";
148511
+ }
148512
+ return "api-test";
148513
+ }
148514
+ function isLikelyUserTask(taskText) {
148515
+ return /(manual|user|approval|credential|login|physical|real world|install locally|access)/u.test(taskText.toLowerCase());
148516
+ }
148517
+ function uniqueNonEmpty(values) {
148518
+ return [...new Set(values.map((value2) => value2.trim()).filter(Boolean))];
148519
+ }
148520
+ async function readArchitectPlanMarkdown(artifactDir) {
148521
+ const planPath = import_node_path21.default.join(artifactDir, PLAN_FILE_NAME);
148522
+ if (!(0, import_node_fs13.existsSync)(planPath)) {
148523
+ return null;
148524
+ }
148525
+ return await import_promises16.default.readFile(planPath, "utf8");
148526
+ }
148527
+ async function readArchitectPlanJson(artifactDir) {
148528
+ const jsonPath = import_node_path21.default.join(artifactDir, ARCHITECT_PLAN_JSON_FILE_NAME);
148529
+ if (!(0, import_node_fs13.existsSync)(jsonPath)) {
148530
+ return null;
148531
+ }
148532
+ return JSON.parse(await import_promises16.default.readFile(jsonPath, "utf8"));
148533
+ }
148534
+ async function upsertProjectPlanFromPlanArtifact(params) {
148535
+ const routes = await resolveDefaultProjectPlanRoutes(params.root);
148536
+ if (!(0, import_node_fs13.existsSync)(params.artifactPath)) {
148537
+ return {
148538
+ ok: false,
148539
+ updatedFeatureIds: [],
148540
+ updatedTaskIds: [],
148541
+ warnings: [`Plan artifact ${params.artifactPath} does not exist.`]
148542
+ };
148543
+ }
148544
+ const markdown = await import_promises16.default.readFile(params.artifactPath, "utf8");
148545
+ const parsed = parseMarkdownPlan(markdown);
148546
+ const title = params.task?.trim() || parsed.summary[0] || "Planned work";
148547
+ const warnings = [];
148548
+ const updatedFeatureIds = [];
148549
+ const updatedTaskIds = [];
148550
+ const deliveryFeature = await upsertProjectPlanFeature({
148551
+ root: params.root,
148552
+ sectionId: routes.featuresSectionId,
148553
+ title,
148554
+ summary: parsed.summary[0] || ""
148555
+ });
148556
+ updatedFeatureIds.push(deliveryFeature.id);
148557
+ const implementationItems = uniqueNonEmpty(parsed.implementationChanges);
148558
+ const implementationTaskSource = implementationItems.length > 0 ? implementationItems : [title];
148559
+ for (const item of implementationTaskSource) {
148560
+ const task = await upsertProjectPlanTask({
148561
+ root: params.root,
148562
+ featureId: deliveryFeature.id,
148563
+ title: item,
148564
+ summary: item,
148565
+ type: classifyImplementationTaskType(item, title),
148566
+ assignee: isLikelyUserTask(item) ? "user" : "agent",
148567
+ status: "planned",
148568
+ acceptanceCriteria: []
148569
+ });
148570
+ updatedTaskIds.push(task.id);
148571
+ }
148572
+ const testItems = uniqueNonEmpty(parsed.testPlan);
148573
+ if (testItems.length > 0) {
148574
+ const testingFeature = await upsertProjectPlanFeature({
148575
+ root: params.root,
148576
+ sectionId: routes.testingSectionId,
148577
+ title: `${title} tests`,
148578
+ summary: parsed.testPlan[0] || ""
148579
+ });
148580
+ updatedFeatureIds.push(testingFeature.id);
148581
+ for (const item of testItems) {
148582
+ const task = await upsertProjectPlanTask({
148583
+ root: params.root,
148584
+ featureId: testingFeature.id,
148585
+ title: item,
148586
+ summary: item,
148587
+ type: classifyTestTaskType(item),
148588
+ assignee: "agent",
148589
+ status: "planned",
148590
+ acceptanceCriteria: []
148591
+ });
148592
+ updatedTaskIds.push(task.id);
148593
+ }
148594
+ }
148595
+ const userFollowUps = uniqueNonEmpty(parsed.assumptions.filter((item) => isLikelyUserTask(item)));
148596
+ if (userFollowUps.length > 0) {
148597
+ const workflowsFeature = await upsertProjectPlanFeature({
148598
+ root: params.root,
148599
+ sectionId: routes.workflowsSectionId,
148600
+ title: `${title} follow-ups`,
148601
+ summary: userFollowUps[0] || ""
148602
+ });
148603
+ updatedFeatureIds.push(workflowsFeature.id);
148604
+ for (const item of userFollowUps) {
148605
+ const task = await upsertProjectPlanTask({
148606
+ root: params.root,
148607
+ featureId: workflowsFeature.id,
148608
+ title: item,
148609
+ summary: item,
148610
+ type: "work",
148611
+ assignee: "user",
148612
+ status: "planned",
148613
+ acceptanceCriteria: []
148614
+ });
148615
+ updatedTaskIds.push(task.id);
148616
+ }
148617
+ }
148618
+ if (implementationItems.length === 0) {
148619
+ warnings.push("Plan artifact did not include explicit Implementation Changes bullets; created a single delivery task from the plan title.");
148620
+ }
148621
+ return {
148622
+ ok: true,
148623
+ updatedFeatureIds: uniqueNonEmpty(updatedFeatureIds),
148624
+ updatedTaskIds: uniqueNonEmpty(updatedTaskIds),
148625
+ warnings
148626
+ };
148627
+ }
148628
+ function normalizeArchitectPhaseTitle(phase, fallbackIndex) {
148629
+ if (typeof phase === "string") {
148630
+ return {
148631
+ title: phase,
148632
+ summary: phase
148633
+ };
148634
+ }
148635
+ return {
148636
+ title: phase.title?.trim() || `Architect phase ${fallbackIndex + 1}`,
148637
+ summary: phase.summary?.trim() || phase.title?.trim() || `Architect phase ${fallbackIndex + 1}`
148638
+ };
148639
+ }
148640
+ async function upsertProjectPlanFromArchitectArtifact(params) {
148641
+ const routes = await resolveDefaultProjectPlanRoutes(params.root);
148642
+ const warnings = [];
148643
+ const updatedFeatureIds = [];
148644
+ const updatedTaskIds = [];
148645
+ const architectJson = await readArchitectPlanJson(params.artifactDir);
148646
+ const architectMarkdown = await readArchitectPlanMarkdown(params.artifactDir);
148647
+ const parsedMarkdown = architectMarkdown ? parseMarkdownPlan(architectMarkdown) : null;
148648
+ const title = params.brief?.trim() || architectJson?.brief?.trim() || "Architected work";
148649
+ const architectureFeature = await upsertProjectPlanFeature({
148650
+ root: params.root,
148651
+ sectionId: routes.architectureSectionId,
148652
+ title,
148653
+ summary: parsedMarkdown?.summary[0] || ""
148654
+ });
148655
+ updatedFeatureIds.push(architectureFeature.id);
148656
+ if (architectJson?.newDataSources && architectJson.newDataSources.length > 0) {
148657
+ const dataSourceNames = architectJson.newDataSources.map((item) => item.title || item.name || item.slug).filter((value2) => typeof value2 === "string" && value2.trim().length > 0);
148658
+ if (dataSourceNames.length > 0) {
148659
+ const task = await upsertProjectPlanTask({
148660
+ root: params.root,
148661
+ featureId: architectureFeature.id,
148662
+ title: `Design and apply data source changes: ${dataSourceNames.join(", ")}`,
148663
+ summary: `Architected data sources: ${dataSourceNames.join(", ")}`,
148664
+ type: "new-implementation",
148665
+ assignee: "agent",
148666
+ status: "planned",
148667
+ acceptanceCriteria: []
148668
+ });
148669
+ updatedTaskIds.push(task.id);
148670
+ }
148671
+ }
148672
+ const phases = architectJson?.applyPhases || [];
148673
+ if (phases.length > 0) {
148674
+ for (const [index2, phase] of phases.entries()) {
148675
+ const normalized = normalizeArchitectPhaseTitle(phase, index2);
148676
+ const isVerification = /verification/u.test(normalized.title.toLowerCase());
148677
+ const task = await upsertProjectPlanTask({
148678
+ root: params.root,
148679
+ featureId: architectureFeature.id,
148680
+ title: normalized.title,
148681
+ summary: normalized.summary,
148682
+ type: isVerification ? "api-test" : "new-implementation",
148683
+ assignee: "agent",
148684
+ status: "planned",
148685
+ acceptanceCriteria: []
148686
+ });
148687
+ updatedTaskIds.push(task.id);
148688
+ }
148689
+ }
148690
+ const architectureItems = uniqueNonEmpty(parsedMarkdown?.implementationChanges || []);
148691
+ if (architectureItems.length > 0) {
148692
+ for (const item of architectureItems) {
148693
+ const task = await upsertProjectPlanTask({
148694
+ root: params.root,
148695
+ featureId: architectureFeature.id,
148696
+ title: item,
148697
+ summary: item,
148698
+ type: /crud|query|docyrus|api/u.test(item.toLowerCase()) ? "work" : "new-implementation",
148699
+ assignee: isLikelyUserTask(item) ? "user" : "agent",
148700
+ status: "planned",
148701
+ acceptanceCriteria: []
148702
+ });
148703
+ updatedTaskIds.push(task.id);
148704
+ }
148705
+ }
148706
+ if (architectMarkdown) {
148707
+ const testItems = uniqueNonEmpty(parsedMarkdown?.testPlan || []);
148708
+ if (testItems.length > 0) {
148709
+ const testingFeature = await upsertProjectPlanFeature({
148710
+ root: params.root,
148711
+ sectionId: routes.testingSectionId,
148712
+ title: `${title} verification`,
148713
+ summary: testItems[0] || ""
148714
+ });
148715
+ updatedFeatureIds.push(testingFeature.id);
148716
+ for (const item of testItems) {
148717
+ const task = await upsertProjectPlanTask({
148718
+ root: params.root,
148719
+ featureId: testingFeature.id,
148720
+ title: item,
148721
+ summary: item,
148722
+ type: classifyTestTaskType(item),
148723
+ assignee: "agent",
148724
+ status: "planned",
148725
+ acceptanceCriteria: []
148726
+ });
148727
+ updatedTaskIds.push(task.id);
148728
+ }
148729
+ }
148730
+ const followUps = uniqueNonEmpty((parsedMarkdown?.assumptions || []).filter((item) => isLikelyUserTask(item)));
148731
+ if (followUps.length > 0) {
148732
+ const workflowsFeature = await upsertProjectPlanFeature({
148733
+ root: params.root,
148734
+ sectionId: routes.workflowsSectionId,
148735
+ title: `${title} manual follow-ups`,
148736
+ summary: followUps[0] || ""
148737
+ });
148738
+ updatedFeatureIds.push(workflowsFeature.id);
148739
+ for (const item of followUps) {
148740
+ const task = await upsertProjectPlanTask({
148741
+ root: params.root,
148742
+ featureId: workflowsFeature.id,
148743
+ title: item,
148744
+ summary: item,
148745
+ type: "work",
148746
+ assignee: "user",
148747
+ status: "planned",
148748
+ acceptanceCriteria: []
148749
+ });
148750
+ updatedTaskIds.push(task.id);
148751
+ }
148752
+ }
148753
+ } else {
148754
+ warnings.push(`Architect artifact ${import_node_path21.default.join(params.artifactDir, PLAN_FILE_NAME)} was not found; project plan sync used JSON-only inputs.`);
148755
+ }
148756
+ return {
148757
+ ok: true,
148758
+ updatedFeatureIds: uniqueNonEmpty(updatedFeatureIds),
148759
+ updatedTaskIds: uniqueNonEmpty(updatedTaskIds),
148760
+ warnings
148761
+ };
148762
+ }
148763
+
148764
+ // src/commands/projectPlanCommands.ts
148765
+ function hasStructuredOutputOverride3(argv) {
148766
+ return argv.some((token) => token === "--json" || token === "--verbose" || token === "--format");
148767
+ }
148768
+ function maybePrintHuman2(context, text3) {
148769
+ if (context.agent || hasStructuredOutputOverride3(process.argv.slice(2)) || !text3) {
148770
+ return;
148771
+ }
148772
+ process.stdout.write(text3.endsWith("\n") ? text3 : `${text3}
148773
+ `);
148774
+ }
148775
+ function formatProjectPlanErrors(errors) {
148776
+ if (errors.length === 0) {
148777
+ return "Project plan check passed.";
148778
+ }
148779
+ return errors.map((error48) => `- [${error48.code}] ${error48.message}${error48.target ? ` (${error48.target})` : ""}`).join("\n");
148780
+ }
148781
+ function parseOptionalStringArray(raw, source) {
148782
+ if (!raw?.trim()) {
148783
+ return [];
148784
+ }
148785
+ const parsed = parseJsonData(raw, source);
148786
+ if (!Array.isArray(parsed) || parsed.some((value2) => typeof value2 !== "string")) {
148787
+ throw new UserInputError(`${source} must be a JSON string array.`);
148788
+ }
148789
+ return parsed.map((value2) => value2.trim()).filter(Boolean);
148790
+ }
148791
+ async function wrapPayload(dependencies, payload) {
148792
+ const apiBaseUrl = await dependencies.environmentConfigService.getActiveApiBaseUrl();
148793
+ return await injectContext({
148794
+ apiBaseUrl,
148795
+ authStore: dependencies.authStore,
148796
+ payload
148797
+ });
148798
+ }
148799
+ function createProjectPlanCli(dependencies) {
148800
+ const projectPlanCli = Cli_exports.create("project-plan", {
148801
+ description: "Repo-tracked project plan graph commands",
148802
+ env: EnvSchema
148803
+ });
148804
+ projectPlanCli.command("show", {
148805
+ description: "Show the current project plan hierarchy",
148806
+ env: EnvSchema,
148807
+ outputPolicy: "agent-only",
148808
+ run: async (context) => {
148809
+ const root = process.cwd();
148810
+ const graph = await readProjectPlanGraph(root);
148811
+ const hierarchy = await buildProjectPlanHierarchy(root, graph);
148812
+ maybePrintHuman2(context, [
148813
+ `projectPlanDir: ${resolveProjectPlanDirectory(root)}`,
148814
+ `sections: ${hierarchy.sections.length}`,
148815
+ `features: ${graph.features.length}`,
148816
+ `tasks: ${graph.tasks.length}`
148817
+ ].join("\n"));
148818
+ return await wrapPayload(dependencies, {
148819
+ graph,
148820
+ hierarchy,
148821
+ graphPath: resolveProjectPlanGraphPath(root),
148822
+ markdownPath: resolveProjectPlanMarkdownPath(root)
148823
+ });
148824
+ }
148825
+ });
148826
+ projectPlanCli.command("check", {
148827
+ description: "Validate the canonical project plan graph against the knowledge graph",
148828
+ env: EnvSchema,
148829
+ outputPolicy: "agent-only",
148830
+ run: async (context) => {
148831
+ const result = await validateProjectPlanGraph(process.cwd());
148832
+ maybePrintHuman2(context, formatProjectPlanErrors(result.errors));
148833
+ return await wrapPayload(dependencies, result);
148834
+ }
148835
+ });
148836
+ projectPlanCli.command("sync-sections", {
148837
+ description: "Seed or re-sync project plan sections from current knowledge section ids",
148838
+ env: EnvSchema,
148839
+ outputPolicy: "agent-only",
148840
+ run: async (context) => {
148841
+ const result = await syncProjectPlanSectionsFromKnowledge(process.cwd());
148842
+ maybePrintHuman2(context, `Synced project plan sections to ${result.graph.sections.length} knowledge section ids.`);
148843
+ return await wrapPayload(dependencies, {
148844
+ graphPath: result.graphPath,
148845
+ markdownPath: result.markdownPath,
148846
+ sectionCount: result.graph.sections.length
148847
+ });
148848
+ }
148849
+ });
148850
+ projectPlanCli.command("ensure", {
148851
+ description: "Ensure the canonical project plan graph exists",
148852
+ env: EnvSchema,
148853
+ outputPolicy: "agent-only",
148854
+ run: async (context) => {
148855
+ const result = await ensureProjectPlanGraph(process.cwd());
148856
+ maybePrintHuman2(context, `Project plan ready at ${result.graphPath}`);
148857
+ return await wrapPayload(dependencies, {
148858
+ graphPath: result.graphPath,
148859
+ markdownPath: result.markdownPath,
148860
+ graph: result.graph
148861
+ });
148862
+ }
148863
+ });
148864
+ projectPlanCli.command("upsert-feature", {
148865
+ description: "Create or update a canonical feature",
148866
+ env: EnvSchema,
148867
+ outputPolicy: "agent-only",
148868
+ options: external_exports.object({
148869
+ featureId: external_exports.string().optional().describe("Optional existing feature id"),
148870
+ sectionId: external_exports.string().min(1).describe("Knowledge section id"),
148871
+ title: external_exports.string().min(1).describe("Feature title"),
148872
+ slug: external_exports.string().optional().describe("Optional feature slug"),
148873
+ summary: external_exports.string().optional().describe("Feature summary")
148874
+ }),
148875
+ run: async (context) => {
148876
+ const feature = await upsertProjectPlanFeature({
148877
+ root: process.cwd(),
148878
+ featureId: context.options.featureId,
148879
+ sectionId: context.options.sectionId,
148880
+ title: context.options.title,
148881
+ slug: context.options.slug,
148882
+ summary: context.options.summary
148883
+ });
148884
+ maybePrintHuman2(context, `Upserted feature ${feature.id}`);
148885
+ return await wrapPayload(dependencies, feature);
148886
+ }
148887
+ });
148888
+ projectPlanCli.command("upsert-task", {
148889
+ description: "Create or update a canonical task",
148890
+ env: EnvSchema,
148891
+ outputPolicy: "agent-only",
148892
+ options: external_exports.object({
148893
+ taskId: external_exports.string().optional().describe("Optional existing task id"),
148894
+ featureId: external_exports.string().min(1).describe("Owning feature id"),
148895
+ sectionId: external_exports.string().optional().describe("Optional explicit section id; defaults to feature section"),
148896
+ title: external_exports.string().min(1).describe("Task title"),
148897
+ summary: external_exports.string().optional().describe("Task summary"),
148898
+ type: external_exports.enum(PROJECT_TASK_TYPES).describe("Task type"),
148899
+ assignee: external_exports.enum(PROJECT_TASK_ASSIGNEES).describe("Task assignee"),
148900
+ status: external_exports.enum(PROJECT_TASK_STATUSES).optional().describe("Task status"),
148901
+ acceptanceCriteria: external_exports.string().optional().describe("JSON string array of acceptance criteria")
148902
+ }),
148903
+ run: async (context) => {
148904
+ const task = await upsertProjectPlanTask({
148905
+ root: process.cwd(),
148906
+ taskId: context.options.taskId,
148907
+ featureId: context.options.featureId,
148908
+ sectionId: context.options.sectionId,
148909
+ title: context.options.title,
148910
+ summary: context.options.summary,
148911
+ type: context.options.type,
148912
+ assignee: context.options.assignee,
148913
+ status: context.options.status,
148914
+ acceptanceCriteria: parseOptionalStringArray(context.options.acceptanceCriteria, "--acceptanceCriteria")
148915
+ });
148916
+ maybePrintHuman2(context, `Upserted task ${task.id}`);
148917
+ return await wrapPayload(dependencies, task);
148918
+ }
148919
+ });
148920
+ projectPlanCli.command("get-task", {
148921
+ description: "Get a task with linked local subtasks",
148922
+ env: EnvSchema,
148923
+ outputPolicy: "agent-only",
148924
+ options: external_exports.object({
148925
+ taskId: external_exports.string().min(1).describe("Task id")
148926
+ }),
148927
+ run: async (context) => {
148928
+ const task = await getProjectPlanTask({
148929
+ root: process.cwd(),
148930
+ taskId: context.options.taskId
148931
+ });
148932
+ if (!task) {
148933
+ throw new UserInputError(`Task "${context.options.taskId}" not found.`);
148934
+ }
148935
+ maybePrintHuman2(context, `${task.id}: ${task.title}`);
148936
+ return await wrapPayload(dependencies, task);
148937
+ }
148938
+ });
148939
+ projectPlanCli.command("set-task-status", {
148940
+ description: "Update a canonical task status",
148941
+ env: EnvSchema,
148942
+ outputPolicy: "agent-only",
148943
+ options: external_exports.object({
148944
+ taskId: external_exports.string().min(1).describe("Task id"),
148945
+ status: external_exports.enum(PROJECT_TASK_STATUSES).describe("Next status")
148946
+ }),
148947
+ run: async (context) => {
148948
+ const task = await updateProjectPlanTaskStatus({
148949
+ root: process.cwd(),
148950
+ taskId: context.options.taskId,
148951
+ status: context.options.status
148952
+ });
148953
+ maybePrintHuman2(context, `Updated ${task.id} to ${task.status}`);
148954
+ return await wrapPayload(dependencies, task);
148955
+ }
148956
+ });
148957
+ projectPlanCli.command("create-linked-todo", {
148958
+ description: "Create a local .pi/todos subtask linked to a canonical task",
148959
+ env: EnvSchema,
148960
+ outputPolicy: "agent-only",
148961
+ options: external_exports.object({
148962
+ taskId: external_exports.string().min(1).describe("Canonical task id"),
148963
+ title: external_exports.string().optional().describe("Optional todo title; defaults to task title"),
148964
+ body: external_exports.string().optional().describe("Optional todo body")
148965
+ }),
148966
+ run: async (context) => {
148967
+ const task = await getProjectPlanTask({
148968
+ root: process.cwd(),
148969
+ taskId: context.options.taskId
148970
+ });
148971
+ if (!task) {
148972
+ throw new UserInputError(`Task "${context.options.taskId}" not found.`);
148973
+ }
148974
+ if (task.assignee !== "agent") {
148975
+ throw new UserInputError(`Task "${task.id}" is assigned to "${task.assignee}" and cannot own local agent subtasks.`);
148976
+ }
148977
+ const linkedTodo = await createLinkedTodo({
148978
+ root: process.cwd(),
148979
+ parentTaskId: task.id,
148980
+ title: context.options.title?.trim() || task.title,
148981
+ body: context.options.body?.trim() || task.summary
148982
+ });
148983
+ maybePrintHuman2(context, `Created linked todo ${linkedTodo.id} for task ${task.id}`);
148984
+ return await wrapPayload(dependencies, linkedTodo);
148985
+ }
148986
+ });
148987
+ projectPlanCli.command("upsert-from-plan", {
148988
+ description: "Internal command used by /plan to sync an ended planning artifact into the canonical graph",
148989
+ env: EnvSchema,
148990
+ outputPolicy: "agent-only",
148991
+ options: external_exports.object({
148992
+ artifactPath: external_exports.string().min(1).describe("Path to the saved plan markdown artifact"),
148993
+ task: external_exports.string().optional().describe("Original planning task")
148994
+ }),
148995
+ run: async (context) => {
148996
+ const result = await upsertProjectPlanFromPlanArtifact({
148997
+ root: process.cwd(),
148998
+ artifactPath: context.options.artifactPath,
148999
+ task: context.options.task
149000
+ });
149001
+ maybePrintHuman2(context, `Synced plan artifact with ${result.updatedTaskIds.length} task updates.`);
149002
+ return await wrapPayload(dependencies, result);
149003
+ }
149004
+ });
149005
+ projectPlanCli.command("upsert-from-architect", {
149006
+ description: "Internal command used by /architect to sync architect artifacts into the canonical graph",
149007
+ env: EnvSchema,
149008
+ outputPolicy: "agent-only",
149009
+ options: external_exports.object({
149010
+ artifactDir: external_exports.string().min(1).describe("Architect artifact directory"),
149011
+ brief: external_exports.string().optional().describe("Original architect brief")
149012
+ }),
149013
+ run: async (context) => {
149014
+ const result = await upsertProjectPlanFromArchitectArtifact({
149015
+ root: process.cwd(),
149016
+ artifactDir: context.options.artifactDir,
149017
+ brief: context.options.brief
149018
+ });
149019
+ maybePrintHuman2(context, `Synced architect artifact with ${result.updatedTaskIds.length} task updates.`);
149020
+ return await wrapPayload(dependencies, result);
149021
+ }
149022
+ });
149023
+ projectPlanCli.command("config", {
149024
+ description: "Show resolved project-plan and knowledge graph paths",
149025
+ env: EnvSchema,
149026
+ outputPolicy: "agent-only",
149027
+ run: async (context) => {
149028
+ const root = process.cwd();
149029
+ const knowledgeDir = import_node_path22.default.join(root, "docyrus", "knowledge");
149030
+ const knowledgeSectionCount = (0, import_node_fs14.existsSync)(knowledgeDir) ? flattenSections(await loadAllSections(knowledgeDir)).length : 0;
149031
+ const payload = {
149032
+ projectRoot: root,
149033
+ knowledgeDir: (0, import_node_fs14.existsSync)(knowledgeDir) ? knowledgeDir : null,
149034
+ projectPlanDir: resolveProjectPlanDirectory(root),
149035
+ graphPath: resolveProjectPlanGraphPath(root),
149036
+ markdownPath: resolveProjectPlanMarkdownPath(root),
149037
+ knowledgeSectionCount
149038
+ };
149039
+ maybePrintHuman2(context, [
149040
+ `knowledgeDir: ${payload.knowledgeDir || "(not found)"}`,
149041
+ `projectPlanDir: ${payload.projectPlanDir}`,
149042
+ `graphPath: ${payload.graphPath}`,
149043
+ `markdownPath: ${payload.markdownPath}`,
149044
+ `knowledgeSections: ${payload.knowledgeSectionCount}`
149045
+ ].join("\n"));
149046
+ return await wrapPayload(dependencies, payload);
149047
+ }
149048
+ });
149049
+ return projectPlanCli;
149050
+ }
149051
+
147650
149052
  // src/services/studioPayload.ts
147651
- var import_promises14 = require("node:fs/promises");
147652
- var import_node_path19 = require("node:path");
149053
+ var import_promises17 = require("node:fs/promises");
149054
+ var import_node_path23 = require("node:path");
147653
149055
  async function readStdinText3() {
147654
149056
  if (process.stdin.isTTY) {
147655
149057
  return "";
@@ -147664,7 +149066,7 @@ async function readStdinText3() {
147664
149066
  }
147665
149067
  return Buffer.concat(chunks).toString("utf8").trim();
147666
149068
  }
147667
- function isRecord3(value2) {
149069
+ function isRecord4(value2) {
147668
149070
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
147669
149071
  }
147670
149072
  async function readStudioWriteInput(params) {
@@ -147672,7 +149074,7 @@ async function readStudioWriteInput(params) {
147672
149074
  data,
147673
149075
  fromFile,
147674
149076
  readStdin: readStdin2 = readStdinText3,
147675
- readFileFn = async (path3, encoding) => await (0, import_promises14.readFile)(path3, encoding)
149077
+ readFileFn = async (path7, encoding) => await (0, import_promises17.readFile)(path7, encoding)
147676
149078
  } = params;
147677
149079
  const trimmedData = data?.trim();
147678
149080
  const trimmedFromFile = fromFile?.trim();
@@ -147680,7 +149082,7 @@ async function readStudioWriteInput(params) {
147680
149082
  throw new UserInputError("Provide either --data or --from-file, not both.");
147681
149083
  }
147682
149084
  if (trimmedFromFile) {
147683
- const extension2 = (0, import_node_path19.extname)(trimmedFromFile).toLowerCase();
149085
+ const extension2 = (0, import_node_path23.extname)(trimmedFromFile).toLowerCase();
147684
149086
  if (extension2 && extension2 !== ".json") {
147685
149087
  throw new UserInputError("Studio commands support only JSON files in --from-file.");
147686
149088
  }
@@ -147704,7 +149106,7 @@ async function readStudioWriteInput(params) {
147704
149106
  return parseJsonData(stdinContent, "stdin");
147705
149107
  }
147706
149108
  function ensureObjectPayload(payload, label) {
147707
- if (!isRecord3(payload)) {
149109
+ if (!isRecord4(payload)) {
147708
149110
  throw new UserInputError(`${label} expects a JSON object payload.`);
147709
149111
  }
147710
149112
  return payload;
@@ -147727,7 +149129,7 @@ function normalizeBatchPayload(payload, key) {
147727
149129
  [key]: payload
147728
149130
  };
147729
149131
  }
147730
- if (isRecord3(payload)) {
149132
+ if (isRecord4(payload)) {
147731
149133
  if (key in payload) {
147732
149134
  return payload;
147733
149135
  }
@@ -147739,7 +149141,7 @@ function normalizeBatchPayload(payload, key) {
147739
149141
  }
147740
149142
 
147741
149143
  // src/services/studioResolver.ts
147742
- function isRecord4(value2) {
149144
+ function isRecord5(value2) {
147743
149145
  return typeof value2 === "object" && value2 !== null;
147744
149146
  }
147745
149147
  function extractString2(record2, key) {
@@ -147748,10 +149150,10 @@ function extractString2(record2, key) {
147748
149150
  }
147749
149151
  function extractArray(payload) {
147750
149152
  if (Array.isArray(payload)) {
147751
- return payload.filter((item) => isRecord4(item));
149153
+ return payload.filter((item) => isRecord5(item));
147752
149154
  }
147753
- if (isRecord4(payload) && Array.isArray(payload.data)) {
147754
- return payload.data.filter((item) => isRecord4(item));
149155
+ if (isRecord5(payload) && Array.isArray(payload.data)) {
149156
+ return payload.data.filter((item) => isRecord5(item));
147755
149157
  }
147756
149158
  return [];
147757
149159
  }
@@ -147919,11 +149321,11 @@ function requireNonEmptyObject(payload, label) {
147919
149321
  throw new UserInputError(`${label} payload is empty. Provide flags, --data, or --from-file.`);
147920
149322
  }
147921
149323
  }
147922
- function isRecord5(value2) {
149324
+ function isRecord6(value2) {
147923
149325
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
147924
149326
  }
147925
149327
  function normalizeBatchUpdateFieldItem(item) {
147926
- if (!isRecord5(item)) {
149328
+ if (!isRecord6(item)) {
147927
149329
  return item;
147928
149330
  }
147929
149331
  const normalized = {
@@ -147957,7 +149359,7 @@ function normalizeBatchUpdateFieldsPayload(payload) {
147957
149359
  };
147958
149360
  }
147959
149361
  function normalizeUpdateEnumItem(item) {
147960
- if (!isRecord5(item)) {
149362
+ if (!isRecord6(item)) {
147961
149363
  return item;
147962
149364
  }
147963
149365
  if (!("enumId" in item) && typeof item.id === "string") {
@@ -148685,8 +150087,8 @@ function createStudioCli(dependencies) {
148685
150087
 
148686
150088
  // src/commands/tuiCommand.ts
148687
150089
  var import_node_child_process5 = require("node:child_process");
148688
- var import_node_fs11 = require("node:fs");
148689
- var import_node_path20 = require("node:path");
150090
+ var import_node_fs15 = require("node:fs");
150091
+ var import_node_path24 = require("node:path");
148690
150092
  function summarizeFailure2(result) {
148691
150093
  const stderr = result.stderr?.toString().trim();
148692
150094
  if (stderr && stderr.length > 0) {
@@ -148703,23 +150105,23 @@ function summarizeFailure2(result) {
148703
150105
  function resolveCliScriptPath() {
148704
150106
  const argvScript = process.argv[1];
148705
150107
  if (argvScript && argvScript.trim().length > 0) {
148706
- return (0, import_node_path20.isAbsolute)(argvScript) ? argvScript : (0, import_node_path20.resolve)(process.cwd(), argvScript);
150108
+ return (0, import_node_path24.isAbsolute)(argvScript) ? argvScript : (0, import_node_path24.resolve)(process.cwd(), argvScript);
148707
150109
  }
148708
150110
  return __filename;
148709
150111
  }
148710
150112
  function resolveOpenTuiEntryPath(options2 = {}) {
148711
150113
  const cwd = options2.cwd ?? process.cwd();
148712
150114
  const dirname13 = options2.dirname ?? __dirname;
148713
- const fileExists = options2.existsSyncFn ?? import_node_fs11.existsSync;
150115
+ const fileExists = options2.existsSyncFn ?? import_node_fs15.existsSync;
148714
150116
  const candidates = [
148715
150117
  // Source/dev mode in monorepo. Prefer this first so Bun resolves deps via
148716
150118
  // apps/api-cli/node_modules in workspace runs (e.g. `pnpm docyrus tui`).
148717
- (0, import_node_path20.resolve)(cwd, "apps/api-cli/src/tui/opentuiMain.tsx"),
148718
- (0, import_node_path20.resolve)(dirname13, "../tui/opentuiMain.tsx"),
150119
+ (0, import_node_path24.resolve)(cwd, "apps/api-cli/src/tui/opentuiMain.tsx"),
150120
+ (0, import_node_path24.resolve)(dirname13, "../tui/opentuiMain.tsx"),
148719
150121
  // Dist mode (bundled command runtime)
148720
- (0, import_node_path20.resolve)(dirname13, "tui.mjs"),
148721
- (0, import_node_path20.resolve)(dirname13, "../tui.mjs"),
148722
- (0, import_node_path20.resolve)(cwd, "dist/apps/api-cli/tui.mjs")
150122
+ (0, import_node_path24.resolve)(dirname13, "tui.mjs"),
150123
+ (0, import_node_path24.resolve)(dirname13, "../tui.mjs"),
150124
+ (0, import_node_path24.resolve)(cwd, "dist/apps/api-cli/tui.mjs")
148723
150125
  ];
148724
150126
  const resolved = candidates.find((candidate) => fileExists(candidate));
148725
150127
  if (!resolved) {
@@ -148860,7 +150262,7 @@ async function parseResponseBody(response) {
148860
150262
  }
148861
150263
  }
148862
150264
  function normalizeErrorResponse(params) {
148863
- const { status, path: path3, headers, body: body2 } = params;
150265
+ const { status, path: path7, headers, body: body2 } = params;
148864
150266
  const bodyObject = typeof body2 === "object" && body2 !== null ? body2 : null;
148865
150267
  const errorCodeValue = bodyObject?.error;
148866
150268
  const errorDescriptionValue = bodyObject?.error_description ?? bodyObject?.message;
@@ -148870,7 +150272,7 @@ function normalizeErrorResponse(params) {
148870
150272
  status,
148871
150273
  error: errorCode,
148872
150274
  error_description: errorDescription,
148873
- path: path3,
150275
+ path: path7,
148874
150276
  rate_limit_limit: headers.get("ratelimit-limit") || void 0,
148875
150277
  rate_limit_remaining: headers.get("ratelimit-remaining") || void 0,
148876
150278
  rate_limit_reset: headers.get("ratelimit-reset") || void 0,
@@ -148878,13 +150280,13 @@ function normalizeErrorResponse(params) {
148878
150280
  raw: body2
148879
150281
  };
148880
150282
  }
148881
- function normalizePathForUrl(path3) {
148882
- return normalizeApiPath(path3);
150283
+ function normalizePathForUrl(path7) {
150284
+ return normalizeApiPath(path7);
148883
150285
  }
148884
150286
  async function requestDocyrusApi(options2) {
148885
150287
  const {
148886
150288
  baseUrl,
148887
- path: path3,
150289
+ path: path7,
148888
150290
  method = "GET",
148889
150291
  headers,
148890
150292
  query,
@@ -148893,7 +150295,7 @@ async function requestDocyrusApi(options2) {
148893
150295
  fetchFn = fetch
148894
150296
  } = options2;
148895
150297
  const normalizedBaseUrl = normalizeApiBaseUrl(baseUrl);
148896
- const normalizedPath = normalizePathForUrl(path3);
150298
+ const normalizedPath = normalizePathForUrl(path7);
148897
150299
  const url2 = `${normalizedBaseUrl}${normalizedPath}${toQueryString(query)}`;
148898
150300
  const requestHeaders = {
148899
150301
  Accept: "application/json",
@@ -148953,12 +150355,12 @@ var ApiClient = class {
148953
150355
  const {
148954
150356
  authRequired = true,
148955
150357
  method = "GET",
148956
- path: path3,
150358
+ path: path7,
148957
150359
  headers,
148958
150360
  query,
148959
150361
  body: body2
148960
150362
  } = options2;
148961
- if (!path3) {
150363
+ if (!path7) {
148962
150364
  throw new UserInputError("Request path is required.");
148963
150365
  }
148964
150366
  let authToken;
@@ -148968,7 +150370,7 @@ var ApiClient = class {
148968
150370
  return await requestDocyrusApi({
148969
150371
  baseUrl: this.#apiBaseUrl,
148970
150372
  method,
148971
- path: path3,
150373
+ path: path7,
148972
150374
  headers,
148973
150375
  query,
148974
150376
  body: body2,
@@ -148980,7 +150382,7 @@ var ApiClient = class {
148980
150382
 
148981
150383
  // src/services/authSession.ts
148982
150384
  var DEFAULT_MANUAL_ACCESS_TOKEN_EXPIRY_SECONDS = 3600;
148983
- function isRecord6(value2) {
150385
+ function isRecord7(value2) {
148984
150386
  return typeof value2 === "object" && value2 !== null;
148985
150387
  }
148986
150388
  function extractRecordValue(record2, keys) {
@@ -149294,11 +150696,11 @@ var AuthSessionService = class {
149294
150696
  fetchFn: this.params.fetchFn
149295
150697
  });
149296
150698
  const payload = response.data;
149297
- const dataCandidate = isRecord6(payload) && isRecord6(payload.data) ? payload.data : payload;
149298
- if (!isRecord6(dataCandidate)) {
150699
+ const dataCandidate = isRecord7(payload) && isRecord7(payload.data) ? payload.data : payload;
150700
+ if (!isRecord7(dataCandidate)) {
149299
150701
  throw new AuthSessionError("Unable to parse /users/me response.");
149300
150702
  }
149301
- const tenantCandidate = isRecord6(dataCandidate.tenant) ? dataCandidate.tenant : void 0;
150703
+ const tenantCandidate = isRecord7(dataCandidate.tenant) ? dataCandidate.tenant : void 0;
149302
150704
  const userId = extractString3(dataCandidate, ["id", "user_id"]);
149303
150705
  const email3 = extractString3(dataCandidate, ["email"]);
149304
150706
  const tenantId = tenantCandidate ? extractString3(tenantCandidate, ["id"]) : extractString3(dataCandidate, ["tenant_id", "tenantId"]);
@@ -149324,13 +150726,13 @@ var AuthSessionService = class {
149324
150726
  fetchFn: this.params.fetchFn
149325
150727
  });
149326
150728
  const payload = response.data;
149327
- const listCandidate = Array.isArray(payload) ? payload : isRecord6(payload) && Array.isArray(payload.data) ? payload.data : null;
150729
+ const listCandidate = Array.isArray(payload) ? payload : isRecord7(payload) && Array.isArray(payload.data) ? payload.data : null;
149328
150730
  if (!listCandidate) {
149329
150731
  throw new AuthSessionError("Unable to parse tenant catalog response.");
149330
150732
  }
149331
150733
  const mapped = [];
149332
150734
  for (const item of listCandidate) {
149333
- if (!isRecord6(item)) {
150735
+ if (!isRecord7(item)) {
149334
150736
  continue;
149335
150737
  }
149336
150738
  const tenantId = extractString3(item, ["id", "tenant_id"]);
@@ -149520,8 +150922,8 @@ var AuthSessionService = class {
149520
150922
  };
149521
150923
 
149522
150924
  // src/services/authStore.ts
149523
- var import_promises15 = require("node:fs/promises");
149524
- var import_node_path21 = require("node:path");
150925
+ var import_promises18 = require("node:fs/promises");
150926
+ var import_node_path25 = require("node:path");
149525
150927
  function createEmptyState() {
149526
150928
  return {
149527
150929
  version: 2,
@@ -149561,7 +150963,7 @@ var AuthStore = class {
149561
150963
  }
149562
150964
  async readState() {
149563
150965
  try {
149564
- const raw = await (0, import_promises15.readFile)(this.authFilePath, "utf8");
150966
+ const raw = await (0, import_promises18.readFile)(this.authFilePath, "utf8");
149565
150967
  const parsed = JSON.parse(raw);
149566
150968
  const legacy = LegacyAuthSessionSchema.safeParse(parsed);
149567
150969
  if (legacy.success) {
@@ -149597,17 +150999,17 @@ var AuthStore = class {
149597
150999
  });
149598
151000
  }
149599
151001
  const normalized = normalizeState2(validated.data);
149600
- const directory = (0, import_node_path21.dirname)(this.authFilePath);
149601
- await (0, import_promises15.mkdir)(directory, {
151002
+ const directory = (0, import_node_path25.dirname)(this.authFilePath);
151003
+ await (0, import_promises18.mkdir)(directory, {
149602
151004
  recursive: true,
149603
151005
  mode: 448
149604
151006
  });
149605
- await (0, import_promises15.writeFile)(this.authFilePath, `${JSON.stringify(normalized, null, 2)}
151007
+ await (0, import_promises18.writeFile)(this.authFilePath, `${JSON.stringify(normalized, null, 2)}
149606
151008
  `, {
149607
151009
  encoding: "utf8",
149608
151010
  mode: 384
149609
151011
  });
149610
- await (0, import_promises15.chmod)(this.authFilePath, 384);
151012
+ await (0, import_promises18.chmod)(this.authFilePath, 384);
149611
151013
  }
149612
151014
  async getActiveProfile(apiBaseUrl) {
149613
151015
  const normalizedApiBaseUrl = normalizeApiBaseUrl(apiBaseUrl);
@@ -149804,15 +151206,15 @@ var AuthStore = class {
149804
151206
  await this.writeState(state);
149805
151207
  }
149806
151208
  async clear() {
149807
- await (0, import_promises15.rm)(this.authFilePath, {
151209
+ await (0, import_promises18.rm)(this.authFilePath, {
149808
151210
  force: true
149809
151211
  });
149810
151212
  }
149811
151213
  };
149812
151214
 
149813
151215
  // src/services/environmentConfig.ts
149814
- var import_promises16 = require("node:fs/promises");
149815
- var import_node_path22 = require("node:path");
151216
+ var import_promises19 = require("node:fs/promises");
151217
+ var import_node_path26 = require("node:path");
149816
151218
  var ENVIRONMENT_ID_ALIASES = {
149817
151219
  "local-development": "dev",
149818
151220
  prod: "live"
@@ -149899,7 +151301,7 @@ var EnvironmentConfigService = class {
149899
151301
  configFilePath;
149900
151302
  async readState() {
149901
151303
  try {
149902
- const raw = await (0, import_promises16.readFile)(this.configFilePath, "utf8");
151304
+ const raw = await (0, import_promises19.readFile)(this.configFilePath, "utf8");
149903
151305
  const parsed = JSON.parse(raw);
149904
151306
  const validated = EnvironmentConfigStateSchema.safeParse(parsed);
149905
151307
  if (!validated.success) {
@@ -149933,17 +151335,17 @@ var EnvironmentConfigService = class {
149933
151335
  });
149934
151336
  }
149935
151337
  const normalized = normalizeState3(validated.data);
149936
- const directory = (0, import_node_path22.dirname)(this.configFilePath);
149937
- await (0, import_promises16.mkdir)(directory, {
151338
+ const directory = (0, import_node_path26.dirname)(this.configFilePath);
151339
+ await (0, import_promises19.mkdir)(directory, {
149938
151340
  recursive: true,
149939
151341
  mode: 448
149940
151342
  });
149941
- await (0, import_promises16.writeFile)(this.configFilePath, `${JSON.stringify(normalized, null, 2)}
151343
+ await (0, import_promises19.writeFile)(this.configFilePath, `${JSON.stringify(normalized, null, 2)}
149942
151344
  `, {
149943
151345
  encoding: "utf8",
149944
151346
  mode: 384
149945
151347
  });
149946
- await (0, import_promises16.chmod)(this.configFilePath, 384);
151348
+ await (0, import_promises19.chmod)(this.configFilePath, 384);
149947
151349
  }
149948
151350
  async getActiveEnvironment() {
149949
151351
  const state = await this.#readStateWithDefaults();
@@ -150010,9 +151412,9 @@ var EnvironmentConfigService = class {
150010
151412
 
150011
151413
  // src/services/piAgentLauncher.ts
150012
151414
  var import_node_child_process6 = require("node:child_process");
150013
- var import_node_fs12 = require("node:fs");
150014
- var import_promises17 = require("node:fs/promises");
150015
- var import_node_path23 = require("node:path");
151415
+ var import_node_fs16 = require("node:fs");
151416
+ var import_promises20 = require("node:fs/promises");
151417
+ var import_node_path27 = require("node:path");
150016
151418
 
150017
151419
  // src/services/spinner.ts
150018
151420
  var import_picocolors2 = __toESM(require_picocolors());
@@ -150075,12 +151477,12 @@ function summarizeFailure3(result, commandLabel = "Command") {
150075
151477
  function resolvePackagedPiResourceRoot(options2 = {}) {
150076
151478
  const cwd = options2.cwd ?? process.cwd();
150077
151479
  const dirname13 = options2.dirname ?? __dirname;
150078
- const fileExists = options2.existsSyncFn ?? import_node_fs12.existsSync;
151480
+ const fileExists = options2.existsSyncFn ?? import_node_fs16.existsSync;
150079
151481
  const candidates = [
150080
- (0, import_node_path23.resolve)(cwd, "apps/api-cli/resources/pi-agent"),
150081
- (0, import_node_path23.resolve)(dirname13, "../resources/pi-agent"),
150082
- (0, import_node_path23.resolve)(dirname13, "resources/pi-agent"),
150083
- (0, import_node_path23.resolve)(cwd, "dist/apps/api-cli/resources/pi-agent")
151482
+ (0, import_node_path27.resolve)(cwd, "apps/api-cli/resources/pi-agent"),
151483
+ (0, import_node_path27.resolve)(dirname13, "../resources/pi-agent"),
151484
+ (0, import_node_path27.resolve)(dirname13, "resources/pi-agent"),
151485
+ (0, import_node_path27.resolve)(cwd, "dist/apps/api-cli/resources/pi-agent")
150084
151486
  ];
150085
151487
  const resolved = candidates.find((candidate) => fileExists(candidate));
150086
151488
  if (!resolved) {
@@ -150091,7 +151493,7 @@ function resolvePackagedPiResourceRoot(options2 = {}) {
150091
151493
  function resolveDocyrusPiLoaderEntryPath(options2 = {}) {
150092
151494
  const cwd = options2.cwd ?? process.cwd();
150093
151495
  const dirname13 = options2.dirname ?? __dirname;
150094
- const fileExists = options2.existsSyncFn ?? import_node_fs12.existsSync;
151496
+ const fileExists = options2.existsSyncFn ?? import_node_fs16.existsSync;
150095
151497
  const seen = /* @__PURE__ */ new Set();
150096
151498
  const candidates = options2.candidatePaths ?? [];
150097
151499
  const addCandidate = (candidate) => {
@@ -150101,23 +151503,23 @@ function resolveDocyrusPiLoaderEntryPath(options2 = {}) {
150101
151503
  }
150102
151504
  };
150103
151505
  const collectAncestorCandidates = (startDir) => {
150104
- let currentDir = (0, import_node_path23.resolve)(startDir);
151506
+ let currentDir = (0, import_node_path27.resolve)(startDir);
150105
151507
  while (true) {
150106
- addCandidate((0, import_node_path23.join)(currentDir, "dist", "apps", "api-cli", "agent-loader.js"));
150107
- addCandidate((0, import_node_path23.join)(currentDir, "agent-loader.js"));
150108
- if ((0, import_node_path23.basename)(currentDir) === "dist") {
150109
- addCandidate((0, import_node_path23.join)(currentDir, "apps", "api-cli", "agent-loader.js"));
151508
+ addCandidate((0, import_node_path27.join)(currentDir, "dist", "apps", "api-cli", "agent-loader.js"));
151509
+ addCandidate((0, import_node_path27.join)(currentDir, "agent-loader.js"));
151510
+ if ((0, import_node_path27.basename)(currentDir) === "dist") {
151511
+ addCandidate((0, import_node_path27.join)(currentDir, "apps", "api-cli", "agent-loader.js"));
150110
151512
  }
150111
- const parentDir = (0, import_node_path23.resolve)(currentDir, "..");
151513
+ const parentDir = (0, import_node_path27.resolve)(currentDir, "..");
150112
151514
  if (parentDir === currentDir) {
150113
151515
  break;
150114
151516
  }
150115
151517
  currentDir = parentDir;
150116
151518
  }
150117
151519
  };
150118
- addCandidate((0, import_node_path23.resolve)(cwd, "dist/apps/api-cli/agent-loader.js"));
150119
- addCandidate((0, import_node_path23.resolve)(dirname13, "../agent-loader.js"));
150120
- addCandidate((0, import_node_path23.resolve)(dirname13, "agent-loader.js"));
151520
+ addCandidate((0, import_node_path27.resolve)(cwd, "dist/apps/api-cli/agent-loader.js"));
151521
+ addCandidate((0, import_node_path27.resolve)(dirname13, "../agent-loader.js"));
151522
+ addCandidate((0, import_node_path27.resolve)(dirname13, "agent-loader.js"));
150121
151523
  collectAncestorCandidates(cwd);
150122
151524
  collectAncestorCandidates(dirname13);
150123
151525
  const resolved = candidates.find((candidate) => fileExists(candidate));
@@ -150130,27 +151532,27 @@ function resolveDocyrusCliEntryPath(options2 = {}) {
150130
151532
  const cwd = options2.cwd ?? process.cwd();
150131
151533
  const dirname13 = options2.dirname ?? __dirname;
150132
151534
  const argv = options2.argv ?? process.argv;
150133
- const fileExists = options2.existsSyncFn ?? import_node_fs12.existsSync;
151535
+ const fileExists = options2.existsSyncFn ?? import_node_fs16.existsSync;
150134
151536
  const seen = /* @__PURE__ */ new Set();
150135
151537
  const candidates = options2.candidatePaths ?? [];
150136
151538
  const addCandidate = (candidate) => {
150137
151539
  if (!candidate) {
150138
151540
  return;
150139
151541
  }
150140
- const resolvedCandidate = (0, import_node_path23.resolve)(candidate);
151542
+ const resolvedCandidate = (0, import_node_path27.resolve)(candidate);
150141
151543
  if (!seen.has(resolvedCandidate)) {
150142
151544
  seen.add(resolvedCandidate);
150143
151545
  candidates.push(resolvedCandidate);
150144
151546
  }
150145
151547
  };
150146
151548
  const argvScript = argv[1]?.trim();
150147
- const normalizedArgvScript = argvScript ? argvScript.startsWith("/") ? argvScript : (0, import_node_path23.resolve)(cwd, argvScript) : void 0;
151549
+ const normalizedArgvScript = argvScript ? argvScript.startsWith("/") ? argvScript : (0, import_node_path27.resolve)(cwd, argvScript) : void 0;
150148
151550
  if (normalizedArgvScript && normalizedArgvScript.endsWith(".js")) {
150149
151551
  addCandidate(normalizedArgvScript);
150150
151552
  }
150151
- addCandidate((0, import_node_path23.resolve)(cwd, "dist/apps/api-cli/main.js"));
150152
- addCandidate((0, import_node_path23.resolve)(dirname13, "../main.js"));
150153
- addCandidate((0, import_node_path23.resolve)(dirname13, "main.js"));
151553
+ addCandidate((0, import_node_path27.resolve)(cwd, "dist/apps/api-cli/main.js"));
151554
+ addCandidate((0, import_node_path27.resolve)(dirname13, "../main.js"));
151555
+ addCandidate((0, import_node_path27.resolve)(dirname13, "main.js"));
150154
151556
  if (normalizedArgvScript) {
150155
151557
  addCandidate(normalizedArgvScript);
150156
151558
  }
@@ -150163,7 +151565,7 @@ function resolveDocyrusCliEntryPath(options2 = {}) {
150163
151565
  function resolveInstalledPiPackageRootPath(options2 = {}) {
150164
151566
  const cwd = options2.cwd ?? process.cwd();
150165
151567
  const dirname13 = options2.dirname ?? __dirname;
150166
- const fileExists = options2.existsSyncFn ?? import_node_fs12.existsSync;
151568
+ const fileExists = options2.existsSyncFn ?? import_node_fs16.existsSync;
150167
151569
  const seen = /* @__PURE__ */ new Set();
150168
151570
  const candidates = options2.candidatePaths ?? [];
150169
151571
  const addCandidate = (candidate) => {
@@ -150173,33 +151575,33 @@ function resolveInstalledPiPackageRootPath(options2 = {}) {
150173
151575
  }
150174
151576
  };
150175
151577
  const collectAncestorCandidates = (startDir) => {
150176
- let currentDir = (0, import_node_path23.resolve)(startDir);
151578
+ let currentDir = (0, import_node_path27.resolve)(startDir);
150177
151579
  while (true) {
150178
- addCandidate((0, import_node_path23.join)(currentDir, "node_modules", "@mariozechner", "pi-coding-agent", "package.json"));
150179
- if ((0, import_node_path23.basename)(currentDir) === "node_modules") {
150180
- addCandidate((0, import_node_path23.join)(currentDir, "@mariozechner", "pi-coding-agent", "package.json"));
151580
+ addCandidate((0, import_node_path27.join)(currentDir, "node_modules", "@mariozechner", "pi-coding-agent", "package.json"));
151581
+ if ((0, import_node_path27.basename)(currentDir) === "node_modules") {
151582
+ addCandidate((0, import_node_path27.join)(currentDir, "@mariozechner", "pi-coding-agent", "package.json"));
150181
151583
  }
150182
- const parentDir = (0, import_node_path23.resolve)(currentDir, "..");
151584
+ const parentDir = (0, import_node_path27.resolve)(currentDir, "..");
150183
151585
  if (parentDir === currentDir) {
150184
151586
  break;
150185
151587
  }
150186
151588
  currentDir = parentDir;
150187
151589
  }
150188
151590
  };
150189
- addCandidate((0, import_node_path23.resolve)(cwd, "apps/api-cli/node_modules/@mariozechner/pi-coding-agent/package.json"));
150190
- addCandidate((0, import_node_path23.resolve)(dirname13, "../../../apps/api-cli/node_modules/@mariozechner/pi-coding-agent/package.json"));
151591
+ addCandidate((0, import_node_path27.resolve)(cwd, "apps/api-cli/node_modules/@mariozechner/pi-coding-agent/package.json"));
151592
+ addCandidate((0, import_node_path27.resolve)(dirname13, "../../../apps/api-cli/node_modules/@mariozechner/pi-coding-agent/package.json"));
150191
151593
  collectAncestorCandidates(cwd);
150192
151594
  collectAncestorCandidates(dirname13);
150193
151595
  const resolvedPackageJson = candidates.find((candidate) => fileExists(candidate));
150194
151596
  if (!resolvedPackageJson) {
150195
151597
  throw new UserInputError(`Unable to locate the installed pi package root. Checked: ${candidates.join(", ")}`);
150196
151598
  }
150197
- return (0, import_node_path23.resolve)(resolvedPackageJson, "..");
151599
+ return (0, import_node_path27.resolve)(resolvedPackageJson, "..");
150198
151600
  }
150199
151601
  function createPiAgentRuntimeSkill(params) {
150200
151602
  const commandPrefix = params.scope === "global" ? "docyrus -g" : "docyrus";
150201
- const knowledgeDir = (0, import_node_path23.join)(params.cwd, "docyrus", "knowledge");
150202
- const hasKnowledgeGraph = (0, import_node_fs12.existsSync)(knowledgeDir);
151603
+ const knowledgeDir = (0, import_node_path27.join)(params.cwd, "docyrus", "knowledge");
151604
+ const hasKnowledgeGraph = (0, import_node_fs16.existsSync)(knowledgeDir);
150203
151605
  const authLines = params.activeProfile ? [
150204
151606
  `- email: \`${params.activeProfile.email}\``,
150205
151607
  `- tenant: \`${params.activeProfile.tenantName} (${params.activeProfile.tenantNo})\``,
@@ -150252,35 +151654,35 @@ function createPiAgentRuntimeSkill(params) {
150252
151654
  ].join("\n");
150253
151655
  }
150254
151656
  async function syncPackagedSkills(params) {
150255
- const sourceSkillsRoot = (0, import_node_path23.join)(params.resourceRoot, "skills");
150256
- const targetSkillsRoot = (0, import_node_path23.join)(params.agentRootPath, "skills");
150257
- await (0, import_promises17.mkdir)(targetSkillsRoot, {
151657
+ const sourceSkillsRoot = (0, import_node_path27.join)(params.resourceRoot, "skills");
151658
+ const targetSkillsRoot = (0, import_node_path27.join)(params.agentRootPath, "skills");
151659
+ await (0, import_promises20.mkdir)(targetSkillsRoot, {
150258
151660
  recursive: true,
150259
151661
  mode: 448
150260
151662
  });
150261
- const entries = await (0, import_promises17.readdir)(sourceSkillsRoot, {
151663
+ const entries = await (0, import_promises20.readdir)(sourceSkillsRoot, {
150262
151664
  withFileTypes: true
150263
151665
  });
150264
151666
  await Promise.all(DOCYRUS_MIGRATED_SKILL_NAMES.map(async (skillName) => {
150265
- await (0, import_promises17.rm)((0, import_node_path23.join)(targetSkillsRoot, skillName), {
151667
+ await (0, import_promises20.rm)((0, import_node_path27.join)(targetSkillsRoot, skillName), {
150266
151668
  recursive: true,
150267
151669
  force: true
150268
151670
  });
150269
151671
  }));
150270
151672
  await Promise.all(entries.map(async (entry) => {
150271
- await (0, import_promises17.cp)((0, import_node_path23.join)(sourceSkillsRoot, entry.name), (0, import_node_path23.join)(targetSkillsRoot, entry.name), {
151673
+ await (0, import_promises20.cp)((0, import_node_path27.join)(sourceSkillsRoot, entry.name), (0, import_node_path27.join)(targetSkillsRoot, entry.name), {
150272
151674
  recursive: true,
150273
151675
  force: true
150274
151676
  });
150275
151677
  }));
150276
151678
  }
150277
151679
  async function writeRuntimeSkill(params) {
150278
- const runtimeSkillDir = (0, import_node_path23.join)(params.agentRootPath, "skills", "docyrus-runtime-context");
150279
- await (0, import_promises17.mkdir)(runtimeSkillDir, {
151680
+ const runtimeSkillDir = (0, import_node_path27.join)(params.agentRootPath, "skills", "docyrus-runtime-context");
151681
+ await (0, import_promises20.mkdir)(runtimeSkillDir, {
150280
151682
  recursive: true,
150281
151683
  mode: 448
150282
151684
  });
150283
- await (0, import_promises17.writeFile)((0, import_node_path23.join)(runtimeSkillDir, "SKILL.md"), `${params.content}
151685
+ await (0, import_promises20.writeFile)((0, import_node_path27.join)(runtimeSkillDir, "SKILL.md"), `${params.content}
150284
151686
  `, {
150285
151687
  encoding: "utf8",
150286
151688
  mode: 384
@@ -150293,10 +151695,10 @@ function resolveNpmCommand() {
150293
151695
  return process.platform === "win32" ? "npm.cmd" : "npm";
150294
151696
  }
150295
151697
  function resolveManagedDiffityInstallRoot(agentRootPath) {
150296
- return (0, import_node_path23.join)(agentRootPath, "tools", "diffity");
151698
+ return (0, import_node_path27.join)(agentRootPath, "tools", "diffity");
150297
151699
  }
150298
151700
  function resolveManagedDiffityExecutablePath(agentRootPath) {
150299
- return (0, import_node_path23.join)(
151701
+ return (0, import_node_path27.join)(
150300
151702
  resolveManagedDiffityInstallRoot(agentRootPath),
150301
151703
  "node_modules",
150302
151704
  ".bin",
@@ -150304,10 +151706,10 @@ function resolveManagedDiffityExecutablePath(agentRootPath) {
150304
151706
  );
150305
151707
  }
150306
151708
  function prependPathEntry(entry, existingPath) {
150307
- const values = existingPath ? existingPath.split(import_node_path23.delimiter).filter((value2) => value2.trim().length > 0) : [];
151709
+ const values = existingPath ? existingPath.split(import_node_path27.delimiter).filter((value2) => value2.trim().length > 0) : [];
150308
151710
  const normalizedEntry = entry.trim();
150309
151711
  const remaining = values.filter((value2) => value2 !== normalizedEntry);
150310
- return [normalizedEntry, ...remaining].join(import_node_path23.delimiter);
151712
+ return [normalizedEntry, ...remaining].join(import_node_path27.delimiter);
150311
151713
  }
150312
151714
  function createDocyrusSkillsInstallArgs(scope) {
150313
151715
  const args2 = [
@@ -150345,8 +151747,8 @@ function createPackagedDocyrusPlatformInstallArgs(params) {
150345
151747
  return args2;
150346
151748
  }
150347
151749
  async function installExternalDocyrusSkillsOnce(params) {
150348
- const markerPath = (0, import_node_path23.join)(params.agentRootPath, DOCYRUS_EXTERNAL_SKILL_MARKER_FILE);
150349
- if ((0, import_node_fs12.existsSync)(markerPath)) {
151750
+ const markerPath = (0, import_node_path27.join)(params.agentRootPath, DOCYRUS_EXTERNAL_SKILL_MARKER_FILE);
151751
+ if ((0, import_node_fs16.existsSync)(markerPath)) {
150350
151752
  return;
150351
151753
  }
150352
151754
  const result = params.spawnCommand(resolveNpxCommand(), createDocyrusSkillsInstallArgs(params.scope), {
@@ -150364,7 +151766,7 @@ async function installExternalDocyrusSkillsOnce(params) {
150364
151766
  );
150365
151767
  return;
150366
151768
  }
150367
- await (0, import_promises17.writeFile)(markerPath, `${JSON.stringify({
151769
+ await (0, import_promises20.writeFile)(markerPath, `${JSON.stringify({
150368
151770
  source: DOCYRUS_EXTERNAL_SKILL_SOURCE,
150369
151771
  skills: DOCYRUS_MIGRATED_SKILL_NAMES,
150370
151772
  agents: DOCYRUS_EXTERNAL_SKILL_AGENT_IDS,
@@ -150378,8 +151780,8 @@ async function installExternalDocyrusSkillsOnce(params) {
150378
151780
  }
150379
151781
  async function ensureManagedDiffityInstalled(params) {
150380
151782
  const executablePath = resolveManagedDiffityExecutablePath(params.agentRootPath);
150381
- const binDir = (0, import_node_path23.dirname)(executablePath);
150382
- if ((0, import_node_fs12.existsSync)(executablePath)) {
151783
+ const binDir = (0, import_node_path27.dirname)(executablePath);
151784
+ if ((0, import_node_fs16.existsSync)(executablePath)) {
150383
151785
  return {
150384
151786
  available: true,
150385
151787
  executablePath,
@@ -150417,19 +151819,19 @@ async function ensureManagedDiffityInstalled(params) {
150417
151819
  };
150418
151820
  }
150419
151821
  function resolvePackagedDocyrusPlatformSkillPath(resourceRoot) {
150420
- return (0, import_node_path23.join)(resourceRoot, "skills", DOCYRUS_PACKAGED_PLATFORM_SKILL_NAME);
151822
+ return (0, import_node_path27.join)(resourceRoot, "skills", DOCYRUS_PACKAGED_PLATFORM_SKILL_NAME);
150421
151823
  }
150422
151824
  function resolvePackagedOfficeCliRootPath(resourceRoot) {
150423
- return (0, import_node_path23.join)((0, import_node_path23.resolve)(resourceRoot, ".."), "officecli");
151825
+ return (0, import_node_path27.join)((0, import_node_path27.resolve)(resourceRoot, ".."), "officecli");
150424
151826
  }
150425
151827
  function resolvePackagedOfficeCliManifestPath(resourceRoot) {
150426
- return (0, import_node_path23.join)(resolvePackagedOfficeCliRootPath(resourceRoot), DOCYRUS_OFFICECLI_MANIFEST_FILE_NAME);
151828
+ return (0, import_node_path27.join)(resolvePackagedOfficeCliRootPath(resourceRoot), DOCYRUS_OFFICECLI_MANIFEST_FILE_NAME);
150427
151829
  }
150428
151830
  function resolveManagedOfficeCliInstallRoot(agentRootPath) {
150429
- return (0, import_node_path23.join)(agentRootPath, "tools", "officecli");
151831
+ return (0, import_node_path27.join)(agentRootPath, "tools", "officecli");
150430
151832
  }
150431
151833
  function resolveManagedOfficeCliExecutablePath(agentRootPath) {
150432
- return (0, import_node_path23.join)(
151834
+ return (0, import_node_path27.join)(
150433
151835
  resolveManagedOfficeCliInstallRoot(agentRootPath),
150434
151836
  process.platform === "win32" ? "officecli.exe" : "officecli"
150435
151837
  );
@@ -150437,7 +151839,7 @@ function resolveManagedOfficeCliExecutablePath(agentRootPath) {
150437
151839
  function resolveOfficeCliReleaseAssetName(options2 = {}) {
150438
151840
  const platform2 = options2.platform ?? process.platform;
150439
151841
  const arch = options2.arch ?? process.arch;
150440
- const isAlpine = options2.isAlpine ?? (0, import_node_fs12.existsSync)("/etc/alpine-release");
151842
+ const isAlpine = options2.isAlpine ?? (0, import_node_fs16.existsSync)("/etc/alpine-release");
150441
151843
  switch (platform2) {
150442
151844
  case "darwin":
150443
151845
  if (arch === "arm64") {
@@ -150471,14 +151873,14 @@ function resolveOfficeCliReleaseAssetName(options2 = {}) {
150471
151873
  throw new UserInputError(`OfficeCLI is not supported on ${platform2}/${arch}.`);
150472
151874
  }
150473
151875
  function resolvePackagedOfficeCliExecutablePath(resourceRoot, options2) {
150474
- return (0, import_node_path23.join)(
151876
+ return (0, import_node_path27.join)(
150475
151877
  resolvePackagedOfficeCliRootPath(resourceRoot),
150476
151878
  "bundled",
150477
151879
  resolveOfficeCliReleaseAssetName(options2)
150478
151880
  );
150479
151881
  }
150480
151882
  async function readPackagedOfficeCliVersion(resourceRoot) {
150481
- const manifestRaw = await (0, import_promises17.readFile)(resolvePackagedOfficeCliManifestPath(resourceRoot), "utf8");
151883
+ const manifestRaw = await (0, import_promises20.readFile)(resolvePackagedOfficeCliManifestPath(resourceRoot), "utf8");
150482
151884
  const manifest = JSON.parse(manifestRaw);
150483
151885
  const version2 = typeof manifest.version === "string" ? manifest.version.trim() : "";
150484
151886
  if (version2.length === 0) {
@@ -150494,16 +151896,16 @@ async function downloadOfficeCliBinary(params) {
150494
151896
  throw new UserInputError(`OfficeCLI download failed with status ${response.status}.`);
150495
151897
  }
150496
151898
  const binary2 = Buffer.from(await response.arrayBuffer());
150497
- await (0, import_promises17.writeFile)(params.destinationPath, binary2, {
151899
+ await (0, import_promises20.writeFile)(params.destinationPath, binary2, {
150498
151900
  mode: process.platform === "win32" ? 384 : 448
150499
151901
  });
150500
151902
  }
150501
151903
  function resolveManagedOfficeCliConfigMarkerPath(agentRootPath) {
150502
- return (0, import_node_path23.join)(resolveManagedOfficeCliInstallRoot(agentRootPath), ".docyrus-officecli-configured.json");
151904
+ return (0, import_node_path27.join)(resolveManagedOfficeCliInstallRoot(agentRootPath), ".docyrus-officecli-configured.json");
150503
151905
  }
150504
151906
  async function disableManagedOfficeCliAutoUpdate(params) {
150505
151907
  const markerPath = resolveManagedOfficeCliConfigMarkerPath(params.agentRootPath);
150506
- if ((0, import_node_fs12.existsSync)(markerPath)) {
151908
+ if ((0, import_node_fs16.existsSync)(markerPath)) {
150507
151909
  return;
150508
151910
  }
150509
151911
  const result = params.spawnCommand(params.executablePath, ["config", "autoUpdate", "false"], {
@@ -150522,7 +151924,7 @@ async function disableManagedOfficeCliAutoUpdate(params) {
150522
151924
  );
150523
151925
  return;
150524
151926
  }
150525
- await (0, import_promises17.writeFile)(markerPath, `${JSON.stringify({
151927
+ await (0, import_promises20.writeFile)(markerPath, `${JSON.stringify({
150526
151928
  configuredAt: (/* @__PURE__ */ new Date()).toISOString()
150527
151929
  }, null, 2)}
150528
151930
  `, {
@@ -150532,8 +151934,8 @@ async function disableManagedOfficeCliAutoUpdate(params) {
150532
151934
  }
150533
151935
  async function ensureManagedOfficeCliInstalled(params) {
150534
151936
  const executablePath = resolveManagedOfficeCliExecutablePath(params.agentRootPath);
150535
- const binDir = (0, import_node_path23.dirname)(executablePath);
150536
- if ((0, import_node_fs12.existsSync)(executablePath)) {
151937
+ const binDir = (0, import_node_path27.dirname)(executablePath);
151938
+ if ((0, import_node_fs16.existsSync)(executablePath)) {
150537
151939
  await disableManagedOfficeCliAutoUpdate({
150538
151940
  agentRootPath: params.agentRootPath,
150539
151941
  executablePath,
@@ -150548,13 +151950,13 @@ async function ensureManagedOfficeCliInstalled(params) {
150548
151950
  }
150549
151951
  const tempPath = `${executablePath}.download${process.platform === "win32" ? ".exe" : ""}`;
150550
151952
  try {
150551
- await (0, import_promises17.mkdir)(binDir, {
151953
+ await (0, import_promises20.mkdir)(binDir, {
150552
151954
  recursive: true,
150553
151955
  mode: 448
150554
151956
  });
150555
151957
  const bundledExecutablePath = resolvePackagedOfficeCliExecutablePath(params.resourceRoot);
150556
- if ((0, import_node_fs12.existsSync)(bundledExecutablePath)) {
150557
- await (0, import_promises17.cp)(bundledExecutablePath, tempPath, {
151958
+ if ((0, import_node_fs16.existsSync)(bundledExecutablePath)) {
151959
+ await (0, import_promises20.cp)(bundledExecutablePath, tempPath, {
150558
151960
  force: true
150559
151961
  });
150560
151962
  } else {
@@ -150564,7 +151966,7 @@ async function ensureManagedOfficeCliInstalled(params) {
150564
151966
  });
150565
151967
  }
150566
151968
  if (process.platform !== "win32") {
150567
- await (0, import_promises17.chmod)(tempPath, 448);
151969
+ await (0, import_promises20.chmod)(tempPath, 448);
150568
151970
  }
150569
151971
  const verificationResult = params.spawnCommand(tempPath, ["--version"], {
150570
151972
  stdio: ["ignore", "pipe", "pipe"],
@@ -150580,9 +151982,9 @@ async function ensureManagedOfficeCliInstalled(params) {
150580
151982
  verificationResult.error?.message || summarizeFailure3(verificationResult, "officecli --version")
150581
151983
  );
150582
151984
  }
150583
- await (0, import_promises17.rename)(tempPath, executablePath);
151985
+ await (0, import_promises20.rename)(tempPath, executablePath);
150584
151986
  if (process.platform !== "win32") {
150585
- await (0, import_promises17.chmod)(executablePath, 448);
151987
+ await (0, import_promises20.chmod)(executablePath, 448);
150586
151988
  }
150587
151989
  await disableManagedOfficeCliAutoUpdate({
150588
151990
  agentRootPath: params.agentRootPath,
@@ -150596,7 +151998,7 @@ async function ensureManagedOfficeCliInstalled(params) {
150596
151998
  binDir
150597
151999
  };
150598
152000
  } catch (error48) {
150599
- await (0, import_promises17.rm)(tempPath, {
152001
+ await (0, import_promises20.rm)(tempPath, {
150600
152002
  force: true
150601
152003
  });
150602
152004
  process.stderr.write(
@@ -150612,7 +152014,7 @@ async function ensureManagedOfficeCliInstalled(params) {
150612
152014
  }
150613
152015
  function installPackagedDocyrusPlatformSkill(params) {
150614
152016
  const skillSourcePath = resolvePackagedDocyrusPlatformSkillPath(params.resourceRoot);
150615
- if (!(0, import_node_fs12.existsSync)(skillSourcePath)) {
152017
+ if (!(0, import_node_fs16.existsSync)(skillSourcePath)) {
150616
152018
  process.stderr.write("[docyrus] Packaged docyrus-platform skill is missing. Continuing without agent sync.\n");
150617
152019
  return;
150618
152020
  }
@@ -150741,8 +152143,8 @@ function createPiAgentLauncher(options2) {
150741
152143
 
150742
152144
  // src/services/piAgentServerLauncher.ts
150743
152145
  var import_node_child_process7 = require("node:child_process");
150744
- var import_node_fs13 = require("node:fs");
150745
- var import_node_path24 = require("node:path");
152146
+ var import_node_fs17 = require("node:fs");
152147
+ var import_node_path28 = require("node:path");
150746
152148
  function serializePiAgentServerRequest(request) {
150747
152149
  return JSON.stringify(request);
150748
152150
  }
@@ -150756,26 +152158,26 @@ function resolveServerLoaderEntryPath(cwd, dirname13) {
150756
152158
  }
150757
152159
  };
150758
152160
  const collectAncestorCandidates = (startDir) => {
150759
- let currentDir = (0, import_node_path24.resolve)(startDir);
152161
+ let currentDir = (0, import_node_path28.resolve)(startDir);
150760
152162
  while (true) {
150761
- addCandidate((0, import_node_path24.join)(currentDir, "dist", "apps", "api-cli", "server-loader.js"));
150762
- addCandidate((0, import_node_path24.join)(currentDir, "server-loader.js"));
150763
- if ((0, import_node_path24.basename)(currentDir) === "dist") {
150764
- addCandidate((0, import_node_path24.join)(currentDir, "apps", "api-cli", "server-loader.js"));
152163
+ addCandidate((0, import_node_path28.join)(currentDir, "dist", "apps", "api-cli", "server-loader.js"));
152164
+ addCandidate((0, import_node_path28.join)(currentDir, "server-loader.js"));
152165
+ if ((0, import_node_path28.basename)(currentDir) === "dist") {
152166
+ addCandidate((0, import_node_path28.join)(currentDir, "apps", "api-cli", "server-loader.js"));
150765
152167
  }
150766
- const parentDir = (0, import_node_path24.resolve)(currentDir, "..");
152168
+ const parentDir = (0, import_node_path28.resolve)(currentDir, "..");
150767
152169
  if (parentDir === currentDir) {
150768
152170
  break;
150769
152171
  }
150770
152172
  currentDir = parentDir;
150771
152173
  }
150772
152174
  };
150773
- addCandidate((0, import_node_path24.resolve)(cwd, "dist/apps/api-cli/server-loader.js"));
150774
- addCandidate((0, import_node_path24.resolve)(dirname13, "../server-loader.js"));
150775
- addCandidate((0, import_node_path24.resolve)(dirname13, "server-loader.js"));
152175
+ addCandidate((0, import_node_path28.resolve)(cwd, "dist/apps/api-cli/server-loader.js"));
152176
+ addCandidate((0, import_node_path28.resolve)(dirname13, "../server-loader.js"));
152177
+ addCandidate((0, import_node_path28.resolve)(dirname13, "server-loader.js"));
150776
152178
  collectAncestorCandidates(cwd);
150777
152179
  collectAncestorCandidates(dirname13);
150778
- const resolved = candidates.find((candidate) => (0, import_node_fs13.existsSync)(candidate));
152180
+ const resolved = candidates.find((candidate) => (0, import_node_fs17.existsSync)(candidate));
150779
152181
  if (!resolved) {
150780
152182
  throw new UserInputError(`Unable to locate Docyrus pi server loader entry file. Checked: ${candidates.join(", ")}`);
150781
152183
  }
@@ -150892,8 +152294,8 @@ async function runWithIncurSkillsOutOfDateWarningSuppressed(params) {
150892
152294
  }
150893
152295
 
150894
152296
  // src/services/tenantOpenApi.ts
150895
- var import_promises18 = require("node:fs/promises");
150896
- var import_node_path25 = require("node:path");
152297
+ var import_promises21 = require("node:fs/promises");
152298
+ var import_node_path29 = require("node:path");
150897
152299
  function resolveSourceUrl(tenantId, template) {
150898
152300
  return template.replace("{tenantId}", encodeURIComponent(tenantId));
150899
152301
  }
@@ -150918,16 +152320,16 @@ var TenantOpenApiService = class {
150918
152320
  params;
150919
152321
  async #writeOpenApiFile(tenantId, parsedContent) {
150920
152322
  const filePath = this.getTenantOpenApiFilePath(tenantId);
150921
- await (0, import_promises18.mkdir)((0, import_node_path25.dirname)(filePath), {
152323
+ await (0, import_promises21.mkdir)((0, import_node_path29.dirname)(filePath), {
150922
152324
  recursive: true,
150923
152325
  mode: 448
150924
152326
  });
150925
- await (0, import_promises18.writeFile)(filePath, `${JSON.stringify(parsedContent, null, 2)}
152327
+ await (0, import_promises21.writeFile)(filePath, `${JSON.stringify(parsedContent, null, 2)}
150926
152328
  `, {
150927
152329
  encoding: "utf8",
150928
152330
  mode: 384
150929
152331
  });
150930
- await (0, import_promises18.chmod)(filePath, 384);
152332
+ await (0, import_promises21.chmod)(filePath, 384);
150931
152333
  return filePath;
150932
152334
  }
150933
152335
  async #generateTenantOpenApiViaAuthenticatedEndpoint(tenantId, options2) {
@@ -150964,7 +152366,7 @@ var TenantOpenApiService = class {
150964
152366
  throw new AuthSessionError("Tenant ID is required to resolve OpenAPI spec path.");
150965
152367
  }
150966
152368
  const rootPath = this.params?.rootPath || TENANT_OPENAPI_ROOT_PATH;
150967
- return (0, import_node_path25.join)(rootPath, normalizedTenantId, "openapi.json");
152369
+ return (0, import_node_path29.join)(rootPath, normalizedTenantId, "openapi.json");
150968
152370
  }
150969
152371
  async downloadTenantOpenApi(tenantId, options2 = {}) {
150970
152372
  const normalizedTenantId = tenantId.trim();
@@ -151045,6 +152447,8 @@ var ROOT_HELP_COMMANDS = [
151045
152447
  { command: "knowledge search <query>", description: "Semantic search across docyrus/knowledge" },
151046
152448
  { command: "knowledge section <query>", description: "Show a knowledge section with refs and backlinks" },
151047
152449
  { command: "knowledge check", description: "Validate docyrus/knowledge links and backlinks" },
152450
+ { command: "project-plan show", description: "Show the canonical project plan graph and hierarchy" },
152451
+ { command: "project-plan check", description: "Validate the canonical project plan graph" },
151048
152452
  { command: "action <appSlug> <actionKey> --params '{...}'", description: "Run a connector or app action" },
151049
152453
  { command: "ds list <appSlug> <dataSourceSlug>", description: "List data source items" },
151050
152454
  { command: "apps list", description: "List apps" },
@@ -151160,6 +152564,11 @@ function createDocyrusCli(params) {
151160
152564
  authStore,
151161
152565
  settingsPaths
151162
152566
  }));
152567
+ cli2.command(createProjectPlanCli({
152568
+ environmentConfigService,
152569
+ authStore,
152570
+ settingsPaths
152571
+ }));
151163
152572
  cli2.command(createAppsCli({
151164
152573
  createApiClient,
151165
152574
  environmentConfigService,