maxsimcli 4.7.0 → 4.7.1

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.
@@ -26771,17 +26771,12 @@ const isSummaryFile = (f) => f.endsWith("-SUMMARY.md") || f === "SUMMARY.md";
26771
26771
  const planId = (f) => f.replace("-PLAN.md", "").replace("PLAN.md", "");
26772
26772
  const summaryId = (f) => f.replace("-SUMMARY.md", "").replace("SUMMARY.md", "");
26773
26773
  /** List subdirectory names, optionally sorted by phase number. */
26774
- function listSubDirs(dir, sortByPhase = false) {
26775
- const dirs = node_fs.default.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
26776
- return sortByPhase ? dirs.sort((a, b) => comparePhaseNum(a, b)) : dirs;
26777
- }
26778
- /** Async version of listSubDirs using fs.promises. */
26779
- async function listSubDirsAsync(dir, sortByPhase = false) {
26774
+ async function listSubDirs(dir, sortByPhase = false) {
26780
26775
  const dirs = (await node_fs.promises.readdir(dir, { withFileTypes: true })).filter((e) => e.isDirectory()).map((e) => e.name);
26781
26776
  return sortByPhase ? dirs.sort((a, b) => comparePhaseNum(a, b)) : dirs;
26782
26777
  }
26783
- /** Async version of safeReadFile using fs.promises. */
26784
- async function safeReadFileAsync(filePath) {
26778
+ /** Read a file, returning null if it doesn't exist or fails. */
26779
+ async function safeReadFile(filePath) {
26785
26780
  try {
26786
26781
  return await node_fs.promises.readFile(filePath, "utf-8");
26787
26782
  } catch {
@@ -26802,15 +26797,65 @@ function debugLog(contextOrError, error) {
26802
26797
  function escapePhaseNum(phase) {
26803
26798
  return String(phase).replace(/\./g, "\\.");
26804
26799
  }
26805
- function safeReadFile(filePath) {
26800
+ let _configCache = null;
26801
+ function normalizePhaseName(phase) {
26802
+ const match = phase.match(/^(\d+)([A-Z])?(\.\d+)?/i);
26803
+ if (!match) return phase;
26804
+ const padded = match[1].padStart(2, "0");
26805
+ const letter = match[2] ? match[2].toUpperCase() : "";
26806
+ const decimal = match[3] || "";
26807
+ return padded + letter + decimal;
26808
+ }
26809
+ function comparePhaseNum(a, b) {
26810
+ const pa = String(a).match(/^(\d+)([A-Z])?(\.\d+)?/i);
26811
+ const pb = String(b).match(/^(\d+)([A-Z])?(\.\d+)?/i);
26812
+ if (!pa || !pb) return String(a).localeCompare(String(b));
26813
+ const intDiff = parseInt(pa[1], 10) - parseInt(pb[1], 10);
26814
+ if (intDiff !== 0) return intDiff;
26815
+ const la = (pa[2] || "").toUpperCase();
26816
+ const lb = (pb[2] || "").toUpperCase();
26817
+ if (la !== lb) {
26818
+ if (!la) return -1;
26819
+ if (!lb) return 1;
26820
+ return la < lb ? -1 : 1;
26821
+ }
26822
+ return (pa[3] ? parseFloat(pa[3]) : -1) - (pb[3] ? parseFloat(pb[3]) : -1);
26823
+ }
26824
+ /**
26825
+ * Returns the canonical regex for matching Phase heading lines in ROADMAP.md.
26826
+ *
26827
+ * General form (no escapedPhaseNum):
26828
+ * Matches: ## Phase 03: Name Here
26829
+ * Group 1: phase number string (e.g. "03", "3A", "2.1")
26830
+ * Group 2: phase name string (e.g. "Name Here")
26831
+ *
26832
+ * Specific form (with escapedPhaseNum):
26833
+ * Matches: ## Phase 03: Name Here
26834
+ * Group 1: phase name string only
26835
+ *
26836
+ * @param escapedPhaseNum - regex-escaped phase number string to match a specific phase
26837
+ * @param flags - regex flags (default: 'gi')
26838
+ */
26839
+ function getPhasePattern(escapedPhaseNum, flags = "gim") {
26840
+ if (escapedPhaseNum) return new RegExp(`^#{2,4}\\s*Phase\\s+${escapedPhaseNum}:\\s*([^\\n]+)`, flags);
26841
+ return new RegExp(`^#{2,4}\\s*Phase\\s+(\\d+[A-Z]?(?:\\.\\d+)?)\\s*:\\s*([^\\n]+)`, flags);
26842
+ }
26843
+ function generateSlugInternal(text) {
26844
+ if (!text) return null;
26845
+ return (0, import_slugify.default)(text, {
26846
+ lower: true,
26847
+ strict: true
26848
+ });
26849
+ }
26850
+ async function pathExistsInternal(p) {
26806
26851
  try {
26807
- return node_fs.default.readFileSync(filePath, "utf-8");
26852
+ await node_fs.promises.access(p);
26853
+ return true;
26808
26854
  } catch {
26809
- return null;
26855
+ return false;
26810
26856
  }
26811
26857
  }
26812
- let _configCache = null;
26813
- function loadConfig(cwd) {
26858
+ async function loadConfig(cwd) {
26814
26859
  if (_configCache && _configCache.cwd === cwd) return _configCache.config;
26815
26860
  const cfgPath = configPath(cwd);
26816
26861
  const defaults = {
@@ -26827,7 +26872,7 @@ function loadConfig(cwd) {
26827
26872
  brave_search: false
26828
26873
  };
26829
26874
  try {
26830
- const raw = node_fs.default.readFileSync(cfgPath, "utf-8");
26875
+ const raw = await node_fs.promises.readFile(cfgPath, "utf-8");
26831
26876
  const parsed = JSON.parse(raw);
26832
26877
  const get = (key, nested) => {
26833
26878
  if (parsed[key] !== void 0) return parsed[key];
@@ -26889,7 +26934,7 @@ function loadConfig(cwd) {
26889
26934
  };
26890
26935
  return result;
26891
26936
  } catch (e) {
26892
- if (node_fs.default.existsSync(cfgPath)) {
26937
+ if (await pathExistsInternal(cfgPath)) {
26893
26938
  console.warn(`[maxsim] Warning: config.json exists but could not be parsed — using defaults.`);
26894
26939
  debugLog("config-load-failed", e);
26895
26940
  }
@@ -26900,57 +26945,15 @@ function loadConfig(cwd) {
26900
26945
  return defaults;
26901
26946
  }
26902
26947
  }
26903
- function normalizePhaseName(phase) {
26904
- const match = phase.match(/^(\d+)([A-Z])?(\.\d+)?/i);
26905
- if (!match) return phase;
26906
- const padded = match[1].padStart(2, "0");
26907
- const letter = match[2] ? match[2].toUpperCase() : "";
26908
- const decimal = match[3] || "";
26909
- return padded + letter + decimal;
26910
- }
26911
- function comparePhaseNum(a, b) {
26912
- const pa = String(a).match(/^(\d+)([A-Z])?(\.\d+)?/i);
26913
- const pb = String(b).match(/^(\d+)([A-Z])?(\.\d+)?/i);
26914
- if (!pa || !pb) return String(a).localeCompare(String(b));
26915
- const intDiff = parseInt(pa[1], 10) - parseInt(pb[1], 10);
26916
- if (intDiff !== 0) return intDiff;
26917
- const la = (pa[2] || "").toUpperCase();
26918
- const lb = (pb[2] || "").toUpperCase();
26919
- if (la !== lb) {
26920
- if (!la) return -1;
26921
- if (!lb) return 1;
26922
- return la < lb ? -1 : 1;
26923
- }
26924
- return (pa[3] ? parseFloat(pa[3]) : -1) - (pb[3] ? parseFloat(pb[3]) : -1);
26925
- }
26926
- /**
26927
- * Returns the canonical regex for matching Phase heading lines in ROADMAP.md.
26928
- *
26929
- * General form (no escapedPhaseNum):
26930
- * Matches: ## Phase 03: Name Here
26931
- * Group 1: phase number string (e.g. "03", "3A", "2.1")
26932
- * Group 2: phase name string (e.g. "Name Here")
26933
- *
26934
- * Specific form (with escapedPhaseNum):
26935
- * Matches: ## Phase 03: Name Here
26936
- * Group 1: phase name string only
26937
- *
26938
- * @param escapedPhaseNum - regex-escaped phase number string to match a specific phase
26939
- * @param flags - regex flags (default: 'gi')
26940
- */
26941
- function getPhasePattern(escapedPhaseNum, flags = "gim") {
26942
- if (escapedPhaseNum) return new RegExp(`^#{2,4}\\s*Phase\\s+${escapedPhaseNum}:\\s*([^\\n]+)`, flags);
26943
- return new RegExp(`^#{2,4}\\s*Phase\\s+(\\d+[A-Z]?(?:\\.\\d+)?)\\s*:\\s*([^\\n]+)`, flags);
26944
- }
26945
- function searchPhaseInDir(baseDir, relBase, normalized) {
26948
+ async function searchPhaseInDir(baseDir, relBase, normalized) {
26946
26949
  try {
26947
- const match = listSubDirs(baseDir, true).find((d) => d.startsWith(normalized));
26950
+ const match = (await listSubDirs(baseDir, true)).find((d) => d.startsWith(normalized));
26948
26951
  if (!match) return null;
26949
26952
  const dirMatch = match.match(/^(\d+[A-Z]?(?:\.\d+)?)-?(.*)/i);
26950
26953
  const phaseNumber = dirMatch ? dirMatch[1] : normalized;
26951
26954
  const phaseName = dirMatch && dirMatch[2] ? dirMatch[2] : null;
26952
26955
  const phaseDir = node_path.default.join(baseDir, match);
26953
- const phaseFiles = node_fs.default.readdirSync(phaseDir);
26956
+ const phaseFiles = await node_fs.promises.readdir(phaseDir);
26954
26957
  const plans = phaseFiles.filter(isPlanFile).sort();
26955
26958
  const summaries = phaseFiles.filter(isSummaryFile).sort();
26956
26959
  const hasResearch = phaseFiles.some((f) => f.endsWith("-RESEARCH.md") || f === "RESEARCH.md");
@@ -26972,7 +26975,7 @@ function searchPhaseInDir(baseDir, relBase, normalized) {
26972
26975
  has_verification: hasVerification
26973
26976
  };
26974
26977
  } catch (e) {
26975
- debugLog("search-phase-in-dir-failed", {
26978
+ debugLog("search-phase-in-dir-async-failed", {
26976
26979
  dir: baseDir,
26977
26980
  phase: normalized,
26978
26981
  error: errorMsg(e)
@@ -26980,148 +26983,82 @@ function searchPhaseInDir(baseDir, relBase, normalized) {
26980
26983
  return null;
26981
26984
  }
26982
26985
  }
26983
- function findPhaseInternal(cwd, phase) {
26986
+ async function findPhaseInternal(cwd, phase) {
26984
26987
  if (!phase) return null;
26985
26988
  const pd = phasesPath(cwd);
26986
26989
  const normalized = normalizePhaseName(phase);
26987
- const current = searchPhaseInDir(pd, node_path.default.join(".planning", "phases"), normalized);
26990
+ const current = await searchPhaseInDir(pd, node_path.default.join(".planning", "phases"), normalized);
26988
26991
  if (current) return current;
26989
- const milestonesDir = planningPath(cwd, "milestones");
26990
- try {
26991
- node_fs.default.statSync(milestonesDir);
26992
- } catch {
26993
- return null;
26992
+ const archiveDir = planningPath(cwd, "archive");
26993
+ if (await pathExistsInternal(archiveDir)) try {
26994
+ const versionDirs = (await node_fs.promises.readdir(archiveDir, { withFileTypes: true })).filter((e) => e.isDirectory()).map((e) => e.name).sort().reverse();
26995
+ for (const versionName of versionDirs) {
26996
+ const result = await searchPhaseInDir(node_path.default.join(archiveDir, versionName), node_path.default.join(".planning", "archive", versionName), normalized);
26997
+ if (result) {
26998
+ result.archived = versionName;
26999
+ return result;
27000
+ }
27001
+ }
27002
+ } catch (e) {
27003
+ debugLog("find-phase-async-archive-search-failed", e);
26994
27004
  }
27005
+ const milestonesDir = planningPath(cwd, "milestones");
27006
+ if (!await pathExistsInternal(milestonesDir)) return null;
26995
27007
  try {
26996
- const archiveDirs = node_fs.default.readdirSync(milestonesDir, { withFileTypes: true }).filter((e) => e.isDirectory() && /^v[\d.]+-phases$/.test(e.name)).map((e) => e.name).sort().reverse();
27008
+ const archiveDirs = (await node_fs.promises.readdir(milestonesDir, { withFileTypes: true })).filter((e) => e.isDirectory() && /^v[\d.]+-phases$/.test(e.name)).map((e) => e.name).sort().reverse();
26997
27009
  for (const archiveName of archiveDirs) {
26998
27010
  const versionMatch = archiveName.match(/^(v[\d.]+)-phases$/);
26999
27011
  if (!versionMatch) continue;
27000
27012
  const version = versionMatch[1];
27001
- const result = searchPhaseInDir(node_path.default.join(milestonesDir, archiveName), node_path.default.join(".planning", "milestones", archiveName), normalized);
27013
+ const result = await searchPhaseInDir(node_path.default.join(milestonesDir, archiveName), node_path.default.join(".planning", "milestones", archiveName), normalized);
27002
27014
  if (result) {
27003
27015
  result.archived = version;
27004
27016
  return result;
27005
27017
  }
27006
27018
  }
27007
27019
  } catch (e) {
27008
- debugLog("find-phase-milestone-search-failed", e);
27020
+ debugLog("find-phase-async-milestone-search-failed", e);
27009
27021
  }
27010
27022
  return null;
27011
27023
  }
27012
- function getArchivedPhaseDirs(cwd) {
27013
- const milestonesDir = planningPath(cwd, "milestones");
27024
+ async function getArchivedPhaseDirs(cwd) {
27014
27025
  const results = [];
27026
+ const archiveDir = planningPath(cwd, "archive");
27015
27027
  try {
27016
- const phaseDirs = node_fs.default.readdirSync(milestonesDir, { withFileTypes: true }).filter((e) => e.isDirectory() && /^v[\d.]+-phases$/.test(e.name)).map((e) => e.name).sort().reverse();
27017
- for (const archiveName of phaseDirs) {
27018
- const versionMatch = archiveName.match(/^(v[\d.]+)-phases$/);
27019
- if (!versionMatch) continue;
27020
- const version = versionMatch[1];
27021
- const archivePath = node_path.default.join(milestonesDir, archiveName);
27022
- const dirs = listSubDirs(archivePath, true);
27028
+ const versionDirs = (await node_fs.promises.readdir(archiveDir, { withFileTypes: true })).filter((e) => e.isDirectory()).map((e) => e.name).sort().reverse();
27029
+ for (const versionName of versionDirs) {
27030
+ const versionPath = node_path.default.join(archiveDir, versionName);
27031
+ const dirs = await listSubDirs(versionPath, true);
27023
27032
  for (const dir of dirs) results.push({
27024
27033
  name: dir,
27025
- milestone: version,
27026
- basePath: node_path.default.join(".planning", "milestones", archiveName),
27027
- fullPath: node_path.default.join(archivePath, dir)
27034
+ milestone: versionName,
27035
+ basePath: node_path.default.join(".planning", "archive", versionName),
27036
+ fullPath: node_path.default.join(versionPath, dir)
27028
27037
  });
27029
27038
  }
27030
27039
  } catch (e) {
27031
- debugLog("get-archived-phase-dirs-failed", e);
27032
- }
27033
- return results;
27034
- }
27035
- function generateSlugInternal(text) {
27036
- if (!text) return null;
27037
- return (0, import_slugify.default)(text, {
27038
- lower: true,
27039
- strict: true
27040
- });
27041
- }
27042
- async function pathExistsAsync(p) {
27043
- try {
27044
- await node_fs.promises.access(p);
27045
- return true;
27046
- } catch {
27047
- return false;
27048
- }
27049
- }
27050
- async function searchPhaseInDirAsync(baseDir, relBase, normalized) {
27051
- try {
27052
- const match = (await listSubDirsAsync(baseDir, true)).find((d) => d.startsWith(normalized));
27053
- if (!match) return null;
27054
- const dirMatch = match.match(/^(\d+[A-Z]?(?:\.\d+)?)-?(.*)/i);
27055
- const phaseNumber = dirMatch ? dirMatch[1] : normalized;
27056
- const phaseName = dirMatch && dirMatch[2] ? dirMatch[2] : null;
27057
- const phaseDir = node_path.default.join(baseDir, match);
27058
- const phaseFiles = await node_fs.promises.readdir(phaseDir);
27059
- const plans = phaseFiles.filter(isPlanFile).sort();
27060
- const summaries = phaseFiles.filter(isSummaryFile).sort();
27061
- const hasResearch = phaseFiles.some((f) => f.endsWith("-RESEARCH.md") || f === "RESEARCH.md");
27062
- const hasContext = phaseFiles.some((f) => f.endsWith("-CONTEXT.md") || f === "CONTEXT.md");
27063
- const hasVerification = phaseFiles.some((f) => f.endsWith("-VERIFICATION.md") || f === "VERIFICATION.md");
27064
- const completedPlanIds = new Set(summaries.map(summaryId));
27065
- const incompletePlans = plans.filter((p) => !completedPlanIds.has(planId(p)));
27066
- return {
27067
- found: true,
27068
- directory: node_path.default.join(relBase, match),
27069
- phase_number: phaseNumber,
27070
- phase_name: phaseName,
27071
- phase_slug: phaseName ? phaseName.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") : null,
27072
- plans,
27073
- summaries,
27074
- incomplete_plans: incompletePlans,
27075
- has_research: hasResearch,
27076
- has_context: hasContext,
27077
- has_verification: hasVerification
27078
- };
27079
- } catch (e) {
27080
- debugLog("search-phase-in-dir-async-failed", {
27081
- dir: baseDir,
27082
- phase: normalized,
27083
- error: errorMsg(e)
27084
- });
27085
- return null;
27086
- }
27087
- }
27088
- async function findPhaseInternalAsync(cwd, phase) {
27089
- if (!phase) return null;
27090
- const pd = phasesPath(cwd);
27091
- const normalized = normalizePhaseName(phase);
27092
- const current = await searchPhaseInDirAsync(pd, node_path.default.join(".planning", "phases"), normalized);
27093
- if (current) return current;
27094
- const archiveDir = planningPath(cwd, "archive");
27095
- if (await pathExistsAsync(archiveDir)) try {
27096
- const versionDirs = (await node_fs.promises.readdir(archiveDir, { withFileTypes: true })).filter((e) => e.isDirectory()).map((e) => e.name).sort().reverse();
27097
- for (const versionName of versionDirs) {
27098
- const result = await searchPhaseInDirAsync(node_path.default.join(archiveDir, versionName), node_path.default.join(".planning", "archive", versionName), normalized);
27099
- if (result) {
27100
- result.archived = versionName;
27101
- return result;
27102
- }
27103
- }
27104
- } catch (e) {
27105
- debugLog("find-phase-async-archive-search-failed", e);
27040
+ debugLog("get-archived-phase-dirs-async-archive-failed", e);
27106
27041
  }
27107
27042
  const milestonesDir = planningPath(cwd, "milestones");
27108
- if (!await pathExistsAsync(milestonesDir)) return null;
27109
27043
  try {
27110
- const archiveDirs = (await node_fs.promises.readdir(milestonesDir, { withFileTypes: true })).filter((e) => e.isDirectory() && /^v[\d.]+-phases$/.test(e.name)).map((e) => e.name).sort().reverse();
27111
- for (const archiveName of archiveDirs) {
27044
+ const phaseDirs = (await node_fs.promises.readdir(milestonesDir, { withFileTypes: true })).filter((e) => e.isDirectory() && /^v[\d.]+-phases$/.test(e.name)).map((e) => e.name).sort().reverse();
27045
+ for (const archiveName of phaseDirs) {
27112
27046
  const versionMatch = archiveName.match(/^(v[\d.]+)-phases$/);
27113
27047
  if (!versionMatch) continue;
27114
27048
  const version = versionMatch[1];
27115
- const result = await searchPhaseInDirAsync(node_path.default.join(milestonesDir, archiveName), node_path.default.join(".planning", "milestones", archiveName), normalized);
27116
- if (result) {
27117
- result.archived = version;
27118
- return result;
27119
- }
27049
+ const archiveMilestonePath = node_path.default.join(milestonesDir, archiveName);
27050
+ const dirs = await listSubDirs(archiveMilestonePath, true);
27051
+ for (const dir of dirs) results.push({
27052
+ name: dir,
27053
+ milestone: version,
27054
+ basePath: node_path.default.join(".planning", "milestones", archiveName),
27055
+ fullPath: node_path.default.join(archiveMilestonePath, dir)
27056
+ });
27120
27057
  }
27121
27058
  } catch (e) {
27122
- debugLog("find-phase-async-milestone-search-failed", e);
27059
+ debugLog("get-archived-phase-dirs-async-failed", e);
27123
27060
  }
27124
- return null;
27061
+ return results;
27125
27062
  }
27126
27063
 
27127
27064
  //#endregion
@@ -33862,7 +33799,7 @@ async function phaseInsertCore(cwd, afterPhase, description, options) {
33862
33799
  const normalizedBase = normalizePhaseName(afterPhase);
33863
33800
  const existingDecimals = [];
33864
33801
  try {
33865
- const dirs = await listSubDirsAsync(phasesDirPath);
33802
+ const dirs = await listSubDirs(phasesDirPath);
33866
33803
  const decimalPattern = new RegExp(`^${normalizedBase}\\.(\\d+)`);
33867
33804
  for (const dir of dirs) {
33868
33805
  const dm = dir.match(decimalPattern);
@@ -33901,12 +33838,12 @@ async function phaseCompleteCore(cwd, phaseNum) {
33901
33838
  const stPath = statePath(cwd);
33902
33839
  const phasesDirPath = phasesPath(cwd);
33903
33840
  const today = todayISO();
33904
- const phaseInfo = await findPhaseInternalAsync(cwd, phaseNum);
33841
+ const phaseInfo = await findPhaseInternal(cwd, phaseNum);
33905
33842
  if (!phaseInfo) throw new Error(`Phase ${phaseNum} not found`);
33906
33843
  const planCount = phaseInfo.plans.length;
33907
33844
  const summaryCount = phaseInfo.summaries.length;
33908
33845
  let requirementsUpdated = false;
33909
- const rmExists = await pathExistsAsync(rmPath);
33846
+ const rmExists = await pathExistsInternal(rmPath);
33910
33847
  if (rmExists) {
33911
33848
  let roadmapContent = await node_fs.promises.readFile(rmPath, "utf-8");
33912
33849
  const checkboxPattern = new RegExp(`(-\\s*\\[)[ ](\\]\\s*.*Phase\\s+${escapePhaseNum(phaseNum)}[:\\s][^\\n]*)`, "i");
@@ -33920,7 +33857,7 @@ async function phaseCompleteCore(cwd, phaseNum) {
33920
33857
  await node_fs.promises.writeFile(rmPath, roadmapContent, "utf-8");
33921
33858
  debugLog("phase-complete-write", `ROADMAP.md updated for phase ${phaseNum}`);
33922
33859
  const reqPath = planningPath(cwd, "REQUIREMENTS.md");
33923
- if (await pathExistsAsync(reqPath)) {
33860
+ if (await pathExistsInternal(reqPath)) {
33924
33861
  const reqMatch = roadmapContent.match(new RegExp(`Phase\\s+${escapePhaseNum(phaseNum)}[\\s\\S]*?\\*\\*Requirements:\\*\\*\\s*([^\\n]+)`, "i"));
33925
33862
  if (reqMatch) {
33926
33863
  const reqIds = reqMatch[1].replace(/[\[\]]/g, "").split(/[,\s]+/).map((r) => r.trim()).filter(Boolean);
@@ -33940,7 +33877,7 @@ async function phaseCompleteCore(cwd, phaseNum) {
33940
33877
  let nextPhaseName = null;
33941
33878
  let isLastPhase = true;
33942
33879
  try {
33943
- const dirs = await listSubDirsAsync(phasesDirPath, true);
33880
+ const dirs = await listSubDirs(phasesDirPath, true);
33944
33881
  for (const dir of dirs) {
33945
33882
  const dm = dir.match(/^(\d+[A-Z]?(?:\.\d+)?)-?(.*)/i);
33946
33883
  if (dm) {
@@ -33955,7 +33892,7 @@ async function phaseCompleteCore(cwd, phaseNum) {
33955
33892
  } catch (e) {
33956
33893
  debugLog("phase-complete-next-phase-scan-failed", e);
33957
33894
  }
33958
- const stExists = await pathExistsAsync(stPath);
33895
+ const stExists = await pathExistsInternal(stPath);
33959
33896
  if (stExists) {
33960
33897
  let stateContent = await node_fs.promises.readFile(stPath, "utf-8");
33961
33898
  stateContent = stateContent.replace(/(\*\*Current Phase:\*\*\s*).*/, `$1${nextPhaseNum || phaseNum}`);
@@ -35523,7 +35460,7 @@ function registerPhaseTools(server) {
35523
35460
  try {
35524
35461
  const cwd = detectProjectRoot();
35525
35462
  if (!cwd) return mcpError("No .planning/ directory found", "Project not detected");
35526
- const result = findPhaseInternal(cwd, phase);
35463
+ const result = await findPhaseInternal(cwd, phase);
35527
35464
  if (!result) return mcpError(`Phase ${phase} not found`, "Phase not found");
35528
35465
  let githubTracking = null;
35529
35466
  let githubTaskIssues = null;
@@ -35588,9 +35525,9 @@ function registerPhaseTools(server) {
35588
35525
  limit,
35589
35526
  has_more: false
35590
35527
  }, "No phases directory found");
35591
- let dirs = listSubDirs(phasesDir);
35528
+ let dirs = await listSubDirs(phasesDir);
35592
35529
  if (include_archived) {
35593
- const archived = getArchivedPhaseDirs(cwd);
35530
+ const archived = await getArchivedPhaseDirs(cwd);
35594
35531
  for (const a of archived) dirs.push(`${a.name} [${a.milestone}]`);
35595
35532
  }
35596
35533
  dirs.sort((a, b) => comparePhaseNum(a, b));
@@ -36297,7 +36234,7 @@ function registerStateTools(server) {
36297
36234
  * Ported from maxsim/bin/lib/roadmap.cjs
36298
36235
  */
36299
36236
  async function cmdRoadmapAnalyze(cwd) {
36300
- const content = await safeReadFileAsync(roadmapPath(cwd));
36237
+ const content = await safeReadFile(roadmapPath(cwd));
36301
36238
  if (!content) return cmdOk({
36302
36239
  error: "ROADMAP.md not found",
36303
36240
  milestones: [],
@@ -36330,7 +36267,7 @@ async function cmdRoadmapAnalyze(cwd) {
36330
36267
  }
36331
36268
  let allDirs = [];
36332
36269
  try {
36333
- allDirs = await listSubDirsAsync(phasesDir);
36270
+ allDirs = await listSubDirs(phasesDir);
36334
36271
  } catch {}
36335
36272
  const phases = await Promise.all(parsedPhases.map(async (p) => {
36336
36273
  let diskStatus = "no_directory";
@@ -36470,9 +36407,9 @@ function loadRoadmapContext(cwd) {
36470
36407
  addIfExists(files, cwd, ".planning/ROADMAP.md", "roadmap");
36471
36408
  return files;
36472
36409
  }
36473
- function loadPhaseContext(cwd, phase) {
36410
+ async function loadPhaseContext(cwd, phase) {
36474
36411
  const files = [];
36475
- const phaseInfo = findPhaseInternal(cwd, phase);
36412
+ const phaseInfo = await findPhaseInternal(cwd, phase);
36476
36413
  if (!phaseInfo?.directory) return files;
36477
36414
  const phaseDir = phaseInfo.directory;
36478
36415
  try {
@@ -36490,7 +36427,7 @@ function loadPhaseContext(cwd, phase) {
36490
36427
  }
36491
36428
  return files;
36492
36429
  }
36493
- function loadArtefakteContext(cwd, phase) {
36430
+ async function loadArtefakteContext(cwd, phase) {
36494
36431
  const files = [];
36495
36432
  for (const filename of [
36496
36433
  "DECISIONS.md",
@@ -36498,7 +36435,7 @@ function loadArtefakteContext(cwd, phase) {
36498
36435
  "NO-GOS.md"
36499
36436
  ]) {
36500
36437
  if (phase) {
36501
- const phaseInfo = findPhaseInternal(cwd, phase);
36438
+ const phaseInfo = await findPhaseInternal(cwd, phase);
36502
36439
  if (phaseInfo?.directory) addIfExists(files, cwd, node_path.default.join(phaseInfo.directory, filename), `artefakt-${filename.toLowerCase()}`);
36503
36440
  }
36504
36441
  addIfExists(files, cwd, `.planning/${filename}`, `artefakt-${filename.toLowerCase()}`);
@@ -36515,11 +36452,11 @@ function loadCodebaseContext(cwd, topic) {
36515
36452
  } catch {}
36516
36453
  return files;
36517
36454
  }
36518
- function loadHistoryContext(cwd, currentPhase) {
36455
+ async function loadHistoryContext(cwd, currentPhase) {
36519
36456
  const files = [];
36520
36457
  const pd = phasesPath(cwd);
36521
36458
  try {
36522
- const dirs = listSubDirs(pd, true);
36459
+ const dirs = await listSubDirs(pd, true);
36523
36460
  for (const dir of dirs) {
36524
36461
  if (currentPhase) {
36525
36462
  if (dir.match(/^(\d+[A-Z]?(?:\.\d+)?)/i)?.[1] === currentPhase) continue;
@@ -36533,15 +36470,15 @@ function loadHistoryContext(cwd, currentPhase) {
36533
36470
  }
36534
36471
  return files;
36535
36472
  }
36536
- function cmdContextLoad(cwd, phase, topic, includeHistory) {
36473
+ async function cmdContextLoad(cwd, phase, topic, includeHistory) {
36537
36474
  const allFiles = [];
36538
36475
  allFiles.push(...loadProjectContext(cwd));
36539
36476
  allFiles.push(...loadRoadmapContext(cwd));
36540
- allFiles.push(...loadArtefakteContext(cwd, phase));
36477
+ allFiles.push(...await loadArtefakteContext(cwd, phase));
36541
36478
  const selectedDocs = selectCodebaseDocs(topic);
36542
36479
  allFiles.push(...loadCodebaseContext(cwd, topic));
36543
- if (phase) allFiles.push(...loadPhaseContext(cwd, phase));
36544
- if (includeHistory) allFiles.push(...loadHistoryContext(cwd, phase));
36480
+ if (phase) allFiles.push(...await loadPhaseContext(cwd, phase));
36481
+ if (includeHistory) allFiles.push(...await loadHistoryContext(cwd, phase));
36545
36482
  const seen = /* @__PURE__ */ new Set();
36546
36483
  const deduped = allFiles.filter((f) => {
36547
36484
  if (seen.has(f.path)) return false;
@@ -36584,7 +36521,7 @@ function registerContextTools(server) {
36584
36521
  current_phase = data.current_phase ?? null;
36585
36522
  next_phase = data.next_phase ?? null;
36586
36523
  }
36587
- const stateContent = safeReadFile(planningPath(cwd, "STATE.md"));
36524
+ const stateContent = await safeReadFile(planningPath(cwd, "STATE.md"));
36588
36525
  if (stateContent) {
36589
36526
  const statePhase = stateExtractField(stateContent, "Current Phase");
36590
36527
  if (statePhase) phase_name = statePhase;
@@ -36605,12 +36542,12 @@ function registerContextTools(server) {
36605
36542
  try {
36606
36543
  const cwd = detectProjectRoot();
36607
36544
  if (!cwd) return mcpError("No .planning/ directory found", "Project not detected");
36608
- const project_vision = safeReadFile(planningPath(cwd, "PROJECT.md"));
36609
- const config = loadConfig(cwd);
36545
+ const project_vision = await safeReadFile(planningPath(cwd, "PROJECT.md"));
36546
+ const config = await loadConfig(cwd);
36610
36547
  let phase_context = null;
36611
36548
  if (phase) {
36612
- const phaseInfo = findPhaseInternal(cwd, phase);
36613
- if (phaseInfo) phase_context = safeReadFile(node_path.default.join(phaseInfo.directory, `${phaseInfo.phase_number}-CONTEXT.md`));
36549
+ const phaseInfo = await findPhaseInternal(cwd, phase);
36550
+ if (phaseInfo) phase_context = await safeReadFile(node_path.default.join(phaseInfo.directory, `${phaseInfo.phase_number}-CONTEXT.md`));
36614
36551
  }
36615
36552
  return mcpSuccess({
36616
36553
  project_vision,
@@ -36628,7 +36565,7 @@ function registerContextTools(server) {
36628
36565
  try {
36629
36566
  const cwd = detectProjectRoot();
36630
36567
  if (!cwd) return mcpError("No .planning/ directory found", "Project not detected");
36631
- const result = cmdContextLoad(cwd, phase, topic, true);
36568
+ const result = await cmdContextLoad(cwd, phase, topic, true);
36632
36569
  if (!result.ok) return mcpError(result.error, "Context load failed");
36633
36570
  return mcpSuccess({ context: result.result }, `Context loaded${phase ? ` for phase ${phase}` : ""}${topic ? ` topic "${topic}"` : ""}`);
36634
36571
  } catch (e) {
@@ -36640,9 +36577,9 @@ function registerContextTools(server) {
36640
36577
  const cwd = detectProjectRoot();
36641
36578
  if (!cwd) return mcpError("No .planning/ directory found", "Project not detected");
36642
36579
  return mcpSuccess({
36643
- project: safeReadFile(planningPath(cwd, "PROJECT.md")),
36644
- requirements: safeReadFile(planningPath(cwd, "REQUIREMENTS.md")),
36645
- state: safeReadFile(planningPath(cwd, "STATE.md"))
36580
+ project: await safeReadFile(planningPath(cwd, "PROJECT.md")),
36581
+ requirements: await safeReadFile(planningPath(cwd, "REQUIREMENTS.md")),
36582
+ state: await safeReadFile(planningPath(cwd, "STATE.md"))
36646
36583
  }, "Project overview loaded");
36647
36584
  } catch (e) {
36648
36585
  return mcpError("Failed: " + e.message, "Error occurred");
@@ -36652,7 +36589,7 @@ function registerContextTools(server) {
36652
36589
  try {
36653
36590
  const cwd = detectProjectRoot();
36654
36591
  if (!cwd) return mcpError("No .planning/ directory found", "Project not detected");
36655
- const phaseInfo = findPhaseInternal(cwd, phase);
36592
+ const phaseInfo = await findPhaseInternal(cwd, phase);
36656
36593
  if (!phaseInfo) return mcpError(`Phase ${phase} not found`, "Phase not found");
36657
36594
  const files = [];
36658
36595
  try {
@@ -36661,7 +36598,7 @@ function registerContextTools(server) {
36661
36598
  const fullPath = node_path.default.join(phaseInfo.directory, entry);
36662
36599
  if (node_fs.default.statSync(fullPath).isFile()) files.push({
36663
36600
  name: entry,
36664
- content: safeReadFile(fullPath)
36601
+ content: await safeReadFile(fullPath)
36665
36602
  });
36666
36603
  }
36667
36604
  } catch {}
@@ -36812,7 +36749,7 @@ function registerConfigTools(server) {
36812
36749
  value: result.rawValue ?? result.result
36813
36750
  }, `Config value for "${key}"`);
36814
36751
  }
36815
- return mcpSuccess({ config: loadConfig(cwd) }, "Full configuration loaded");
36752
+ return mcpSuccess({ config: await loadConfig(cwd) }, "Full configuration loaded");
36816
36753
  } catch (e) {
36817
36754
  return mcpError("Failed: " + e.message, "Error occurred");
36818
36755
  }