maxsimcli 3.12.0 → 4.0.0

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.
Files changed (178) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/adapters/index.d.ts +0 -11
  3. package/dist/adapters/index.d.ts.map +1 -1
  4. package/dist/adapters/index.js +4 -40
  5. package/dist/adapters/index.js.map +1 -1
  6. package/dist/assets/CHANGELOG.md +17 -0
  7. package/dist/assets/dashboard/client/assets/{index-wtQDvXzr.js → index-C_eAetZJ.js} +60 -60
  8. package/dist/assets/dashboard/client/assets/index-CmiJKqOU.css +32 -0
  9. package/dist/assets/dashboard/client/index.html +2 -2
  10. package/dist/assets/dashboard/server.js +467 -271
  11. package/dist/assets/templates/agents/AGENTS.md +13 -1
  12. package/dist/assets/templates/agents/maxsim-debugger.md +2 -2
  13. package/dist/assets/templates/agents/maxsim-executor.md +5 -5
  14. package/dist/assets/templates/agents/maxsim-phase-researcher.md +2 -2
  15. package/dist/assets/templates/agents/maxsim-plan-checker.md +2 -2
  16. package/dist/assets/templates/agents/maxsim-planner.md +3 -3
  17. package/dist/assets/templates/commands/maxsim/add-todo.md +15 -5
  18. package/dist/assets/templates/commands/maxsim/discuss-phase.md +1 -0
  19. package/dist/assets/templates/commands/maxsim/init-existing.md +4 -0
  20. package/dist/assets/templates/commands/maxsim/new-project.md +4 -0
  21. package/dist/assets/templates/references/thinking-partner.md +41 -0
  22. package/dist/assets/templates/skills/batch-worktree/SKILL.md +137 -0
  23. package/dist/assets/templates/skills/brainstorming/SKILL.md +159 -0
  24. package/dist/assets/templates/skills/roadmap-writing/SKILL.md +198 -0
  25. package/dist/assets/templates/skills/sdd/SKILL.md +175 -0
  26. package/dist/assets/templates/skills/simplify/SKILL.md +48 -0
  27. package/dist/assets/templates/skills/using-maxsim/SKILL.md +6 -1
  28. package/dist/assets/templates/templates/acceptance-criteria.md +10 -0
  29. package/dist/assets/templates/templates/decisions.md +10 -0
  30. package/dist/assets/templates/templates/no-gos.md +9 -0
  31. package/dist/assets/templates/workflows/add-todo.md +89 -0
  32. package/dist/assets/templates/workflows/discuss-phase.md +85 -1
  33. package/dist/assets/templates/workflows/execute-phase.md +22 -2
  34. package/dist/assets/templates/workflows/execute-plan.md +166 -0
  35. package/dist/assets/templates/workflows/init-existing.md +116 -0
  36. package/dist/assets/templates/workflows/new-project.md +105 -1
  37. package/dist/assets/templates/workflows/plan-phase.md +3 -3
  38. package/dist/assets/templates/workflows/quick.md +2 -2
  39. package/dist/cli.cjs +1264 -882
  40. package/dist/cli.cjs.map +1 -1
  41. package/dist/cli.js +97 -74
  42. package/dist/cli.js.map +1 -1
  43. package/dist/core/artefakte.d.ts +12 -0
  44. package/dist/core/artefakte.d.ts.map +1 -0
  45. package/dist/core/artefakte.js +136 -0
  46. package/dist/core/artefakte.js.map +1 -0
  47. package/dist/core/commands.d.ts +13 -13
  48. package/dist/core/commands.d.ts.map +1 -1
  49. package/dist/core/commands.js +44 -57
  50. package/dist/core/commands.js.map +1 -1
  51. package/dist/core/config.d.ts +4 -3
  52. package/dist/core/config.d.ts.map +1 -1
  53. package/dist/core/config.js +14 -18
  54. package/dist/core/config.js.map +1 -1
  55. package/dist/core/context-loader.d.ts +20 -0
  56. package/dist/core/context-loader.d.ts.map +1 -0
  57. package/dist/core/context-loader.js +154 -0
  58. package/dist/core/context-loader.js.map +1 -0
  59. package/dist/core/core.d.ts +8 -2
  60. package/dist/core/core.d.ts.map +1 -1
  61. package/dist/core/core.js +47 -11
  62. package/dist/core/core.js.map +1 -1
  63. package/dist/core/dashboard-launcher.d.ts +1 -1
  64. package/dist/core/dashboard-launcher.d.ts.map +1 -1
  65. package/dist/core/dashboard-launcher.js +18 -15
  66. package/dist/core/dashboard-launcher.js.map +1 -1
  67. package/dist/core/frontmatter.d.ts +5 -5
  68. package/dist/core/frontmatter.d.ts.map +1 -1
  69. package/dist/core/frontmatter.js +21 -26
  70. package/dist/core/frontmatter.js.map +1 -1
  71. package/dist/core/index.d.ts +8 -3
  72. package/dist/core/index.d.ts.map +1 -1
  73. package/dist/core/index.js +23 -3
  74. package/dist/core/index.js.map +1 -1
  75. package/dist/core/init.d.ts +14 -14
  76. package/dist/core/init.d.ts.map +1 -1
  77. package/dist/core/init.js +93 -154
  78. package/dist/core/init.js.map +1 -1
  79. package/dist/core/milestone.d.ts +3 -3
  80. package/dist/core/milestone.d.ts.map +1 -1
  81. package/dist/core/milestone.js +9 -9
  82. package/dist/core/milestone.js.map +1 -1
  83. package/dist/core/phase.d.ts +9 -9
  84. package/dist/core/phase.d.ts.map +1 -1
  85. package/dist/core/phase.js +64 -68
  86. package/dist/core/phase.js.map +1 -1
  87. package/dist/core/roadmap.d.ts +4 -3
  88. package/dist/core/roadmap.d.ts.map +1 -1
  89. package/dist/core/roadmap.js +46 -109
  90. package/dist/core/roadmap.js.map +1 -1
  91. package/dist/core/skills.d.ts +19 -0
  92. package/dist/core/skills.d.ts.map +1 -0
  93. package/dist/core/skills.js +145 -0
  94. package/dist/core/skills.js.map +1 -0
  95. package/dist/core/start.d.ts +15 -0
  96. package/dist/core/start.d.ts.map +1 -0
  97. package/dist/core/start.js +80 -0
  98. package/dist/core/start.js.map +1 -0
  99. package/dist/core/state.d.ts +13 -13
  100. package/dist/core/state.d.ts.map +1 -1
  101. package/dist/core/state.js +119 -126
  102. package/dist/core/state.js.map +1 -1
  103. package/dist/core/template.d.ts +3 -3
  104. package/dist/core/template.d.ts.map +1 -1
  105. package/dist/core/template.js +12 -14
  106. package/dist/core/template.js.map +1 -1
  107. package/dist/core/types.d.ts +14 -2
  108. package/dist/core/types.d.ts.map +1 -1
  109. package/dist/core/types.js +8 -0
  110. package/dist/core/types.js.map +1 -1
  111. package/dist/core/verify.d.ts +10 -9
  112. package/dist/core/verify.d.ts.map +1 -1
  113. package/dist/core/verify.js +38 -48
  114. package/dist/core/verify.js.map +1 -1
  115. package/dist/core-TFSlUjV1.cjs +4312 -0
  116. package/dist/core-TFSlUjV1.cjs.map +1 -0
  117. package/dist/install/adapters.d.ts +2 -11
  118. package/dist/install/adapters.d.ts.map +1 -1
  119. package/dist/install/adapters.js +16 -154
  120. package/dist/install/adapters.js.map +1 -1
  121. package/dist/install/copy.d.ts +1 -10
  122. package/dist/install/copy.d.ts.map +1 -1
  123. package/dist/install/copy.js +5 -125
  124. package/dist/install/copy.js.map +1 -1
  125. package/dist/install/hooks.d.ts +4 -5
  126. package/dist/install/hooks.d.ts.map +1 -1
  127. package/dist/install/hooks.js +46 -71
  128. package/dist/install/hooks.js.map +1 -1
  129. package/dist/install/index.js +163 -226
  130. package/dist/install/index.js.map +1 -1
  131. package/dist/install/manifest.d.ts +5 -2
  132. package/dist/install/manifest.d.ts.map +1 -1
  133. package/dist/install/manifest.js +20 -26
  134. package/dist/install/manifest.js.map +1 -1
  135. package/dist/install/patches.d.ts +1 -2
  136. package/dist/install/patches.d.ts.map +1 -1
  137. package/dist/install/patches.js +4 -16
  138. package/dist/install/patches.js.map +1 -1
  139. package/dist/install/shared.d.ts +24 -18
  140. package/dist/install/shared.d.ts.map +1 -1
  141. package/dist/install/shared.js +65 -35
  142. package/dist/install/shared.js.map +1 -1
  143. package/dist/install/uninstall.d.ts +2 -3
  144. package/dist/install/uninstall.d.ts.map +1 -1
  145. package/dist/install/uninstall.js +24 -82
  146. package/dist/install/uninstall.js.map +1 -1
  147. package/dist/install.cjs +321 -1230
  148. package/dist/install.cjs.map +1 -1
  149. package/dist/mcp-server.cjs +38 -14
  150. package/dist/mcp-server.cjs.map +1 -1
  151. package/dist/skills-BOSxYUzf.cjs +6812 -0
  152. package/dist/skills-BOSxYUzf.cjs.map +1 -0
  153. package/package.json +1 -1
  154. package/dist/adapters/codex.d.ts +0 -19
  155. package/dist/adapters/codex.d.ts.map +0 -1
  156. package/dist/adapters/codex.js +0 -94
  157. package/dist/adapters/codex.js.map +0 -1
  158. package/dist/adapters/gemini.d.ts +0 -19
  159. package/dist/adapters/gemini.d.ts.map +0 -1
  160. package/dist/adapters/gemini.js +0 -96
  161. package/dist/adapters/gemini.js.map +0 -1
  162. package/dist/adapters/opencode.d.ts +0 -17
  163. package/dist/adapters/opencode.d.ts.map +0 -1
  164. package/dist/adapters/opencode.js +0 -111
  165. package/dist/adapters/opencode.js.map +0 -1
  166. package/dist/adapters/transforms/content.d.ts +0 -39
  167. package/dist/adapters/transforms/content.d.ts.map +0 -1
  168. package/dist/adapters/transforms/content.js +0 -125
  169. package/dist/adapters/transforms/content.js.map +0 -1
  170. package/dist/adapters/transforms/frontmatter.d.ts +0 -42
  171. package/dist/adapters/transforms/frontmatter.d.ts.map +0 -1
  172. package/dist/adapters/transforms/frontmatter.js +0 -204
  173. package/dist/adapters/transforms/frontmatter.js.map +0 -1
  174. package/dist/adapters/transforms/tool-maps.d.ts +0 -20
  175. package/dist/adapters/transforms/tool-maps.d.ts.map +0 -1
  176. package/dist/adapters/transforms/tool-maps.js +0 -64
  177. package/dist/adapters/transforms/tool-maps.js.map +0 -1
  178. package/dist/assets/dashboard/client/assets/index-CxFKStBk.css +0 -32
