@docyrus/docyrus 0.0.39 → 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
  }
@@ -100323,7 +100323,7 @@ var require_snapshot_utils = __commonJS({
100323
100323
  var require_snapshot_recorder = __commonJS({
100324
100324
  "../../node_modules/.pnpm/undici@7.22.0/node_modules/undici/lib/mock/snapshot-recorder.js"(exports2, module2) {
100325
100325
  "use strict";
100326
- var { writeFile: writeFile9, readFile: readFile16, mkdir: mkdir10 } = require("node:fs/promises");
100326
+ var { writeFile: writeFile9, readFile: readFile17, mkdir: mkdir10 } = require("node:fs/promises");
100327
100327
  var { dirname: dirname13, resolve: resolve2 } = require("node:path");
100328
100328
  var { setTimeout: setTimeout2, clearTimeout: clearTimeout2 } = require("node:timers");
100329
100329
  var { InvalidArgumentError, UndiciError } = require_errors3();
@@ -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 readFile16(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,13 +137151,16 @@ function buildInputSchema(args2, env2, options2) {
137151
137151
  // package.json
137152
137152
  var package_default = {
137153
137153
  name: "@docyrus/docyrus",
137154
- version: "0.0.39",
137154
+ version: "0.0.41",
137155
137155
  private: false,
137156
137156
  description: "Docyrus API CLI",
137157
137157
  main: "./main.js",
137158
137158
  bin: {
137159
137159
  docyrus: "main.js"
137160
137160
  },
137161
+ scripts: {
137162
+ postinstall: "node ./resources/officecli/install.mjs"
137163
+ },
137161
137164
  dependencies: {
137162
137165
  "@clack/prompts": "^0.11.0",
137163
137166
  "@hono/node-server": "^1.14.1",
@@ -137393,7 +137396,7 @@ function createActionCli(dependencies) {
137393
137396
  const apiClient = dependencies.createApiClient(apiBaseUrl);
137394
137397
  const { appSlug, actionKey } = context.args;
137395
137398
  const body2 = context.options.params ? parseJsonParams(context.options.params) : {};
137396
- const path3 = `/v1/apps/${encodeURIComponent(appSlug)}/actions/${encodeURIComponent(actionKey)}/run`;
137399
+ const path7 = `/v1/apps/${encodeURIComponent(appSlug)}/actions/${encodeURIComponent(actionKey)}/run`;
137397
137400
  const headers = {};
137398
137401
  if (context.options.connectionId) {
137399
137402
  headers["x-connection-id"] = context.options.connectionId;
@@ -137408,7 +137411,7 @@ function createActionCli(dependencies) {
137408
137411
  payload: {
137409
137412
  dryRun: true,
137410
137413
  method: "POST",
137411
- path: path3,
137414
+ path: path7,
137412
137415
  headers: Object.keys(headers).length > 0 ? headers : void 0,
137413
137416
  body: body2
137414
137417
  }
@@ -137416,7 +137419,7 @@ function createActionCli(dependencies) {
137416
137419
  }
137417
137420
  const response = await apiClient.request({
137418
137421
  method: "POST",
137419
- path: path3,
137422
+ path: path7,
137420
137423
  headers: Object.keys(headers).length > 0 ? headers : void 0,
137421
137424
  body: body2
137422
137425
  });
@@ -137638,10 +137641,10 @@ function createAiCli(dependencies) {
137638
137641
  const deploymentId = context.options.deploymentId?.trim() || void 0;
137639
137642
  const apiBaseUrl = await dependencies.environmentConfigService.getActiveApiBaseUrl();
137640
137643
  const apiClient = dependencies.createApiClient(apiBaseUrl);
137641
- 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`;
137642
137645
  const response = await apiClient.request({
137643
137646
  method: "POST",
137644
- path: path3,
137647
+ path: path7,
137645
137648
  body: {
137646
137649
  messages: [
137647
137650
  {
@@ -138621,7 +138624,7 @@ async function readDataInput(params) {
138621
138624
  data,
138622
138625
  fromFile,
138623
138626
  readStdin: readStdin2 = readStdinText,
138624
- readFileFn = async (path3, encoding) => await (0, import_promises2.readFile)(path3, encoding)
138627
+ readFileFn = async (path7, encoding) => await (0, import_promises2.readFile)(path7, encoding)
138625
138628
  } = params;
138626
138629
  const trimmedData = data?.trim();
138627
138630
  const trimmedFromFile = fromFile?.trim();
@@ -139318,8 +139321,8 @@ function getEntities(document4) {
139318
139321
  }
139319
139322
  function extractNamespaces(paths) {
139320
139323
  const namespaces = /* @__PURE__ */ new Set();
139321
- for (const path3 of Object.keys(paths)) {
139322
- 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);
139323
139326
  if (segments.length === 0) {
139324
139327
  continue;
139325
139328
  }
@@ -139341,8 +139344,8 @@ function getPathOperation(pathItem, method) {
139341
139344
  function toEndpointMethodEntries(paths, pathFilter) {
139342
139345
  const entries = [];
139343
139346
  const sortedPaths = Object.keys(paths).filter(pathFilter).sort((left, right) => left.localeCompare(right));
139344
- for (const path3 of sortedPaths) {
139345
- const pathItem = paths[path3];
139347
+ for (const path7 of sortedPaths) {
139348
+ const pathItem = paths[path7];
139346
139349
  if (!isRecord2(pathItem)) {
139347
139350
  continue;
139348
139351
  }
@@ -139355,7 +139358,7 @@ function toEndpointMethodEntries(paths, pathFilter) {
139355
139358
  const summaryValue = operation.summary;
139356
139359
  const description = typeof descriptionValue === "string" ? descriptionValue : typeof summaryValue === "string" ? summaryValue : void 0;
139357
139360
  entries.push({
139358
- path: toOutputPath(path3),
139361
+ path: toOutputPath(path7),
139359
139362
  method,
139360
139363
  description
139361
139364
  });
@@ -139481,7 +139484,7 @@ function createDiscoverCli(dependencies) {
139481
139484
  const candidates = buildPathCandidates(context.args.prefix);
139482
139485
  const endpoints = toEndpointMethodEntries(
139483
139486
  paths,
139484
- (path3) => candidates.some((candidate) => path3.startsWith(candidate))
139487
+ (path7) => candidates.some((candidate) => path7.startsWith(candidate))
139485
139488
  );
139486
139489
  return await injectContext({
139487
139490
  apiBaseUrl,
@@ -139578,7 +139581,7 @@ function createDiscoverCli(dependencies) {
139578
139581
  const loweredTerm = term.toLowerCase();
139579
139582
  const matchingEndpoints = toEndpointMethodEntries(
139580
139583
  pathMap,
139581
- (path3) => path3.toLowerCase().includes(loweredTerm)
139584
+ (path7) => path7.toLowerCase().includes(loweredTerm)
139582
139585
  );
139583
139586
  const matchingEntities = entityNames.filter((entityName) => entityName.toLowerCase().includes(loweredTerm));
139584
139587
  return {
@@ -139792,8 +139795,8 @@ function createEnvCli(dependencies) {
139792
139795
  }
139793
139796
 
139794
139797
  // src/commands/knowledgeCommands.ts
139795
- var import_node_crypto4 = require("node:crypto");
139796
- var import_node_path18 = require("node:path");
139798
+ var import_node_crypto6 = require("node:crypto");
139799
+ var import_node_path20 = require("node:path");
139797
139800
  init_graph();
139798
139801
 
139799
139802
  // src/knowledge/query.ts
@@ -142097,11 +142100,11 @@ var Module2 = (() => {
142097
142100
  throw toThrow;
142098
142101
  }, "quit_");
142099
142102
  var scriptDirectory = "";
142100
- function locateFile(path3) {
142103
+ function locateFile(path7) {
142101
142104
  if (Module["locateFile"]) {
142102
- return Module["locateFile"](path3, scriptDirectory);
142105
+ return Module["locateFile"](path7, scriptDirectory);
142103
142106
  }
142104
- return scriptDirectory + path3;
142107
+ return scriptDirectory + path7;
142105
142108
  }
142106
142109
  __name(locateFile, "locateFile");
142107
142110
  var readAsync, readBinary;
@@ -144016,6 +144019,9 @@ function extractName(node2) {
144016
144019
  const nameNode = node2.childForFieldName("name");
144017
144020
  return nameNode ? nameNode.text : null;
144018
144021
  }
144022
+ function isSyntaxNode(node2) {
144023
+ return node2 !== null;
144024
+ }
144019
144025
  function firstLine(text3) {
144020
144026
  const newLineIndex = text3.indexOf("\n");
144021
144027
  return newLineIndex === -1 ? text3 : text3.slice(0, newLineIndex);
@@ -144049,7 +144055,7 @@ function extractTsSymbols(tree) {
144049
144055
  continue;
144050
144056
  }
144051
144057
  if (node2.type === "export_statement") {
144052
- 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;
144053
144059
  }
144054
144060
  const startLine = node2.startPosition.row + 1;
144055
144061
  const endLine = node2.endPosition.row + 1;
@@ -144085,6 +144091,9 @@ function extractTsSymbols(tree) {
144085
144091
  }
144086
144092
  if (node2.type === "lexical_declaration") {
144087
144093
  for (const declaration of node2.namedChildren) {
144094
+ if (!declaration) {
144095
+ continue;
144096
+ }
144088
144097
  if (declaration.type !== "variable_declarator") {
144089
144098
  continue;
144090
144099
  }
@@ -144461,6 +144470,9 @@ function cFieldName(declarator) {
144461
144470
  }
144462
144471
  function collectFieldsFromList(fieldList, structName, symbols) {
144463
144472
  for (const field of fieldList.namedChildren) {
144473
+ if (!field) {
144474
+ continue;
144475
+ }
144464
144476
  if (field.type !== "field_declaration") {
144465
144477
  continue;
144466
144478
  }
@@ -144480,8 +144492,14 @@ function collectFieldsFromList(fieldList, structName, symbols) {
144480
144492
  continue;
144481
144493
  }
144482
144494
  for (const inner of field.namedChildren) {
144495
+ if (!inner) {
144496
+ continue;
144497
+ }
144483
144498
  if ((inner.type === "union_specifier" || inner.type === "struct_specifier") && !extractName(inner)) {
144484
144499
  for (const nested of inner.namedChildren) {
144500
+ if (!nested) {
144501
+ continue;
144502
+ }
144485
144503
  if (nested.type === "field_declaration_list") {
144486
144504
  collectFieldsFromList(nested, structName, symbols);
144487
144505
  }
@@ -144492,6 +144510,9 @@ function collectFieldsFromList(fieldList, structName, symbols) {
144492
144510
  }
144493
144511
  function collectCStructFields(structNode, structName, symbols) {
144494
144512
  for (const child of structNode.namedChildren) {
144513
+ if (!child) {
144514
+ continue;
144515
+ }
144495
144516
  if (child.type === "field_declaration_list") {
144496
144517
  collectFieldsFromList(child, structName, symbols);
144497
144518
  }
@@ -144499,10 +144520,16 @@ function collectCStructFields(structNode, structName, symbols) {
144499
144520
  }
144500
144521
  function collectCEnumMembers(enumSpecifier, symbols, enumName) {
144501
144522
  for (const child of enumSpecifier.namedChildren) {
144523
+ if (!child) {
144524
+ continue;
144525
+ }
144502
144526
  if (child.type !== "enumerator_list") {
144503
144527
  continue;
144504
144528
  }
144505
144529
  for (const enumerator of child.namedChildren) {
144530
+ if (!enumerator) {
144531
+ continue;
144532
+ }
144506
144533
  if (enumerator.type !== "enumerator") {
144507
144534
  continue;
144508
144535
  }
@@ -144568,6 +144595,9 @@ function collectCNodes(parent, symbols) {
144568
144595
  symbols.push({ name: name2, kind: "type", startLine, endLine, signature: firstLine(node2.text) });
144569
144596
  }
144570
144597
  for (const child of node2.namedChildren) {
144598
+ if (!child) {
144599
+ continue;
144600
+ }
144571
144601
  if (child.type === "enum_specifier") {
144572
144602
  collectCEnumMembers(child, symbols, name2 || extractName(child) || void 0);
144573
144603
  } else if (child.type === "struct_specifier" && name2) {
@@ -145547,9 +145577,9 @@ function shouldUseKnowledgeColors() {
145547
145577
  }
145548
145578
 
145549
145579
  // src/knowledge/init.ts
145550
- var import_node_fs8 = require("node:fs");
145551
- var import_promises12 = require("node:fs/promises");
145552
- 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");
145553
145583
  init_graph();
145554
145584
 
145555
145585
  // src/knowledge/bootstrap.ts
@@ -145961,6 +145991,754 @@ async function generateInitialKnowledge(params) {
145961
145991
  };
145962
145992
  }
145963
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
+
145964
146742
  // src/knowledge/init.ts
145965
146743
  var MARKER_BEGIN = "%% docyrus-knowledge:begin %%";
145966
146744
  var MARKER_END = "%% docyrus-knowledge:end %%";
@@ -145972,60 +146750,60 @@ ${content3}${content3.endsWith("\n") ? "" : "\n"}${MARKER_END}
145972
146750
  `;
145973
146751
  }
145974
146752
  async function ensureDirectory(pathValue) {
145975
- await (0, import_promises12.mkdir)(pathValue, {
146753
+ await (0, import_promises14.mkdir)(pathValue, {
145976
146754
  recursive: true,
145977
146755
  mode: 493
145978
146756
  });
145979
146757
  }
145980
146758
  async function writeIfMissing(filePath, content3) {
145981
- if ((0, import_node_fs8.existsSync)(filePath)) {
146759
+ if ((0, import_node_fs10.existsSync)(filePath)) {
145982
146760
  return "kept";
145983
146761
  }
145984
- await ensureDirectory((0, import_node_path16.dirname)(filePath));
145985
- 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");
145986
146764
  return "created";
145987
146765
  }
145988
146766
  async function writeOrUpdate(filePath, content3) {
145989
- if (!(0, import_node_fs8.existsSync)(filePath)) {
145990
- await ensureDirectory((0, import_node_path16.dirname)(filePath));
145991
- 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");
145992
146770
  return "created";
145993
146771
  }
145994
- const current = await (0, import_promises12.readFile)(filePath, "utf8");
146772
+ const current = await (0, import_promises14.readFile)(filePath, "utf8");
145995
146773
  if (current === content3) {
145996
146774
  return "kept";
145997
146775
  }
145998
- await ensureDirectory((0, import_node_path16.dirname)(filePath));
145999
- 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");
146000
146778
  return "updated";
146001
146779
  }
146002
146780
  async function upsertManagedBlock(filePath, content3) {
146003
146781
  const wrapped = wrapManagedBlock(content3);
146004
- if (!(0, import_node_fs8.existsSync)(filePath)) {
146005
- await ensureDirectory((0, import_node_path16.dirname)(filePath));
146006
- 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");
146007
146785
  return "created";
146008
146786
  }
146009
- const current = await (0, import_promises12.readFile)(filePath, "utf8");
146787
+ const current = await (0, import_promises14.readFile)(filePath, "utf8");
146010
146788
  const beginIndex = current.indexOf(MARKER_BEGIN);
146011
146789
  const endIndex = current.indexOf(MARKER_END);
146012
146790
  if (beginIndex !== -1 && endIndex !== -1 && endIndex > beginIndex) {
146013
146791
  const replaceEnd = current[endIndex + MARKER_END.length] === "\n" ? endIndex + MARKER_END.length + 1 : endIndex + MARKER_END.length;
146014
146792
  const updated = `${current.slice(0, beginIndex)}${wrapped}${current.slice(replaceEnd)}`;
146015
- await (0, import_promises12.writeFile)(filePath, updated, "utf8");
146793
+ await (0, import_promises14.writeFile)(filePath, updated, "utf8");
146016
146794
  return "updated";
146017
146795
  }
146018
146796
  const separator = current.endsWith("\n") ? "\n" : "\n\n";
146019
- await (0, import_promises12.writeFile)(filePath, `${current}${separator}${wrapped}`, "utf8");
146797
+ await (0, import_promises14.writeFile)(filePath, `${current}${separator}${wrapped}`, "utf8");
146020
146798
  return "appended";
146021
146799
  }
146022
146800
  function normalizeObject(value2) {
146023
146801
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2) ? { ...value2 } : {};
146024
146802
  }
146025
146803
  async function updateJsonFile(filePath, updater) {
146026
- const current = (0, import_node_fs8.existsSync)(filePath) ? normalizeObject(JSON.parse((0, import_node_fs8.readFileSync)(filePath, "utf8"))) : {};
146027
- await ensureDirectory((0, import_node_path16.dirname)(filePath));
146028
- 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)}
146029
146807
  `, "utf8");
146030
146808
  }
146031
146809
  function wrapHookBlock(content3) {
@@ -146035,17 +146813,17 @@ ${content3}${content3.endsWith("\n") ? "" : "\n"}${HOOK_MARKER_END}
146035
146813
  }
146036
146814
  async function upsertShellHook(filePath, content3, shellHeader) {
146037
146815
  const wrapped = wrapHookBlock(content3);
146038
- if (!(0, import_node_fs8.existsSync)(filePath)) {
146039
- 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));
146040
146818
  const initial = `${shellHeader || ""}${wrapped}`;
146041
- await (0, import_promises12.writeFile)(filePath, initial, {
146819
+ await (0, import_promises14.writeFile)(filePath, initial, {
146042
146820
  encoding: "utf8",
146043
146821
  mode: 493
146044
146822
  });
146045
- await (0, import_promises12.chmod)(filePath, 493);
146823
+ await (0, import_promises14.chmod)(filePath, 493);
146046
146824
  return "created";
146047
146825
  }
146048
- const current = await (0, import_promises12.readFile)(filePath, "utf8");
146826
+ const current = await (0, import_promises14.readFile)(filePath, "utf8");
146049
146827
  const beginIndex = current.indexOf(HOOK_MARKER_BEGIN);
146050
146828
  const endIndex = current.indexOf(HOOK_MARKER_END);
146051
146829
  if (beginIndex !== -1 && endIndex !== -1 && endIndex > beginIndex) {
@@ -146054,13 +146832,13 @@ async function upsertShellHook(filePath, content3, shellHeader) {
146054
146832
  if (nextContent === current) {
146055
146833
  return "kept";
146056
146834
  }
146057
- await (0, import_promises12.writeFile)(filePath, nextContent, "utf8");
146058
- await (0, import_promises12.chmod)(filePath, 493);
146835
+ await (0, import_promises14.writeFile)(filePath, nextContent, "utf8");
146836
+ await (0, import_promises14.chmod)(filePath, 493);
146059
146837
  return "updated";
146060
146838
  }
146061
146839
  const separator = current.endsWith("\n") ? "\n" : "\n\n";
146062
- await (0, import_promises12.writeFile)(filePath, `${current}${separator}${wrapped}`, "utf8");
146063
- 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);
146064
146842
  return "appended";
146065
146843
  }
146066
146844
  function buildKnowledgeDocumentTemplate() {
@@ -146154,33 +146932,34 @@ function syncCursorHooks(settings, commandPrefix) {
146154
146932
  };
146155
146933
  }
146156
146934
  async function initializeKnowledgeRepo(params) {
146157
- const root = (0, import_node_path16.resolve)(params.root || process.cwd());
146935
+ const root = (0, import_node_path18.resolve)(params.root || process.cwd());
146158
146936
  const knowledgeDir = getKnowledgeDirectory(root);
146159
- const knowledgeFile = (0, import_node_path16.join)(knowledgeDir, "knowledge.md");
146937
+ const knowledgeFile = (0, import_node_path18.join)(knowledgeDir, "knowledge.md");
146160
146938
  await ensureDirectory(knowledgeDir);
146161
146939
  const knowledgeFileStatus = await writeIfMissing(knowledgeFile, `${buildKnowledgeDocumentTemplate()}
146162
146940
  `);
146163
- const agentsStatus = await upsertManagedBlock((0, import_node_path16.join)(root, "AGENTS.md"), buildAgentsTemplate(params.commandPrefix));
146164
- const claudeStatus = await upsertManagedBlock((0, import_node_path16.join)(root, "CLAUDE.md"), buildAgentsTemplate(params.commandPrefix));
146165
- 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)}
146166
146944
  `);
146167
146945
  const bootstrap = (await generateInitialKnowledge({
146168
146946
  root,
146169
146947
  brief: params.brief
146170
146948
  })).files;
146171
- await updateJsonFile((0, import_node_path16.join)(root, ".claude", "settings.json"), (value2) => syncClaudeHooks(value2, params.commandPrefix));
146172
- 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));
146173
146952
  let huskyHookStatus;
146174
- const huskyDir = (0, import_node_path16.join)(root, ".husky");
146175
- if ((0, import_node_fs8.existsSync)(huskyDir)) {
146176
- const huskyHookPath = (0, import_node_path16.join)(huskyDir, "pre-commit");
146177
- 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;
146178
146957
  huskyHookStatus = await upsertShellHook(huskyHookPath, `${params.commandPrefix} knowledge pre-commit
146179
146958
  `, huskyHeader);
146180
146959
  }
146181
146960
  let gitHookStatus;
146182
146961
  if (!huskyHookStatus && params.installGitHook) {
146183
- 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");
146184
146963
  gitHookStatus = await upsertShellHook(gitHookPath, `${params.commandPrefix} knowledge pre-commit
146185
146964
  `, "#!/usr/bin/env sh\n\n");
146186
146965
  }
@@ -146188,6 +146967,8 @@ async function initializeKnowledgeRepo(params) {
146188
146967
  root,
146189
146968
  knowledgeDir,
146190
146969
  knowledgeFile,
146970
+ projectPlanGraphPath: projectPlan.graphPath,
146971
+ projectPlanMarkdownPath: projectPlan.markdownPath,
146191
146972
  agentsStatus,
146192
146973
  claudeStatus,
146193
146974
  cursorRulesStatus,
@@ -146202,9 +146983,9 @@ async function initializeKnowledgeRepo(params) {
146202
146983
  init_graph();
146203
146984
 
146204
146985
  // src/knowledge/validation.ts
146205
- var import_node_fs9 = require("node:fs");
146206
- var import_promises13 = require("node:fs/promises");
146207
- 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");
146208
146989
  init_graph();
146209
146990
  var MAX_BODY_LENGTH = 250;
146210
146991
  function bodyTextLength(body2) {
@@ -146237,15 +147018,15 @@ async function tryResolveSourceRef(target, projectRoot) {
146237
147018
  const hashIndex = target.indexOf("#");
146238
147019
  const filePart = hashIndex === -1 ? target : target.slice(0, hashIndex);
146239
147020
  const symbolPart = hashIndex === -1 ? "" : target.slice(hashIndex + 1);
146240
- const extension2 = (0, import_node_path17.extname)(filePart);
147021
+ const extension2 = (0, import_node_path19.extname)(filePart);
146241
147022
  if (!SOURCE_EXTENSIONS.has(extension2)) {
146242
147023
  if (extension2 && hashIndex !== -1) {
146243
147024
  return `broken link [[${target}]] - unsupported file extension "${extension2}"`;
146244
147025
  }
146245
147026
  return `broken link [[${target}]] - no matching section found`;
146246
147027
  }
146247
- const absolutePath = (0, import_node_path17.join)(projectRoot, filePart);
146248
- 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)) {
146249
147030
  return `broken link [[${target}]] - file "${filePart}" not found`;
146250
147031
  }
146251
147032
  if (!symbolPart) {
@@ -146262,7 +147043,7 @@ async function tryResolveSourceRef(target, projectRoot) {
146262
147043
  }
146263
147044
  async function checkKnowledgeMarkdown(knowledgeDir) {
146264
147045
  clearSymbolCache();
146265
- 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));
146266
147047
  const files = await listKnowledgeFiles(knowledgeDir);
146267
147048
  const sections = await loadAllSections(knowledgeDir);
146268
147049
  const flat = flattenSections(sections);
@@ -146271,9 +147052,9 @@ async function checkKnowledgeMarkdown(knowledgeDir) {
146271
147052
  const fileIndex = buildFileIndex(sections);
146272
147053
  const errors = [];
146273
147054
  for (const filePath of files) {
146274
- const content3 = await (0, import_promises13.readFile)(filePath, "utf8");
147055
+ const content3 = await (0, import_promises15.readFile)(filePath, "utf8");
146275
147056
  const refs = extractRefs(filePath, content3, projectRoot);
146276
- const displayPath = (0, import_node_path17.relative)(process.cwd(), filePath);
147057
+ const displayPath = (0, import_node_path19.relative)(process.cwd(), filePath);
146277
147058
  for (const ref of refs) {
146278
147059
  const resolved = resolveRef2(ref.target, sectionIds, fileIndex, canonicalSectionIds);
146279
147060
  if (resolved.ambiguous) {
@@ -146305,7 +147086,7 @@ async function checkKnowledgeMarkdown(knowledgeDir) {
146305
147086
  };
146306
147087
  }
146307
147088
  async function checkKnowledgeCodeRefs(knowledgeDir) {
146308
- 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));
146309
147090
  const sections = await loadAllSections(knowledgeDir);
146310
147091
  const flat = flattenSections(sections);
146311
147092
  const sectionIds = new Set(flat.map((section2) => section2.id.toLowerCase()));
@@ -146317,7 +147098,7 @@ async function checkKnowledgeCodeRefs(knowledgeDir) {
146317
147098
  for (const ref of scan.refs) {
146318
147099
  const resolved = resolveRef2(ref.target, sectionIds, fileIndex, canonicalSectionIds);
146319
147100
  mentionedSections.add(resolved.resolved.toLowerCase());
146320
- 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));
146321
147102
  if (resolved.ambiguous) {
146322
147103
  errors.push({
146323
147104
  file: displayPath,
@@ -146337,12 +147118,12 @@ async function checkKnowledgeCodeRefs(knowledgeDir) {
146337
147118
  }
146338
147119
  }
146339
147120
  for (const filePath of await listKnowledgeFiles(knowledgeDir)) {
146340
- const content3 = await (0, import_promises13.readFile)(filePath, "utf8");
147121
+ const content3 = await (0, import_promises15.readFile)(filePath, "utf8");
146341
147122
  if (!parseFrontmatter(content3).requireCodeMention) {
146342
147123
  continue;
146343
147124
  }
146344
147125
  const leafSections = flattenSections(parseSections(filePath, content3, projectRoot)).filter((section2) => section2.children.length === 0);
146345
- const displayPath = (0, import_node_path17.relative)(process.cwd(), filePath);
147126
+ const displayPath = (0, import_node_path19.relative)(process.cwd(), filePath);
146346
147127
  for (const section2 of leafSections) {
146347
147128
  if (!mentionedSections.has(section2.id.toLowerCase())) {
146348
147129
  errors.push({
@@ -146366,7 +147147,7 @@ async function checkKnowledgeIndex(knowledgeDir) {
146366
147147
  const name2 = pathValue.includes("/") ? pathValue.slice(pathValue.lastIndexOf("/") + 1) : pathValue;
146367
147148
  if (!name2.endsWith(".md")) {
146368
147149
  errors.push({
146369
- dir: `${(0, import_node_path17.basename)(knowledgeDir)}/`,
147150
+ dir: `${(0, import_node_path19.basename)(knowledgeDir)}/`,
146370
147151
  message: `"${pathValue}" is not a .md file - only markdown files belong in docyrus/knowledge/`
146371
147152
  });
146372
147153
  }
@@ -146380,7 +147161,7 @@ async function checkKnowledgeIndex(knowledgeDir) {
146380
147161
  }
146381
147162
  }
146382
147163
  for (const dir of dirs) {
146383
- 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);
146384
147165
  const indexFileName = dirName.endsWith(".md") ? dirName : `${dirName}.md`;
146385
147166
  const indexRelPath = dir === "" ? indexFileName : `${dir}/${indexFileName}`;
146386
147167
  const prefix = dir === "" ? "" : `${dir}/`;
@@ -146389,11 +147170,11 @@ async function checkKnowledgeIndex(knowledgeDir) {
146389
147170
  if (children.length === 0) {
146390
147171
  continue;
146391
147172
  }
146392
- const indexFullPath = (0, import_node_path17.join)(knowledgeDir, indexRelPath);
146393
- 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}/`;
146394
147175
  let content3;
146395
147176
  try {
146396
- content3 = await (0, import_promises13.readFile)(indexFullPath, "utf8");
147177
+ content3 = await (0, import_promises15.readFile)(indexFullPath, "utf8");
146397
147178
  } catch {
146398
147179
  errors.push({
146399
147180
  dir: displayDir,
@@ -146429,12 +147210,12 @@ ${indexSnippet(missing)}`,
146429
147210
  return errors;
146430
147211
  }
146431
147212
  async function checkKnowledgeSections(knowledgeDir) {
146432
- 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));
146433
147214
  const errors = [];
146434
147215
  for (const filePath of await listKnowledgeFiles(knowledgeDir)) {
146435
- const content3 = await (0, import_promises13.readFile)(filePath, "utf8");
147216
+ const content3 = await (0, import_promises15.readFile)(filePath, "utf8");
146436
147217
  const sections = flattenSections(parseSections(filePath, content3, projectRoot));
146437
- const displayPath = (0, import_node_path17.relative)(process.cwd(), filePath);
147218
+ const displayPath = (0, import_node_path19.relative)(process.cwd(), filePath);
146438
147219
  for (const section2 of sections) {
146439
147220
  if (!section2.firstParagraph) {
146440
147221
  errors.push({
@@ -146489,7 +147270,7 @@ function formatKnowledgeIndexErrors(errors, styler) {
146489
147270
 
146490
147271
  // src/knowledge/audit.ts
146491
147272
  var import_node_child_process4 = require("node:child_process");
146492
- var import_node_fs10 = require("node:fs");
147273
+ var import_node_fs12 = require("node:fs");
146493
147274
  init_graph();
146494
147275
  function runGit(projectRoot, args2) {
146495
147276
  return new Promise((resolve2) => {
@@ -146624,7 +147405,7 @@ async function analyzeKnowledgeImpacts(params) {
146624
147405
  const changedFiles = await getChangedFiles(params.projectRoot, params.mode);
146625
147406
  const knowledgeChangedFiles = changedFiles.filter((filePath) => filePath.startsWith("docyrus/knowledge/"));
146626
147407
  const diffStats = await getDiffStats(params.projectRoot, params.mode);
146627
- if (!params.knowledgeDir || !(0, import_node_fs10.existsSync)(params.knowledgeDir)) {
147408
+ if (!params.knowledgeDir || !(0, import_node_fs12.existsSync)(params.knowledgeDir)) {
146628
147409
  return {
146629
147410
  ok: true,
146630
147411
  mode: params.mode,
@@ -146730,7 +147511,7 @@ async function analyzeKnowledgeImpacts(params) {
146730
147511
  };
146731
147512
  }
146732
147513
  async function analyzeKnowledgeDoctor(params) {
146733
- if (!params.knowledgeDir || !(0, import_node_fs10.existsSync)(params.knowledgeDir)) {
147514
+ if (!params.knowledgeDir || !(0, import_node_fs12.existsSync)(params.knowledgeDir)) {
146734
147515
  return {
146735
147516
  ok: false,
146736
147517
  warnings: [{
@@ -146890,7 +147671,8 @@ async function getStopReason(knowledgeDir) {
146890
147671
  const code = await checkKnowledgeCodeRefs(knowledgeDir);
146891
147672
  const indexErrors = await checkKnowledgeIndex(knowledgeDir);
146892
147673
  const sectionErrors = await checkKnowledgeSections(knowledgeDir);
146893
- 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;
146894
147676
  const audit = await analyzeKnowledgeImpacts({
146895
147677
  projectRoot: process.cwd(),
146896
147678
  knowledgeDir,
@@ -146903,6 +147685,9 @@ async function getStopReason(knowledgeDir) {
146903
147685
  if (totalErrors > 0) {
146904
147686
  parts2.push(`docyrus knowledge check failed with ${totalErrors} error${totalErrors === 1 ? "" : "s"}.`);
146905
147687
  }
147688
+ for (const error48 of projectPlanErrors.errors) {
147689
+ parts2.push(error48.message);
147690
+ }
146906
147691
  for (const error48 of audit.blockingErrors) {
146907
147692
  parts2.push(error48.message);
146908
147693
  }
@@ -147052,6 +147837,7 @@ function createKnowledgeCli(dependencies) {
147052
147837
  maybePrintHuman(context, [
147053
147838
  `Knowledge graph ready at ${result.knowledgeDir}`,
147054
147839
  `knowledge.md: ${result.knowledgeFileStatus}`,
147840
+ `project-plan: ${result.projectPlanGraphPath}`,
147055
147841
  `AGENTS.md: ${result.agentsStatus}`,
147056
147842
  `CLAUDE.md: ${result.claudeStatus}`,
147057
147843
  `.cursor/rules/docyrus-knowledge.md: ${result.cursorRulesStatus}`,
@@ -147079,8 +147865,10 @@ function createKnowledgeCli(dependencies) {
147079
147865
  root: process.cwd(),
147080
147866
  brief: context.args.brief
147081
147867
  });
147868
+ const projectPlan = await syncProjectPlanSectionsFromKnowledge(process.cwd());
147082
147869
  maybePrintHuman(context, [
147083
- `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}`,
147084
147872
  `root: ${result.files.rootKnowledgeStatus}`,
147085
147873
  `architecture: ${result.files.architectureStatus}`,
147086
147874
  `features: ${result.files.featuresStatus}`,
@@ -147105,17 +147893,19 @@ function createKnowledgeCli(dependencies) {
147105
147893
  const codeRefs = await checkKnowledgeCodeRefs(knowledgeContext.knowledgeDir);
147106
147894
  const indexErrors = await checkKnowledgeIndex(knowledgeContext.knowledgeDir);
147107
147895
  const sectionErrors = await checkKnowledgeSections(knowledgeContext.knowledgeDir);
147896
+ const projectPlan = await validateProjectPlanGraph(process.cwd());
147108
147897
  const fileStats = { ...markdown.files };
147109
147898
  for (const [extension2, count] of Object.entries(codeRefs.files)) {
147110
147899
  fileStats[extension2] = (fileStats[extension2] || 0) + count;
147111
147900
  }
147112
- 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;
147113
147902
  const human = [
147114
147903
  formatKnowledgeFileStats(fileStats, knowledgeContext.styler),
147115
147904
  ...formatKnowledgeCheckErrors(markdown.errors, knowledgeContext.styler),
147116
147905
  ...formatKnowledgeCheckErrors(codeRefs.errors, knowledgeContext.styler),
147117
147906
  ...formatKnowledgeIndexErrors(indexErrors, knowledgeContext.styler),
147118
147907
  ...formatKnowledgeCheckErrors(sectionErrors, knowledgeContext.styler),
147908
+ ...projectPlan.errors.map((error48) => `- ${knowledgeContext.styler.cyan("docyrus/project-plan/project-plan.json")}: ${knowledgeContext.styler.red(error48.message)}`),
147119
147909
  totalErrors === 0 ? knowledgeContext.styler.green("All knowledge checks passed") : knowledgeContext.styler.red(`${totalErrors} error${totalErrors === 1 ? "" : "s"} found`)
147120
147910
  ].join("\n");
147121
147911
  maybePrintHuman(context, human);
@@ -147128,7 +147918,8 @@ function createKnowledgeCli(dependencies) {
147128
147918
  markdown: markdown.errors,
147129
147919
  codeRefs: codeRefs.errors,
147130
147920
  index: indexErrors,
147131
- sections: sectionErrors
147921
+ sections: sectionErrors,
147922
+ projectPlan: projectPlan.errors
147132
147923
  },
147133
147924
  files: fileStats,
147134
147925
  ok: totalErrors === 0
@@ -147453,9 +148244,10 @@ function createKnowledgeCli(dependencies) {
147453
148244
  markdown: await checkKnowledgeMarkdown(knowledgeContext.knowledgeDir),
147454
148245
  codeRefs: await checkKnowledgeCodeRefs(knowledgeContext.knowledgeDir),
147455
148246
  index: await checkKnowledgeIndex(knowledgeContext.knowledgeDir),
147456
- sections: await checkKnowledgeSections(knowledgeContext.knowledgeDir)
148247
+ sections: await checkKnowledgeSections(knowledgeContext.knowledgeDir),
148248
+ projectPlan: await validateProjectPlanGraph(process.cwd())
147457
148249
  } : null;
147458
- 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;
147459
148251
  const ok3 = blockingCheckErrors === 0 && audit.blockingErrors.length === 0;
147460
148252
  const payload = {
147461
148253
  ok: ok3,
@@ -147463,7 +148255,8 @@ function createKnowledgeCli(dependencies) {
147463
148255
  markdown: checkResult.markdown.errors,
147464
148256
  codeRefs: checkResult.codeRefs.errors,
147465
148257
  index: checkResult.index,
147466
- sections: checkResult.sections
148258
+ sections: checkResult.sections,
148259
+ projectPlan: checkResult.projectPlan.errors
147467
148260
  } : null,
147468
148261
  audit
147469
148262
  };
@@ -147537,8 +148330,10 @@ function createKnowledgeCli(dependencies) {
147537
148330
  brief: context.args.brief,
147538
148331
  targetSectionIds: sectionIds
147539
148332
  });
148333
+ const projectPlan = await syncProjectPlanSectionsFromKnowledge(process.cwd());
147540
148334
  maybePrintHuman(context, [
147541
148335
  `Refreshed managed knowledge files.`,
148336
+ `project-plan: ${projectPlan.graphPath}`,
147542
148337
  `Targets: ${sectionIds.length > 0 ? sectionIds.join(", ") : "all starter files"}`,
147543
148338
  `root: ${result.files.rootKnowledgeStatus}`,
147544
148339
  `architecture: ${result.files.architectureStatus}`,
@@ -147552,6 +148347,8 @@ function createKnowledgeCli(dependencies) {
147552
148347
  authStore: dependencies.authStore,
147553
148348
  payload: {
147554
148349
  ...result,
148350
+ projectPlanGraphPath: projectPlan.graphPath,
148351
+ projectPlanMarkdownPath: projectPlan.markdownPath,
147555
148352
  targetSectionIds: sectionIds
147556
148353
  }
147557
148354
  });
@@ -147599,7 +148396,7 @@ function createKnowledgeCli(dependencies) {
147599
148396
  settingsRootPath: dependencies.settingsPaths.rootPath
147600
148397
  });
147601
148398
  const payload = {
147602
- id: (0, import_node_crypto4.randomUUID)(),
148399
+ id: (0, import_node_crypto6.randomUUID)(),
147603
148400
  projectRoot,
147604
148401
  knowledgeDir,
147605
148402
  settingsScope: dependencies.settingsPaths.scope,
@@ -147644,9 +148441,617 @@ function createKnowledgeCli(dependencies) {
147644
148441
  return knowledgeCli;
147645
148442
  }
147646
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
+
147647
149052
  // src/services/studioPayload.ts
147648
- var import_promises14 = require("node:fs/promises");
147649
- var import_node_path19 = require("node:path");
149053
+ var import_promises17 = require("node:fs/promises");
149054
+ var import_node_path23 = require("node:path");
147650
149055
  async function readStdinText3() {
147651
149056
  if (process.stdin.isTTY) {
147652
149057
  return "";
@@ -147661,7 +149066,7 @@ async function readStdinText3() {
147661
149066
  }
147662
149067
  return Buffer.concat(chunks).toString("utf8").trim();
147663
149068
  }
147664
- function isRecord3(value2) {
149069
+ function isRecord4(value2) {
147665
149070
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
147666
149071
  }
147667
149072
  async function readStudioWriteInput(params) {
@@ -147669,7 +149074,7 @@ async function readStudioWriteInput(params) {
147669
149074
  data,
147670
149075
  fromFile,
147671
149076
  readStdin: readStdin2 = readStdinText3,
147672
- readFileFn = async (path3, encoding) => await (0, import_promises14.readFile)(path3, encoding)
149077
+ readFileFn = async (path7, encoding) => await (0, import_promises17.readFile)(path7, encoding)
147673
149078
  } = params;
147674
149079
  const trimmedData = data?.trim();
147675
149080
  const trimmedFromFile = fromFile?.trim();
@@ -147677,7 +149082,7 @@ async function readStudioWriteInput(params) {
147677
149082
  throw new UserInputError("Provide either --data or --from-file, not both.");
147678
149083
  }
147679
149084
  if (trimmedFromFile) {
147680
- const extension2 = (0, import_node_path19.extname)(trimmedFromFile).toLowerCase();
149085
+ const extension2 = (0, import_node_path23.extname)(trimmedFromFile).toLowerCase();
147681
149086
  if (extension2 && extension2 !== ".json") {
147682
149087
  throw new UserInputError("Studio commands support only JSON files in --from-file.");
147683
149088
  }
@@ -147701,7 +149106,7 @@ async function readStudioWriteInput(params) {
147701
149106
  return parseJsonData(stdinContent, "stdin");
147702
149107
  }
147703
149108
  function ensureObjectPayload(payload, label) {
147704
- if (!isRecord3(payload)) {
149109
+ if (!isRecord4(payload)) {
147705
149110
  throw new UserInputError(`${label} expects a JSON object payload.`);
147706
149111
  }
147707
149112
  return payload;
@@ -147724,7 +149129,7 @@ function normalizeBatchPayload(payload, key) {
147724
149129
  [key]: payload
147725
149130
  };
147726
149131
  }
147727
- if (isRecord3(payload)) {
149132
+ if (isRecord4(payload)) {
147728
149133
  if (key in payload) {
147729
149134
  return payload;
147730
149135
  }
@@ -147736,7 +149141,7 @@ function normalizeBatchPayload(payload, key) {
147736
149141
  }
147737
149142
 
147738
149143
  // src/services/studioResolver.ts
147739
- function isRecord4(value2) {
149144
+ function isRecord5(value2) {
147740
149145
  return typeof value2 === "object" && value2 !== null;
147741
149146
  }
147742
149147
  function extractString2(record2, key) {
@@ -147745,10 +149150,10 @@ function extractString2(record2, key) {
147745
149150
  }
147746
149151
  function extractArray(payload) {
147747
149152
  if (Array.isArray(payload)) {
147748
- return payload.filter((item) => isRecord4(item));
149153
+ return payload.filter((item) => isRecord5(item));
147749
149154
  }
147750
- if (isRecord4(payload) && Array.isArray(payload.data)) {
147751
- return payload.data.filter((item) => isRecord4(item));
149155
+ if (isRecord5(payload) && Array.isArray(payload.data)) {
149156
+ return payload.data.filter((item) => isRecord5(item));
147752
149157
  }
147753
149158
  return [];
147754
149159
  }
@@ -147916,11 +149321,11 @@ function requireNonEmptyObject(payload, label) {
147916
149321
  throw new UserInputError(`${label} payload is empty. Provide flags, --data, or --from-file.`);
147917
149322
  }
147918
149323
  }
147919
- function isRecord5(value2) {
149324
+ function isRecord6(value2) {
147920
149325
  return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
147921
149326
  }
147922
149327
  function normalizeBatchUpdateFieldItem(item) {
147923
- if (!isRecord5(item)) {
149328
+ if (!isRecord6(item)) {
147924
149329
  return item;
147925
149330
  }
147926
149331
  const normalized = {
@@ -147954,7 +149359,7 @@ function normalizeBatchUpdateFieldsPayload(payload) {
147954
149359
  };
147955
149360
  }
147956
149361
  function normalizeUpdateEnumItem(item) {
147957
- if (!isRecord5(item)) {
149362
+ if (!isRecord6(item)) {
147958
149363
  return item;
147959
149364
  }
147960
149365
  if (!("enumId" in item) && typeof item.id === "string") {
@@ -148682,8 +150087,8 @@ function createStudioCli(dependencies) {
148682
150087
 
148683
150088
  // src/commands/tuiCommand.ts
148684
150089
  var import_node_child_process5 = require("node:child_process");
148685
- var import_node_fs11 = require("node:fs");
148686
- var import_node_path20 = require("node:path");
150090
+ var import_node_fs15 = require("node:fs");
150091
+ var import_node_path24 = require("node:path");
148687
150092
  function summarizeFailure2(result) {
148688
150093
  const stderr = result.stderr?.toString().trim();
148689
150094
  if (stderr && stderr.length > 0) {
@@ -148700,23 +150105,23 @@ function summarizeFailure2(result) {
148700
150105
  function resolveCliScriptPath() {
148701
150106
  const argvScript = process.argv[1];
148702
150107
  if (argvScript && argvScript.trim().length > 0) {
148703
- 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);
148704
150109
  }
148705
150110
  return __filename;
148706
150111
  }
148707
150112
  function resolveOpenTuiEntryPath(options2 = {}) {
148708
150113
  const cwd = options2.cwd ?? process.cwd();
148709
150114
  const dirname13 = options2.dirname ?? __dirname;
148710
- const fileExists = options2.existsSyncFn ?? import_node_fs11.existsSync;
150115
+ const fileExists = options2.existsSyncFn ?? import_node_fs15.existsSync;
148711
150116
  const candidates = [
148712
150117
  // Source/dev mode in monorepo. Prefer this first so Bun resolves deps via
148713
150118
  // apps/api-cli/node_modules in workspace runs (e.g. `pnpm docyrus tui`).
148714
- (0, import_node_path20.resolve)(cwd, "apps/api-cli/src/tui/opentuiMain.tsx"),
148715
- (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"),
148716
150121
  // Dist mode (bundled command runtime)
148717
- (0, import_node_path20.resolve)(dirname13, "tui.mjs"),
148718
- (0, import_node_path20.resolve)(dirname13, "../tui.mjs"),
148719
- (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")
148720
150125
  ];
148721
150126
  const resolved = candidates.find((candidate) => fileExists(candidate));
148722
150127
  if (!resolved) {
@@ -148857,7 +150262,7 @@ async function parseResponseBody(response) {
148857
150262
  }
148858
150263
  }
148859
150264
  function normalizeErrorResponse(params) {
148860
- const { status, path: path3, headers, body: body2 } = params;
150265
+ const { status, path: path7, headers, body: body2 } = params;
148861
150266
  const bodyObject = typeof body2 === "object" && body2 !== null ? body2 : null;
148862
150267
  const errorCodeValue = bodyObject?.error;
148863
150268
  const errorDescriptionValue = bodyObject?.error_description ?? bodyObject?.message;
@@ -148867,7 +150272,7 @@ function normalizeErrorResponse(params) {
148867
150272
  status,
148868
150273
  error: errorCode,
148869
150274
  error_description: errorDescription,
148870
- path: path3,
150275
+ path: path7,
148871
150276
  rate_limit_limit: headers.get("ratelimit-limit") || void 0,
148872
150277
  rate_limit_remaining: headers.get("ratelimit-remaining") || void 0,
148873
150278
  rate_limit_reset: headers.get("ratelimit-reset") || void 0,
@@ -148875,13 +150280,13 @@ function normalizeErrorResponse(params) {
148875
150280
  raw: body2
148876
150281
  };
148877
150282
  }
148878
- function normalizePathForUrl(path3) {
148879
- return normalizeApiPath(path3);
150283
+ function normalizePathForUrl(path7) {
150284
+ return normalizeApiPath(path7);
148880
150285
  }
148881
150286
  async function requestDocyrusApi(options2) {
148882
150287
  const {
148883
150288
  baseUrl,
148884
- path: path3,
150289
+ path: path7,
148885
150290
  method = "GET",
148886
150291
  headers,
148887
150292
  query,
@@ -148890,7 +150295,7 @@ async function requestDocyrusApi(options2) {
148890
150295
  fetchFn = fetch
148891
150296
  } = options2;
148892
150297
  const normalizedBaseUrl = normalizeApiBaseUrl(baseUrl);
148893
- const normalizedPath = normalizePathForUrl(path3);
150298
+ const normalizedPath = normalizePathForUrl(path7);
148894
150299
  const url2 = `${normalizedBaseUrl}${normalizedPath}${toQueryString(query)}`;
148895
150300
  const requestHeaders = {
148896
150301
  Accept: "application/json",
@@ -148950,12 +150355,12 @@ var ApiClient = class {
148950
150355
  const {
148951
150356
  authRequired = true,
148952
150357
  method = "GET",
148953
- path: path3,
150358
+ path: path7,
148954
150359
  headers,
148955
150360
  query,
148956
150361
  body: body2
148957
150362
  } = options2;
148958
- if (!path3) {
150363
+ if (!path7) {
148959
150364
  throw new UserInputError("Request path is required.");
148960
150365
  }
148961
150366
  let authToken;
@@ -148965,7 +150370,7 @@ var ApiClient = class {
148965
150370
  return await requestDocyrusApi({
148966
150371
  baseUrl: this.#apiBaseUrl,
148967
150372
  method,
148968
- path: path3,
150373
+ path: path7,
148969
150374
  headers,
148970
150375
  query,
148971
150376
  body: body2,
@@ -148977,7 +150382,7 @@ var ApiClient = class {
148977
150382
 
148978
150383
  // src/services/authSession.ts
148979
150384
  var DEFAULT_MANUAL_ACCESS_TOKEN_EXPIRY_SECONDS = 3600;
148980
- function isRecord6(value2) {
150385
+ function isRecord7(value2) {
148981
150386
  return typeof value2 === "object" && value2 !== null;
148982
150387
  }
148983
150388
  function extractRecordValue(record2, keys) {
@@ -149291,11 +150696,11 @@ var AuthSessionService = class {
149291
150696
  fetchFn: this.params.fetchFn
149292
150697
  });
149293
150698
  const payload = response.data;
149294
- const dataCandidate = isRecord6(payload) && isRecord6(payload.data) ? payload.data : payload;
149295
- if (!isRecord6(dataCandidate)) {
150699
+ const dataCandidate = isRecord7(payload) && isRecord7(payload.data) ? payload.data : payload;
150700
+ if (!isRecord7(dataCandidate)) {
149296
150701
  throw new AuthSessionError("Unable to parse /users/me response.");
149297
150702
  }
149298
- const tenantCandidate = isRecord6(dataCandidate.tenant) ? dataCandidate.tenant : void 0;
150703
+ const tenantCandidate = isRecord7(dataCandidate.tenant) ? dataCandidate.tenant : void 0;
149299
150704
  const userId = extractString3(dataCandidate, ["id", "user_id"]);
149300
150705
  const email3 = extractString3(dataCandidate, ["email"]);
149301
150706
  const tenantId = tenantCandidate ? extractString3(tenantCandidate, ["id"]) : extractString3(dataCandidate, ["tenant_id", "tenantId"]);
@@ -149321,13 +150726,13 @@ var AuthSessionService = class {
149321
150726
  fetchFn: this.params.fetchFn
149322
150727
  });
149323
150728
  const payload = response.data;
149324
- 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;
149325
150730
  if (!listCandidate) {
149326
150731
  throw new AuthSessionError("Unable to parse tenant catalog response.");
149327
150732
  }
149328
150733
  const mapped = [];
149329
150734
  for (const item of listCandidate) {
149330
- if (!isRecord6(item)) {
150735
+ if (!isRecord7(item)) {
149331
150736
  continue;
149332
150737
  }
149333
150738
  const tenantId = extractString3(item, ["id", "tenant_id"]);
@@ -149517,8 +150922,8 @@ var AuthSessionService = class {
149517
150922
  };
149518
150923
 
149519
150924
  // src/services/authStore.ts
149520
- var import_promises15 = require("node:fs/promises");
149521
- var import_node_path21 = require("node:path");
150925
+ var import_promises18 = require("node:fs/promises");
150926
+ var import_node_path25 = require("node:path");
149522
150927
  function createEmptyState() {
149523
150928
  return {
149524
150929
  version: 2,
@@ -149558,7 +150963,7 @@ var AuthStore = class {
149558
150963
  }
149559
150964
  async readState() {
149560
150965
  try {
149561
- const raw = await (0, import_promises15.readFile)(this.authFilePath, "utf8");
150966
+ const raw = await (0, import_promises18.readFile)(this.authFilePath, "utf8");
149562
150967
  const parsed = JSON.parse(raw);
149563
150968
  const legacy = LegacyAuthSessionSchema.safeParse(parsed);
149564
150969
  if (legacy.success) {
@@ -149594,17 +150999,17 @@ var AuthStore = class {
149594
150999
  });
149595
151000
  }
149596
151001
  const normalized = normalizeState2(validated.data);
149597
- const directory = (0, import_node_path21.dirname)(this.authFilePath);
149598
- await (0, import_promises15.mkdir)(directory, {
151002
+ const directory = (0, import_node_path25.dirname)(this.authFilePath);
151003
+ await (0, import_promises18.mkdir)(directory, {
149599
151004
  recursive: true,
149600
151005
  mode: 448
149601
151006
  });
149602
- 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)}
149603
151008
  `, {
149604
151009
  encoding: "utf8",
149605
151010
  mode: 384
149606
151011
  });
149607
- await (0, import_promises15.chmod)(this.authFilePath, 384);
151012
+ await (0, import_promises18.chmod)(this.authFilePath, 384);
149608
151013
  }
149609
151014
  async getActiveProfile(apiBaseUrl) {
149610
151015
  const normalizedApiBaseUrl = normalizeApiBaseUrl(apiBaseUrl);
@@ -149801,15 +151206,15 @@ var AuthStore = class {
149801
151206
  await this.writeState(state);
149802
151207
  }
149803
151208
  async clear() {
149804
- await (0, import_promises15.rm)(this.authFilePath, {
151209
+ await (0, import_promises18.rm)(this.authFilePath, {
149805
151210
  force: true
149806
151211
  });
149807
151212
  }
149808
151213
  };
149809
151214
 
149810
151215
  // src/services/environmentConfig.ts
149811
- var import_promises16 = require("node:fs/promises");
149812
- var import_node_path22 = require("node:path");
151216
+ var import_promises19 = require("node:fs/promises");
151217
+ var import_node_path26 = require("node:path");
149813
151218
  var ENVIRONMENT_ID_ALIASES = {
149814
151219
  "local-development": "dev",
149815
151220
  prod: "live"
@@ -149896,7 +151301,7 @@ var EnvironmentConfigService = class {
149896
151301
  configFilePath;
149897
151302
  async readState() {
149898
151303
  try {
149899
- const raw = await (0, import_promises16.readFile)(this.configFilePath, "utf8");
151304
+ const raw = await (0, import_promises19.readFile)(this.configFilePath, "utf8");
149900
151305
  const parsed = JSON.parse(raw);
149901
151306
  const validated = EnvironmentConfigStateSchema.safeParse(parsed);
149902
151307
  if (!validated.success) {
@@ -149930,17 +151335,17 @@ var EnvironmentConfigService = class {
149930
151335
  });
149931
151336
  }
149932
151337
  const normalized = normalizeState3(validated.data);
149933
- const directory = (0, import_node_path22.dirname)(this.configFilePath);
149934
- await (0, import_promises16.mkdir)(directory, {
151338
+ const directory = (0, import_node_path26.dirname)(this.configFilePath);
151339
+ await (0, import_promises19.mkdir)(directory, {
149935
151340
  recursive: true,
149936
151341
  mode: 448
149937
151342
  });
149938
- 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)}
149939
151344
  `, {
149940
151345
  encoding: "utf8",
149941
151346
  mode: 384
149942
151347
  });
149943
- await (0, import_promises16.chmod)(this.configFilePath, 384);
151348
+ await (0, import_promises19.chmod)(this.configFilePath, 384);
149944
151349
  }
149945
151350
  async getActiveEnvironment() {
149946
151351
  const state = await this.#readStateWithDefaults();
@@ -150007,9 +151412,9 @@ var EnvironmentConfigService = class {
150007
151412
 
150008
151413
  // src/services/piAgentLauncher.ts
150009
151414
  var import_node_child_process6 = require("node:child_process");
150010
- var import_node_fs12 = require("node:fs");
150011
- var import_promises17 = require("node:fs/promises");
150012
- 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");
150013
151418
 
150014
151419
  // src/services/spinner.ts
150015
151420
  var import_picocolors2 = __toESM(require_picocolors());
@@ -150055,7 +151460,7 @@ var DOCYRUS_EXTERNAL_SKILL_AGENT_IDS = [
150055
151460
  ];
150056
151461
  var DOCYRUS_EXTERNAL_SKILL_MARKER_FILE = ".docyrus-external-skills-installed.json";
150057
151462
  var DOCYRUS_DIFFITY_PACKAGE_SPEC = "diffity@0.9.0";
150058
- var DOCYRUS_OFFICECLI_RELEASES_BASE_URL = "https://github.com/iOfficeAI/OfficeCli/releases/latest/download";
151463
+ var DOCYRUS_OFFICECLI_MANIFEST_FILE_NAME = "manifest.json";
150059
151464
  function summarizeFailure3(result, commandLabel = "Command") {
150060
151465
  const stderr = result.stderr?.toString().trim();
150061
151466
  if (stderr && stderr.length > 0) {
@@ -150072,12 +151477,12 @@ function summarizeFailure3(result, commandLabel = "Command") {
150072
151477
  function resolvePackagedPiResourceRoot(options2 = {}) {
150073
151478
  const cwd = options2.cwd ?? process.cwd();
150074
151479
  const dirname13 = options2.dirname ?? __dirname;
150075
- const fileExists = options2.existsSyncFn ?? import_node_fs12.existsSync;
151480
+ const fileExists = options2.existsSyncFn ?? import_node_fs16.existsSync;
150076
151481
  const candidates = [
150077
- (0, import_node_path23.resolve)(cwd, "apps/api-cli/resources/pi-agent"),
150078
- (0, import_node_path23.resolve)(dirname13, "../resources/pi-agent"),
150079
- (0, import_node_path23.resolve)(dirname13, "resources/pi-agent"),
150080
- (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")
150081
151486
  ];
150082
151487
  const resolved = candidates.find((candidate) => fileExists(candidate));
150083
151488
  if (!resolved) {
@@ -150088,7 +151493,7 @@ function resolvePackagedPiResourceRoot(options2 = {}) {
150088
151493
  function resolveDocyrusPiLoaderEntryPath(options2 = {}) {
150089
151494
  const cwd = options2.cwd ?? process.cwd();
150090
151495
  const dirname13 = options2.dirname ?? __dirname;
150091
- const fileExists = options2.existsSyncFn ?? import_node_fs12.existsSync;
151496
+ const fileExists = options2.existsSyncFn ?? import_node_fs16.existsSync;
150092
151497
  const seen = /* @__PURE__ */ new Set();
150093
151498
  const candidates = options2.candidatePaths ?? [];
150094
151499
  const addCandidate = (candidate) => {
@@ -150098,23 +151503,23 @@ function resolveDocyrusPiLoaderEntryPath(options2 = {}) {
150098
151503
  }
150099
151504
  };
150100
151505
  const collectAncestorCandidates = (startDir) => {
150101
- let currentDir = (0, import_node_path23.resolve)(startDir);
151506
+ let currentDir = (0, import_node_path27.resolve)(startDir);
150102
151507
  while (true) {
150103
- addCandidate((0, import_node_path23.join)(currentDir, "dist", "apps", "api-cli", "agent-loader.js"));
150104
- addCandidate((0, import_node_path23.join)(currentDir, "agent-loader.js"));
150105
- if ((0, import_node_path23.basename)(currentDir) === "dist") {
150106
- 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"));
150107
151512
  }
150108
- const parentDir = (0, import_node_path23.resolve)(currentDir, "..");
151513
+ const parentDir = (0, import_node_path27.resolve)(currentDir, "..");
150109
151514
  if (parentDir === currentDir) {
150110
151515
  break;
150111
151516
  }
150112
151517
  currentDir = parentDir;
150113
151518
  }
150114
151519
  };
150115
- addCandidate((0, import_node_path23.resolve)(cwd, "dist/apps/api-cli/agent-loader.js"));
150116
- addCandidate((0, import_node_path23.resolve)(dirname13, "../agent-loader.js"));
150117
- 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"));
150118
151523
  collectAncestorCandidates(cwd);
150119
151524
  collectAncestorCandidates(dirname13);
150120
151525
  const resolved = candidates.find((candidate) => fileExists(candidate));
@@ -150127,27 +151532,27 @@ function resolveDocyrusCliEntryPath(options2 = {}) {
150127
151532
  const cwd = options2.cwd ?? process.cwd();
150128
151533
  const dirname13 = options2.dirname ?? __dirname;
150129
151534
  const argv = options2.argv ?? process.argv;
150130
- const fileExists = options2.existsSyncFn ?? import_node_fs12.existsSync;
151535
+ const fileExists = options2.existsSyncFn ?? import_node_fs16.existsSync;
150131
151536
  const seen = /* @__PURE__ */ new Set();
150132
151537
  const candidates = options2.candidatePaths ?? [];
150133
151538
  const addCandidate = (candidate) => {
150134
151539
  if (!candidate) {
150135
151540
  return;
150136
151541
  }
150137
- const resolvedCandidate = (0, import_node_path23.resolve)(candidate);
151542
+ const resolvedCandidate = (0, import_node_path27.resolve)(candidate);
150138
151543
  if (!seen.has(resolvedCandidate)) {
150139
151544
  seen.add(resolvedCandidate);
150140
151545
  candidates.push(resolvedCandidate);
150141
151546
  }
150142
151547
  };
150143
151548
  const argvScript = argv[1]?.trim();
150144
- 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;
150145
151550
  if (normalizedArgvScript && normalizedArgvScript.endsWith(".js")) {
150146
151551
  addCandidate(normalizedArgvScript);
150147
151552
  }
150148
- addCandidate((0, import_node_path23.resolve)(cwd, "dist/apps/api-cli/main.js"));
150149
- addCandidate((0, import_node_path23.resolve)(dirname13, "../main.js"));
150150
- 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"));
150151
151556
  if (normalizedArgvScript) {
150152
151557
  addCandidate(normalizedArgvScript);
150153
151558
  }
@@ -150160,7 +151565,7 @@ function resolveDocyrusCliEntryPath(options2 = {}) {
150160
151565
  function resolveInstalledPiPackageRootPath(options2 = {}) {
150161
151566
  const cwd = options2.cwd ?? process.cwd();
150162
151567
  const dirname13 = options2.dirname ?? __dirname;
150163
- const fileExists = options2.existsSyncFn ?? import_node_fs12.existsSync;
151568
+ const fileExists = options2.existsSyncFn ?? import_node_fs16.existsSync;
150164
151569
  const seen = /* @__PURE__ */ new Set();
150165
151570
  const candidates = options2.candidatePaths ?? [];
150166
151571
  const addCandidate = (candidate) => {
@@ -150170,33 +151575,33 @@ function resolveInstalledPiPackageRootPath(options2 = {}) {
150170
151575
  }
150171
151576
  };
150172
151577
  const collectAncestorCandidates = (startDir) => {
150173
- let currentDir = (0, import_node_path23.resolve)(startDir);
151578
+ let currentDir = (0, import_node_path27.resolve)(startDir);
150174
151579
  while (true) {
150175
- addCandidate((0, import_node_path23.join)(currentDir, "node_modules", "@mariozechner", "pi-coding-agent", "package.json"));
150176
- if ((0, import_node_path23.basename)(currentDir) === "node_modules") {
150177
- 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"));
150178
151583
  }
150179
- const parentDir = (0, import_node_path23.resolve)(currentDir, "..");
151584
+ const parentDir = (0, import_node_path27.resolve)(currentDir, "..");
150180
151585
  if (parentDir === currentDir) {
150181
151586
  break;
150182
151587
  }
150183
151588
  currentDir = parentDir;
150184
151589
  }
150185
151590
  };
150186
- addCandidate((0, import_node_path23.resolve)(cwd, "apps/api-cli/node_modules/@mariozechner/pi-coding-agent/package.json"));
150187
- 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"));
150188
151593
  collectAncestorCandidates(cwd);
150189
151594
  collectAncestorCandidates(dirname13);
150190
151595
  const resolvedPackageJson = candidates.find((candidate) => fileExists(candidate));
150191
151596
  if (!resolvedPackageJson) {
150192
151597
  throw new UserInputError(`Unable to locate the installed pi package root. Checked: ${candidates.join(", ")}`);
150193
151598
  }
150194
- return (0, import_node_path23.resolve)(resolvedPackageJson, "..");
151599
+ return (0, import_node_path27.resolve)(resolvedPackageJson, "..");
150195
151600
  }
150196
151601
  function createPiAgentRuntimeSkill(params) {
150197
151602
  const commandPrefix = params.scope === "global" ? "docyrus -g" : "docyrus";
150198
- const knowledgeDir = (0, import_node_path23.join)(params.cwd, "docyrus", "knowledge");
150199
- 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);
150200
151605
  const authLines = params.activeProfile ? [
150201
151606
  `- email: \`${params.activeProfile.email}\``,
150202
151607
  `- tenant: \`${params.activeProfile.tenantName} (${params.activeProfile.tenantNo})\``,
@@ -150249,35 +151654,35 @@ function createPiAgentRuntimeSkill(params) {
150249
151654
  ].join("\n");
150250
151655
  }
150251
151656
  async function syncPackagedSkills(params) {
150252
- const sourceSkillsRoot = (0, import_node_path23.join)(params.resourceRoot, "skills");
150253
- const targetSkillsRoot = (0, import_node_path23.join)(params.agentRootPath, "skills");
150254
- 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, {
150255
151660
  recursive: true,
150256
151661
  mode: 448
150257
151662
  });
150258
- const entries = await (0, import_promises17.readdir)(sourceSkillsRoot, {
151663
+ const entries = await (0, import_promises20.readdir)(sourceSkillsRoot, {
150259
151664
  withFileTypes: true
150260
151665
  });
150261
151666
  await Promise.all(DOCYRUS_MIGRATED_SKILL_NAMES.map(async (skillName) => {
150262
- 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), {
150263
151668
  recursive: true,
150264
151669
  force: true
150265
151670
  });
150266
151671
  }));
150267
151672
  await Promise.all(entries.map(async (entry) => {
150268
- 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), {
150269
151674
  recursive: true,
150270
151675
  force: true
150271
151676
  });
150272
151677
  }));
150273
151678
  }
150274
151679
  async function writeRuntimeSkill(params) {
150275
- const runtimeSkillDir = (0, import_node_path23.join)(params.agentRootPath, "skills", "docyrus-runtime-context");
150276
- 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, {
150277
151682
  recursive: true,
150278
151683
  mode: 448
150279
151684
  });
150280
- 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}
150281
151686
  `, {
150282
151687
  encoding: "utf8",
150283
151688
  mode: 384
@@ -150290,10 +151695,10 @@ function resolveNpmCommand() {
150290
151695
  return process.platform === "win32" ? "npm.cmd" : "npm";
150291
151696
  }
150292
151697
  function resolveManagedDiffityInstallRoot(agentRootPath) {
150293
- return (0, import_node_path23.join)(agentRootPath, "tools", "diffity");
151698
+ return (0, import_node_path27.join)(agentRootPath, "tools", "diffity");
150294
151699
  }
150295
151700
  function resolveManagedDiffityExecutablePath(agentRootPath) {
150296
- return (0, import_node_path23.join)(
151701
+ return (0, import_node_path27.join)(
150297
151702
  resolveManagedDiffityInstallRoot(agentRootPath),
150298
151703
  "node_modules",
150299
151704
  ".bin",
@@ -150301,10 +151706,10 @@ function resolveManagedDiffityExecutablePath(agentRootPath) {
150301
151706
  );
150302
151707
  }
150303
151708
  function prependPathEntry(entry, existingPath) {
150304
- 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) : [];
150305
151710
  const normalizedEntry = entry.trim();
150306
151711
  const remaining = values.filter((value2) => value2 !== normalizedEntry);
150307
- return [normalizedEntry, ...remaining].join(import_node_path23.delimiter);
151712
+ return [normalizedEntry, ...remaining].join(import_node_path27.delimiter);
150308
151713
  }
150309
151714
  function createDocyrusSkillsInstallArgs(scope) {
150310
151715
  const args2 = [
@@ -150342,8 +151747,8 @@ function createPackagedDocyrusPlatformInstallArgs(params) {
150342
151747
  return args2;
150343
151748
  }
150344
151749
  async function installExternalDocyrusSkillsOnce(params) {
150345
- const markerPath = (0, import_node_path23.join)(params.agentRootPath, DOCYRUS_EXTERNAL_SKILL_MARKER_FILE);
150346
- 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)) {
150347
151752
  return;
150348
151753
  }
150349
151754
  const result = params.spawnCommand(resolveNpxCommand(), createDocyrusSkillsInstallArgs(params.scope), {
@@ -150361,7 +151766,7 @@ async function installExternalDocyrusSkillsOnce(params) {
150361
151766
  );
150362
151767
  return;
150363
151768
  }
150364
- await (0, import_promises17.writeFile)(markerPath, `${JSON.stringify({
151769
+ await (0, import_promises20.writeFile)(markerPath, `${JSON.stringify({
150365
151770
  source: DOCYRUS_EXTERNAL_SKILL_SOURCE,
150366
151771
  skills: DOCYRUS_MIGRATED_SKILL_NAMES,
150367
151772
  agents: DOCYRUS_EXTERNAL_SKILL_AGENT_IDS,
@@ -150375,8 +151780,8 @@ async function installExternalDocyrusSkillsOnce(params) {
150375
151780
  }
150376
151781
  async function ensureManagedDiffityInstalled(params) {
150377
151782
  const executablePath = resolveManagedDiffityExecutablePath(params.agentRootPath);
150378
- const binDir = (0, import_node_path23.dirname)(executablePath);
150379
- if ((0, import_node_fs12.existsSync)(executablePath)) {
151783
+ const binDir = (0, import_node_path27.dirname)(executablePath);
151784
+ if ((0, import_node_fs16.existsSync)(executablePath)) {
150380
151785
  return {
150381
151786
  available: true,
150382
151787
  executablePath,
@@ -150414,54 +151819,129 @@ async function ensureManagedDiffityInstalled(params) {
150414
151819
  };
150415
151820
  }
150416
151821
  function resolvePackagedDocyrusPlatformSkillPath(resourceRoot) {
150417
- 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);
151823
+ }
151824
+ function resolvePackagedOfficeCliRootPath(resourceRoot) {
151825
+ return (0, import_node_path27.join)((0, import_node_path27.resolve)(resourceRoot, ".."), "officecli");
151826
+ }
151827
+ function resolvePackagedOfficeCliManifestPath(resourceRoot) {
151828
+ return (0, import_node_path27.join)(resolvePackagedOfficeCliRootPath(resourceRoot), DOCYRUS_OFFICECLI_MANIFEST_FILE_NAME);
150418
151829
  }
150419
151830
  function resolveManagedOfficeCliInstallRoot(agentRootPath) {
150420
- return (0, import_node_path23.join)(agentRootPath, "tools", "officecli");
151831
+ return (0, import_node_path27.join)(agentRootPath, "tools", "officecli");
150421
151832
  }
150422
151833
  function resolveManagedOfficeCliExecutablePath(agentRootPath) {
150423
- return (0, import_node_path23.join)(
151834
+ return (0, import_node_path27.join)(
150424
151835
  resolveManagedOfficeCliInstallRoot(agentRootPath),
150425
151836
  process.platform === "win32" ? "officecli.exe" : "officecli"
150426
151837
  );
150427
151838
  }
150428
- function resolveOfficeCliReleaseAssetName() {
150429
- switch (process.platform) {
151839
+ function resolveOfficeCliReleaseAssetName(options2 = {}) {
151840
+ const platform2 = options2.platform ?? process.platform;
151841
+ const arch = options2.arch ?? process.arch;
151842
+ const isAlpine = options2.isAlpine ?? (0, import_node_fs16.existsSync)("/etc/alpine-release");
151843
+ switch (platform2) {
150430
151844
  case "darwin":
150431
- if (process.arch === "arm64") {
151845
+ if (arch === "arm64") {
150432
151846
  return "officecli-mac-arm64";
150433
151847
  }
150434
- if (process.arch === "x64") {
151848
+ if (arch === "x64") {
150435
151849
  return "officecli-mac-x64";
150436
151850
  }
150437
151851
  break;
150438
151852
  case "linux": {
150439
- const alpineSuffix = (0, import_node_fs12.existsSync)("/etc/alpine-release") ? "-alpine" : "";
150440
- if (process.arch === "arm64") {
151853
+ const alpineSuffix = isAlpine ? "-alpine" : "";
151854
+ if (arch === "arm64") {
150441
151855
  return `officecli-linux${alpineSuffix}-arm64`;
150442
151856
  }
150443
- if (process.arch === "x64") {
151857
+ if (arch === "x64") {
150444
151858
  return `officecli-linux${alpineSuffix}-x64`;
150445
151859
  }
150446
151860
  break;
150447
151861
  }
150448
151862
  case "win32":
150449
- if (process.arch === "arm64") {
151863
+ if (arch === "arm64") {
150450
151864
  return "officecli-win-arm64.exe";
150451
151865
  }
150452
- if (process.arch === "x64") {
151866
+ if (arch === "x64") {
150453
151867
  return "officecli-win-x64.exe";
150454
151868
  }
150455
151869
  break;
150456
151870
  default:
150457
151871
  break;
150458
151872
  }
150459
- throw new UserInputError(`OfficeCLI is not supported on ${process.platform}/${process.arch}.`);
151873
+ throw new UserInputError(`OfficeCLI is not supported on ${platform2}/${arch}.`);
151874
+ }
151875
+ function resolvePackagedOfficeCliExecutablePath(resourceRoot, options2) {
151876
+ return (0, import_node_path27.join)(
151877
+ resolvePackagedOfficeCliRootPath(resourceRoot),
151878
+ "bundled",
151879
+ resolveOfficeCliReleaseAssetName(options2)
151880
+ );
151881
+ }
151882
+ async function readPackagedOfficeCliVersion(resourceRoot) {
151883
+ const manifestRaw = await (0, import_promises20.readFile)(resolvePackagedOfficeCliManifestPath(resourceRoot), "utf8");
151884
+ const manifest = JSON.parse(manifestRaw);
151885
+ const version2 = typeof manifest.version === "string" ? manifest.version.trim() : "";
151886
+ if (version2.length === 0) {
151887
+ throw new UserInputError("OfficeCLI manifest is missing a valid version.");
151888
+ }
151889
+ return version2;
151890
+ }
151891
+ async function downloadOfficeCliBinary(params) {
151892
+ const assetName = resolveOfficeCliReleaseAssetName();
151893
+ const version2 = await readPackagedOfficeCliVersion(params.resourceRoot);
151894
+ const response = await fetch(`https://github.com/iOfficeAI/OfficeCLI/releases/download/v${version2}/${assetName}`);
151895
+ if (!response.ok) {
151896
+ throw new UserInputError(`OfficeCLI download failed with status ${response.status}.`);
151897
+ }
151898
+ const binary2 = Buffer.from(await response.arrayBuffer());
151899
+ await (0, import_promises20.writeFile)(params.destinationPath, binary2, {
151900
+ mode: process.platform === "win32" ? 384 : 448
151901
+ });
151902
+ }
151903
+ function resolveManagedOfficeCliConfigMarkerPath(agentRootPath) {
151904
+ return (0, import_node_path27.join)(resolveManagedOfficeCliInstallRoot(agentRootPath), ".docyrus-officecli-configured.json");
151905
+ }
151906
+ async function disableManagedOfficeCliAutoUpdate(params) {
151907
+ const markerPath = resolveManagedOfficeCliConfigMarkerPath(params.agentRootPath);
151908
+ if ((0, import_node_fs16.existsSync)(markerPath)) {
151909
+ return;
151910
+ }
151911
+ const result = params.spawnCommand(params.executablePath, ["config", "autoUpdate", "false"], {
151912
+ stdio: ["ignore", "pipe", "pipe"],
151913
+ encoding: "utf8",
151914
+ cwd: params.cwd,
151915
+ env: {
151916
+ ...process.env,
151917
+ OFFICECLI_SKIP_UPDATE: "1"
151918
+ }
151919
+ });
151920
+ if (result.error || result.status !== 0) {
151921
+ process.stderr.write(
151922
+ `[docyrus] OfficeCLI auto-update disable failed. Continuing with env override only: ${result.error?.message || summarizeFailure3(result, "officecli config autoUpdate false")}
151923
+ `
151924
+ );
151925
+ return;
151926
+ }
151927
+ await (0, import_promises20.writeFile)(markerPath, `${JSON.stringify({
151928
+ configuredAt: (/* @__PURE__ */ new Date()).toISOString()
151929
+ }, null, 2)}
151930
+ `, {
151931
+ encoding: "utf8",
151932
+ mode: 384
151933
+ });
150460
151934
  }
150461
151935
  async function ensureManagedOfficeCliInstalled(params) {
150462
151936
  const executablePath = resolveManagedOfficeCliExecutablePath(params.agentRootPath);
150463
- const binDir = (0, import_node_path23.dirname)(executablePath);
150464
- if ((0, import_node_fs12.existsSync)(executablePath)) {
151937
+ const binDir = (0, import_node_path27.dirname)(executablePath);
151938
+ if ((0, import_node_fs16.existsSync)(executablePath)) {
151939
+ await disableManagedOfficeCliAutoUpdate({
151940
+ agentRootPath: params.agentRootPath,
151941
+ executablePath,
151942
+ cwd: params.cwd,
151943
+ spawnCommand: params.spawnCommand
151944
+ });
150465
151945
  return {
150466
151946
  available: true,
150467
151947
  executablePath,
@@ -150470,21 +151950,23 @@ async function ensureManagedOfficeCliInstalled(params) {
150470
151950
  }
150471
151951
  const tempPath = `${executablePath}.download${process.platform === "win32" ? ".exe" : ""}`;
150472
151952
  try {
150473
- await (0, import_promises17.mkdir)(binDir, {
151953
+ await (0, import_promises20.mkdir)(binDir, {
150474
151954
  recursive: true,
150475
151955
  mode: 448
150476
151956
  });
150477
- const assetName = resolveOfficeCliReleaseAssetName();
150478
- const response = await fetch(`${DOCYRUS_OFFICECLI_RELEASES_BASE_URL}/${assetName}`);
150479
- if (!response.ok) {
150480
- throw new UserInputError(`OfficeCLI download failed with status ${response.status}.`);
151957
+ const bundledExecutablePath = resolvePackagedOfficeCliExecutablePath(params.resourceRoot);
151958
+ if ((0, import_node_fs16.existsSync)(bundledExecutablePath)) {
151959
+ await (0, import_promises20.cp)(bundledExecutablePath, tempPath, {
151960
+ force: true
151961
+ });
151962
+ } else {
151963
+ await downloadOfficeCliBinary({
151964
+ resourceRoot: params.resourceRoot,
151965
+ destinationPath: tempPath
151966
+ });
150481
151967
  }
150482
- const binary2 = Buffer.from(await response.arrayBuffer());
150483
- await (0, import_promises17.writeFile)(tempPath, binary2, {
150484
- mode: process.platform === "win32" ? 384 : 448
150485
- });
150486
151968
  if (process.platform !== "win32") {
150487
- await (0, import_promises17.chmod)(tempPath, 448);
151969
+ await (0, import_promises20.chmod)(tempPath, 448);
150488
151970
  }
150489
151971
  const verificationResult = params.spawnCommand(tempPath, ["--version"], {
150490
151972
  stdio: ["ignore", "pipe", "pipe"],
@@ -150500,17 +151982,23 @@ async function ensureManagedOfficeCliInstalled(params) {
150500
151982
  verificationResult.error?.message || summarizeFailure3(verificationResult, "officecli --version")
150501
151983
  );
150502
151984
  }
150503
- await (0, import_promises17.rename)(tempPath, executablePath);
151985
+ await (0, import_promises20.rename)(tempPath, executablePath);
150504
151986
  if (process.platform !== "win32") {
150505
- await (0, import_promises17.chmod)(executablePath, 448);
151987
+ await (0, import_promises20.chmod)(executablePath, 448);
150506
151988
  }
151989
+ await disableManagedOfficeCliAutoUpdate({
151990
+ agentRootPath: params.agentRootPath,
151991
+ executablePath,
151992
+ cwd: params.cwd,
151993
+ spawnCommand: params.spawnCommand
151994
+ });
150507
151995
  return {
150508
151996
  available: true,
150509
151997
  executablePath,
150510
151998
  binDir
150511
151999
  };
150512
152000
  } catch (error48) {
150513
- await (0, import_promises17.rm)(tempPath, {
152001
+ await (0, import_promises20.rm)(tempPath, {
150514
152002
  force: true
150515
152003
  });
150516
152004
  process.stderr.write(
@@ -150526,7 +152014,7 @@ async function ensureManagedOfficeCliInstalled(params) {
150526
152014
  }
150527
152015
  function installPackagedDocyrusPlatformSkill(params) {
150528
152016
  const skillSourcePath = resolvePackagedDocyrusPlatformSkillPath(params.resourceRoot);
150529
- if (!(0, import_node_fs12.existsSync)(skillSourcePath)) {
152017
+ if (!(0, import_node_fs16.existsSync)(skillSourcePath)) {
150530
152018
  process.stderr.write("[docyrus] Packaged docyrus-platform skill is missing. Continuing without agent sync.\n");
150531
152019
  return;
150532
152020
  }
@@ -150616,6 +152104,7 @@ function createPiAgentLauncher(options2) {
150616
152104
  });
150617
152105
  const officeCli = await ensureManagedOfficeCliInstalled({
150618
152106
  agentRootPath,
152107
+ resourceRoot,
150619
152108
  cwd,
150620
152109
  spawnCommand
150621
152110
  });
@@ -150654,8 +152143,8 @@ function createPiAgentLauncher(options2) {
150654
152143
 
150655
152144
  // src/services/piAgentServerLauncher.ts
150656
152145
  var import_node_child_process7 = require("node:child_process");
150657
- var import_node_fs13 = require("node:fs");
150658
- var import_node_path24 = require("node:path");
152146
+ var import_node_fs17 = require("node:fs");
152147
+ var import_node_path28 = require("node:path");
150659
152148
  function serializePiAgentServerRequest(request) {
150660
152149
  return JSON.stringify(request);
150661
152150
  }
@@ -150669,26 +152158,26 @@ function resolveServerLoaderEntryPath(cwd, dirname13) {
150669
152158
  }
150670
152159
  };
150671
152160
  const collectAncestorCandidates = (startDir) => {
150672
- let currentDir = (0, import_node_path24.resolve)(startDir);
152161
+ let currentDir = (0, import_node_path28.resolve)(startDir);
150673
152162
  while (true) {
150674
- addCandidate((0, import_node_path24.join)(currentDir, "dist", "apps", "api-cli", "server-loader.js"));
150675
- addCandidate((0, import_node_path24.join)(currentDir, "server-loader.js"));
150676
- if ((0, import_node_path24.basename)(currentDir) === "dist") {
150677
- 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"));
150678
152167
  }
150679
- const parentDir = (0, import_node_path24.resolve)(currentDir, "..");
152168
+ const parentDir = (0, import_node_path28.resolve)(currentDir, "..");
150680
152169
  if (parentDir === currentDir) {
150681
152170
  break;
150682
152171
  }
150683
152172
  currentDir = parentDir;
150684
152173
  }
150685
152174
  };
150686
- addCandidate((0, import_node_path24.resolve)(cwd, "dist/apps/api-cli/server-loader.js"));
150687
- addCandidate((0, import_node_path24.resolve)(dirname13, "../server-loader.js"));
150688
- 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"));
150689
152178
  collectAncestorCandidates(cwd);
150690
152179
  collectAncestorCandidates(dirname13);
150691
- const resolved = candidates.find((candidate) => (0, import_node_fs13.existsSync)(candidate));
152180
+ const resolved = candidates.find((candidate) => (0, import_node_fs17.existsSync)(candidate));
150692
152181
  if (!resolved) {
150693
152182
  throw new UserInputError(`Unable to locate Docyrus pi server loader entry file. Checked: ${candidates.join(", ")}`);
150694
152183
  }
@@ -150734,6 +152223,7 @@ function createPiAgentServerLauncher(options2) {
150734
152223
  spinner.update("Installing tools...");
150735
152224
  const officeCli = await ensureManagedOfficeCliInstalled({
150736
152225
  agentRootPath,
152226
+ resourceRoot,
150737
152227
  cwd,
150738
152228
  spawnCommand: import_node_child_process7.spawnSync
150739
152229
  });
@@ -150804,8 +152294,8 @@ async function runWithIncurSkillsOutOfDateWarningSuppressed(params) {
150804
152294
  }
150805
152295
 
150806
152296
  // src/services/tenantOpenApi.ts
150807
- var import_promises18 = require("node:fs/promises");
150808
- var import_node_path25 = require("node:path");
152297
+ var import_promises21 = require("node:fs/promises");
152298
+ var import_node_path29 = require("node:path");
150809
152299
  function resolveSourceUrl(tenantId, template) {
150810
152300
  return template.replace("{tenantId}", encodeURIComponent(tenantId));
150811
152301
  }
@@ -150830,16 +152320,16 @@ var TenantOpenApiService = class {
150830
152320
  params;
150831
152321
  async #writeOpenApiFile(tenantId, parsedContent) {
150832
152322
  const filePath = this.getTenantOpenApiFilePath(tenantId);
150833
- await (0, import_promises18.mkdir)((0, import_node_path25.dirname)(filePath), {
152323
+ await (0, import_promises21.mkdir)((0, import_node_path29.dirname)(filePath), {
150834
152324
  recursive: true,
150835
152325
  mode: 448
150836
152326
  });
150837
- await (0, import_promises18.writeFile)(filePath, `${JSON.stringify(parsedContent, null, 2)}
152327
+ await (0, import_promises21.writeFile)(filePath, `${JSON.stringify(parsedContent, null, 2)}
150838
152328
  `, {
150839
152329
  encoding: "utf8",
150840
152330
  mode: 384
150841
152331
  });
150842
- await (0, import_promises18.chmod)(filePath, 384);
152332
+ await (0, import_promises21.chmod)(filePath, 384);
150843
152333
  return filePath;
150844
152334
  }
150845
152335
  async #generateTenantOpenApiViaAuthenticatedEndpoint(tenantId, options2) {
@@ -150876,7 +152366,7 @@ var TenantOpenApiService = class {
150876
152366
  throw new AuthSessionError("Tenant ID is required to resolve OpenAPI spec path.");
150877
152367
  }
150878
152368
  const rootPath = this.params?.rootPath || TENANT_OPENAPI_ROOT_PATH;
150879
- return (0, import_node_path25.join)(rootPath, normalizedTenantId, "openapi.json");
152369
+ return (0, import_node_path29.join)(rootPath, normalizedTenantId, "openapi.json");
150880
152370
  }
150881
152371
  async downloadTenantOpenApi(tenantId, options2 = {}) {
150882
152372
  const normalizedTenantId = tenantId.trim();
@@ -150957,6 +152447,8 @@ var ROOT_HELP_COMMANDS = [
150957
152447
  { command: "knowledge search <query>", description: "Semantic search across docyrus/knowledge" },
150958
152448
  { command: "knowledge section <query>", description: "Show a knowledge section with refs and backlinks" },
150959
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" },
150960
152452
  { command: "action <appSlug> <actionKey> --params '{...}'", description: "Run a connector or app action" },
150961
152453
  { command: "ds list <appSlug> <dataSourceSlug>", description: "List data source items" },
150962
152454
  { command: "apps list", description: "List apps" },
@@ -151072,6 +152564,11 @@ function createDocyrusCli(params) {
151072
152564
  authStore,
151073
152565
  settingsPaths
151074
152566
  }));
152567
+ cli2.command(createProjectPlanCli({
152568
+ environmentConfigService,
152569
+ authStore,
152570
+ settingsPaths
152571
+ }));
151075
152572
  cli2.command(createAppsCli({
151076
152573
  createApiClient,
151077
152574
  environmentConfigService,