@@ -26636,9 +26636,9 @@ var require_mime_types = /* @__PURE__ */ __commonJSMin(((exports) => {
26636
26636
  * @param {string} path
26637
26637
  * @return {boolean|string}
26638
26638
  */
26639
- function lookup(path$70) {
26640
- if (!path$70 || typeof path$70 !== "string") return false;
26641
- var extension = extname("x." + path$70).toLowerCase().substr(1);
26639
+ function lookup(path$74) {
26640
+ if (!path$74 || typeof path$74 !== "string") return false;
26641
+ var extension = extname("x." + path$74).toLowerCase().substr(1);
26642
26642
  if (!extension) return false;
26643
26643
  return exports.types[extension] || false;
26644
26644
  }
@@ -32132,17 +32132,17 @@ var require_view = /* @__PURE__ */ __commonJSMin(((exports, module) => {
32132
32132
  * @private
32133
32133
  */
32134
32134
  var debug = require_src$3()("express:view");
32135
- var path$15 = require("path");
32136
- var fs$20 = require("fs");
32135
+ var path$19 = require("path");
32136
+ var fs$23 = require("fs");
32137
32137
  /**
32138
32138
  * Module variables.
32139
32139
  * @private
32140
32140
  */
32141
- var dirname = path$15.dirname;
32142
- var basename = path$15.basename;
32143
- var extname = path$15.extname;
32144
- var join = path$15.join;
32145
- var resolve = path$15.resolve;
32141
+ var dirname = path$19.dirname;
32142
+ var basename = path$19.basename;
32143
+ var extname = path$19.extname;
32144
+ var join = path$19.join;
32145
+ var resolve = path$19.resolve;
32146
32146
  /**
32147
32147
  * Module exports.
32148
32148
  * @public
@@ -32190,17 +32190,17 @@ var require_view = /* @__PURE__ */ __commonJSMin(((exports, module) => {
32190
32190
  * @private
32191
32191
  */
32192
32192
  View.prototype.lookup = function lookup(name) {
32193
- var path$67;
32193
+ var path$71;
32194
32194
  var roots = [].concat(this.root);
32195
32195
  debug("lookup \"%s\"", name);
32196
- for (var i = 0; i < roots.length && !path$67; i++) {
32196
+ for (var i = 0; i < roots.length && !path$71; i++) {
32197
32197
  var root = roots[i];
32198
32198
  var loc = resolve(root, name);
32199
32199
  var dir = dirname(loc);
32200
32200
  var file = basename(loc);
32201
- path$67 = this.resolve(dir, file);
32201
+ path$71 = this.resolve(dir, file);
32202
32202
  }
32203
- return path$67;
32203
+ return path$71;
32204
32204
  };
32205
32205
  /**
32206
32206
  * Render with the given options.
@@ -32222,12 +32222,12 @@ var require_view = /* @__PURE__ */ __commonJSMin(((exports, module) => {
32222
32222
  */
32223
32223
  View.prototype.resolve = function resolve(dir, file) {
32224
32224
  var ext = this.ext;
32225
- var path$68 = join(dir, file);
32226
- var stat = tryStat(path$68);
32227
- if (stat && stat.isFile()) return path$68;
32228
- path$68 = join(dir, basename(file, ext), "index" + ext);
32229
- stat = tryStat(path$68);
32230
- if (stat && stat.isFile()) return path$68;
32225
+ var path$72 = join(dir, file);
32226
+ var stat = tryStat(path$72);
32227
+ if (stat && stat.isFile()) return path$72;
32228
+ path$72 = join(dir, basename(file, ext), "index" + ext);
32229
+ stat = tryStat(path$72);
32230
+ if (stat && stat.isFile()) return path$72;
32231
32231
  };
32232
32232
  /**
32233
32233
  * Return a stat, maybe.
@@ -32236,10 +32236,10 @@ var require_view = /* @__PURE__ */ __commonJSMin(((exports, module) => {
32236
32236
  * @return {fs.Stats}
32237
32237
  * @private
32238
32238
  */
32239
- function tryStat(path$69) {
32240
- debug("stat \"%s\"", path$69);
32239
+ function tryStat(path$73) {
32240
+ debug("stat \"%s\"", path$73);
32241
32241
  try {
32242
- return fs$20.statSync(path$69);
32242
+ return fs$23.statSync(path$73);
32243
32243
  } catch (e) {
32244
32244
  return;
32245
32245
  }
@@ -34460,7 +34460,7 @@ var require_types$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
34460
34460
  //#region ../../node_modules/send/node_modules/mime/mime.js
34461
34461
  var require_mime = /* @__PURE__ */ __commonJSMin(((exports, module) => {
34462
34462
  require("path");
34463
- var fs$19 = require("fs");
34463
+ var fs$22 = require("fs");
34464
34464
  function Mime() {
34465
34465
  this.types = Object.create(null);
34466
34466
  this.extensions = Object.create(null);
@@ -34495,7 +34495,7 @@ var require_mime = /* @__PURE__ */ __commonJSMin(((exports, module) => {
34495
34495
  Mime.prototype.load = function(file) {
34496
34496
  this._loading = file;
34497
34497
  var map = {};
34498
- fs$19.readFileSync(file, "ascii").split(/[\r\n]+/).forEach(function(line) {
34498
+ fs$22.readFileSync(file, "ascii").split(/[\r\n]+/).forEach(function(line) {
34499
34499
  var fields = line.replace(/\s*#.*|^\s*|\s*$/g, "").split(/\s+/);
34500
34500
  map[fields.shift()] = fields;
34501
34501
  });
@@ -34505,8 +34505,8 @@ var require_mime = /* @__PURE__ */ __commonJSMin(((exports, module) => {
34505
34505
  /**
34506
34506
  * Lookup a mime type based on extension
34507
34507
  */
34508
- Mime.prototype.lookup = function(path$66, fallback) {
34509
- var ext = path$66.replace(/^.*[\.\/\\]/, "").toLowerCase();
34508
+ Mime.prototype.lookup = function(path$70, fallback) {
34509
+ var ext = path$70.replace(/^.*[\.\/\\]/, "").toLowerCase();
34510
34510
  return this.types[ext] || fallback || this.default_type;
34511
34511
  };
34512
34512
  /**
@@ -34774,12 +34774,12 @@ var require_send = /* @__PURE__ */ __commonJSMin(((exports, module) => {
34774
34774
  var escapeHtml = require_escape_html();
34775
34775
  var etag = require_etag();
34776
34776
  var fresh = require_fresh();
34777
- var fs$18 = require("fs");
34777
+ var fs$21 = require("fs");
34778
34778
  var mime = require_mime();
34779
34779
  var ms = require_ms();
34780
34780
  var onFinished = require_on_finished();
34781
34781
  var parseRange = require_range_parser();
34782
- var path$14 = require("path");
34782
+ var path$18 = require("path");
34783
34783
  var statuses = require_statuses();
34784
34784
  var Stream = require("stream");
34785
34785
  var util$2 = require("util");
@@ -34787,11 +34787,11 @@ var require_send = /* @__PURE__ */ __commonJSMin(((exports, module) => {
34787
34787
  * Path function references.
34788
34788
  * @private
34789
34789
  */
34790
- var extname = path$14.extname;
34791
- var join = path$14.join;
34792
- var normalize = path$14.normalize;
34793
- var resolve = path$14.resolve;
34794
- var sep = path$14.sep;
34790
+ var extname = path$18.extname;
34791
+ var join = path$18.join;
34792
+ var normalize = path$18.normalize;
34793
+ var resolve = path$18.resolve;
34794
+ var sep = path$18.sep;
34795
34795
  /**
34796
34796
  * Regular expression for identifying a bytes Range header.
34797
34797
  * @private
@@ -34822,8 +34822,8 @@ var require_send = /* @__PURE__ */ __commonJSMin(((exports, module) => {
34822
34822
  * @return {SendStream}
34823
34823
  * @public
34824
34824
  */
34825
- function send(req, path$54, options) {
34826
- return new SendStream(req, path$54, options);
34825
+ function send(req, path$58, options) {
34826
+ return new SendStream(req, path$58, options);
34827
34827
  }
34828
34828
  /**
34829
34829
  * Initialize a `SendStream` with the given `path`.
@@ -34833,11 +34833,11 @@ var require_send = /* @__PURE__ */ __commonJSMin(((exports, module) => {
34833
34833
  * @param {object} [options]
34834
34834
  * @private
34835
34835
  */
34836
- function SendStream(req, path$55, options) {
34836
+ function SendStream(req, path$59, options) {
34837
34837
  Stream.call(this);
34838
34838
  var opts = options || {};
34839
34839
  this.options = opts;
34840
- this.path = path$55;
34840
+ this.path = path$59;
34841
34841
  this.req = req;
34842
34842
  this._acceptRanges = opts.acceptRanges !== void 0 ? Boolean(opts.acceptRanges) : true;
34843
34843
  this._cacheControl = opts.cacheControl !== void 0 ? Boolean(opts.cacheControl) : true;
@@ -34907,8 +34907,8 @@ var require_send = /* @__PURE__ */ __commonJSMin(((exports, module) => {
34907
34907
  * @return {SendStream}
34908
34908
  * @api public
34909
34909
  */
34910
- SendStream.prototype.root = function root(path$56) {
34911
- this._root = resolve(String(path$56));
34910
+ SendStream.prototype.root = function root(path$60) {
34911
+ this._root = resolve(String(path$60));
34912
34912
  debug("root %s", this._root);
34913
34913
  return this;
34914
34914
  };
@@ -35085,10 +35085,10 @@ var require_send = /* @__PURE__ */ __commonJSMin(((exports, module) => {
35085
35085
  * @param {string} path
35086
35086
  * @private
35087
35087
  */
35088
- SendStream.prototype.redirect = function redirect(path$57) {
35088
+ SendStream.prototype.redirect = function redirect(path$61) {
35089
35089
  var res = this.res;
35090
35090
  if (hasListeners(this, "directory")) {
35091
- this.emit("directory", res, path$57);
35091
+ this.emit("directory", res, path$61);
35092
35092
  return;
35093
35093
  }
35094
35094
  if (this.hasTrailingSlash()) {
@@ -35115,38 +35115,38 @@ var require_send = /* @__PURE__ */ __commonJSMin(((exports, module) => {
35115
35115
  SendStream.prototype.pipe = function pipe(res) {
35116
35116
  var root = this._root;
35117
35117
  this.res = res;
35118
- var path$58 = decode(this.path);
35119
- if (path$58 === -1) {
35118
+ var path$62 = decode(this.path);
35119
+ if (path$62 === -1) {
35120
35120
  this.error(400);
35121
35121
  return res;
35122
35122
  }
35123
- if (~path$58.indexOf("\0")) {
35123
+ if (~path$62.indexOf("\0")) {
35124
35124
  this.error(400);
35125
35125
  return res;
35126
35126
  }
35127
35127
  var parts;
35128
35128
  if (root !== null) {
35129
- if (path$58) path$58 = normalize("." + sep + path$58);
35130
- if (UP_PATH_REGEXP.test(path$58)) {
35131
- debug("malicious path \"%s\"", path$58);
35129
+ if (path$62) path$62 = normalize("." + sep + path$62);
35130
+ if (UP_PATH_REGEXP.test(path$62)) {
35131
+ debug("malicious path \"%s\"", path$62);
35132
35132
  this.error(403);
35133
35133
  return res;
35134
35134
  }
35135
- parts = path$58.split(sep);
35136
- path$58 = normalize(join(root, path$58));
35135
+ parts = path$62.split(sep);
35136
+ path$62 = normalize(join(root, path$62));
35137
35137
  } else {
35138
- if (UP_PATH_REGEXP.test(path$58)) {
35139
- debug("malicious path \"%s\"", path$58);
35138
+ if (UP_PATH_REGEXP.test(path$62)) {
35139
+ debug("malicious path \"%s\"", path$62);
35140
35140
  this.error(403);
35141
35141
  return res;
35142
35142
  }
35143
- parts = normalize(path$58).split(sep);
35144
- path$58 = resolve(path$58);
35143
+ parts = normalize(path$62).split(sep);
35144
+ path$62 = resolve(path$62);
35145
35145
  }
35146
35146
  if (containsDotFile(parts)) {
35147
35147
  var access = this._dotfiles;
35148
35148
  if (access === void 0) access = parts[parts.length - 1][0] === "." ? this._hidden ? "allow" : "ignore" : "allow";
35149
- debug("%s dotfile \"%s\"", access, path$58);
35149
+ debug("%s dotfile \"%s\"", access, path$62);
35150
35150
  switch (access) {
35151
35151
  case "allow": break;
35152
35152
  case "deny":
@@ -35158,10 +35158,10 @@ var require_send = /* @__PURE__ */ __commonJSMin(((exports, module) => {
35158
35158
  }
35159
35159
  }
35160
35160
  if (this._index.length && this.hasTrailingSlash()) {
35161
- this.sendIndex(path$58);
35161
+ this.sendIndex(path$62);
35162
35162
  return res;
35163
35163
  }
35164
- this.sendFile(path$58);
35164
+ this.sendFile(path$62);
35165
35165
  return res;
35166
35166
  };
35167
35167
  /**
@@ -35170,7 +35170,7 @@ var require_send = /* @__PURE__ */ __commonJSMin(((exports, module) => {
35170
35170
  * @param {String} path
35171
35171
  * @api public
35172
35172
  */
35173
- SendStream.prototype.send = function send(path$59, stat) {
35173
+ SendStream.prototype.send = function send(path$63, stat) {
35174
35174
  var len = stat.size;
35175
35175
  var options = this.options;
35176
35176
  var opts = {};
@@ -35182,9 +35182,9 @@ var require_send = /* @__PURE__ */ __commonJSMin(((exports, module) => {
35182
35182
  this.headersAlreadySent();
35183
35183
  return;
35184
35184
  }
35185
- debug("pipe \"%s\"", path$59);
35186
- this.setHeader(path$59, stat);
35187
- this.type(path$59);
35185
+ debug("pipe \"%s\"", path$63);
35186
+ this.setHeader(path$63, stat);
35187
+ this.type(path$63);
35188
35188
  if (this.isConditionalGET()) {
35189
35189
  if (this.isPreconditionFailure()) {
35190
35190
  this.error(412);
@@ -35227,7 +35227,7 @@ var require_send = /* @__PURE__ */ __commonJSMin(((exports, module) => {
35227
35227
  res.end();
35228
35228
  return;
35229
35229
  }
35230
- this.stream(path$59, opts);
35230
+ this.stream(path$63, opts);
35231
35231
  };
35232
35232
  /**
35233
35233
  * Transfer file for `path`.
@@ -35235,22 +35235,22 @@ var require_send = /* @__PURE__ */ __commonJSMin(((exports, module) => {
35235
35235
  * @param {String} path
35236
35236
  * @api private
35237
35237
  */
35238
- SendStream.prototype.sendFile = function sendFile(path$60) {
35238
+ SendStream.prototype.sendFile = function sendFile(path$64) {
35239
35239
  var i = 0;
35240
35240
  var self = this;
35241
- debug("stat \"%s\"", path$60);
35242
- fs$18.stat(path$60, function onstat(err, stat) {
35243
- if (err && err.code === "ENOENT" && !extname(path$60) && path$60[path$60.length - 1] !== sep) return next(err);
35241
+ debug("stat \"%s\"", path$64);
35242
+ fs$21.stat(path$64, function onstat(err, stat) {
35243
+ if (err && err.code === "ENOENT" && !extname(path$64) && path$64[path$64.length - 1] !== sep) return next(err);
35244
35244
  if (err) return self.onStatError(err);
35245
- if (stat.isDirectory()) return self.redirect(path$60);
35246
- self.emit("file", path$60, stat);
35247
- self.send(path$60, stat);
35245
+ if (stat.isDirectory()) return self.redirect(path$64);
35246
+ self.emit("file", path$64, stat);
35247
+ self.send(path$64, stat);
35248
35248
  });
35249
35249
  function next(err) {
35250
35250
  if (self._extensions.length <= i) return err ? self.onStatError(err) : self.error(404);
35251
- var p = path$60 + "." + self._extensions[i++];
35251
+ var p = path$64 + "." + self._extensions[i++];
35252
35252
  debug("stat \"%s\"", p);
35253
- fs$18.stat(p, function(err, stat) {
35253
+ fs$21.stat(p, function(err, stat) {
35254
35254
  if (err) return next(err);
35255
35255
  if (stat.isDirectory()) return next();
35256
35256
  self.emit("file", p, stat);
@@ -35264,7 +35264,7 @@ var require_send = /* @__PURE__ */ __commonJSMin(((exports, module) => {
35264
35264
  * @param {String} path
35265
35265
  * @api private
35266
35266
  */
35267
- SendStream.prototype.sendIndex = function sendIndex(path$61) {
35267
+ SendStream.prototype.sendIndex = function sendIndex(path$65) {
35268
35268
  var i = -1;
35269
35269
  var self = this;
35270
35270
  function next(err) {
@@ -35272,9 +35272,9 @@ var require_send = /* @__PURE__ */ __commonJSMin(((exports, module) => {
35272
35272
  if (err) return self.onStatError(err);
35273
35273
  return self.error(404);
35274
35274
  }
35275
- var p = join(path$61, self._index[i]);
35275
+ var p = join(path$65, self._index[i]);
35276
35276
  debug("stat \"%s\"", p);
35277
- fs$18.stat(p, function(err, stat) {
35277
+ fs$21.stat(p, function(err, stat) {
35278
35278
  if (err) return next(err);
35279
35279
  if (stat.isDirectory()) return next();
35280
35280
  self.emit("file", p, stat);
@@ -35290,10 +35290,10 @@ var require_send = /* @__PURE__ */ __commonJSMin(((exports, module) => {
35290
35290
  * @param {Object} options
35291
35291
  * @api private
35292
35292
  */
35293
- SendStream.prototype.stream = function stream(path$62, options) {
35293
+ SendStream.prototype.stream = function stream(path$66, options) {
35294
35294
  var self = this;
35295
35295
  var res = this.res;
35296
- var stream$5 = fs$18.createReadStream(path$62, options);
35296
+ var stream$5 = fs$21.createReadStream(path$66, options);
35297
35297
  this.emit("stream", stream$5);
35298
35298
  stream$5.pipe(res);
35299
35299
  function cleanup() {
@@ -35315,10 +35315,10 @@ var require_send = /* @__PURE__ */ __commonJSMin(((exports, module) => {
35315
35315
  * @param {String} path
35316
35316
  * @api private
35317
35317
  */
35318
- SendStream.prototype.type = function type(path$63) {
35318
+ SendStream.prototype.type = function type(path$67) {
35319
35319
  var res = this.res;
35320
35320
  if (res.getHeader("Content-Type")) return;
35321
- var type = mime.lookup(path$63);
35321
+ var type = mime.lookup(path$67);
35322
35322
  if (!type) {
35323
35323
  debug("no content-type");
35324
35324
  return;
@@ -35335,9 +35335,9 @@ var require_send = /* @__PURE__ */ __commonJSMin(((exports, module) => {
35335
35335
  * @param {Object} stat
35336
35336
  * @api private
35337
35337
  */
35338
- SendStream.prototype.setHeader = function setHeader(path$64, stat) {
35338
+ SendStream.prototype.setHeader = function setHeader(path$68, stat) {
35339
35339
  var res = this.res;
35340
- this.emit("headers", res, path$64, stat);
35340
+ this.emit("headers", res, path$68, stat);
35341
35341
  if (this._acceptRanges && !res.getHeader("Accept-Ranges")) {
35342
35342
  debug("accept ranges");
35343
35343
  res.setHeader("Accept-Ranges", "bytes");
@@ -35431,9 +35431,9 @@ var require_send = /* @__PURE__ */ __commonJSMin(((exports, module) => {
35431
35431
  * @param {String} path
35432
35432
  * @api private
35433
35433
  */
35434
- function decode(path$65) {
35434
+ function decode(path$69) {
35435
35435
  try {
35436
- return decodeURIComponent(path$65);
35436
+ return decodeURIComponent(path$69);
35437
35437
  } catch (err) {
35438
35438
  return -1;
35439
35439
  }
@@ -36855,13 +36855,13 @@ var require_application = /* @__PURE__ */ __commonJSMin(((exports, module) => {
36855
36855
  */
36856
36856
  app.use = function use(fn) {
36857
36857
  var offset = 0;
36858
- var path$49 = "/";
36858
+ var path$53 = "/";
36859
36859
  if (typeof fn !== "function") {
36860
36860
  var arg = fn;
36861
36861
  while (Array.isArray(arg) && arg.length !== 0) arg = arg[0];
36862
36862
  if (typeof arg !== "function") {
36863
36863
  offset = 1;
36864
- path$49 = fn;
36864
+ path$53 = fn;
36865
36865
  }
36866
36866
  }
36867
36867
  var fns = flatten(slice.call(arguments, offset));
@@ -36869,11 +36869,11 @@ var require_application = /* @__PURE__ */ __commonJSMin(((exports, module) => {
36869
36869
  this.lazyrouter();
36870
36870
  var router = this._router;
36871
36871
  fns.forEach(function(fn) {
36872
- if (!fn || !fn.handle || !fn.set) return router.use(path$49, fn);
36873
- debug(".use app under %s", path$49);
36874
- fn.mountpath = path$49;
36872
+ if (!fn || !fn.handle || !fn.set) return router.use(path$53, fn);
36873
+ debug(".use app under %s", path$53);
36874
+ fn.mountpath = path$53;
36875
36875
  fn.parent = this;
36876
- router.use(path$49, function mounted_app(req, res, next) {
36876
+ router.use(path$53, function mounted_app(req, res, next) {
36877
36877
  var orig = req.app;
36878
36878
  fn.handle(req, res, function(err) {
36879
36879
  setPrototypeOf(req, orig.request);
@@ -36894,9 +36894,9 @@ var require_application = /* @__PURE__ */ __commonJSMin(((exports, module) => {
36894
36894
  *
36895
36895
  * @public
36896
36896
  */
36897
- app.route = function route(path$50) {
36897
+ app.route = function route(path$54) {
36898
36898
  this.lazyrouter();
36899
- return this._router.route(path$50);
36899
+ return this._router.route(path$54);
36900
36900
  };
36901
36901
  /**
36902
36902
  * Register the given template engine callback `fn`
@@ -37012,7 +37012,7 @@ var require_application = /* @__PURE__ */ __commonJSMin(((exports, module) => {
37012
37012
  * @return {String}
37013
37013
  * @private
37014
37014
  */
37015
- app.path = function path$51() {
37015
+ app.path = function path$55() {
37016
37016
  return this.parent ? this.parent.path() + this.mountpath : "";
37017
37017
  };
37018
37018
  /**
@@ -37073,10 +37073,10 @@ var require_application = /* @__PURE__ */ __commonJSMin(((exports, module) => {
37073
37073
  * Delegate `.VERB(...)` calls to `router.VERB(...)`.
37074
37074
  */
37075
37075
  methods.forEach(function(method) {
37076
- app[method] = function(path$52) {
37077
- if (method === "get" && arguments.length === 1) return this.set(path$52);
37076
+ app[method] = function(path$56) {
37077
+ if (method === "get" && arguments.length === 1) return this.set(path$56);
37078
37078
  this.lazyrouter();
37079
- var route = this._router.route(path$52);
37079
+ var route = this._router.route(path$56);
37080
37080
  route[method].apply(route, slice.call(arguments, 1));
37081
37081
  return this;
37082
37082
  };
@@ -37090,9 +37090,9 @@ var require_application = /* @__PURE__ */ __commonJSMin(((exports, module) => {
37090
37090
  * @return {app} for chaining
37091
37091
  * @public
37092
37092
  */
37093
- app.all = function all(path$53) {
37093
+ app.all = function all(path$57) {
37094
37094
  this.lazyrouter();
37095
- var route = this._router.route(path$53);
37095
+ var route = this._router.route(path$57);
37096
37096
  var args = slice.call(arguments, 1);
37097
37097
  for (var i = 0; i < methods.length; i++) route[methods[i]].apply(route, args);
37098
37098
  return this;
@@ -38827,7 +38827,7 @@ var require_response = /* @__PURE__ */ __commonJSMin(((exports, module) => {
38827
38827
  var http$3 = require("http");
38828
38828
  var isAbsolute = require_utils$1().isAbsolute;
38829
38829
  var onFinished = require_on_finished();
38830
- var path$13 = require("path");
38830
+ var path$17 = require("path");
38831
38831
  var statuses = require_statuses();
38832
38832
  var merge = require_utils_merge();
38833
38833
  var sign = require_cookie_signature().sign;
@@ -38836,9 +38836,9 @@ var require_response = /* @__PURE__ */ __commonJSMin(((exports, module) => {
38836
38836
  var setCharset = require_utils$1().setCharset;
38837
38837
  var cookie = require_cookie();
38838
38838
  var send = require_send();
38839
- var extname = path$13.extname;
38839
+ var extname = path$17.extname;
38840
38840
  var mime = send.mime;
38841
- var resolve = path$13.resolve;
38841
+ var resolve = path$17.resolve;
38842
38842
  var vary = require_vary();
38843
38843
  /**
38844
38844
  * Response prototype.
@@ -39102,20 +39102,20 @@ var require_response = /* @__PURE__ */ __commonJSMin(((exports, module) => {
39102
39102
  *
39103
39103
  * @public
39104
39104
  */
39105
- res.sendFile = function sendFile(path$46, options, callback) {
39105
+ res.sendFile = function sendFile(path$50, options, callback) {
39106
39106
  var done = callback;
39107
39107
  var req = this.req;
39108
39108
  var res = this;
39109
39109
  var next = req.next;
39110
39110
  var opts = options || {};
39111
- if (!path$46) throw new TypeError("path argument is required to res.sendFile");
39112
- if (typeof path$46 !== "string") throw new TypeError("path must be a string to res.sendFile");
39111
+ if (!path$50) throw new TypeError("path argument is required to res.sendFile");
39112
+ if (typeof path$50 !== "string") throw new TypeError("path must be a string to res.sendFile");
39113
39113
  if (typeof options === "function") {
39114
39114
  done = options;
39115
39115
  opts = {};
39116
39116
  }
39117
- if (!opts.root && !isAbsolute(path$46)) throw new TypeError("path must be absolute or specify root to res.sendFile");
39118
- sendfile(res, send(req, encodeURI(path$46), opts), opts, function(err) {
39117
+ if (!opts.root && !isAbsolute(path$50)) throw new TypeError("path must be absolute or specify root to res.sendFile");
39118
+ sendfile(res, send(req, encodeURI(path$50), opts), opts, function(err) {
39119
39119
  if (done) return done(err);
39120
39120
  if (err && err.code === "EISDIR") return next();
39121
39121
  if (err && err.code !== "ECONNABORTED" && err.syscall !== "write") next(err);
@@ -39161,7 +39161,7 @@ var require_response = /* @__PURE__ */ __commonJSMin(((exports, module) => {
39161
39161
  *
39162
39162
  * @public
39163
39163
  */
39164
- res.sendfile = function(path$47, options, callback) {
39164
+ res.sendfile = function(path$51, options, callback) {
39165
39165
  var done = callback;
39166
39166
  var req = this.req;
39167
39167
  var res = this;
@@ -39171,7 +39171,7 @@ var require_response = /* @__PURE__ */ __commonJSMin(((exports, module) => {
39171
39171
  done = options;
39172
39172
  opts = {};
39173
39173
  }
39174
- sendfile(res, send(req, path$47, opts), opts, function(err) {
39174
+ sendfile(res, send(req, path$51, opts), opts, function(err) {
39175
39175
  if (done) return done(err);
39176
39176
  if (err && err.code === "EISDIR") return next();
39177
39177
  if (err && err.code !== "ECONNABORTED" && err.syscall !== "write") next(err);
@@ -39195,7 +39195,7 @@ var require_response = /* @__PURE__ */ __commonJSMin(((exports, module) => {
39195
39195
  *
39196
39196
  * @public
39197
39197
  */
39198
- res.download = function download(path$48, filename, options, callback) {
39198
+ res.download = function download(path$52, filename, options, callback) {
39199
39199
  var done = callback;
39200
39200
  var name = filename;
39201
39201
  var opts = options || null;
@@ -39211,7 +39211,7 @@ var require_response = /* @__PURE__ */ __commonJSMin(((exports, module) => {
39211
39211
  name = null;
39212
39212
  opts = filename;
39213
39213
  }
39214
- var headers = { "Content-Disposition": contentDisposition(name || path$48) };
39214
+ var headers = { "Content-Disposition": contentDisposition(name || path$52) };
39215
39215
  if (opts && opts.headers) {
39216
39216
  var keys = Object.keys(opts.headers);
39217
39217
  for (var i = 0; i < keys.length; i++) {
@@ -39221,7 +39221,7 @@ var require_response = /* @__PURE__ */ __commonJSMin(((exports, module) => {
39221
39221
  }
39222
39222
  opts = Object.create(opts);
39223
39223
  opts.headers = headers;
39224
- var fullPath = !opts.root ? resolve(path$48) : path$48;
39224
+ var fullPath = !opts.root ? resolve(path$52) : path$52;
39225
39225
  return this.sendFile(fullPath, opts, done);
39226
39226
  };
39227
39227
  /**
@@ -39707,9 +39707,9 @@ var require_serve_static = /* @__PURE__ */ __commonJSMin(((exports, module) => {
39707
39707
  }
39708
39708
  var forwardError = !fallthrough;
39709
39709
  var originalUrl = parseUrl.original(req);
39710
- var path$45 = parseUrl(req).pathname;
39711
- if (path$45 === "/" && originalUrl.pathname.substr(-1) !== "/") path$45 = "";
39712
- var stream = send(req, path$45, opts);
39710
+ var path$49 = parseUrl(req).pathname;
39711
+ if (path$49 === "/" && originalUrl.pathname.substr(-1) !== "/") path$49 = "";
39712
+ var stream = send(req, path$49, opts);
39713
39713
  stream.on("directory", onDirectory);
39714
39714
  if (setHeaders) stream.on("headers", setHeaders);
39715
39715
  if (fallthrough) stream.on("file", function onFile() {
@@ -64021,28 +64021,40 @@ const EMPTY_COMPLETION_RESULT = { completion: {
64021
64021
  //#endregion
64022
64022
  //#region src/mcp-server.ts
64023
64023
  function createMcpServer(deps) {
64024
- const { wss, questionQueue, pendingAnswers, currentLifecycleState, broadcast } = deps;
64024
+ const { wss, questionQueue, pendingAnswers, currentLifecycleState, conversations, broadcast } = deps;
64025
64025
  const server = new McpServer({
64026
64026
  name: "maxsim-dashboard",
64027
64027
  version: "1.0.0"
64028
64028
  });
64029
- server.tool("ask_question", "Present a question to the dashboard user and wait for their answer", {
64029
+ server.tool("ask_question", "Present a question to the dashboard user and wait for their answer. Optionally link to a conversation for multi-turn discussions.", {
64030
64030
  question: string(),
64031
64031
  options: array(object$1({
64032
64032
  value: string(),
64033
64033
  label: string(),
64034
64034
  description: string().optional()
64035
64035
  })).optional(),
64036
- allow_free_text: boolean().default(true)
64037
- }, async ({ question, options, allow_free_text }) => {
64036
+ allow_free_text: boolean().default(true),
64037
+ conversation_id: string().optional().describe("Link this question to an existing conversation for multi-turn flow")
64038
+ }, async ({ question, options, allow_free_text, conversation_id }) => {
64038
64039
  const questionId = (0, node_crypto.randomUUID)();
64039
64040
  const pending = {
64040
64041
  id: questionId,
64041
64042
  question,
64042
64043
  options: options ?? [],
64043
64044
  allowFreeText: allow_free_text,
64044
- receivedAt: Date.now()
64045
+ receivedAt: Date.now(),
64046
+ conversationId: conversation_id
64045
64047
  };
64048
+ if (conversation_id && conversations.has(conversation_id)) {
64049
+ const conv = conversations.get(conversation_id);
64050
+ conv.messages.push({
64051
+ role: "assistant",
64052
+ content: question,
64053
+ timestamp: Date.now(),
64054
+ questionId
64055
+ });
64056
+ conv.updatedAt = Date.now();
64057
+ }
64046
64058
  questionQueue.push(pending);
64047
64059
  broadcast(wss, {
64048
64060
  type: "question-received",
@@ -64054,9 +64066,20 @@ function createMcpServer(deps) {
64054
64066
  });
64055
64067
  const idx = questionQueue.findIndex((q) => q.id === questionId);
64056
64068
  if (idx !== -1) questionQueue.splice(idx, 1);
64069
+ if (conversation_id && conversations.has(conversation_id)) {
64070
+ const conv = conversations.get(conversation_id);
64071
+ conv.messages.push({
64072
+ role: "user",
64073
+ content: answer,
64074
+ timestamp: Date.now(),
64075
+ questionId
64076
+ });
64077
+ conv.updatedAt = Date.now();
64078
+ }
64057
64079
  broadcast(wss, {
64058
64080
  type: "answer-given",
64059
64081
  questionId,
64082
+ conversationId: conversation_id,
64060
64083
  remainingQueue: questionQueue.length
64061
64084
  });
64062
64085
  return { content: [{
@@ -64064,6 +64087,43 @@ function createMcpServer(deps) {
64064
64087
  text: answer
64065
64088
  }] };
64066
64089
  });
64090
+ server.tool("start_conversation", "Start a new multi-turn conversation thread with the dashboard user", { topic: string().describe("A short label for this conversation thread") }, async ({ topic }) => {
64091
+ const id = (0, node_crypto.randomUUID)();
64092
+ const conv = {
64093
+ id,
64094
+ topic,
64095
+ messages: [],
64096
+ createdAt: Date.now(),
64097
+ updatedAt: Date.now()
64098
+ };
64099
+ conversations.set(id, conv);
64100
+ broadcast(wss, {
64101
+ type: "conversation-started",
64102
+ conversation: {
64103
+ id,
64104
+ topic,
64105
+ createdAt: conv.createdAt
64106
+ }
64107
+ });
64108
+ return { content: [{
64109
+ type: "text",
64110
+ text: JSON.stringify({
64111
+ conversation_id: id,
64112
+ topic
64113
+ })
64114
+ }] };
64115
+ });
64116
+ server.tool("get_conversation_history", "Retrieve the full message history of a conversation", { conversation_id: string() }, async ({ conversation_id }) => {
64117
+ const conv = conversations.get(conversation_id);
64118
+ if (!conv) return { content: [{
64119
+ type: "text",
64120
+ text: JSON.stringify({ error: "Conversation not found" })
64121
+ }] };
64122
+ return { content: [{
64123
+ type: "text",
64124
+ text: JSON.stringify(conv, null, 2)
64125
+ }] };
64126
+ });
64067
64127
  server.tool("submit_lifecycle_event", "Broadcast a workflow lifecycle event to connected dashboard clients", {
64068
64128
  event_type: _enum([
64069
64129
  "phase-started",
@@ -75574,14 +75634,6 @@ function extractFrontmatter(content) {
75574
75634
  }
75575
75635
  }
75576
75636
 
75577
- //#endregion
75578
- //#region ../cli/src/core/config.ts
75579
- /**
75580
- * Config — Planning config CRUD operations
75581
- *
75582
- * Ported from maxsim/bin/lib/config.cjs
75583
- */
75584
-
75585
75637
  //#endregion
75586
75638
  //#region ../../node_modules/escape-string-regexp/index.js
75587
75639
  function escapeStringRegexp(string) {
@@ -75597,15 +75649,22 @@ function escapeStringRegexp(string) {
75597
75649
  * Ported from maxsim/bin/lib/state.cjs
75598
75650
  */
75599
75651
  function stateExtractField(content, fieldName) {
75600
- const pattern = new RegExp(`\\*\\*${fieldName}:\\*\\*\\s*(.+)`, "i");
75601
- const match = content.match(pattern);
75602
- return match ? match[1].trim() : null;
75652
+ const escaped = escapeStringRegexp(fieldName);
75653
+ const boldPattern = new RegExp(`\\*\\*\\s*${escaped}\\s*:\\s*\\*\\*\\s*(.+)`, "i");
75654
+ const boldMatch = content.match(boldPattern);
75655
+ if (boldMatch) return boldMatch[1].trim();
75656
+ const plainPattern = new RegExp(`^\\s*${escaped}\\s*:\\s*(.+)`, "im");
75657
+ const plainMatch = content.match(plainPattern);
75658
+ return plainMatch ? plainMatch[1].trim() : null;
75603
75659
  }
75604
75660
  function stateReplaceField(content, fieldName, newValue) {
75605
75661
  const escaped = escapeStringRegexp(fieldName);
75606
- const pattern = new RegExp(`(\\*\\*${escaped}:\\*\\*\\s*)(.*)`, "i");
75607
- if (pattern.test(content)) return content.replace(pattern, (_match, prefix) => `${prefix}${newValue}`);
75608
- return null;
75662
+ const boldPattern = new RegExp(`(\\*\\*\\s*${escaped}\\s*:\\s*\\*\\*\\s*)(.*)`, "i");
75663
+ let replaced = content.replace(boldPattern, (_match, prefix) => `${prefix}${newValue}`);
75664
+ if (replaced !== content) return replaced;
75665
+ const plainPattern = new RegExp(`(^[ \\t]*${escaped}\\s*:\\s*)(.*)`, "im");
75666
+ replaced = content.replace(plainPattern, (_match, prefix) => `${prefix}${newValue}`);
75667
+ return replaced !== content ? replaced : null;
75609
75668
  }
75610
75669
 
75611
75670
  //#endregion
@@ -75656,6 +75715,53 @@ function stateReplaceField(content, fieldName, newValue) {
75656
75715
  * Ported from maxsim/bin/lib/template.cjs
75657
75716
  */
75658
75717
 
75718
+ //#endregion
75719
+ //#region ../cli/src/core/artefakte.ts
75720
+ /**
75721
+ * Artefakte — CRUD operations for project-level artefakte files
75722
+ *
75723
+ * Manages DECISIONS.md, ACCEPTANCE-CRITERIA.md, and NO-GOS.md
75724
+ * at both project level (.planning/) and phase level (.planning/phases/<phase>/).
75725
+ */
75726
+
75727
+ //#endregion
75728
+ //#region ../cli/src/core/context-loader.ts
75729
+ /**
75730
+ * Context Loader — Intelligent file selection for workflow context assembly
75731
+ *
75732
+ * Selects relevant planning files based on the current task/phase domain,
75733
+ * preventing context overload by loading only what matters.
75734
+ */
75735
+
75736
+ //#endregion
75737
+ //#region ../cli/src/core/skills.ts
75738
+ /**
75739
+ * Skills — List, install, and update skill templates
75740
+ *
75741
+ * Skills are installed to `.claude/skills/<name>/SKILL.md`.
75742
+ * Source templates live in `templates/skills/<name>/SKILL.md`.
75743
+ */
75744
+
75745
+ //#endregion
75746
+ //#region ../cli/src/core/dashboard-launcher.ts
75747
+ /**
75748
+ * Dashboard Launcher — Shared dashboard lifecycle utilities
75749
+ *
75750
+ * Used by both cli.ts (tool-router) and install.ts (npx entry point).
75751
+ */
75752
+
75753
+ //#endregion
75754
+ //#region ../cli/src/core/start.ts
75755
+ /**
75756
+ * Start — Orchestrates Dashboard launch + browser open
75757
+ *
75758
+ * Provides a unified `maxsimcli start` entry point that:
75759
+ * 1. Checks for a running dashboard
75760
+ * 2. Starts the dashboard if needed
75761
+ * 3. Opens the browser
75762
+ * 4. Reports status
75763
+ */
75764
+
75659
75765
  //#endregion
75660
75766
  //#region ../cli/src/core/init.ts
75661
75767
  /**
@@ -76213,14 +76319,14 @@ const FsWatchInstances = /* @__PURE__ */ new Map();
76213
76319
  * @param emitRaw emits raw event data
76214
76320
  * @returns {NativeFsWatcher}
76215
76321
  */
76216
- function createFsWatchInstance(path$37, options, listener, errHandler, emitRaw) {
76322
+ function createFsWatchInstance(path$41, options, listener, errHandler, emitRaw) {
76217
76323
  const handleEvent = (rawEvent, evPath) => {
76218
- listener(path$37);
76219
- emitRaw(rawEvent, evPath, { watchedPath: path$37 });
76220
- if (evPath && path$37 !== evPath) fsWatchBroadcast(path.resolve(path$37, evPath), KEY_LISTENERS, path.join(path$37, evPath));
76324
+ listener(path$41);
76325
+ emitRaw(rawEvent, evPath, { watchedPath: path$41 });
76326
+ if (evPath && path$41 !== evPath) fsWatchBroadcast(path.resolve(path$41, evPath), KEY_LISTENERS, path.join(path$41, evPath));
76221
76327
  };
76222
76328
  try {
76223
- return (0, fs.watch)(path$37, { persistent: options.persistent }, handleEvent);
76329
+ return (0, fs.watch)(path$41, { persistent: options.persistent }, handleEvent);
76224
76330
  } catch (error) {
76225
76331
  errHandler(error);
76226
76332
  return;
@@ -76245,12 +76351,12 @@ const fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
76245
76351
  * @param options to be passed to fs_watch
76246
76352
  * @param handlers container for event listener functions
76247
76353
  */
76248
- const setFsWatchListener = (path$41, fullPath, options, handlers) => {
76354
+ const setFsWatchListener = (path$45, fullPath, options, handlers) => {
76249
76355
  const { listener, errHandler, rawEmitter } = handlers;
76250
76356
  let cont = FsWatchInstances.get(fullPath);
76251
76357
  let watcher;
76252
76358
  if (!options.persistent) {
76253
- watcher = createFsWatchInstance(path$41, options, listener, errHandler, rawEmitter);
76359
+ watcher = createFsWatchInstance(path$45, options, listener, errHandler, rawEmitter);
76254
76360
  if (!watcher) return;
76255
76361
  return watcher.close.bind(watcher);
76256
76362
  }
@@ -76259,13 +76365,13 @@ const setFsWatchListener = (path$41, fullPath, options, handlers) => {
76259
76365
  addAndConvert(cont, KEY_ERR, errHandler);
76260
76366
  addAndConvert(cont, KEY_RAW, rawEmitter);
76261
76367
  } else {
76262
- watcher = createFsWatchInstance(path$41, options, fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS), errHandler, fsWatchBroadcast.bind(null, fullPath, KEY_RAW));
76368
+ watcher = createFsWatchInstance(path$45, options, fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS), errHandler, fsWatchBroadcast.bind(null, fullPath, KEY_RAW));
76263
76369
  if (!watcher) return;
76264
76370
  watcher.on(EV.ERROR, async (error) => {
76265
76371
  const broadcastErr = fsWatchBroadcast.bind(null, fullPath, KEY_ERR);
76266
76372
  if (cont) cont.watcherUnusable = true;
76267
76373
  if (isWindows && error.code === "EPERM") try {
76268
- await (await (0, fs_promises.open)(path$41, "r")).close();
76374
+ await (await (0, fs_promises.open)(path$45, "r")).close();
76269
76375
  broadcastErr(error);
76270
76376
  } catch (err) {}
76271
76377
  else broadcastErr(error);
@@ -76301,7 +76407,7 @@ const FsWatchFileInstances = /* @__PURE__ */ new Map();
76301
76407
  * @param handlers container for event listener functions
76302
76408
  * @returns closer
76303
76409
  */
76304
- const setFsWatchFileListener = (path$42, fullPath, options, handlers) => {
76410
+ const setFsWatchFileListener = (path$46, fullPath, options, handlers) => {
76305
76411
  const { listener, rawEmitter } = handlers;
76306
76412
  let cont = FsWatchFileInstances.get(fullPath);
76307
76413
  const copts = cont && cont.options;
@@ -76325,7 +76431,7 @@ const setFsWatchFileListener = (path$42, fullPath, options, handlers) => {
76325
76431
  });
76326
76432
  });
76327
76433
  const currmtime = curr.mtimeMs;
76328
- if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) foreach(cont.listeners, (listener) => listener(path$42, curr));
76434
+ if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) foreach(cont.listeners, (listener) => listener(path$46, curr));
76329
76435
  })
76330
76436
  };
76331
76437
  FsWatchFileInstances.set(fullPath, cont);
@@ -76355,22 +76461,22 @@ var NodeFsHandler = class {
76355
76461
  * @param listener on fs change
76356
76462
  * @returns closer for the watcher instance
76357
76463
  */
76358
- _watchWithNodeFs(path$38, listener) {
76464
+ _watchWithNodeFs(path$42, listener) {
76359
76465
  const opts = this.fsw.options;
76360
- const directory = path.dirname(path$38);
76361
- const basename = path.basename(path$38);
76466
+ const directory = path.dirname(path$42);
76467
+ const basename = path.basename(path$42);
76362
76468
  this.fsw._getWatchedDir(directory).add(basename);
76363
- const absolutePath = path.resolve(path$38);
76469
+ const absolutePath = path.resolve(path$42);
76364
76470
  const options = { persistent: opts.persistent };
76365
76471
  if (!listener) listener = EMPTY_FN;
76366
76472
  let closer;
76367
76473
  if (opts.usePolling) {
76368
76474
  options.interval = opts.interval !== opts.binaryInterval && isBinaryPath(basename) ? opts.binaryInterval : opts.interval;
76369
- closer = setFsWatchFileListener(path$38, absolutePath, options, {
76475
+ closer = setFsWatchFileListener(path$42, absolutePath, options, {
76370
76476
  listener,
76371
76477
  rawEmitter: this.fsw._emitRaw
76372
76478
  });
76373
- } else closer = setFsWatchListener(path$38, absolutePath, options, {
76479
+ } else closer = setFsWatchListener(path$42, absolutePath, options, {
76374
76480
  listener,
76375
76481
  errHandler: this._boundHandleError,
76376
76482
  rawEmitter: this.fsw._emitRaw
@@ -76388,7 +76494,7 @@ var NodeFsHandler = class {
76388
76494
  const parent = this.fsw._getWatchedDir(dirname);
76389
76495
  let prevStats = stats;
76390
76496
  if (parent.has(basename)) return;
76391
- const listener = async (path$43, newStats) => {
76497
+ const listener = async (path$47, newStats) => {
76392
76498
  if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5)) return;
76393
76499
  if (!newStats || newStats.mtimeMs === 0) try {
76394
76500
  const newStats = await (0, fs_promises.stat)(file);
@@ -76397,10 +76503,10 @@ var NodeFsHandler = class {
76397
76503
  const mt = newStats.mtimeMs;
76398
76504
  if (!at || at <= mt || mt !== prevStats.mtimeMs) this.fsw._emit(EV.CHANGE, file, newStats);
76399
76505
  if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats.ino) {
76400
- this.fsw._closeFile(path$43);
76506
+ this.fsw._closeFile(path$47);
76401
76507
  prevStats = newStats;
76402
76508
  const closer = this._watchWithNodeFs(file, listener);
76403
- if (closer) this.fsw._addPathCloser(path$43, closer);
76509
+ if (closer) this.fsw._addPathCloser(path$47, closer);
76404
76510
  } else prevStats = newStats;
76405
76511
  } catch (error) {
76406
76512
  this.fsw._remove(dirname, basename);
@@ -76427,7 +76533,7 @@ var NodeFsHandler = class {
76427
76533
  * @param item basename of this item
76428
76534
  * @returns true if no more processing is needed for this entry.
76429
76535
  */
76430
- async _handleSymlink(entry, directory, path$44, item) {
76536
+ async _handleSymlink(entry, directory, path$48, item) {
76431
76537
  if (this.fsw.closed) return;
76432
76538
  const full = entry.fullPath;
76433
76539
  const dir = this.fsw._getWatchedDir(directory);
@@ -76435,7 +76541,7 @@ var NodeFsHandler = class {
76435
76541
  this.fsw._incrReadyCount();
76436
76542
  let linkPath;
76437
76543
  try {
76438
- linkPath = await (0, fs_promises.realpath)(path$44);
76544
+ linkPath = await (0, fs_promises.realpath)(path$48);
76439
76545
  } catch (e) {
76440
76546
  this.fsw._emitReady();
76441
76547
  return true;
@@ -76444,12 +76550,12 @@ var NodeFsHandler = class {
76444
76550
  if (dir.has(item)) {
76445
76551
  if (this.fsw._symlinkPaths.get(full) !== linkPath) {
76446
76552
  this.fsw._symlinkPaths.set(full, linkPath);
76447
- this.fsw._emit(EV.CHANGE, path$44, entry.stats);
76553
+ this.fsw._emit(EV.CHANGE, path$48, entry.stats);
76448
76554
  }
76449
76555
  } else {
76450
76556
  dir.add(item);
76451
76557
  this.fsw._symlinkPaths.set(full, linkPath);
76452
- this.fsw._emit(EV.ADD, path$44, entry.stats);
76558
+ this.fsw._emit(EV.ADD, path$48, entry.stats);
76453
76559
  }
76454
76560
  this.fsw._emitReady();
76455
76561
  return true;
@@ -76474,17 +76580,17 @@ var NodeFsHandler = class {
76474
76580
  return;
76475
76581
  }
76476
76582
  const item = entry.path;
76477
- let path$39 = path.join(directory, item);
76583
+ let path$43 = path.join(directory, item);
76478
76584
  current.add(item);
76479
- if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path$39, item)) return;
76585
+ if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path$43, item)) return;
76480
76586
  if (this.fsw.closed) {
76481
76587
  stream = void 0;
76482
76588
  return;
76483
76589
  }
76484
76590
  if (item === target || !target && !previous.has(item)) {
76485
76591
  this.fsw._incrReadyCount();
76486
- path$39 = path.join(dir, path.relative(dir, path$39));
76487
- this._addToNodeFs(path$39, initialAdd, wh, depth + 1);
76592
+ path$43 = path.join(dir, path.relative(dir, path$43));
76593
+ this._addToNodeFs(path$43, initialAdd, wh, depth + 1);
76488
76594
  }
76489
76595
  }).on(EV.ERROR, this._boundHandleError);
76490
76596
  return new Promise((resolve, reject) => {
@@ -76547,13 +76653,13 @@ var NodeFsHandler = class {
76547
76653
  * @param depth Child path actually targeted for watch
76548
76654
  * @param target Child path actually targeted for watch
76549
76655
  */
76550
- async _addToNodeFs(path$40, initialAdd, priorWh, depth, target) {
76656
+ async _addToNodeFs(path$44, initialAdd, priorWh, depth, target) {
76551
76657
  const ready = this.fsw._emitReady;
76552
- if (this.fsw._isIgnored(path$40) || this.fsw.closed) {
76658
+ if (this.fsw._isIgnored(path$44) || this.fsw.closed) {
76553
76659
  ready();
76554
76660
  return false;
76555
76661
  }
76556
- const wh = this.fsw._getWatchHelpers(path$40);
76662
+ const wh = this.fsw._getWatchHelpers(path$44);
76557
76663
  if (priorWh) {
76558
76664
  wh.filterPath = (entry) => priorWh.filterPath(entry);
76559
76665
  wh.filterDir = (entry) => priorWh.filterDir(entry);
@@ -76568,29 +76674,29 @@ var NodeFsHandler = class {
76568
76674
  const follow = this.fsw.options.followSymlinks;
76569
76675
  let closer;
76570
76676
  if (stats.isDirectory()) {
76571
- const absPath = path.resolve(path$40);
76572
- const targetPath = follow ? await (0, fs_promises.realpath)(path$40) : path$40;
76677
+ const absPath = path.resolve(path$44);
76678
+ const targetPath = follow ? await (0, fs_promises.realpath)(path$44) : path$44;
76573
76679
  if (this.fsw.closed) return;
76574
76680
  closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
76575
76681
  if (this.fsw.closed) return;
76576
76682
  if (absPath !== targetPath && targetPath !== void 0) this.fsw._symlinkPaths.set(absPath, targetPath);
76577
76683
  } else if (stats.isSymbolicLink()) {
76578
- const targetPath = follow ? await (0, fs_promises.realpath)(path$40) : path$40;
76684
+ const targetPath = follow ? await (0, fs_promises.realpath)(path$44) : path$44;
76579
76685
  if (this.fsw.closed) return;
76580
76686
  const parent = path.dirname(wh.watchPath);
76581
76687
  this.fsw._getWatchedDir(parent).add(wh.watchPath);
76582
76688
  this.fsw._emit(EV.ADD, wh.watchPath, stats);
76583
- closer = await this._handleDir(parent, stats, initialAdd, depth, path$40, wh, targetPath);
76689
+ closer = await this._handleDir(parent, stats, initialAdd, depth, path$44, wh, targetPath);
76584
76690
  if (this.fsw.closed) return;
76585
- if (targetPath !== void 0) this.fsw._symlinkPaths.set(path.resolve(path$40), targetPath);
76691
+ if (targetPath !== void 0) this.fsw._symlinkPaths.set(path.resolve(path$44), targetPath);
76586
76692
  } else closer = this._handleFile(wh.watchPath, stats, initialAdd);
76587
76693
  ready();
76588
- if (closer) this.fsw._addPathCloser(path$40, closer);
76694
+ if (closer) this.fsw._addPathCloser(path$44, closer);
76589
76695
  return false;
76590
76696
  } catch (error) {
76591
76697
  if (this.fsw._handleError(error)) {
76592
76698
  ready();
76593
- return path$40;
76699
+ return path$44;
76594
76700
  }
76595
76701
  }
76596
76702
  }
@@ -76627,22 +76733,22 @@ function createPattern(matcher) {
76627
76733
  };
76628
76734
  return () => false;
76629
76735
  }
76630
- function normalizePath(path$16) {
76631
- if (typeof path$16 !== "string") throw new Error("string expected");
76632
- path$16 = path.normalize(path$16);
76633
- path$16 = path$16.replace(/\\/g, "/");
76736
+ function normalizePath(path$20) {
76737
+ if (typeof path$20 !== "string") throw new Error("string expected");
76738
+ path$20 = path.normalize(path$20);
76739
+ path$20 = path$20.replace(/\\/g, "/");
76634
76740
  let prepend = false;
76635
- if (path$16.startsWith("//")) prepend = true;
76741
+ if (path$20.startsWith("//")) prepend = true;
76636
76742
  const DOUBLE_SLASH_RE = /\/\//;
76637
- while (path$16.match(DOUBLE_SLASH_RE)) path$16 = path$16.replace(DOUBLE_SLASH_RE, "/");
76638
- if (prepend) path$16 = "/" + path$16;
76639
- return path$16;
76743
+ while (path$20.match(DOUBLE_SLASH_RE)) path$20 = path$20.replace(DOUBLE_SLASH_RE, "/");
76744
+ if (prepend) path$20 = "/" + path$20;
76745
+ return path$20;
76640
76746
  }
76641
76747
  function matchPatterns(patterns, testString, stats) {
76642
- const path$26 = normalizePath(testString);
76748
+ const path$30 = normalizePath(testString);
76643
76749
  for (let index = 0; index < patterns.length; index++) {
76644
76750
  const pattern = patterns[index];
76645
- if (pattern(path$26, stats)) return true;
76751
+ if (pattern(path$30, stats)) return true;
76646
76752
  }
76647
76753
  return false;
76648
76754
  }
@@ -76667,14 +76773,14 @@ const toUnix = (string) => {
76667
76773
  if (prepend) str = SLASH + str;
76668
76774
  return str;
76669
76775
  };
76670
- const normalizePathToUnix = (path$17) => toUnix(path.normalize(toUnix(path$17)));
76671
- const normalizeIgnored = (cwd = "") => (path$18) => {
76672
- if (typeof path$18 === "string") return normalizePathToUnix(path.isAbsolute(path$18) ? path$18 : path.join(cwd, path$18));
76673
- else return path$18;
76776
+ const normalizePathToUnix = (path$21) => toUnix(path.normalize(toUnix(path$21)));
76777
+ const normalizeIgnored = (cwd = "") => (path$22) => {
76778
+ if (typeof path$22 === "string") return normalizePathToUnix(path.isAbsolute(path$22) ? path$22 : path.join(cwd, path$22));
76779
+ else return path$22;
76674
76780
  };
76675
- const getAbsolutePath = (path$19, cwd) => {
76676
- if (path.isAbsolute(path$19)) return path$19;
76677
- return path.join(cwd, path$19);
76781
+ const getAbsolutePath = (path$23, cwd) => {
76782
+ if (path.isAbsolute(path$23)) return path$23;
76783
+ return path.join(cwd, path$23);
76678
76784
  };
76679
76785
  const EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
76680
76786
  /**
@@ -76724,10 +76830,10 @@ var DirEntry = class {
76724
76830
  const STAT_METHOD_F = "stat";
76725
76831
  const STAT_METHOD_L = "lstat";
76726
76832
  var WatchHelper = class {
76727
- constructor(path$20, follow, fsw) {
76833
+ constructor(path$24, follow, fsw) {
76728
76834
  this.fsw = fsw;
76729
- const watchPath = path$20;
76730
- this.path = path$20 = path$20.replace(REPLACER_RE, "");
76835
+ const watchPath = path$24;
76836
+ this.path = path$24 = path$24.replace(REPLACER_RE, "");
76731
76837
  this.watchPath = watchPath;
76732
76838
  this.fullWatchPath = path.resolve(watchPath);
76733
76839
  this.dirParts = [];
@@ -76840,17 +76946,17 @@ var FSWatcher = class extends events.EventEmitter {
76840
76946
  this.closed = false;
76841
76947
  this._closePromise = void 0;
76842
76948
  let paths = unifyPaths(paths_);
76843
- if (cwd) paths = paths.map((path$27) => {
76844
- return getAbsolutePath(path$27, cwd);
76949
+ if (cwd) paths = paths.map((path$31) => {
76950
+ return getAbsolutePath(path$31, cwd);
76845
76951
  });
76846
- paths.forEach((path$28) => {
76847
- this._removeIgnoredPath(path$28);
76952
+ paths.forEach((path$32) => {
76953
+ this._removeIgnoredPath(path$32);
76848
76954
  });
76849
76955
  this._userIgnored = void 0;
76850
76956
  if (!this._readyCount) this._readyCount = 0;
76851
76957
  this._readyCount += paths.length;
76852
- Promise.all(paths.map(async (path$29) => {
76853
- const res = await this._nodeFsHandler._addToNodeFs(path$29, !_internal, void 0, 0, _origAdd);
76958
+ Promise.all(paths.map(async (path$33) => {
76959
+ const res = await this._nodeFsHandler._addToNodeFs(path$33, !_internal, void 0, 0, _origAdd);
76854
76960
  if (res) this._emitReady();
76855
76961
  return res;
76856
76962
  })).then((results) => {
@@ -76868,15 +76974,15 @@ var FSWatcher = class extends events.EventEmitter {
76868
76974
  if (this.closed) return this;
76869
76975
  const paths = unifyPaths(paths_);
76870
76976
  const { cwd } = this.options;
76871
- paths.forEach((path$21) => {
76872
- if (!path.isAbsolute(path$21) && !this._closers.has(path$21)) {
76873
- if (cwd) path$21 = path.join(cwd, path$21);
76874
- path$21 = path.resolve(path$21);
76875
- }
76876
- this._closePath(path$21);
76877
- this._addIgnoredPath(path$21);
76878
- if (this._watched.has(path$21)) this._addIgnoredPath({
76879
- path: path$21,
76977
+ paths.forEach((path$25) => {
76978
+ if (!path.isAbsolute(path$25) && !this._closers.has(path$25)) {
76979
+ if (cwd) path$25 = path.join(cwd, path$25);
76980
+ path$25 = path.resolve(path$25);
76981
+ }
76982
+ this._closePath(path$25);
76983
+ this._addIgnoredPath(path$25);
76984
+ if (this._watched.has(path$25)) this._addIgnoredPath({
76985
+ path: path$25,
76880
76986
  recursive: true
76881
76987
  });
76882
76988
  this._userIgnored = void 0;
@@ -76932,34 +77038,34 @@ var FSWatcher = class extends events.EventEmitter {
76932
77038
  * @param stats arguments to be passed with event
76933
77039
  * @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
76934
77040
  */
76935
- async _emit(event, path$22, stats) {
77041
+ async _emit(event, path$26, stats) {
76936
77042
  if (this.closed) return;
76937
77043
  const opts = this.options;
76938
- if (isWindows) path$22 = path.normalize(path$22);
76939
- if (opts.cwd) path$22 = path.relative(opts.cwd, path$22);
76940
- const args = [path$22];
77044
+ if (isWindows) path$26 = path.normalize(path$26);
77045
+ if (opts.cwd) path$26 = path.relative(opts.cwd, path$26);
77046
+ const args = [path$26];
76941
77047
  if (stats != null) args.push(stats);
76942
77048
  const awf = opts.awaitWriteFinish;
76943
77049
  let pw;
76944
- if (awf && (pw = this._pendingWrites.get(path$22))) {
77050
+ if (awf && (pw = this._pendingWrites.get(path$26))) {
76945
77051
  pw.lastChange = /* @__PURE__ */ new Date();
76946
77052
  return this;
76947
77053
  }
76948
77054
  if (opts.atomic) {
76949
77055
  if (event === EVENTS.UNLINK) {
76950
- this._pendingUnlinks.set(path$22, [event, ...args]);
77056
+ this._pendingUnlinks.set(path$26, [event, ...args]);
76951
77057
  setTimeout(() => {
76952
- this._pendingUnlinks.forEach((entry, path$30) => {
77058
+ this._pendingUnlinks.forEach((entry, path$34) => {
76953
77059
  this.emit(...entry);
76954
77060
  this.emit(EVENTS.ALL, ...entry);
76955
- this._pendingUnlinks.delete(path$30);
77061
+ this._pendingUnlinks.delete(path$34);
76956
77062
  });
76957
77063
  }, typeof opts.atomic === "number" ? opts.atomic : 100);
76958
77064
  return this;
76959
77065
  }
76960
- if (event === EVENTS.ADD && this._pendingUnlinks.has(path$22)) {
77066
+ if (event === EVENTS.ADD && this._pendingUnlinks.has(path$26)) {
76961
77067
  event = EVENTS.CHANGE;
76962
- this._pendingUnlinks.delete(path$22);
77068
+ this._pendingUnlinks.delete(path$26);
76963
77069
  }
76964
77070
  }
76965
77071
  if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
@@ -76974,14 +77080,14 @@ var FSWatcher = class extends events.EventEmitter {
76974
77080
  this.emitWithAll(event, args);
76975
77081
  }
76976
77082
  };
76977
- this._awaitWriteFinish(path$22, awf.stabilityThreshold, event, awfEmit);
77083
+ this._awaitWriteFinish(path$26, awf.stabilityThreshold, event, awfEmit);
76978
77084
  return this;
76979
77085
  }
76980
77086
  if (event === EVENTS.CHANGE) {
76981
- if (!this._throttle(EVENTS.CHANGE, path$22, 50)) return this;
77087
+ if (!this._throttle(EVENTS.CHANGE, path$26, 50)) return this;
76982
77088
  }
76983
77089
  if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
76984
- const fullPath = opts.cwd ? path.join(opts.cwd, path$22) : path$22;
77090
+ const fullPath = opts.cwd ? path.join(opts.cwd, path$26) : path$26;
76985
77091
  let stats;
76986
77092
  try {
76987
77093
  stats = await (0, fs_promises.stat)(fullPath);
@@ -77008,20 +77114,20 @@ var FSWatcher = class extends events.EventEmitter {
77008
77114
  * @param timeout duration of time to suppress duplicate actions
77009
77115
  * @returns tracking object or false if action should be suppressed
77010
77116
  */
77011
- _throttle(actionType, path$31, timeout) {
77117
+ _throttle(actionType, path$35, timeout) {
77012
77118
  if (!this._throttled.has(actionType)) this._throttled.set(actionType, /* @__PURE__ */ new Map());
77013
77119
  const action = this._throttled.get(actionType);
77014
77120
  if (!action) throw new Error("invalid throttle");
77015
- const actionPath = action.get(path$31);
77121
+ const actionPath = action.get(path$35);
77016
77122
  if (actionPath) {
77017
77123
  actionPath.count++;
77018
77124
  return false;
77019
77125
  }
77020
77126
  let timeoutObject;
77021
77127
  const clear = () => {
77022
- const item = action.get(path$31);
77128
+ const item = action.get(path$35);
77023
77129
  const count = item ? item.count : 0;
77024
- action.delete(path$31);
77130
+ action.delete(path$35);
77025
77131
  clearTimeout(timeoutObject);
77026
77132
  if (item) clearTimeout(item.timeoutObject);
77027
77133
  return count;
@@ -77032,7 +77138,7 @@ var FSWatcher = class extends events.EventEmitter {
77032
77138
  clear,
77033
77139
  count: 0
77034
77140
  };
77035
- action.set(path$31, thr);
77141
+ action.set(path$35, thr);
77036
77142
  return thr;
77037
77143
  }
77038
77144
  _incrReadyCount() {
@@ -77046,34 +77152,34 @@ var FSWatcher = class extends events.EventEmitter {
77046
77152
  * @param event
77047
77153
  * @param awfEmit Callback to be called when ready for event to be emitted.
77048
77154
  */
77049
- _awaitWriteFinish(path$23, threshold, event, awfEmit) {
77155
+ _awaitWriteFinish(path$27, threshold, event, awfEmit) {
77050
77156
  const awf = this.options.awaitWriteFinish;
77051
77157
  if (typeof awf !== "object") return;
77052
77158
  const pollInterval = awf.pollInterval;
77053
77159
  let timeoutHandler;
77054
- let fullPath = path$23;
77055
- if (this.options.cwd && !path.isAbsolute(path$23)) fullPath = path.join(this.options.cwd, path$23);
77160
+ let fullPath = path$27;
77161
+ if (this.options.cwd && !path.isAbsolute(path$27)) fullPath = path.join(this.options.cwd, path$27);
77056
77162
  const now = /* @__PURE__ */ new Date();
77057
77163
  const writes = this._pendingWrites;
77058
77164
  function awaitWriteFinishFn(prevStat) {
77059
77165
  (0, fs.stat)(fullPath, (err, curStat) => {
77060
- if (err || !writes.has(path$23)) {
77166
+ if (err || !writes.has(path$27)) {
77061
77167
  if (err && err.code !== "ENOENT") awfEmit(err);
77062
77168
  return;
77063
77169
  }
77064
77170
  const now = Number(/* @__PURE__ */ new Date());
77065
- if (prevStat && curStat.size !== prevStat.size) writes.get(path$23).lastChange = now;
77066
- if (now - writes.get(path$23).lastChange >= threshold) {
77067
- writes.delete(path$23);
77171
+ if (prevStat && curStat.size !== prevStat.size) writes.get(path$27).lastChange = now;
77172
+ if (now - writes.get(path$27).lastChange >= threshold) {
77173
+ writes.delete(path$27);
77068
77174
  awfEmit(void 0, curStat);
77069
77175
  } else timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
77070
77176
  });
77071
77177
  }
77072
- if (!writes.has(path$23)) {
77073
- writes.set(path$23, {
77178
+ if (!writes.has(path$27)) {
77179
+ writes.set(path$27, {
77074
77180
  lastChange: now,
77075
77181
  cancelWait: () => {
77076
- writes.delete(path$23);
77182
+ writes.delete(path$27);
77077
77183
  clearTimeout(timeoutHandler);
77078
77184
  return event;
77079
77185
  }
@@ -77084,24 +77190,24 @@ var FSWatcher = class extends events.EventEmitter {
77084
77190
  /**
77085
77191
  * Determines whether user has asked to ignore this path.
77086
77192
  */
77087
- _isIgnored(path$32, stats) {
77088
- if (this.options.atomic && DOT_RE.test(path$32)) return true;
77193
+ _isIgnored(path$36, stats) {
77194
+ if (this.options.atomic && DOT_RE.test(path$36)) return true;
77089
77195
  if (!this._userIgnored) {
77090
77196
  const { cwd } = this.options;
77091
77197
  const ignored = (this.options.ignored || []).map(normalizeIgnored(cwd));
77092
77198
  this._userIgnored = anymatch([...[...this._ignoredPaths].map(normalizeIgnored(cwd)), ...ignored], void 0);
77093
77199
  }
77094
- return this._userIgnored(path$32, stats);
77200
+ return this._userIgnored(path$36, stats);
77095
77201
  }
77096
- _isntIgnored(path$33, stat) {
77097
- return !this._isIgnored(path$33, stat);
77202
+ _isntIgnored(path$37, stat) {
77203
+ return !this._isIgnored(path$37, stat);
77098
77204
  }
77099
77205
  /**
77100
77206
  * Provides a set of common helpers and properties relating to symlink handling.
77101
77207
  * @param path file or directory pattern being watched
77102
77208
  */
77103
- _getWatchHelpers(path$34) {
77104
- return new WatchHelper(path$34, this.options.followSymlinks, this);
77209
+ _getWatchHelpers(path$38) {
77210
+ return new WatchHelper(path$38, this.options.followSymlinks, this);
77105
77211
  }
77106
77212
  /**
77107
77213
  * Provides directory tracking objects
@@ -77127,50 +77233,50 @@ var FSWatcher = class extends events.EventEmitter {
77127
77233
  * @param item base path of item/directory
77128
77234
  */
77129
77235
  _remove(directory, item, isDirectory) {
77130
- const path$24 = path.join(directory, item);
77131
- const fullPath = path.resolve(path$24);
77132
- isDirectory = isDirectory != null ? isDirectory : this._watched.has(path$24) || this._watched.has(fullPath);
77133
- if (!this._throttle("remove", path$24, 100)) return;
77236
+ const path$28 = path.join(directory, item);
77237
+ const fullPath = path.resolve(path$28);
77238
+ isDirectory = isDirectory != null ? isDirectory : this._watched.has(path$28) || this._watched.has(fullPath);
77239
+ if (!this._throttle("remove", path$28, 100)) return;
77134
77240
  if (!isDirectory && this._watched.size === 1) this.add(directory, item, true);
77135
- this._getWatchedDir(path$24).getChildren().forEach((nested) => this._remove(path$24, nested));
77241
+ this._getWatchedDir(path$28).getChildren().forEach((nested) => this._remove(path$28, nested));
77136
77242
  const parent = this._getWatchedDir(directory);
77137
77243
  const wasTracked = parent.has(item);
77138
77244
  parent.remove(item);
77139
77245
  if (this._symlinkPaths.has(fullPath)) this._symlinkPaths.delete(fullPath);
77140
- let relPath = path$24;
77141
- if (this.options.cwd) relPath = path.relative(this.options.cwd, path$24);
77246
+ let relPath = path$28;
77247
+ if (this.options.cwd) relPath = path.relative(this.options.cwd, path$28);
77142
77248
  if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
77143
77249
  if (this._pendingWrites.get(relPath).cancelWait() === EVENTS.ADD) return;
77144
77250
  }
77145
- this._watched.delete(path$24);
77251
+ this._watched.delete(path$28);
77146
77252
  this._watched.delete(fullPath);
77147
77253
  const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
77148
- if (wasTracked && !this._isIgnored(path$24)) this._emit(eventName, path$24);
77149
- this._closePath(path$24);
77254
+ if (wasTracked && !this._isIgnored(path$28)) this._emit(eventName, path$28);
77255
+ this._closePath(path$28);
77150
77256
  }
77151
77257
  /**
77152
77258
  * Closes all watchers for a path
77153
77259
  */
77154
- _closePath(path$25) {
77155
- this._closeFile(path$25);
77156
- const dir = path.dirname(path$25);
77157
- this._getWatchedDir(dir).remove(path.basename(path$25));
77260
+ _closePath(path$29) {
77261
+ this._closeFile(path$29);
77262
+ const dir = path.dirname(path$29);
77263
+ this._getWatchedDir(dir).remove(path.basename(path$29));
77158
77264
  }
77159
77265
  /**
77160
77266
  * Closes only file-specific watchers
77161
77267
  */
77162
- _closeFile(path$35) {
77163
- const closers = this._closers.get(path$35);
77268
+ _closeFile(path$39) {
77269
+ const closers = this._closers.get(path$39);
77164
77270
  if (!closers) return;
77165
77271
  closers.forEach((closer) => closer());
77166
- this._closers.delete(path$35);
77272
+ this._closers.delete(path$39);
77167
77273
  }
77168
- _addPathCloser(path$36, closer) {
77274
+ _addPathCloser(path$40, closer) {
77169
77275
  if (!closer) return;
77170
- let list = this._closers.get(path$36);
77276
+ let list = this._closers.get(path$40);
77171
77277
  if (!list) {
77172
77278
  list = [];
77173
- this._closers.set(path$36, list);
77279
+ this._closers.set(path$40, list);
77174
77280
  }
77175
77281
  list.push(closer);
77176
77282
  }
@@ -77711,6 +77817,31 @@ function log(level, tag, ...args) {
77711
77817
  const projectCwd = process.env.MAXSIM_PROJECT_CWD || process.cwd();
77712
77818
  const networkMode = process.env.MAXSIM_NETWORK_MODE === "1";
77713
77819
  let resolvedPort = 3333;
77820
+ /**
77821
+ * Derive a deterministic port for a project path (range 3100-3199).
77822
+ * Simple djb2 hash mapped to 100-port range.
77823
+ */
77824
+ function projectPort(projectPath) {
77825
+ let hash = 5381;
77826
+ for (let i = 0; i < projectPath.length; i++) hash = (hash << 5) + hash + projectPath.charCodeAt(i) >>> 0;
77827
+ return 3100 + hash % 100;
77828
+ }
77829
+ /**
77830
+ * List running MAXSIM dashboard instances by scanning the port range.
77831
+ */
77832
+ async function listRunningDashboards() {
77833
+ const results = [];
77834
+ const checks = [];
77835
+ for (let port = 3100; port <= 3199; port++) checks.push(fetch(`http://localhost:${port}/api/health`, { signal: AbortSignal.timeout(500) }).then((r) => r.json()).then((data) => {
77836
+ if (data.status === "ok" && data.cwd) results.push({
77837
+ port,
77838
+ cwd: data.cwd,
77839
+ uptime: data.uptime ?? 0
77840
+ });
77841
+ }).catch(() => {}));
77842
+ await Promise.all(checks);
77843
+ return results.sort((a, b) => a.port - b.port);
77844
+ }
77714
77845
  function getTailscaleIp() {
77715
77846
  const ifaces = node_os.networkInterfaces();
77716
77847
  for (const [name, iface] of Object.entries(ifaces)) {
@@ -77770,6 +77901,7 @@ let clientCount = 0;
77770
77901
  const questionQueue = [];
77771
77902
  const pendingAnswers = /* @__PURE__ */ new Map();
77772
77903
  const currentLifecycleState = { value: null };
77904
+ const conversations = /* @__PURE__ */ new Map();
77773
77905
  function createWSS(onClientCountChange) {
77774
77906
  const wss = new import_websocket_server.default({ noServer: true });
77775
77907
  wss.on("connection", (ws) => {
@@ -77824,7 +77956,7 @@ function setupWatcher(cwd, wss) {
77824
77956
  timestamp: Date.now()
77825
77957
  });
77826
77958
  }
77827
- }, 200);
77959
+ }, 500);
77828
77960
  function onFileChange(filePath) {
77829
77961
  const normalized = normalizeFsPath(filePath);
77830
77962
  if (isSuppressed(normalized)) {
@@ -78098,14 +78230,27 @@ function parseProject(cwd) {
78098
78230
  }
78099
78231
  const app = (0, import_express.default)();
78100
78232
  app.use(import_express.json());
78233
+ let serverReady = false;
78101
78234
  app.get("/api/health", (_req, res) => {
78102
78235
  res.json({
78103
78236
  status: "ok",
78104
- port: process.env.PORT || 3333,
78237
+ ready: serverReady,
78238
+ port: resolvedPort,
78105
78239
  cwd: projectCwd,
78106
78240
  uptime: process.uptime()
78107
78241
  });
78108
78242
  });
78243
+ app.get("/api/ready", (_req, res) => {
78244
+ if (serverReady) return res.json({
78245
+ ready: true,
78246
+ port: resolvedPort,
78247
+ cwd: projectCwd
78248
+ });
78249
+ return res.status(503).json({
78250
+ ready: false,
78251
+ message: "Server is starting up"
78252
+ });
78253
+ });
78109
78254
  app.get("/api/roadmap", (_req, res) => {
78110
78255
  const data = parseRoadmap(projectCwd);
78111
78256
  if (!data) return res.status(404).json({ error: "ROADMAP.md not found" });
@@ -78326,7 +78471,9 @@ app.get("/api/server-info", (_req, res) => {
78326
78471
  networkEnabled: networkMode,
78327
78472
  localUrl: `http://localhost:${resolvedPort}`,
78328
78473
  networkUrl: localNetworkIp ? `http://${localNetworkIp}:${resolvedPort}` : null,
78329
- tailscaleUrl: tailscaleIp ? `http://${tailscaleIp}:${resolvedPort}` : null
78474
+ tailscaleUrl: tailscaleIp ? `http://${tailscaleIp}:${resolvedPort}` : null,
78475
+ projectName: node_path.basename(projectCwd),
78476
+ projectCwd
78330
78477
  });
78331
78478
  });
78332
78479
  let shutdownFn = null;
@@ -78359,6 +78506,21 @@ app.post("/api/simple-mode-config", (req, res) => {
78359
78506
  default_mode
78360
78507
  });
78361
78508
  });
78509
+ app.get("/api/conversations", (_req, res) => {
78510
+ const list = Array.from(conversations.values()).map((c) => ({
78511
+ id: c.id,
78512
+ topic: c.topic,
78513
+ messageCount: c.messages.length,
78514
+ createdAt: c.createdAt,
78515
+ updatedAt: c.updatedAt
78516
+ }));
78517
+ return res.json(list);
78518
+ });
78519
+ app.get("/api/conversations/:id", (req, res) => {
78520
+ const conv = conversations.get(req.params.id);
78521
+ if (!conv) return res.status(404).json({ error: "Conversation not found" });
78522
+ return res.json(conv);
78523
+ });
78362
78524
  if (node_fs.existsSync(clientDir)) app.use(build_default(clientDir, { single: true }));
78363
78525
  else app.get("/", (_req, res) => {
78364
78526
  res.send("<html><body><p>Dashboard client not found. Run <code>pnpm run build</code> first.</p></body></html>");
@@ -78401,6 +78563,15 @@ function unregisterMcpServerFromClaudeJson(projectPath) {
78401
78563
  } catch {}
78402
78564
  }
78403
78565
  async function main() {
78566
+ if (process.argv.includes("--list")) {
78567
+ const dashboards = await listRunningDashboards();
78568
+ if (dashboards.length === 0) console.log("No running MAXSIM dashboards found.");
78569
+ else {
78570
+ console.log("Running MAXSIM dashboards:");
78571
+ for (const d of dashboards) console.log(` Port ${d.port} → ${d.cwd} (uptime: ${Math.round(d.uptime)}s)`);
78572
+ }
78573
+ process.exit(0);
78574
+ }
78404
78575
  let autoShutdownTimer = null;
78405
78576
  const wss = createWSS((count) => {
78406
78577
  if (count > 0) {
@@ -78419,22 +78590,46 @@ async function main() {
78419
78590
  log("INFO", "server", `Auto-shutdown scheduled in ${AUTO_SHUTDOWN_DELAY_MS / 1e3}s (no clients)`);
78420
78591
  }
78421
78592
  });
78422
- const mcpServer = createMcpServer({
78593
+ const mcpDeps = {
78423
78594
  wss,
78424
78595
  questionQueue,
78425
78596
  pendingAnswers,
78426
78597
  currentLifecycleState,
78598
+ conversations,
78427
78599
  broadcast
78428
- });
78600
+ };
78429
78601
  app.post("/mcp", async (req, res) => {
78430
- const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: void 0 });
78431
- await mcpServer.connect(transport);
78432
- await transport.handleRequest(req, res, req.body);
78602
+ const mcpServer = createMcpServer(mcpDeps);
78603
+ try {
78604
+ const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: void 0 });
78605
+ await mcpServer.connect(transport);
78606
+ await transport.handleRequest(req, res, req.body);
78607
+ res.on("close", () => {
78608
+ transport.close();
78609
+ mcpServer.close();
78610
+ });
78611
+ } catch (error) {
78612
+ log("ERROR", "mcp", "Error handling MCP POST request:", error);
78613
+ if (!res.headersSent) res.status(500).json({
78614
+ jsonrpc: "2.0",
78615
+ error: {
78616
+ code: -32603,
78617
+ message: "Internal server error"
78618
+ },
78619
+ id: null
78620
+ });
78621
+ }
78433
78622
  });
78434
78623
  app.get("/mcp", async (req, res) => {
78435
- const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: void 0 });
78436
- await mcpServer.connect(transport);
78437
- await transport.handleRequest(req, res);
78624
+ log("INFO", "mcp", "Received GET /mcp method not allowed in stateless mode");
78625
+ res.writeHead(405).end(JSON.stringify({
78626
+ jsonrpc: "2.0",
78627
+ error: {
78628
+ code: -32e3,
78629
+ message: "Method not allowed."
78630
+ },
78631
+ id: null
78632
+ }));
78438
78633
  });
78439
78634
  app.delete("/mcp", (_req, res) => {
78440
78635
  res.status(200).end();
@@ -78538,11 +78733,12 @@ async function main() {
78538
78733
  } catch (err) {
78539
78734
  console.error("[server] Failed to start file watcher:", err.message);
78540
78735
  }
78541
- const port = await esm_default(3333);
78736
+ const port = await esm_default(projectPort(projectCwd));
78542
78737
  resolvedPort = port;
78543
78738
  const localUrl = `http://localhost:${port}`;
78544
78739
  const bindHost = networkMode || tailscaleIp !== null ? "0.0.0.0" : "127.0.0.1";
78545
78740
  server.listen(port, bindHost, () => {
78741
+ serverReady = true;
78546
78742
  log("INFO", "server", `Dashboard ready at ${localUrl}, log file: ${logFile}`);
78547
78743
  console.error(`Dashboard ready at ${localUrl}`);
78548
78744
  if (localNetworkIp) console.error(`LAN URL: http://${localNetworkIp}:${port}`);